@bridge-ds/mcp
An MCP server that connects your own Claude (Claude Code, Claude Desktop or any MCP client) to your own
design system repo. Claude can read your DTCG tokens, components and docs, run your contrast gate, and
propose token changes as reviewable branches and pull requests. It never writes to main.
Free and source available (FSL-1.1-MIT, each version becomes MIT after two years). Local, no backend, no account: it reads files on your disk, or a GitHub repo with your own token.
Run it
From npm, nothing to build:
npx -y @bridge-ds/mcp --repo owner/name # GitHub repo: your gh sign-in, else read-only
GITHUB_TOKEN=... npx -y @bridge-ds/mcp --repo owner/name # GitHub repo, can open PRs
npx -y @bridge-ds/mcp --root . # local folder (default: current directory)
npx -y @bridge-ds/mcp --help
Connect it to Claude Code:
claude mcp add bridge -s user -- npx -y @bridge-ds/mcp --repo owner/name
# so Claude can open pull requests (a fine-grained token limited to that repo):
claude mcp add bridge -s user -e GITHUB_TOKEN=your-github-token -- npx -y @bridge-ds/mcp --repo owner/name
# or a local checkout:
claude mcp add bridge -- npx -y @bridge-ds/mcp --root /abs/path/to/your-ds
Or commit a project .mcp.json. Claude Desktop, other clients and the full guide: docs/AI.md.
Working on the server itself: npm run mcp:build in a clone of this repo builds it to
packages/mcp/dist/index.js, which this repo's own .mcp.json runs.
Modes
| Mode | Start with | Reads | Writes |
|---|---|---|---|
| Local | --root <dir> (default cwd) | working tree | a commit on a new local bridge/* branch, via git plumbing: your checkout, index and working tree are untouched. Never pushes. |
| Remote, no token | --repo owner/name | GitHub (raw files, one API call for the tree) | nothing |
| Remote, token | --repo owner/name + GITHUB_TOKEN | GitHub API | new bridge/* branch, commit, draft PR labelled source: mcp and tier: N |
Tools
79 tools. "writes" tools change files, branches, pull requests or issues; they need a token in remote mode and only run when the person asked.
| Tool | Access | What it does |
|---|---|---|
bridge_apply_suggestion | writes | Apply a Bridge suggestion to today's code ("Apply Bridge suggestion #42"). |
bridge_archive_exploration | writes | Archive an exploration, as in Studio: the archived label on its still open pull request hides it from the default lists, home and counts (bridge_list_explorations with archived: true lists them). |
bridge_ask_someone_else | writes | Ask the other people who can give the missing approvals to review a branch, as "Ask someone else to review" in the Studio review queue, and take the person off its requested reviewers. |
bridge_audit | reads | Measure how a product codebase uses this design system (local only). |
bridge_back_to_draft | writes | Take a branch out of review back to draft, as in Studio's More menu. |
bridge_branch_status | reads | One branch in review as Studio shows it: its product, status (draft, in review, needs design or tech approval, blocked by tests, conflict, ready to merge, merged, closed), approvals (Tier 1: one owner approval; a branch that applies an approved suggestion carries its approvals), tests, how it stands against main, whether the person may merge it (the same verdict as the Merge button and status chips in Studio), and the next step. |
bridge_check_contrast | reads | Run the repo's WCAG contrast gate (every pair in every brand x theme). |
bridge_close_branch | writes | Close a branch without merging it, as in Studio's More menu. |
bridge_close_exploration | writes | Close an exploration without merging it. |
bridge_combine_branches | reads | Combined preview of 2 to 4 token branches, as "Try together" in Studio: each branch's own token edits on the latest main, the tokens two branches set differently (pick one per key with picks), and the links that open the combination (the admin demo with the Bridge toolbar, the library views). |
bridge_comment | writes | Post a comment on a branch, or reply in the thread of a line comment (replyTo: its id from bridge_list_comments). |
bridge_continue_exploration | writes | Pick an exploration up where it was left, when the person says "Continue Bridge exploration #12" (Studio's Continue line; shop#12 for a product with its own repository) or asks to continue one by name. |
bridge_create_request | writes | File a component change request as a GitHub issue labeled component-change (source: mcp), in the same format as Figma and Bridge Studio requests. |
bridge_create_suggestion | writes | File any change as a suggestion from its payload (schema bridge.suggestion/1: kind, title, summary, and tokens edits, docs, componentSpec or files). |
bridge_draft_docs | reads | Start or refresh a component's docs.json. |
bridge_exploration_to_figma | reads | What Claude needs to rebuild an exploration in a new page of the team's Figma file, when the person says put or send this exploration in Figma (Studio's line: "Put Bridge exploration shop#12 in Figma"). |
bridge_figma_changes | reads | The library branches the DS Bridge Figma plugin opened for components changed in Figma (label from-figma), with where each stands: an exact token change (no AI, contrast gated), or a branch carrying the spec, waiting for Claude AI to draft the code, then drafted by Claude AI and reviewed by a person. |
bridge_figma_coverage | reads | Which components are in Figma, in Studio's words (Yes, Drafted, Auto layout, Not yet with the reason), and whether code images exist for the fidelity check the DS Bridge Figma plugin runs (its scores live in Figma). |
bridge_figma_gaps | reads | The components whose Figma build differs from their story (Differs) or cannot be checked (Can't check, with the reason), from the latest Check fidelity run of the DS Bridge plugin (the story shots are the referee), else from the measure's own check; a status fix in figma-fixes.json shows with its reason. |
bridge_get_build_request | reads | One build request, ready to build: what the designer sent (the request, before and after images, props needed, the spec when the issue keeps it), the status timeline, the linked pull request, the Jira key, the component files and brief, the prompt to build it in this repo. |
bridge_get_claude_design_system | reads | The Bridge Library as a Claude Design System, at the version Bridge serves now: the version, a manifest (path, size, sha256 and download url of each file, published under project/), the team's Design System artifact when Bridge knows it, what to do ("create", "update" or "none"), the files that changed since the team last published, and the steps. |
bridge_get_component | reads | One component: props parsed from TypeScript (type, default, description, allowed values), usage docs (summary, whenToUse, whenNotToUse, dos/donts with examples, accessibility, contentGuidelines, anatomy), CSS variables it uses, story names, and figma: its Figma component and link from bridge.components.json, or "not linked to Figma yet". |
bridge_get_config | reads | Where the design system lives and what Bridge may do: source (local path or GitHub repo), write access, token tiers, modes (brand/theme/density...) and the full bridge.config.json. |
bridge_get_design_language | reads | The design language doc (principles, color, type, space, density, radius, elevation, motion, icons, voice, accessibility). |
bridge_get_figma_change | reads | One library branch sent from Figma: its spec (variant matrix, properties, bound variables per variant, layers, what code gave Figma before, the exact token swaps) and the brief to draft the code on that branch. |
bridge_get_gap_case | reads | One component's gap case: per differing variant, its story, args, state, shot and every difference with the part id, property, expected (code) and actual (Figma) and the delta in px. |
bridge_get_guidelines | reads | Rules for agents in this repo (AGENTS.md): always / ask before / never lists, token conventions, risk tiers, and what Bridge enforces. |
bridge_get_history | reads | History of the design tokens: merged token-changing PRs and commits (local git: first parent of HEAD; GitHub: PR merge commits), newest first, each with author, date, why (changeset summary, PR or commit body), version it shipped in, risk tier, semver bump, breaking flag and change counts, plus the timeline of design system versions. |
bridge_get_request | reads | One request, ready to implement: the parsed request (component, kind, summary, changes asked, Figma link, images), its status and linked pull requests, the component files found under the components directory, the agent rules file, and brief: the prompt to implement it in this repo. |
bridge_get_review | reads | Review a token change: designer-readable diff table, contrast before -> after, new validation errors, downstream impact, computed risk tier (and a warning if labelled lower), and for PRs the CI status, approvals and roles: who may approve design, approve tech and ship, with GitHub teams named and their size, and any team that cannot be read with the fix. |
bridge_get_settings | reads | What Studio Settings shows that is safe to read: who approves design and tech (GitHub teams named with their size), who may merge, the owner override (who, what reason), whether main is protected, the products, the preview apps and the visual impact mode. |
bridge_get_suggestion | reads | One suggestion: the change (tokens before and after, docs, component spec, files), the checks when suggested, links, its version (payloadSha: what approvals bind to), who approved it, which approvals are missing for its tier, reviews that no longer count (an older version, or not an owner), whether the machine-readable block was edited by hand, linked pull requests, and for a component spec the brief to implement it. |
bridge_get_token | reads | Everything about one token: CSS variable, type, tier, description, the files that define it, resolved value in every mode (brand x theme x density, collapsed where equal) with its alias chain, tokens that alias it, and components whose CSS uses it (directly or through a component token). |
bridge_get_token_history | reads | Every recorded change of one token, newest first, renames followed: value before and after per mode (raw and resolved CSS), who, when, the PR and why. |
bridge_link_suggestion | writes | Record the pull request (or branch, or commit) that applies a suggestion: a comment on the issue and the "suggestion: applying" label. |
bridge_list_brands | reads | Brands of the repo: slug, name, default, primary action color and theme override files. |
bridge_list_build_requests | reads | Build requests: structure changes pushed from Figma (a new variant, option, layout or component) that developers build, as GitHub issues labeled component-change and bridge-build, plus library branches from Figma waiting for a developer. |
bridge_list_comments | reads | The conversation on a branch and its line comment threads, with the ids to reply to (bridge_comment with replyTo). |
bridge_list_components | reads | List design system components with family, one-line summary (what it is for) and figma: the Figma component and its link, or "not linked to Figma yet". |
bridge_list_explorations | reads | Explorations (pull requests on explore/* branches) of the design system repository and of every product with its own repository (bridge.config.json products[].repo, one read each; a product repository Bridge cannot reach is left out, bridge_list_products says which): ref ("#12", or "shop#12" in a product repository: pass it as is to the other exploration tools), repo, name, purpose, status (active: running; ready: done exploring, waiting for code; building: developers push to it; shipped: merged; promoted: sent to review the older way; closed), archived, author, last update, for open ones the preview links Vercel reports (url null while it has not reported one yet) and the install command a product staging branch uses, read from the preview comment on the pull request (state building until the snapshot of the latest commit is published, never a guessed command), and the component requests implemented on each. |
bridge_list_products | reads | The products of this design system (bridge.config.json "products": name, repo or folder, preview link pattern, framework; for a product with its own repository, connection: connected, read-only or not-connected, where not-connected means its explorations are left out of the lists until an admin installs the Bridge GitHub App there; access says in one sentence whether this person can start and save its explorations, trust it over connection) and the one the current folder or repo belongs to, which tools that start work use when no product is given. |
bridge_list_requests | reads | Component change requests: GitHub issues labeled component-change (from Figma, Bridge Studio, the CLI or an AI tool). |
bridge_list_reviews | reads | Open pull requests on the repo (flagging the ones Bridge opened) and, locally, the bridge/* proposal branches. |
bridge_list_suggestions | reads | Suggestions in the repo: GitHub issues labeled bridge-suggestion, each an exact change (tokens, docs, a component spec, a brand, a revert, settings) that the owners approve and a developer applies. |
bridge_list_tokens | reads | List tokens with their resolved CSS value in one mode. |
bridge_mark_figma_change_drafted | writes | After you pushed the code for a component change from Figma to its branch: mark its pull request ready for review, label it drafted-by-claude (no longer waiting-for-claude) and say so in its description, in one step, for a person to review. |
bridge_merge_branch | writes | Merge a branch into main through the same gate as Studio's Merge button: tests pass, the approvals its tier needs (Tier 1: one owner approval; Tier 2 and 3: design and tech; a branch that applies an approved suggestion with Closes #n carries its approvals while the suggestion stays approved and the tier is not higher), no changes requested, no conflict, not a draft or an exploration, and the person holds the right to ship (governance.rights). |
bridge_missing_pieces | writes | Check a product branch (an exploration started for a product) against the library: the adoption audit on each product file it changes, at its start and at its head, keeps what the branch added. |
bridge_open_library_branch | writes | Turn one recorded missing piece into a library branch linked to the product branch, as Bridge Studio does: a token piece opens a token change (same gate and body as bridge_propose_token_change, a draft for design and tech review) and the product branch takes its preview; a variant opens a library exploration with the brief to build it (build it there, then bridge_use_library_preview); a new component opens a component request. |
bridge_pending_drafts | reads | Change texts a designer asked their own Claude to write from the DS Bridge Figma plugin ("Draft with my Claude"), waiting on the bridge-requests branch. |
bridge_plan_brand | reads | Dry run of a new brand: the brand token file (generated primary and neutral ramps, radius and font roles), copied theme overrides, the bridge.config.json change, every contrast pair for the new brand in light and dark (ok, or the failing pairs), validation issues, the risk tier (always Tier 3, minor) and the PR body. |
bridge_plan_revert | reads | What undoing a merged token change takes, computed against the CURRENT base branch (not a blind git revert): the inverse edits, conflicts where a token changed again later (with the later PR), changes already undone, contrast before and after, new validation errors, risk tier, files and the PR body ("Revert: ", links the original PR).</td></tr> <tr><td><code>bridge_product_branch</code></td><td>reads</td><td>A product branch as Studio shows it: the summary sentence, each linked library branch with its status and reviewers, what its preview means for the product branch and the next action, and the pieces with no library branch yet.</td></tr> <tr><td><code>bridge_promote_exploration</code></td><td>writes</td><td>"Done exploring" on an exploration (explore/<name>), as in Studio (the tool keeps its old name).</td></tr> <tr><td><code>bridge_propose_brand</code></td><td>writes</td><td>Propose a new brand as a reviewable change.</td></tr> <tr><td><code>bridge_propose_component_map</code></td><td>writes</td><td>Proposes bridge.components.json entries that link Library components to their Figma components, and opens them for review like other Bridge changes (a suggestion, or a draft pull request in direct mode; never main).</td></tr> <tr><td><code>bridge_propose_revert</code></td><td>writes</td><td>Plans the revert (or restore) like bridge_plan_revert, then: local repo, commits to a new local bridge/* branch without touching your working tree (never pushes); GitHub with token, new bridge/* branch and a PR labelled revert and its tier (draft for Tier 2 and 3).</td></tr> <tr><td><code>bridge_propose_token_change</code></td><td>writes</td><td>Propose token edits as a reviewable change.</td></tr> <tr><td><code>bridge_push_figma_component</code></td><td>writes</td><td>What the DS Bridge plugin Push tab does, from a structured diff of a Figma component (the v 1 spec shape: component, figmaName, coded, kind, title, summary, changes, rebinds, needsCode, unknown, variantAxes, properties, bindings, anatomy).</td></tr> <tr><td><code>bridge_reopen_branch</code></td><td>writes</td><td>Reopen a closed branch, with Studio's rule: its author or an owner with write access, and only while its work is still on GitHub.</td></tr> <tr><td><code>bridge_review_branch</code></td><td>writes</td><td>Approve, request changes or comment on a branch, as the review box in Studio, on the version the person saw, under their GitHub account.</td></tr> <tr><td><code>bridge_review_pr</code></td><td>writes</td><td>Post a review on a PR as the token owner: comment, approve or request changes, with a body.</td></tr> <tr><td><code>bridge_review_suggestion</code></td><td>writes</td><td>Approve, request changes on, comment on or decline a suggestion, as the person whose GitHub token the server has.</td></tr> <tr><td><code>bridge_save_docs</code></td><td>writes</td><td>Save a component's usage guidance (docs.json sections: summary, whenToUse, whenNotToUse, dos, donts, accessibility, contentGuidelines, anatomy, preview) the way the Library edit mode does: merged into the docs on the branch, cleaned and checked (a summary, no empty items, no em dash).</td></tr> <tr><td><code>bridge_save_exploration</code></td><td>writes</td><td>Save prototype code on an exploration: one commit with the files you send on its explore/<name> branch, so its preview updates in a few minutes.</td></tr> <tr><td><code>bridge_scaffold_component</code></td><td>writes</td><td>Generate a new component folder per the repo checklist: Name.tsx (forwardRef, typed props), Name.module.css (existing tokens only), stories with AllStates, docs.json with the reference component's keys, a keyboard + axe test when interactive, index.ts.</td></tr> <tr><td><code>bridge_search_tokens</code></td><td>reads</td><td>Find tokens by words in the path or description ("danger text", "focus ring"), by CSS variable, or by value ("#c2410c", "16px": exact and near colors).</td></tr> <tr><td><code>bridge_send_for_review</code></td><td>writes</td><td>Ask for review: a draft branch becomes ready for review, as "Mark as ready" in Studio.</td></tr> <tr><td><code>bridge_set_claude_design_system_url</code></td><td>writes</td><td>Saves, for the team, the address of its Design System artifact in Claude Design and the version just published to it, so the next bridge_get_claude_design_system lists only the files that changed and Studio Settings says when an update is ready.</td></tr> <tr><td><code>bridge_start_exploration</code></td><td>writes</td><td>Start an exploration: a branch explore/<slug> from the default branch with a note file, and a DRAFT pull request labeled exploration.</td></tr> <tr><td><code>bridge_switch_to_published</code></td><td>writes</td><td>Once its library branches shipped, bring main into the product branch (GitHub update branch): it stops carrying the library change and uses the shipped one.</td></tr> <tr><td><code>bridge_try_branch</code></td><td>reads</td><td>Try a branch before it merges: the preview link of each product Vercel reported for it (the admin demo opens with the Bridge toolbar on, as "Try it in the product" in Studio), the other previews, and "Share with a product team": the install command a product team runs in a staging branch, or why there is none yet, with a ready-to-paste message.</td></tr> <tr><td><code>bridge_update_from_main</code></td><td>writes</td><td>Bring the latest main into a branch, as "Update from main" in Studio.</td></tr> <tr><td><code>bridge_use_library_preview</code></td><td>writes</td><td>The product branch takes the latest commits of the library branch of a piece (Bridge merges it in), so the product preview shows the real library change before it ships.</td></tr> <tr><td><code>bridge_validate_tokens</code></td><td>reads</td><td>Validate tokens: DTCG 2025.10 shape per $type, names, broken and circular aliases in every mode, alias type mismatches, missing layer files, and mode parity (a semantic token must exist in both light and dark).</td></tr> <tr><td><code>bridge_visual_impact</code></td><td>writes</td><td>Screenshots what a design system change touches, before and after, and pixel-diffs them.</td></tr> <tr><td><code>bridge_what_needs_me</code></td><td>reads</td><td>The review queue, as Studio counts it (open branches, without running explorations and the release automation), each with its status in designer words, and first the ones where the person acts now: an approval they can give, their own branch blocked, ready for them to merge.</td></tr> <tr><td><code>bridge_whoami</code></td><td>reads</td><td>Who this session acts as: the person's name, their role in the team (Admin, Reviewer, Can edit or Reader), how they signed in (GitHub login, or email member with the address masked), the team, and in one line what a save means for them (through Bridge as them, or with their own GitHub access).</td></tr> <tr><td><code>bridge_write_drafts</code></td><td>writes</td><td>Write the titles, summaries and change lines (or, for docs items, the docs sections or the rewritten passage) you drafted for a session from bridge_pending_drafts.</td></tr> </tbody> </table> <!-- tools:end --> <p>Resources: <code>bridge://tokens/resolved</code>, <code>bridge://design-language</code>, <code>bridge://guidelines</code>, <code>bridge://components/{name}</code>. Prompts: <code>review-token-pr</code>, <code>add-component</code>, <code>audit-ui-for-tokens</code>, <code>migrate-file-to-ds</code>.</p> <h3 id="the-merge-gate-is-studios">The merge gate is Studio's</h3> <p><code>bridge_branch_status</code>, <code>bridge_merge_branch</code> and <code>bridge_what_needs_me</code> (and <code>bridge branch status|merge|list</code> in the CLI) read the same verdict as Studio's branch page and status chips: <code>branchVerdict</code> in <code>@bridge-ds/core</code>. Tier 1 needs one owner approval; Tier 2 and 3 a design owner and a tech owner. A branch whose body says <code>Closes #<n></code> for an approved suggestion carries that suggestion's approvals while it stays approved and the branch's tier is not higher. The owner override (<code>overrideReason</code>) is for owners named in <code>governance.override.allowed</code> only, skips missing approvals only, and always needs a reason of at least <code>minReasonLength</code> characters (20 by default). See <a href="../../docs/GOVERNANCE.md#one-verdict-everywhere">GOVERNANCE.md</a>.</p> <h2 id="configuration">Configuration</h2> <p><code>bridge.config.json</code> at the repo root says where tokens live, how they layer per mode, and what Bridge may write. It is the same file the Figma plugin and the docs site read, with one schema: <a href="../core/bridge.config.schema.json"><code>packages/core/bridge.config.schema.json</code></a>. Without one, Bridge detects a config (token directory, tiers by folder name, light/dark and density files as modes); <code>bridge init</code> writes the detected one so you can pin and edit it.</p> <pre><code class="language-jsonc">{ "$schema": "./packages/core/bridge.config.schema.json", "repo": { "owner": "acme", "name": "design-system", "defaultBranch": "main" }, "tokens": { "root": "packages/tokens/src", "include": ["**/*.tokens.json"], "tiers": { "primitive": ["primitives"], "semantic": ["semantic"], "component": ["components"] }, // lowest first; {mode} placeholders pick the file per mode value "layers": [ { "files": "primitives/*.tokens.json" }, { "files": "brands/{brand}.tokens.json" }, { "files": "semantic/{theme}.tokens.json" }, { "files": "brands/{brand}.{theme}.tokens.json", "optional": true }, { "files": "components/*.tokens.json" } ] }, "modes": { "theme": { "values": ["light", "dark"], "default": "light", "parity": true } }, "contrast": { "path": "packages/tokens/src/contrast.checks.json" }, "components": { "dir": "packages/react/src/components" }, "changesets": { "dir": ".changeset", "package": "@acme/tokens" }, "governance": { "protectedBranches": ["main", "master"], "branchPrefix": "bridge/", "labels": ["source: mcp"], "owners": { "design": ["designer-login"], "tech": ["engineer-login"] } } } </code></pre> <h2 id="develop">Develop</h2> <pre><code class="language-sh">npm run mcp:test # builds both packages, runs vitest (real repo tokens, a fixture repo, fake GitHub, stdio smoke test) </code></pre> <p>All design-system logic comes from <code>@bridge-ds/core</code>, through <code>src/core-adapter.ts</code>: layered token sets, validation, contrast, minimal-diff edits, diffs, the PR body, changesets, the GitHub client, the local git writer (<code>@bridge-ds/core/node</code>) and the risk classifier the Figma plugin and the docs site use too. <code>npm run mcp:build</code> bundles the server and the CLI with esbuild, compiling <code>@bridge-ds/core</code> in.</p> <h2 id="license">License</h2> <p>MIT</p> |