Keep Cursor and Claude Code on your tokens

Coding agents make up values when they can't see your tokens. Connect them to Flash over MCP and make them check their own output.

Why agents drift off brand

Ask an agent for a settings card and it will write something plausible: bg-white, rounded-lg, text-gray-600, p-4. Nothing is broken, it's just not your product. The agent had no way of knowing your surface is --surface-raised, your radius is 12px and your muted text is a warm grey, so it reached for the most common values on the internet.

Better prompting won't fix that. The agent needs to be able to see your tokens. Flash gives it two ways to do that, and they work best together:

  • An MCP server the agent calls while it writes. It serves your current tokens on every call, so a colour you changed this morning is in the next component.
  • A rules file in the repo. It carries conventions: which component to reach for, how the system likes to be composed, what never to do.

Rules for conventions, MCP for values.

Turn on MCP access

Every plan can connect. On Free, the heavier reads (a whole system, a component, a module) are capped at 50 every 14 days; Pro and up have no cap. There are two ways to connect by hand, and the difference is who should be able to read your tokens. A host that signs in with OAuth, like Claude, ChatGPT or the Figma agent, has a third: paste the URL and approve it on Flash's consent screen. The MCP guide covers it.

Share linkAccess token
Endpointhttps://flashdsm.com/api/v1/mcp/<slug>https://flashdsm.com/api/v1/mcp
CredentialThe slug in the URLFlash sign-in in the browser
Where to turn it on[[Sync > Agents]], Enable MCP access[[Export > Cursor / Claude > MCP server]], Create access token
Who can readAnyone holding the URLOnly clients with the token
Can propose tokensNoYes, into Sync > Review

Use the share link for an open-source system or one you already publish. Use a token for anything private. Either way, save the system to your workspace first. A system that only exists in your browser has no server to connect to, which is why the buttons are disabled on it.

On the Agents tab, the MCP access card gives you four copy buttons: Copy URL, Cursor / VS Code config, Claude Code command and Setup prompt. They come pre-filled with your own URL, so the snippets below only show you the shape.

Connect Cursor or VS Code

Put this in ~/.cursor/mcp.json for every project, or .cursor/mcp.json in one project. VS Code reads .vscode/mcp.json and wants the block under "servers" rather than "mcpServers". The snippet below is the Cursor format.

{
  "mcpServers": {
    "flash-my-system": {
      "url": "https://flashdsm.com/api/v1/mcp"
    }
  }
}

On a share link, put the slug in the URL instead. Flash speaks stateless streamable HTTP, so it has to be url, not a command. A client that tries to open an SSE stream gets a 405. Do not add an Authorization header. Cursor opens Flash sign-in the first time the server is used.

Connect Claude Code

Add the server from your terminal:

claude mcp add --transport http flash-my-system \
  https://flashdsm.com/api/v1/mcp

Then run /mcp in the session and sign in in the browser. Do not pass --header.

For a share link, pass https://flashdsm.com/api/v1/mcp/<slug> instead. No sign-in.

To check it worked, ask the agent what your accent colour is. If it answers with your hex, it's reading the real system. If you'd rather not hand-edit anything, the Setup prompt is a paste for the tool's chat: it configures the server and then proves the connection works.

One token per machine

Cursor and Claude Code do not use this token. They sign in in the browser. The token is for a script or for Genome, the local CLI, when something cannot open a browser.

When you click Create access token, the raw flash_mcp_ value appears once, under "Copy this now - it is not shown again". Flash only keeps a hash of it. There is no way to show it again, so connecting a second machine that cannot use sign-in means creating a second token. That is also the right habit to have:

  • One token per person or CI job, never one shared across the company.
  • The panel lists every token by its prefix with when it was last used. The trash icon revokes that one token and nothing else.
  • A revoked token gets a 401. It is never quietly downgraded to public access, even if the system also has a share link, so revoking actually works.

The server allows 120 calls a minute per IP address. A well-behaved agent calls get_kit once per session and never gets close.

Which rules file for which tool

[[Sync > Agents]] also lists files an agent reads from the repo. Each has Copy rules and a download.

FileWhere it goesBest for
AGENTS.mdRepo rootAny agent. The cross-tool convention, and the one to ship if you ship only one
DESIGN.mdNext to your token filesLayout judgment: type steps, rhythm, where the primary colour goes
SKILL.md.claude/skills/<system>/SKILL.mdClaude Code, which pulls it in when a task matches the skill's description
CLAUDE.mdRepo root, or claude.ai project knowledgeClaude Code and claude.ai projects
.cursorrulesProject rootCursor

AGENTS.md tells the agent which values it may use. DESIGN.md tells it how to compose with them, which is the part agents are worst at on their own. In practice: AGENTS.md plus DESIGN.md for everyone, the skill if your team lives in Claude Code, and MCP underneath all of it for live values.

[!NOTE] Rules files are snapshots. Change a token and the file in your repo is out of date until you copy it again. MCP doesn't have that problem, which is why the two go together.

check_violations in practice

check_violations is the tool you'll use most. The agent hands it a snippet of CSS, JSX or HTML and gets back every hard-coded colour and spacing value that should have been a token. Where one fits, it names the token. Add a line to your rules file or prompt: "Before you call a UI task done, run check_violations on what you wrote and fix everything it reports."

A result looks like this:

{
  "count": 2,
  "violations": [
    {
      "rule": "prefer-token",
      "message": "Hardcoded color #3d6bf5 matches token primary-500 - use the token",
      "match": "#3d6bf5",
      "line": 3,
      "column": 18,
      "suggestion": "primary-500"
    },
    {
      "rule": "arbitrary-tailwind-spacing",
      "message": "Arbitrary spacing p-[18px] is not in spacing tokens",
      "match": "p-[18px]",
      "line": 3,
      "column": 40,
      "suggestion": null
    }
  ],
  "indexed_colors": 64
}

Watch indexed_colors. It is how many token colours the linter could compare against. Zero means there was nothing to check against, not that the code is clean.

suggest_token takes one raw value like 12px and names the matching token or the nearest one. propose_token (token connections only) files a missing token into [[Sync > Review]] rather than letting the agent invent one. Nothing changes until a person accepts it.

[!WARNING] The first 512 characters of a snippet sent to check_violations are kept on the system's activity feed, like every tool call's arguments. Know that before you point it at a private codebase.

The same button, before and after

Before, an agent with no context:

<button className="bg-blue-600 hover:bg-blue-700 text-white px-[18px] py-2 rounded-lg">
  Save changes
</button>

After, the same prompt with MCP connected and AGENTS.md in the repo:

<button className="bg-primary-500 hover:bg-primary-600 text-on-primary px-4 py-2 rounded-md focus-visible:outline-focus">
  Save changes
</button>

The class names come from your Tailwind export and the values from your system. It remembered a focus state because your rules asked for one. If you then rename primary in Flash, the next button follows without anyone editing a rules file.

For the full tool list and a table of errors with their fixes, see the MCP guide. If the agent is a builder like Lovable or v0 rather than an editor, read Hand off to Lovable, v0 and Bolt next.