@neuctra/ui-mcp 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,57 +1,228 @@
1
1
  # @neuctra/ui-mcp
2
2
 
3
- An MCP (Model Context Protocol) server that gives AI coding assistants ground-truth
4
- knowledge of the [`@neuctra/ui`](../neuctra-ui-package) component library — real prop
5
- names, types, defaults, and usage examples straight from source, plus the semantic
6
- theming rules — so generated code doesn't guess or hallucinate.
7
-
8
- ## Tools
9
-
10
- - **`list_components`** — list all components, optionally filtered by category
11
- (`layout`, `typography`, `form`, `actions`, `data-display`, `feedback`, `overlay`,
12
- `navigation`).
13
- - **`get_component`** — full spec for one component: every prop (type, required,
14
- default, description) plus a real usage example scraped from the docs site.
15
- - **`search_components`** — keyword search across name/category/description/prop names.
16
- - **`get_theme`** — the semantic color token system (`bg-primary`, `text-foreground`, ...)
17
- and the rule set for using it instead of hardcoded Tailwind colors, so generated UI
18
- respects the consumer's light/dark theme.
19
-
20
- ## Data source
21
-
22
- `data/components.json` is a synced copy of
23
- [`neuctra-ui-package/registry/components.json`](../neuctra-ui-package/registry/components.json),
24
- which is generated from the TypeScript source via `npm run registry:generate` in that
25
- package (parses prop interfaces + JSDoc with `ts-morph`, plus scrapes one usage example
26
- per component from the docs site). Run `npm run sync-registry` here after regenerating it
27
- there. `data/theme.json` is hand-curated from the CLI's CSS template
28
- (`neuctra-ui-cli/lib/update-css.js`) and updated manually if the token set changes.
29
-
30
- ## Local development
3
+ An MCP server that gives AI coding assistants (Claude Code, Claude Desktop, Cursor,
4
+ Antigravity, or anything else that speaks MCP) ground-truth knowledge of the
5
+ [`@neuctra/ui`](../neuctra-ui-package) component library, so they write correct code
6
+ instead of guessing.
7
+
8
+ This document explains what that means, why it exists, and how every piece of it works.
9
+
10
+ ---
11
+
12
+ ## 1. The problem this solves
13
+
14
+ Ask an AI assistant to "build a login form with Neuctra UI" and it has two options:
15
+
16
+ - **Recall from training data.** If Neuctra UI wasn't in its training set (likely — it's
17
+ a small library), it has nothing to recall. It will pattern-match against libraries it
18
+ *does* know (shadcn/ui, MUI, Chakra) and invent plausible-looking but wrong props —
19
+ `<Input variant="outline" />` when your `Input` has no `variant` prop, or
20
+ `<Button color="blue">` when colors come from `bg-primary`-style tokens, not a `color`
21
+ prop.
22
+ - **Read your source files.** Possible, but slow (it has to find and open several
23
+ `.tsx` files), token-expensive, and it still has to reverse-engineer the API from
24
+ implementation code rather than being told it directly.
25
+
26
+ This package gives it a third option: **ask**. It exposes a small set of tools an AI can
27
+ call mid-conversation — "what props does `Select` take?", "what components exist for
28
+ forms?", "what color classes should I use?" — and gets back exact, structured answers
29
+ generated from your actual TypeScript source. No guessing, no file-spelunking.
30
+
31
+ ---
32
+
33
+ ## 2. How the pieces fit together
34
+
35
+ ```
36
+ neuctra-ui-package/src/components/basic/*.tsx (your actual component source)
37
+ │
38
+ │ npm run registry:generate (ts-morph reads props/JSDoc/defaults,
39
+ │ scrapes one example per component
40
+ │ from neuctra-ui-docs)
41
+ ▼
42
+ neuctra-ui-package/registry/components.json (source of truth)
43
+ │
44
+ │ npm run sync-registry (plain file copy)
45
+ ▼
46
+ neuctra-ui-mcp/data/components.json (this package's local copy)
47
+ │
48
+ │ read once at server startup
49
+ ▼
50
+ neuctra-ui-mcp/src/server.mjs (defines 4 MCP tools over that data)
51
+ │
52
+ │ spoken over stdio (stdin/stdout), JSON-RPC under the hood
53
+ ▼
54
+ Claude Code / Cursor / Antigravity / any MCP client
55
+ ```
56
+
57
+ Two independently-regenerable files feed the server:
58
+
59
+ - **`data/components.json`** — synced from `neuctra-ui-package/registry/components.json`.
60
+ Never edit this by hand; run `npm run sync-registry` after the upstream file changes.
61
+ - **`data/theme.json`** — hand-curated from `neuctra-ui-cli/lib/update-css.js` (the CSS
62
+ the setup CLI generates for consumers). Update it manually if the token set changes —
63
+ it doesn't have an automated generator because it also encodes *rules* ("never
64
+ hardcode colors"), not just data.
65
+
66
+ ---
67
+
68
+ ## 3. What MCP actually is (30-second primer)
69
+
70
+ MCP (**M**odel **C**ontext **P**rotocol) is a standard for connecting an AI assistant to
71
+ external tools. Three roles:
72
+
73
+ - **Host** — the AI app itself (Claude Code, Cursor, Antigravity).
74
+ - **Client** — the part of the host that manages a connection to one server.
75
+ - **Server** — a small program (this package) that exposes **tools** (named actions with
76
+ typed inputs) the AI can decide to call.
77
+
78
+ The host starts your server as a subprocess and talks to it over **stdio** — your
79
+ server's stdout carries JSON-RPC messages, not human-readable logs (that's why
80
+ `bin/cli.mjs` prints nothing except protocol traffic; use `console.error`, never
81
+ `console.log`, if you ever add debug output). On connect, the client asks "what tools do
82
+ you have?", gets back the 4 tool definitions below, and adds them to the AI's available
83
+ actions — the same way the tools listed in *this* conversation's system prompt work.
84
+ From then on, the AI decides on its own when a tool call would help, calls it, and reads
85
+ the result back into its context before continuing.
86
+
87
+ ---
88
+
89
+ ## 4. The four tools, in detail
90
+
91
+ ### `list_components`
92
+
93
+ Lists every exported component, optionally filtered to one category. Cheap and compact
94
+ (no props) — meant for browsing, not for writing code against.
95
+
96
+ **Input:** `{ category?: "layout" | "typography" | "form" | "actions" | "data-display" | "feedback" | "overlay" | "navigation" }`
97
+
98
+ **Example call → response:**
99
+ ```jsonc
100
+ // list_components({ category: "form" })
101
+ [
102
+ { "name": "Calendar", "category": "form", "description": "", "propCount": 9 },
103
+ { "name": "Checkbox", "category": "form", "description": "A flexible checkbox component...", "propCount": 29 },
104
+ { "name": "DatePicker", "category": "form", "description": "", "propCount": 15 }
105
+ // ...
106
+ ]
107
+ ```
108
+
109
+ ### `get_component`
110
+
111
+ The main tool. Full spec for exactly one component — every prop's name, TypeScript
112
+ type, whether it's required, its default value, its JSDoc description if it has one,
113
+ and a real usage snippet. The AI is instructed (via the tool's own description) to call
114
+ this before writing code against any component it hasn't already used in the
115
+ conversation.
116
+
117
+ **Input:** `{ name: string }` — exact component name, e.g. `"Input"`, `"CardHeader"`.
118
+
119
+ **Example call → response** (trimmed):
120
+ ```jsonc
121
+ // get_component({ name: "Button" })
122
+ {
123
+ "name": "Button",
124
+ "category": "actions",
125
+ "description": "The Button component is a flexible, highly customizable UI primitive...",
126
+ "props": [
127
+ { "name": "children", "type": "React.ReactNode", "required": false, "default": null,
128
+ "description": "Optional so icon-only buttons are possible — pair with `aria-label`." },
129
+ { "name": "loading", "type": "boolean", "required": false, "default": "false", "description": "" },
130
+ { "name": "variant", "type": "\"default\" | \"outline\" | \"ghost\"", "required": false, "default": null, "description": "" }
131
+ // ...
132
+ ],
133
+ "example": "import { Button } from '@neuctra/ui';\n\nfunction BasicExample() {\n return (\n <Button onClick={() => console.log('Button clicked')}>\n Click Me\n </Button>\n );\n}"
134
+ }
135
+ ```
136
+
137
+ If the name doesn't match, it doesn't just fail — it returns an error result with
138
+ substring-matched suggestions (e.g. asking for `"Inpu"` suggests `"Input"`), so the AI
139
+ can self-correct instead of giving up.
140
+
141
+ ### `search_components`
142
+
143
+ For when the AI knows what it needs but not the exact name — "date picker", "loading
144
+ state", "icon button". Matches against name, category, description, and prop names.
145
+
146
+ **Example:**
147
+ ```jsonc
148
+ // search_components({ query: "date" })
149
+ [
150
+ { "name": "Calendar", ... },
151
+ { "name": "DatePicker", ... },
152
+ { "name": "TagInput", ... } // matched because it has an "updatedAt"-style prop, etc.
153
+ ]
154
+ ```
155
+
156
+ ### `get_theme`
157
+
158
+ Returns the semantic color token system and the styling rules for using it. This is the
159
+ piece that stops generated UI from looking "off-brand" or breaking in dark mode —
160
+ without it, an AI would happily write `className="bg-blue-500"`, which ignores whatever
161
+ theme the consumer's project has configured.
162
+
163
+ **Response shape:**
164
+ ```jsonc
165
+ {
166
+ "system": "Tailwind CSS v4, semantic CSS-variable tokens mapped via @theme, toggled by a .dark class...",
167
+ "rules": [
168
+ "Never use hardcoded Tailwind palette colors...",
169
+ "Always use the semantic token classes below...",
170
+ // ...
171
+ ],
172
+ "tokens": [
173
+ { "token": "primary", "className": "bg-primary / text-primary / border-primary",
174
+ "pairsWith": "primary-foreground", "light": "#00c214", "dark": "#00c214",
175
+ "usage": "Brand color: primary buttons, active states, links, focus accents." },
176
+ // ...23 tokens total
177
+ ]
178
+ }
179
+ ```
180
+
181
+ ---
182
+
183
+ ## 5. Local development
31
184
 
32
185
  ```bash
33
186
  npm install
34
187
  npm run sync-registry # pulls the latest registry.json from neuctra-ui-package
35
- npm start # runs the server on stdio
188
+ npm start # runs the server on stdio — it will sit there silently, that's correct
36
189
  ```
37
190
 
38
- ## Using with Claude Code / Claude Desktop
191
+ `npm start` alone won't show you anything (it's waiting for a client to speak JSON-RPC
192
+ to it, not for a human to type at it). To actually exercise it, either wire it into a
193
+ real client (section 6) or write a small script using
194
+ `@modelcontextprotocol/sdk`'s `Client` + `StdioClientTransport` to spawn `bin/cli.mjs`
195
+ and call the tools programmatically — that's how this server was verified while building
196
+ it.
197
+
198
+ ---
199
+
200
+ ## 6. Connecting it to a client
39
201
 
