# matchcn technical reference matchcn is a semantic index of shadcn-format UI components, exposed through a local Model Context Protocol (MCP) server. It finds existing components from a plain-language description of the UI a developer needs and returns the original registry's installation command. It does not generate component source code or host a replacement component registry. This reference describes the local v0.1.0 source and development reports inspected on September 20, 2026. The counts and findings below are a snapshot, not a live inventory or a guarantee of future registry availability. ## What matchcn does A developer can ask for a component by purpose, motion, density, or interaction instead of knowing its registry-specific name. A coding agent calls `pick_component`, reads the outcome and explanation, and can use the returned `npx shadcn@latest add ` command to install from the original publisher. The current index contains 6,119 components from ten registries. matchcn is a discovery layer for the shadcn registry ecosystem. shadcn/ui supplies the registry format and installation tooling; it is not a seventh indexed catalog in this snapshot. The landing page's interactive example displays recorded responses from the development demo report, including component reasons and install commands. It does not perform a live component search. ## Installation and runtime The documented CLI entry point is `npx matchcn`. It starts a stdio MCP server, not an interactive search shell. Node.js 20 or newer is required. For an MCP client, configure the command as `npx` with arguments `-y` and `matchcn`: ```json { "mcpServers": { "matchcn": { "command": "npx", "args": ["-y", "matchcn"] } } } ``` The configuration belongs in the selected client's MCP settings. Claude Code can use a project's `.mcp.json`; Cursor can use `.cursor/mcp.json`. Codex uses its own TOML configuration format rather than this JSON wrapper. The page provides separate setup prompts. The Grok prompt provides configuration guidance for a local MCP-capable client; it is not a claim that this server runs directly in Grok chat. The inspected source package is version 0.1.0. The npm package `matchcn` is published and the source repository is public: [github.com/francesco0242/matchcn](https://github.com/francesco0242/matchcn). ## MCP tool and parameters The server exposes one tool: `pick_component(brief, registry?, maxResults?)`. The MCP adapter returns a text content block containing the result serialized as JSON. | Parameter | Type | Behavior | | --- | --- | --- | | `brief` | Required string | Plain-language description of the required UI. English is recommended based on current tests. | | `registry` | Optional enum | Restricts matching to one of the ten exact registry identifiers listed below. | | `maxResults` | Optional integer, 1–10 | Maximum candidates returned for a shortlist or no-match result. Default: 3. It does not expand Resolve beyond its top-five comparison. | Example tool arguments: ```json { "brief": "a dense bento grid for a landing page", "registry": "magicui", "maxResults": 3 } ``` The tool discovers components and returns commands. Component installation is a separate action performed by the developer or coding agent. A returned component still needs to be evaluated against the application's dependencies, design, and accessibility requirements. Source: [MCP adapter](https://matchcn.dev/reference/mcp-server.ts.txt). ## Result fields and outcomes Every result contains `outcome`, `message`, `resolveUsed`, and `decisionsSpent`. The fields `chosen`, `candidates`, and `differentiators` appear when applicable. | Outcome | Meaning | How to use it | | --- | --- | --- | | `confident` | The selection logic identifies one component. `chosen` contains its details. | Review its reasons and source install command. | | `shortlist` | There is no sufficiently decisive selection. `candidates` contains ranked options, and `differentiators` names differences visible to the tag schema. | Compare those differences before choosing. | | `no_match` | Resolve explicitly rejects the candidates, or no tagged components are available. There is no `chosen` field. | Do not treat any diagnostic candidates as a recommended installation. | A component result includes `name`, `registry`, nullable `title`, `sourceUrl`, `installCommand`, `confidence`, and `reasons`. Optional `variants` list available stack variants with their own `registryItemName` and install command. Each reason contains `dimension`, `briefWants`, `componentHas`, `matched`, and `weight`. A no-match response can include nearby candidates for reference. Rejection is communicated by the overall outcome and message; the component objects do not have a separate `rejected` boolean. A shortlist's differentiators contain the dimension and the candidates' values. Choice dimensions differ when their known labels differ; probability dimensions differ when their known values span more than 0.2. `confidence` indicates fit or selection confidence, not component quality, security, accessibility, or measured probability of success. For a chosen result it can come from Resolve when available, otherwise from the ranking score. Candidate lists use the ranking score, rounded to two decimals. These values should not be conflated with benchmark accuracy. Source: [selection logic and response types](https://matchcn.dev/reference/pick.ts.txt). ## The five-stage pipeline 1. **Ingest:** fetch registry indexes, normalize metadata, and filter known demo wrappers, duplicate stack variants, and non-component entries. In the development snapshot, 2,012 raw records became 1,069 taggable components after 943 exclusions. 2. **Tag:** classify each retained component across six dimensions using classifier.dev. The derived tag data is stored as per-registry JSON under `data/tags/` for inspection and versioning. 3. **Match:** classify the incoming brief into the same dimension schema, then rank the stored components locally using a confidence-weighted distance function. 4. **Resolve:** when the leading match is not decisive, compare up to five candidates through one additional classification decision, with an explicit “none of these” option. 5. **Surface:** expose the result through the stdio MCP tool. The development demo calls the same core selection function without the MCP transport. The pipeline uses files rather than a database. Ingestion can enrich missing or short descriptions from a registry's per-item endpoint, using source excerpts as tagging input. This does not make matchcn a component-source mirror: published tag outputs contain derived data and links, not redistributed component source. ## The six matching dimensions | Dimension | Representation | What it describes | | --- | --- | --- | | `category` | Unordered label | Primary UI purpose, such as hero, navigation, card, form input, chart, layout section, background effect, cursor, or transition wrapper. Includes an escape label. | | `motion` | Ordered label | `static`, `subtle-transitions`, `animated-on-interaction`, or `continuous-background-motion`. | | `visual_density` | Ordered label | `minimal`, `moderate`, or `dense`. Describes perceived density rather than a literal element count. | | `interaction_model` | Unordered label | `display-only`, `hover`, `click-toggle`, `form-input`, `drag-or-gesture`, or `none of these`. | | `needs_external_data` | Probability or null | Whether useful operation requires caller-supplied data, state, or non-trivial props. | | `decorative_only` | Probability or null | Whether the component is primarily a decorative effect rather than functional or informational content. | The probability dimensions are implemented through yes/no classification scores. A value near 0.5 represents uncertainty, not a middle category. `compositionLevel` is derived from registry metadata; it is not a seventh model-tagged dimension. Source: [dimension definitions and exact criteria](https://matchcn.dev/reference/dimensions.ts.txt). ## Ranking, determinism, and Resolve The ranking function computes a weighted average distance. Matching unordered labels have zero distance and mismatches have distance one. Ordered labels use normalized index distance, so adjacent values are closer than distant ones. Probability dimensions use the absolute difference between their values. For choice dimensions, the weight is the smaller confidence of the brief and the component. For probability dimensions, certainty is `2 * abs(probability - 0.5)`, and the smaller certainty of the two sides is used. Null or zero-weight dimensions contribute no evidence. If all weights are zero, distance is one. Lower distance ranks first, and the ranking confidence is `1 - distance`. The ranking stage is deterministic for identical parsed dimension vectors, tag records, and input order. The complete text-to-result process is not guaranteed to return identical values on every call, because brief parsing and Resolve call an external classifier. Resolve is skipped when the leader's ranking confidence is at least 0.55 and its distance advantage over the runner-up is at least 0.15. For a single candidate, only the confidence floor applies. Resolve compares at most five candidates using their names, registry, composition level, and tagged properties; it does not inspect full component source at query time. The 0.55 and 0.15 thresholds are MVP heuristics, not values optimized against a labeled accuracy dataset. Sources: [ranking implementation](https://matchcn.dev/reference/match.ts.txt), [Resolve implementation](https://matchcn.dev/reference/resolve.ts.txt). ## Indexed registries and coverage | Exact registry identifier | Publisher | Components in snapshot | | --- | --- | ---: | | `react-bits` | [React Bits](https://reactbits.dev) | 204 | | `magicui` | [Magic UI](https://magicui.design) | 79 | | `aceternity` | [Aceternity UI](https://ui.aceternity.com) | 282 | | `kokonutui` | [Kokonut UI](https://kokonutui.com) | 51 | | `animate-ui` | [Animate UI](https://animate-ui.com) | 420 | | `motion-primitives` | [Motion Primitives](https://motion-primitives.com) | 33 | | `shadcnblocks` | [shadcnblocks.com](https://shadcnblocks.com) | 4,171 | | `shadcn-dashboard` | [shadcndashboard.dev](https://shadcndashboard.dev) | 508 | | `assistant-ui` | [assistant-ui.com](https://www.assistant-ui.com) | 154 | | `bundui` | [bundui.io](https://bundui.io) | 217 | These counts total 6,119 components. They describe the indexed snapshot, not the current size of each publisher's library. The first six registries are the original motion/marketing family; the last four (shadcnblocks, shadcn-dashboard, assistant-ui, bundui) are a product-UI expansion added after per-registry filter verification. cult-ui was excluded because its index was behind a bot challenge. Aceternity's 170 block/demo records were tagged using short index descriptions because their per-item endpoints returned HTTP 401; its 112 UI primitives were source-enriched. ## Benchmark evidence and its limits The original full tagging run processed 1,069 components across six dimensions, spending 6,414 classification decisions, in a first-to-last tagging timestamp window of approximately 2 minutes 43 seconds. A second run added the four product-UI registries, spending 30,300 more decisions across 5,050 components, split across two IPs to cover the free tier's daily quota. Combined: 6,119 components, 36,714 tagging decisions. These exclude throttling and debugging time and are not a measurement of search latency or total setup duration. The five-brief demo spent 35 decisions: six for parsing and one for Resolve per brief in that run. It returned a shortlist for a subtly animated hero, a confident React Bits cursor result, a confident Magic UI bento-grid result, and two no-match outcomes for a Polish pricing brief and a range date picker. This is a development demonstration, not a labeled accuracy benchmark, a comparison against another product, or evidence that every request needs seven decisions. Resolve can be skipped. The bento grid is also a named example in the visual-density criteria, so its result is not an independent validation of those criteria. The revised pilot reported 36% of visual-density answers below 0.6 confidence. Across the full 6,119-component catalog, 25.9% of answers on the four choice dimensions were below 0.6, up from 23.9% at the original 1,069-component size. assistant-ui is the outlier driving that increase: 37.0% of its choice-dimension answers land under 0.6 confidence, worse than aceternity's 28.7% (the prior worst registry) on every single dimension. It is now the lowest-confidence registry in the catalog, likely because its content (agent and chat UI: tool timelines, trace waterfalls, reasoning panels) is further from the schema's original motion/marketing anchors than any other registry. These are tag-confidence statistics, not error rates. Non-English behavior was examined on three Polish briefs; these tests do not establish performance across languages. Evidence: [full tagging report](https://matchcn.dev/reports/full-run.md), [five-brief demo with raw output](https://matchcn.dev/reports/demo.md), [pilot report](https://matchcn.dev/reference/pilot-report.md). ## Network behavior and data handling The MCP transport and deterministic ranking run locally, but the tool is not offline-only. The client sends the brief and classification criteria to `https://classifier.dev/v1/classify` using the `fast` tier. Resolve can send the brief with descriptions assembled from the top candidates' tagged properties. The inspected HTTP client supplies no API key or authorization header. During ingestion and tagging, registry metadata and available source excerpts can be used as classification input. Raw fetch data is cached locally; derived tags are stored separately. This reference describes the source's data flow, not the external provider's retention policy or a guarantee about its future availability, pricing, or rate limits. Errors and exhausted retries are not equivalent to a `no_match` result. Source: [HTTP classification client](https://matchcn.dev/reference/classify.ts.txt). ## Known limits and project scope The MVP covers ten registries rather than the full shadcn ecosystem. English briefs are currently more reliable than the tested Polish inputs. Visual density remains the weakest tagged dimension. Short or inaccessible registry descriptions can reduce tagging evidence. There is no implemented compatibility guarantee for React, Tailwind, or other dependency versions; no accessibility-quality score; no dedicated domain/use-case dimension; and no general code-quality ranking. A description mentioning a landing page is accepted as text, but “landing page” is not a separate domain tag in v0. The tool does not generate UI code, host component source, or replace the original registry's installer. The roadmap discusses additional dimensions, registry coverage, and evaluation. Those are future possibilities, not shipped capabilities or release commitments. The landing page is documentation and an installation entry point, not the searchable catalog UI that the source roadmap lists as a possible future feature. ## License, attribution, and project links matchcn is an independent MIT-licensed project. It is not affiliated with or endorsed by shadcn, the indexed registries, classifier.dev, or TypeSafe. Its license does not replace the individual licenses of components installed from other publishers. Project: [matchcn.dev](https://matchcn.dev). Updates: [@matchcndev](https://x.com/matchcndev). Built by [@whosfranki](https://x.com/whosfranki). Source: [github.com/francesco0242/matchcn](https://github.com/francesco0242/matchcn). For citation, use the relevant section of this reference and the linked implementation or report. Attribute the figures to the September 20, 2026 development snapshot. Distinguish implemented behavior from intended behavior, fit confidence from accuracy, and local ranking from the network-dependent pipeline.