ds-canon
The ds-canon server provides a read-only MCP interface to query a design system's tokens, components, conventions, and deprecations, serving as an authoritative source of truth for agents and developers.
Tokens: List all design tokens with optional filters (group, status, substring search). Get a specific token's full details (value, type, group, status, aliases, and which components consume it), with suggestions if misspelled.
Components: List components with optional status/tag filters, including summaries. Get full component details (props, variants, tokens used, deprecation info, and anti-pattern guidance), with suggestions if misspelled.
Dependency analysis: Perform reverse-dependency lookup to see what depends on a token or component, helping you understand the impact of changes.
Deprecations: Get a list of all deprecated tokens and components, their replacements, and how many active items still depend on them.
Conventions: Retrieve house rules for naming, spacing, color, accessibility, and deprecation, optionally filtered by topic.
Token drift detection: Scan code snippets (CSS, JSX, plain text) for hardcoded colors/px values and suggest matching design tokens to enforce token usage.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ds-canonI want to change space.inset.md. What will it affect?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ds-canon
Your design system's canon, queryable by agents. What exists, what is deprecated, what breaks if you touch it.
Design systems decay into tribal knowledge the moment the token sheet drifts from the code and the person who remembers why gets pulled onto another project. Agents writing UI code make this worse: they hallucinate plausible token names and confident-sounding component APIs because they have nothing authoritative to check against. ds-canon puts your design system's tokens, components, conventions, and deprecations behind a read-only MCP server, so agents and the humans directing them query the same system of record instead of guessing.
The path from zero to a drift sweep
The user journey, end to end:
flowchart LR
A[Find the repo] --> B[npx -y ds-canon: try the demo]
B --> C[Clone and build]
C --> D[Register as an MCP server]
D --> E[Query the tools]
E --> F[Author your own canon]
F --> G[Boot your system]
G --> H[Sweep for drift]
H --> I[Read the findings]Related MCP server: Design System MCP Server
The 60-second demo
Run it straight from npm, nothing to clone:
npx -y ds-canonYou'll see a one-line banner confirming what loaded:
ds-canon v0.2.0 serving Nimbus DS (40 tokens, 9 components) from /path/to/ds-canon/fixtures, read-only. Waiting for an MCP client on stdin (Ctrl+C to exit). For a one-off CLI drift scan, run: ds-canon drift <path>.Then it sits there. That is correct: ds-canon is a stdio MCP server, so after the banner it blocks waiting for a client to speak JSON-RPC on stdin. It is not hung. Register it with an MCP client (below), run the bundled smoke-test client (node examples/mcp-client.js), or press Ctrl+C to exit.
The banner prints to stderr, not stdout, because stdout is reserved for the MCP protocol stream; a stray log line on stdout would corrupt the JSON-RPC frames a client reads. So if you are watching stdout you will see nothing until a client connects, and that is by design.
The server ships with a fixture design system called Nimbus DS so you can try it immediately, no setup required. Point an MCP-aware agent at it and ask it real questions.
"Which accent color should I use, and is anything deprecated?"
The agent calls list_tokens with group: "color", query: "color.accent", then whats_deprecated. Real output, verbatim:
{
"tokens": [
{
"name": "color.accent.primary",
"value": "#3B5BDB",
"type": "color",
"group": "color",
"status": "active",
"description": "Primary brand accent. Used for primary actions, active navigation state, and focus affordances."
},
{
"name": "color.accent.secondary",
"value": "#5C7CFA",
"type": "color",
"group": "color",
"status": "active",
"description": "Secondary accent for lower-emphasis interactive elements that still need to read as brand-colored."
},
{
"name": "color.accent.legacy",
"value": "#4C6EF5",
"type": "color",
"group": "color",
"status": "deprecated",
"description": "Original brand blue from the v1.x palette. Slightly less saturated than accent.primary; kept only for Banner and LegacyButton until both migrate.",
"deprecatedBy": "color.accent.primary"
}
]
}(The query parameter is a substring match on name and description, so a looser query like "accent" also surfaces tokens whose descriptions mention accent usage. Scoping the query to the name prefix keeps the answer tight.)
{
"deprecated": [
{ "name": "color.accent.legacy", "kind": "token", "deprecatedBy": "color.accent.primary", "dependentCount": 1 },
{ "name": "LegacyButton", "kind": "component", "deprecatedBy": "Button", "dependentCount": 0 }
],
"legacy": []
}The agent now knows to recommend color.accent.primary and to flag color.accent.legacy as on its way out, with one live component (Banner) still depending on it. The separate legacy array (empty here) is for values that are live and intentionally kept, not scheduled for removal, so they never get mixed in with the migrate-off-me list.
"I want to change space.inset.md. What will it affect?"
This is the question a design system actually needs to answer before anyone touches a shared value. The agent calls find_usages:
{
"entity": "space.inset.md",
"usages": [
{ "dependent": "Button", "dependentKind": "component", "relation": "consumes token" },
{ "dependent": "Card", "dependentKind": "component", "relation": "consumes token" },
{ "dependent": "Field", "dependentKind": "component", "relation": "consumes token" },
{ "dependent": "Modal", "dependentKind": "component", "relation": "consumes token" }
]
}Blast radius, in one call: four components, named exactly. No spelunking through a component library to find every place 12px got typed in by hand.
"Write a secondary button that follows our conventions."
The agent calls get_component for Button (props, variants, the tokens it consumes, and its doNotUse guidance) and get_conventions for the color topic, then writes the component. Now suppose it (or a human) had instead hardcoded the color:
<button style={{ background: '#3B5BDB', padding: '12px' }}>Save</button>Running that snippet through check_token_drift catches both literals:
{
"findings": [
{
"severity": "error",
"raw": "#3B5BDB",
"suggestion": "color.accent.primary",
"message": "Hardcoded value #3B5BDB matches token \"color.accent.primary\". Use the token instead of the raw value."
},
{
"severity": "error",
"raw": "12px",
"suggestion": "space.inset.md",
"message": "Hardcoded value 12px matches token \"space.inset.md\". Use the token instead of the raw value."
}
]
}#3B5BDB and 12px are exact token values, so each finding is error: a token already exists, so this should be fixed. Findings come in three tiers. error means an exact token exists for the value. warn means a near-miss (a value close to a token, or an off-scale spacing value near a step) worth a look. info covers everything else: unmatched values, and matches whose token role does not fit the property (a background token suggested for a color property is reported honestly, not as an action).
Install
ds-canon runs as a local MCP server over stdio. There is no separate service to deploy.
mcp.json (Claude Desktop, or a project-level .mcp.json for Claude Code):
{
"mcpServers": {
"ds-canon": {
"command": "npx",
"args": ["-y", "ds-canon"]
}
}
}Claude Code, one line:
claude mcp add ds-canon -- npx -y ds-canonClaude Desktop: add the same mcpServers entry to your claude_desktop_config.json and restart the app.
Working from a clone instead (for development or custom fixtures): git clone, npm install, npm run build, then point command at node with args: ["/absolute/path/to/ds-canon/dist/index.js"].
Tools
Eight tools, all read-only.
Tool | What it answers | Key inputs |
| What tokens exist? |
|
| What is this token and who uses it? |
|
| What components exist? |
|
| What does this component look like? |
|
| What breaks if I change this? |
|
| What should I stop using? | none |
| What are the house rules? |
|
| Does this code drift from the token system? |
|
get_token, get_component, and find_usages look up by exact name; a miss returns a not_found error with up to three closest-name suggestions instead of an empty result, so a typo doesn't read as "this doesn't exist."
check_token_drift takes either a snippet string or a path to a single file (read-only, 20MB cap). Give it a path and every finding carries a 1-based line. whats_deprecated returns two arrays: deprecated (scheduled for removal) and legacy (live and intentionally kept, see below), so a rebrand alias you keep on purpose does not read as something to migrate off.
Drift on the command line (CI)
Drift is also reachable without an MCP client, for pre-commit hooks and CI:
npx ds-canon drift "src/**/*.css" --fixtures /path/to/your/fixtures --fail-on errorIt reads the files directly (a file, a directory, or a glob), prints a file:line table, and exits non-zero when findings meet the threshold. --fail-on error (the default) fails only when an exact token exists for a hardcoded value; --fail-on warn also fails on near-misses. --fixtures defaults to DS_CANON_FIXTURES, then the bundled Nimbus fixtures. The CLI and the MCP tool share one scan path, so a finding reads the same either way.
The bundled smoke-test client
examples/mcp-client.js is a tiny, dependency-free stdio client (initialize, tools/list, tools/call). It doubles as a smoke test: after npm run build, run
node examples/mcp-client.jsand it starts the server, lists the tools, runs a drift check, and prints a token count, then exits. If you want to see the JSON-RPC framing ds-canon expects from a client, this is the shortest complete example.
Pitfalls
Two behaviors surprised early users. Both are handled now; this is how they work so the output is never misread.
Definitions are not usages. A line that defines a custom property (
--card: #fff;) is the token's own source, not a place that drifted from it, socheck_token_driftnever flags the value on a--name:declaration. It handles several declarations packed on one line and names with digits (--paper-2:). Only actual usages (background: #fff) are flagged. Earlier versions flagged every:rootdefinition, which made a fully tokenized stylesheet look like nothing but drift.No space tokens means no spacing noise. If your canon defines zero
space.*tokens (a legitimate choice), px values are not measured against a scale that does not exist. Instead of one "off-scale" finding per literal, you get a single info noting that spacing literals were not checked. The same rule applies to font-size and line-height literals when notype/dimensiontokens are defined.
Point it at your own system
ds-canon reads three files from a fixture directory: tokens.json, components.json, and conventions.md. By default it loads the bundled Nimbus DS fixtures. Set DS_CANON_FIXTURES to point it at your own:
DS_CANON_FIXTURES=/path/to/your/design-system node dist/index.jsor in mcp.json:
{
"mcpServers": {
"ds-canon": {
"command": "npx",
"args": ["-y", "ds-canon"],
"env": { "DS_CANON_FIXTURES": "/path/to/your/design-system" }
}
}
}tokens.json accepts the tested flat, string-valued W3C DTCG token shape: groups may be nested, and each token leaf must provide string $value and $type fields, with optional string $description. Style Dictionary or Tokens Studio exports work only when they match that shape. Composite values and tool-specific export shapes need an adapter before loading. Deprecation and aliasing use two extensions on top of the base spec: an $extensions["ds-canon"] block for status/deprecatedBy, and DTCG's own {token.path} reference syntax for aliases. The server also requires components.json, a flat { meta, components } shape matching the DsComponent type in src/types.ts, and conventions.md, with one ## topic section per convention (naming, spacing, color, accessibility, deprecation) plus Rule:, Rationale:, and Example: lines. The loader validates all three at startup and throws a specific file-and-field-level error on malformed input rather than serving a partially loaded system.
Two $extensions["ds-canon"] features cover the messy parts of a real system. Set a token's status to legacy for a value that is live and intentionally kept but no longer preferred (a rebrand alias), distinct from deprecated, which implies removal. And declare intentional raw values so drift never flags them, with a top-level sanctionedLiterals list where each entry needs a value and a required reason:
{
"$extensions": {
"ds-canon": {
"sanctionedLiterals": [
{ "value": "#f7f7f5", "reason": "page background, intentionally not tokenized" }
]
}
},
"color": {}
}For a full worked example that converts a flat CSS custom-property sheet into this shape, see docs/adopting-your-own-system.md.
Why read-only, why stdio, why no network
Every tool in ds-canon reads from an in-memory index built once at startup. Nothing in this server writes to the fixture files, calls out to a network, or accepts write operations of any kind. That's not an implementation gap, it's the point: a design system's system of record should not be mutable by the same agents that consume it, and a tool that only answers "what exists" cannot be tricked into becoming a tool that changes what exists.
Running over stdio means ds-canon has no exposed network listener. Risk is limited to local process input, file access, and parser behavior. The process caps each fixture file at 20 MB and caps fuzzy name and entity lookups at 256 characters before similarity work begins. The deployment model doubles as the governance model: install it, point it at your fixtures, and every agent that would otherwise guess now has one unwritable source of truth to query instead.
How this was built
ds-canon was built by a multi-agent factory in an afternoon: parallel contract-first builders working from frozen type definitions, adversarial challengers doing black-box QA and architecture review against the built server, and agent-to-agent fix loops that dispositioned every finding before the next phase started. Of 28 findings, 24 were fully fixed, 2 were accepted or required no change with written rationale, and 2 were partially fixed with scoped follow-on enhancements deferred. The full build log, prompts, and challenge reports are in factory/.
License
MIT. See LICENSE.
Jay Trainer, Sr. Director, Product Design, AI-Native. jaytrainerdesign.com
Available Tools
8 toolscheck_token_driftCheck token driftA
Does this code drift from the token system? Scans a snippet for hardcoded hex colors and px values and suggests the matching or nearest token.
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | ||
| snippet | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| findings | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must convey behavior. It states the scan targets (hex colors, px values) and the suggestion of matching or nearest token. It does not discuss edge cases such as no matching token, language support, or that the operation is read-only, leaving gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that gets straight to the point. It avoids redundancy and front-loads the core question.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has a clear purpose and an output schema, but the description omits the meaning of the 'lang' parameter and lacks details about failure/fallback behavior. For a tool with only 2 parameters and no annotations, this is adequate but not complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description explains 'snippet' implicitly, but 'lang' is entirely unexplained. The schema provides no descriptions, and the enum values (css, jsx, text) lack context for why lang matters, which is a significant gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Scans') and identifies the resource ('a snippet') and the action ('suggests the matching or nearest token'). It clearly differentiates from sibling tools like list_tokens or get_token by focusing on drift detection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The question format 'Does this code drift from the token system?' establishes a clear use case. However, it doesn't explicitly mention when not to use this tool or point to alternatives like list_tokens, though the sibling context makes the distinction implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_usagesFind usagesA
What breaks if I change this? Reverse-dependency lookup for a token or component, by exact name.
| Name | Required | Description | Default |
|---|---|---|---|
| entity | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| entity | Yes | |
| usages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It does add key behavior: the lookup is by exact name, and it targets reverse dependencies. However, it omits other behavioral aspects such as whether the search is case-sensitive, whether it scans all files/projects, or if it includes transitive dependencies. The existence of an output schema covers return format, so this is acceptable but not comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence. It opens with a meaningful framing question and immediately follows with the technical definition. Every word serves a purpose, with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with an output schema, the description covers the purpose, the key matching constraint, and parameter semantics. It could add more explicit guidance on usage context (e.g., 'before changing a token or component'), but the question at the start already conveys this. Overall, it is sufficiently complete given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has only 'entity' with no description and no schema description coverage. The description adds crucial meaning by stating the lookup is 'for a token or component' and 'by exact name', thus clarifying that 'entity' is the exact name of a token or component. This significantly compensates for the schema's lack of documentation, though it doesn't address edge cases like not found behavior, so not a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly frames the tool's purpose with the question 'What breaks if I change this?' and then defines it as a 'Reverse-dependency lookup for a token or component, by exact name.' This specifies the verb (lookup) and resource (reverse-dependencies), effectively distinguishing it from siblings like get_token/get_component which fetch the entity itself, and list_* tools that enumerate all.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use this tool: to assess the impact of changing a token or component, by finding reverse dependencies. The phrase 'by exact name' is an explicit usage condition. However, it does not name specific alternatives or explicitly state when not to use it, but the context is clear enough given the sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_componentGet componentA
What does this component look like? Returns full component detail: props, variants, tokens it consumes, and anti-pattern guidance, by exact name.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| component | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the output contents and the exact-name requirement, but does not reveal behavior on missing components, error handling, or authorization needs, which are relevant for a lookup tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one concise sentence, front-loaded with a question, and lists the return contents efficiently. Every word adds value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simplicity of the tool (one parameter), the description provides adequate context about what is returned and the need for exact name. The presence of an output schema covers return shape, but edge-case behavior (e.g., not found) is not described, preventing a perfect score.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description only says 'by exact name' without elaborating on the 'name' parameter's format, case sensitivity, or examples. The description does not sufficiently compensate for the lack of schema-level parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns full component detail including props, variants, tokens, and anti-pattern guidance. This distinguishes it from siblings like get_token or list_components by focusing on the component itself.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for looking up a component by exact name, providing clear context. However, it does not explicitly mention alternative tools or when not to use it, such as when needing a list of components or token-specific information.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_conventionsGet conventionsB
What are the house rules? Returns naming, spacing, color, accessibility, or deprecation conventions, optionally filtered to one topic.
| Name | Required | Description | Default |
|---|---|---|---|
| topic | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| conventions | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden of explaining behavior. It states that the tool returns conventions and optionally filters by topic, which is useful. However, it does not disclose default behavior (e.g., returns all topics when no filter is provided) or any other behavioral details such as output format or handling of empty results. The presence of an output schema partially compensates.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short sentences, front-loaded with a plain-language question and then a crisp summary of the return value and optional filter. Every word earns its place, with no redundant or ambiguous filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one enum parameter and an output schema, the description is reasonably complete: it communicates the core purpose, the topics covered, and the optional filtering behavior. It lacks sibling differentiation and usage guidance, but those gaps are partially acceptable given the tool's low complexity and the output schema's presence.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single 'topic' parameter is fully enumerated in the schema with an enum, and the description lists the same five topics. The phrase 'optionally filtered to one topic' clarifies that the parameter is optional and controls filtering, adding modest meaning beyond the schema. It does not explain the semantics of each topic choice, but those are largely self-explanatory.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool 'returns naming, spacing, color, accessibility, or deprecation conventions' with an optional topic filter. The verb 'Returns' plus the resource 'conventions' makes the purpose specific, but it does not explicitly distinguish itself from the sibling tool 'whats_deprecated', which may overlap on the deprecation topic.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives context about what the tool does and the optional filter, but it provides no explicit guidance on when to use this tool versus alternatives like 'whats_deprecated' or 'list_tokens'. There is no when-to-use or when-not-to-use framing, leaving the agent to infer usage from the topic list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tokenGet tokenA
What is this token and who uses it? Returns full token detail plus the components that consume it, by exact name.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| token | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full responsibility. It discloses that the tool returns full token detail and consumers, and indicates exact-name matching. However, it does not explain error behavior, permissions, or other potential side effects, which would be useful for a get operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with a purpose question followed by a direct statement. It earns its place without being wordy, though the question could be integrated into a single declarative sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given its simplicity (one parameter, output schema present), the description covers the essential information: what is returned, the exact-name constraint, and the resource focus. It is complete enough for an agent to select and invoke the tool correctly, though it does not mention edge-case behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage, so the description must compensate. Saying 'by exact name' adds context that the 'name' parameter is an exact match identifier, but it omits details like case sensitivity or token format. This is partial compensation for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns full token detail plus consuming components by exact name. This specific verb and resource scope distinguish it from siblings like list_tokens (which lists tokens) and list_components.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'by exact name' implies the tool is intended for when the exact token name is known, not for searching. However, it does not explicitly mention alternatives or when not to use this tool, leaving the guidance implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_componentsList componentsA
What components exist? Lists component names, status, tags, and summaries, optionally filtered by status or tag.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | ||
| status | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| components | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It discloses that the tool lists summaries and supports filtering, which is useful. But it omits details like default behavior when no filters are provided, pagination, or any side-effect guarantees. A simple list tool likely needs no such warnings, so a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two punchy sentences: a front-loaded question that sets context, followed by a compact declaration of the tool's output and optional filtering. Every word earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that an output schema exists and the tool has only two optional parameters, the description covers the core functionality well. It mentions the returned data points (names, status, tags, summaries) and the filtering capability. It lacks some nuance like how filters interact, but overall is complete for a straightforward list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the description only says 'optionally filtered by status or tag.' It adds the meaning that these parameters are filters, but it does not explain the tag parameter's format or semantics, nor what values are allowed beyond the enum visible in the schema. The description partially compensates but leaves gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'What components exist?' and then states 'Lists component names, status, tags, and summaries' – a specific verb and resource. It clearly distinguishes from siblings like get_component (single retrieval) and list_tokens (different resource).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'optionally filtered by status or tag' provides clear context for when to use the tool (exploration/discovery). However, it does not explicitly name alternatives or state when not to use it, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tokensList tokensA
What tokens exist? Lists design tokens, optionally filtered by group, status, or a case-insensitive substring match on name and description.
| Name | Required | Description | Default |
|---|---|---|---|
| group | No | ||
| query | No | ||
| status | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| tokens | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does disclose the case-insensitive substring matching and optional filtering behavior. However, it does not state default behavior (e.g., returns all tokens when no filters are provided), result ordering, or any performance caveats. The read-only nature is implied but not explicitly stated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short sentences, front-loaded with a clear question and concise statement. Every word earns its place, and it avoids unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema provided, return values are already covered. The description covers the core behavior and all filter options. It lacks an explicit statement about the no-filter case, but that is easily inferred. The overall simplicity of the tool makes this description sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It names all three parameters (group, status, and implicitly query via 'substring match') and adds specific semantics for query (case-insensitive match on name and description). Group and status receive no additional meaning beyond their names, though status has an enum in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Lists design tokens' with optional filters, providing a specific verb and resource. It distinguishes from sibling tools like get_token (single token) and list_components (components) by focusing on the token collection with filtering.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for browsing tokens and mentions the available filters, but it does not explicitly state when to use this tool versus alternatives like get_token or whats_deprecated. It provides no exclusions or alternative recommendations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whats_deprecatedWhat's deprecatedA
What should I stop using? Lists every deprecated token and component, its migration target, and how many active entities still depend on it.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| deprecated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the full burden. It discloses the output contents (deprecated items, migration targets, dependency counts) but does not mention potential performance implications of scanning 'every' deprecated item, what 'active entities' means, or any limitations. It provides basic transparency but lacks deeper behavioral details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise, just two short sentences. The rhetorical question front-loads the purpose, and the subsequent sentence packs all key information without wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (0 parameters, output schema present), the description is sufficient for an agent to understand what the tool returns and when it might be relevant. It doesn't explain how its output relates to sibling tools like check_token_drift, but that is a minor gap given the clear purpose and existing structured context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema covers everything. The description adds no parameter semantics, but with 0 params the baseline is 4 per the rubric. There is nothing to compensate for.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states what it does: 'Lists every deprecated token and component, its migration target, and how many active entities still depend on it.' This specifically distinguishes it from sibling tools like list_tokens or list_components, which list all items, not just deprecated ones.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The opening question 'What should I stop using?' implies a use case, but the description does not explicitly contrast with alternatives (e.g., use this instead of list_tokens when you only care about deprecated items). No exclusions or when-not-to-use guidance is provided, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.1.0- First observed
check_token_drift - First observed
find_usages - First observed
get_component - First observed
get_conventions - First observed
get_token - First observed
list_components - First observed
list_tokens - First observed
whats_deprecated
TDQS
Scored across 8 tools
Each tool has a clearly distinct purpose: listing vs. retrieving specific entities, finding usages, checking deprecations, conventions, and code drift. The overlap between whats_deprecated and filtered token/component lists is minimal because the former is specifically about deprecated items and their migration targets.
Most tools follow a verb_noun pattern (list_tokens, get_component, find_usages, check_token_drift), but whats_deprecated breaks the pattern with a question-style name. Overall the naming is predictable and readable, with one minor deviation.
8 tools is well-scoped for a design system canonical server. Each tool addresses a distinct need (querying, detail lookup, dependency analysis, conventions, drift checking) and none feel redundant or unnecessary.
The tool surface comprehensively covers the design system domain: token and component listing/detail, deprecation info, reverse dependencies, conventions, and code drift detection. For a read-only reference server, the coverage is complete and leaves no obvious dead ends.
Maintenance
Related MCP Connectors
Read-only MCP over the Mzizi design system registry — nodes, components, ownership.
Public read-only MCP for products, frameworks, guides, methodology, and blog metadata.
Read-only MCP server for turva.dev's published service catalog, pricing and contact details. Five tools return JSON, including dated agent-readiness and security evidence with verification links. Connect over Streamable HTTP without an API key. The server answers questions about turva.dev and does not scan other websites or run audits.
Read-only MCP server for AIStatusDashboard status, incidents, metrics, and fallback recommendations.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server that exposes your design system components and tokens to AI agents, preventing duplicate component creation and hardcoded token values.9 npm9MIT
- AlicenseNot gradedqualityDmaintenanceProvides resources, tools, and prompts for a Design System via MCP protocol, enabling component search, reading, and related component discovery.205 npmMIT
- AlicenseNot gradedqualityAmaintenanceA read-only MCP server that provides AI coding agents with a queryable contract for design system tokens, components, patterns, and anti-patterns.12 npm1Apache 2.0
- AlicenseNot gradedqualityBmaintenanceAn MCP server that gives AI assistants structured access to a design system's tokens, components, guidelines, and patterns, enabling them to read, lint, and author design system data.1MIT