40
- Add to your MCP config (`.mcp.json` for a project, or Claude Desktop's config file):
202
+ All MCP clients use the same JSON shape — the differences are just *where* the config
203
+ file lives.
41
204
 
205
+ **Claude Code** — project-scoped, via CLI:
206
+ ```bash
207
+ claude mcp add neuctra-ui -- npx -y @neuctra/ui-mcp
208
+ ```
209
+ or by hand in `.mcp.json` at the repo root:
42
210
  ```json
43
211
  {
44
212
  "mcpServers": {
45
- "neuctra-ui": {
46
- "command": "npx",
47
- "args": ["-y", "@neuctra/ui-mcp"]
48
- }
213
+ "neuctra-ui": { "command": "npx", "args": ["-y", "@neuctra/ui-mcp"] }
49
214
  }
50
215
  }
51
216
  ```
52
217
 
53
- Or, for local development against this repo:
218
+ **Cursor** — Settings → MCP → "Add new MCP server", or edit `.cursor/mcp.json`
219
+ (project) / `~/.cursor/mcp.json` (global) with the same JSON shape as above.
54
220
 
221
+ **Antigravity** — Settings → search "MCP" → "Manage MCP Servers" opens a JSON config
222
+ using the same `mcpServers` shape (or a form asking for command + args — use `npx` and
223
+ `-y @neuctra/ui-mcp`).
224
+
225
+ **Local development, any client** (before publishing, or to test changes):
55
226
  ```json
56
227
  {
57
228
  "mcpServers": {
@@ -63,9 +234,62 @@ Or, for local development against this repo:
63
234
  }
64
235
  ```
65
236
 
66
- ## Publishing
237
+ Restart the client after editing its config — servers are only launched on startup.
238
+
239
+ ---
240
+
241
+ ## 7. Keeping the registry in sync
242
+
243
+ The registry is generated, not hand-maintained. Whenever a component's props change:
244
+
245
+ ```bash
246
+ cd neuctra-ui-package
247
+ npm run registry:generate # re-parses source, re-scrapes docs examples
248
+
249
+ cd ../neuctra-ui-mcp
250
+ npm run sync-registry # copies the updated file in
251
+ ```
252
+
253
+ `registry:generate` also runs automatically as part of `neuctra-ui-package`'s
254
+ `prepublishOnly`, and `sync-registry` runs automatically as part of this package's own
255
+ `prepublishOnly` — so a normal `npm publish` in each package keeps things current without
256
+ remembering these steps by hand. `data/theme.json` is the one file with no generator;
257
+ edit it directly if the token set in `neuctra-ui-cli/lib/update-css.js` ever changes.
258
+
259
+ ---
260
+
261
+ ## 8. Publishing
67
262
 
68
263
  ```bash
69
- npm run sync-registry # or rely on prepublishOnly, which does this automatically
70
- npm publish --access public
264
+ npm run sync-registry
265
+ npm publish --access public # --access public is required: scoped packages default to private
71
266
  ```
267
+
268
+ ---
269
+
270
+ ## 9. Project structure
271
+
272
+ ```
273
+ neuctra-ui-mcp/
274
+ ├── bin/
275
+ │ └── cli.mjs # entry point: connects the server to a stdio transport
276
+ ├── src/
277
+ │ └── server.mjs # defines the 4 tools and their handlers
278
+ ├── scripts/
279
+ │ └── sync-registry.mjs # copies registry/components.json from neuctra-ui-package
280
+ ├── data/
281
+ │ ├── components.json # synced (generated) — don't edit by hand
282
+ │ └── theme.json # hand-curated token/rules data
283
+ └── package.json
284
+ ```
285
+
286
+ ---
287
+
288
+ ## 10. Extending it
289
+
290
+ To add a new tool (e.g. `get_example` returning just the code snippet, or
291
+ `list_categories`), open `src/server.mjs` and add another `server.registerTool(...)`
292
+ call following the existing pattern: a name, a `title`/`description` (the description is
293
+ what the AI reads to decide *when* to call it — be specific), a `zod` input schema, and
294
+ an async handler returning `{ content: [{ type: "text", text: ... }] }`. No other file
295
+ needs to change — `bin/cli.mjs` just connects whatever `createServer()` returns.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema#",
3
3
  "package": "@neuctra/ui",
4
- "version": "0.5.1",
5
- "generatedAt": "2026-08-14T05:17:59.722Z",
4
+ "version": "0.5.2",
5
+ "generatedAt": "2026-08-14T05:45:27.177Z",
6
6
  "componentCount": 76,
7
7
  "components": [
8
8
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuctra/ui-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "MCP server exposing the @neuctra/ui component registry (props, defaults, examples, theme tokens) so AI coding tools generate accurate Neuctra UI code.",
5
5
  "type": "module",
6
6
  "license": "MIT",