@refineui/mcp 0.1.0
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 +69 -0
- package/lib/chunk-BIQ6ODHB.js +1522 -0
- package/lib/index.d.ts +34 -0
- package/lib/index.js +24 -0
- package/lib/server.d.ts +2 -0
- package/lib/server.js +413 -0
- package/package.json +48 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded from `docs/public/DESIGN.md` at MCP build time (Stitch DESIGN.md alpha).
|
|
3
|
+
* Prefer `getDesignMd()` for new call sites.
|
|
4
|
+
*/
|
|
5
|
+
declare const DESIGN_RULES: string;
|
|
6
|
+
|
|
7
|
+
type DocCategory = "components" | "foundations" | "development" | "guides" | "ai-tools";
|
|
8
|
+
type DocSummary = {
|
|
9
|
+
slug: string;
|
|
10
|
+
href: string;
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
category: DocCategory;
|
|
14
|
+
};
|
|
15
|
+
type DocPage = DocSummary & {
|
|
16
|
+
content: string;
|
|
17
|
+
};
|
|
18
|
+
declare const TOKEN_CATEGORIES: readonly ["colors", "typography", "spacing", "sizing", "radius", "stroke", "shadows", "motion", "zIndex"];
|
|
19
|
+
type TokenCategory = (typeof TOKEN_CATEGORIES)[number];
|
|
20
|
+
declare function normalizeSlug(input: string): string;
|
|
21
|
+
declare function getLlmIndex(): string;
|
|
22
|
+
/** Canonical DESIGN.md (Google Stitch alpha) embedded at MCP build time. */
|
|
23
|
+
declare function getDesignMd(): string;
|
|
24
|
+
declare function listPages(category?: DocCategory): DocSummary[];
|
|
25
|
+
declare function getDocPage(slugInput: string): DocPage | null;
|
|
26
|
+
declare function searchDocs(query: string, category?: DocCategory, limit?: number): DocSummary[];
|
|
27
|
+
declare function listTokenCategories(): TokenCategory[];
|
|
28
|
+
declare function listSemanticTextRoles(): string[];
|
|
29
|
+
declare function getIndexMeta(): {
|
|
30
|
+
generatedAt: string;
|
|
31
|
+
pageCount: number;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export { DESIGN_RULES, type DocCategory, type DocPage, type DocSummary, getDesignMd, getDocPage, getIndexMeta, getLlmIndex, listPages, listSemanticTextRoles, listTokenCategories, normalizeSlug, searchDocs };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DESIGN_RULES,
|
|
3
|
+
getDesignMd,
|
|
4
|
+
getDocPage,
|
|
5
|
+
getIndexMeta,
|
|
6
|
+
getLlmIndex,
|
|
7
|
+
listPages,
|
|
8
|
+
listSemanticTextRoles,
|
|
9
|
+
listTokenCategories,
|
|
10
|
+
normalizeSlug,
|
|
11
|
+
searchDocs
|
|
12
|
+
} from "./chunk-BIQ6ODHB.js";
|
|
13
|
+
export {
|
|
14
|
+
DESIGN_RULES,
|
|
15
|
+
getDesignMd,
|
|
16
|
+
getDocPage,
|
|
17
|
+
getIndexMeta,
|
|
18
|
+
getLlmIndex,
|
|
19
|
+
listPages,
|
|
20
|
+
listSemanticTextRoles,
|
|
21
|
+
listTokenCategories,
|
|
22
|
+
normalizeSlug,
|
|
23
|
+
searchDocs
|
|
24
|
+
};
|
package/lib/server.d.ts
ADDED
package/lib/server.js
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DESIGN_RULES,
|
|
3
|
+
getDesignMd,
|
|
4
|
+
getDocPage,
|
|
5
|
+
getIndexMeta,
|
|
6
|
+
getLlmIndex,
|
|
7
|
+
listPages,
|
|
8
|
+
listSemanticTextRoles,
|
|
9
|
+
listTokenCategories,
|
|
10
|
+
normalizeSlug,
|
|
11
|
+
searchDocs
|
|
12
|
+
} from "./chunk-BIQ6ODHB.js";
|
|
13
|
+
|
|
14
|
+
// src/server.ts
|
|
15
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
16
|
+
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
import { discoverWorkspaces, runDoctor, reportToSummary } from "@refineui/doctor";
|
|
19
|
+
|
|
20
|
+
// src/token-spec.ts
|
|
21
|
+
import { existsSync, readFileSync } from "fs";
|
|
22
|
+
import { dirname, join } from "path";
|
|
23
|
+
import { fileURLToPath } from "url";
|
|
24
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
25
|
+
function resolveTokensSpecPath(...segments) {
|
|
26
|
+
const candidates = [
|
|
27
|
+
join(__dirname, "../../tokens/dist/spec", ...segments),
|
|
28
|
+
join(process.cwd(), "node_modules/@refineui/tokens/dist/spec", ...segments),
|
|
29
|
+
join(process.cwd(), "packages/tokens/dist/spec", ...segments)
|
|
30
|
+
];
|
|
31
|
+
for (const path of candidates) {
|
|
32
|
+
if (existsSync(path)) return path;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function resolveReactSpecPath(...segments) {
|
|
37
|
+
const candidates = [
|
|
38
|
+
join(__dirname, "../../react/dist/spec", ...segments),
|
|
39
|
+
join(__dirname, "../../react/spec", ...segments),
|
|
40
|
+
join(process.cwd(), "node_modules/@refineui/react/dist/spec", ...segments),
|
|
41
|
+
join(process.cwd(), "node_modules/@refineui/react/spec", ...segments),
|
|
42
|
+
join(process.cwd(), "packages/react/dist/spec", ...segments),
|
|
43
|
+
join(process.cwd(), "packages/react/spec", ...segments)
|
|
44
|
+
];
|
|
45
|
+
for (const path of candidates) {
|
|
46
|
+
if (existsSync(path)) return path;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
function readJson(path) {
|
|
51
|
+
if (!path || !existsSync(path)) return null;
|
|
52
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
53
|
+
}
|
|
54
|
+
function normalizeTokenQuery(name) {
|
|
55
|
+
return name.replace(/^component\./, "").trim();
|
|
56
|
+
}
|
|
57
|
+
function buildChainFromTraceV2(entry) {
|
|
58
|
+
const chain = [];
|
|
59
|
+
if (entry.type === "component") chain.push("component token");
|
|
60
|
+
const resolved = entry.resolvesTo;
|
|
61
|
+
if (!resolved) return chain;
|
|
62
|
+
if ("semantic" in resolved && resolved.semantic) {
|
|
63
|
+
chain.push(`semantic.${resolved.semantic}`);
|
|
64
|
+
}
|
|
65
|
+
if (resolved.light) {
|
|
66
|
+
chain.push(`foundation.${resolved.light.foundation} (light: ${resolved.light.value})`);
|
|
67
|
+
}
|
|
68
|
+
if (resolved.dark) {
|
|
69
|
+
chain.push(`foundation.${resolved.dark.foundation} (dark: ${resolved.dark.value})`);
|
|
70
|
+
}
|
|
71
|
+
return chain;
|
|
72
|
+
}
|
|
73
|
+
function inspectToken(name) {
|
|
74
|
+
const componentTrace = readJson(resolveReactSpecPath("token-trace-v2.json"));
|
|
75
|
+
const query = normalizeTokenQuery(name);
|
|
76
|
+
const componentKey = Object.keys(componentTrace?.tokens ?? {}).find(
|
|
77
|
+
(k) => k === query || k.endsWith(`.${query}`) || k.includes(query)
|
|
78
|
+
);
|
|
79
|
+
if (componentKey && componentTrace?.tokens?.[componentKey]) {
|
|
80
|
+
const entry = componentTrace.tokens[componentKey];
|
|
81
|
+
return {
|
|
82
|
+
query: name,
|
|
83
|
+
layer: "component",
|
|
84
|
+
token: componentKey,
|
|
85
|
+
chain: [
|
|
86
|
+
componentKey,
|
|
87
|
+
`semantic.${entry.resolvesTo.semantic}`,
|
|
88
|
+
`light \u2192 foundation.${entry.resolvesTo.light.foundation} \u2192 ${entry.resolvesTo.light.value}`,
|
|
89
|
+
`dark \u2192 foundation.${entry.resolvesTo.dark.foundation} \u2192 ${entry.resolvesTo.dark.value}`
|
|
90
|
+
],
|
|
91
|
+
resolvesTo: entry.resolvesTo
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const semanticTrace = readJson(resolveTokensSpecPath("trace-v2.json"));
|
|
95
|
+
const semanticKey = Object.keys(semanticTrace?.tokens ?? {}).find(
|
|
96
|
+
(k) => k === name || k.toLowerCase() === name.toLowerCase()
|
|
97
|
+
) ?? null;
|
|
98
|
+
if (semanticKey && semanticTrace?.tokens?.[semanticKey]) {
|
|
99
|
+
const entry = semanticTrace.tokens[semanticKey];
|
|
100
|
+
return {
|
|
101
|
+
query: name,
|
|
102
|
+
layer: "semantic",
|
|
103
|
+
token: semanticKey,
|
|
104
|
+
cssVar: entry.cssVar,
|
|
105
|
+
chain: buildChainFromTraceV2({ type: "semantic", resolvesTo: { ...entry.resolvesTo, semantic: semanticKey } }),
|
|
106
|
+
resolvesTo: entry.resolvesTo
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
query: name,
|
|
111
|
+
error: "Token not found in trace spec. Run build:tokens and build:react.",
|
|
112
|
+
hint: "Try button.primary.background, backgroundBrand, or inspect token-graph.json"
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function getComponentSpec(name) {
|
|
116
|
+
const manifest = readJson(resolveReactSpecPath("manifest.json"));
|
|
117
|
+
if (!manifest?.components) {
|
|
118
|
+
return { error: "Component manifest not found." };
|
|
119
|
+
}
|
|
120
|
+
const key = name.toLowerCase();
|
|
121
|
+
const entry = manifest.components.find((c) => c.id === key || c.name.toLowerCase() === key);
|
|
122
|
+
if (!entry) {
|
|
123
|
+
return {
|
|
124
|
+
error: `No component spec for "${name}".`,
|
|
125
|
+
available: manifest.components.map((c) => c.id)
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const spec = readJson(resolveReactSpecPath(entry.spec.replace(/^\.\//, "")));
|
|
129
|
+
return { ...entry, spec };
|
|
130
|
+
}
|
|
131
|
+
function getComponentRecipe(name) {
|
|
132
|
+
const spec = getComponentSpec(name);
|
|
133
|
+
if ("error" in spec && spec.error) return spec;
|
|
134
|
+
const componentSpec = spec.spec;
|
|
135
|
+
if (!componentSpec?.recipe) {
|
|
136
|
+
return { error: "No recipe reference on component spec.", component: spec };
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
component: spec.id ?? name,
|
|
140
|
+
recipe: componentSpec.recipe,
|
|
141
|
+
note: "Recipe defines appearance; Component Spec defines contract."
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function getTokenSpecIndex() {
|
|
145
|
+
return readJson(resolveReactSpecPath("contract-index.json")) ?? readJson(resolveTokensSpecPath("index.json"));
|
|
146
|
+
}
|
|
147
|
+
function listComponentSpecs() {
|
|
148
|
+
const manifest = readJson(resolveReactSpecPath("manifest.json"));
|
|
149
|
+
return manifest ?? { error: "manifest.json not found" };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/server.ts
|
|
153
|
+
function textResult(text) {
|
|
154
|
+
return {
|
|
155
|
+
content: [{ type: "text", text }]
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function jsonResult(value) {
|
|
159
|
+
return textResult(JSON.stringify(value, null, 2));
|
|
160
|
+
}
|
|
161
|
+
function createServer() {
|
|
162
|
+
const server = new McpServer({
|
|
163
|
+
name: "refineui",
|
|
164
|
+
version: "0.1.0"
|
|
165
|
+
});
|
|
166
|
+
server.registerResource(
|
|
167
|
+
"llm-index",
|
|
168
|
+
"refineui://llm.txt",
|
|
169
|
+
{
|
|
170
|
+
title: "RefineUI llm.txt",
|
|
171
|
+
description: "Machine-readable RefineUI documentation index",
|
|
172
|
+
mimeType: "text/plain"
|
|
173
|
+
},
|
|
174
|
+
async () => ({
|
|
175
|
+
contents: [
|
|
176
|
+
{
|
|
177
|
+
uri: "refineui://llm.txt",
|
|
178
|
+
mimeType: "text/plain",
|
|
179
|
+
text: getLlmIndex()
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
})
|
|
183
|
+
);
|
|
184
|
+
server.registerResource(
|
|
185
|
+
"design-md",
|
|
186
|
+
"refineui://DESIGN.md",
|
|
187
|
+
{
|
|
188
|
+
title: "RefineUI DESIGN.md",
|
|
189
|
+
description: "Stitch-compatible design system identity and agent rules",
|
|
190
|
+
mimeType: "text/markdown"
|
|
191
|
+
},
|
|
192
|
+
async () => ({
|
|
193
|
+
contents: [
|
|
194
|
+
{
|
|
195
|
+
uri: "refineui://DESIGN.md",
|
|
196
|
+
mimeType: "text/markdown",
|
|
197
|
+
text: getDesignMd()
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
})
|
|
201
|
+
);
|
|
202
|
+
server.registerResource(
|
|
203
|
+
"design-rules",
|
|
204
|
+
"refineui://design-rules",
|
|
205
|
+
{
|
|
206
|
+
title: "RefineUI design rules",
|
|
207
|
+
description: "Alias of DESIGN.md for backward compatibility",
|
|
208
|
+
mimeType: "text/markdown"
|
|
209
|
+
},
|
|
210
|
+
async () => ({
|
|
211
|
+
contents: [
|
|
212
|
+
{
|
|
213
|
+
uri: "refineui://design-rules",
|
|
214
|
+
mimeType: "text/markdown",
|
|
215
|
+
text: DESIGN_RULES
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
})
|
|
219
|
+
);
|
|
220
|
+
server.registerTool(
|
|
221
|
+
"search_docs",
|
|
222
|
+
{
|
|
223
|
+
title: "Search RefineUI docs",
|
|
224
|
+
description: "Search RefineUI documentation pages by keyword.",
|
|
225
|
+
inputSchema: z.object({
|
|
226
|
+
query: z.string().describe("Search terms, e.g. 'button variant' or 'color alias'"),
|
|
227
|
+
category: z.enum(["components", "foundations", "development", "guides", "ai-tools"]).optional().describe("Optional docs section filter"),
|
|
228
|
+
limit: z.number().int().min(1).max(25).optional().describe("Max results (default 10)")
|
|
229
|
+
})
|
|
230
|
+
},
|
|
231
|
+
async ({ query, category, limit }) => jsonResult({
|
|
232
|
+
query,
|
|
233
|
+
results: searchDocs(query, category, limit ?? 10)
|
|
234
|
+
})
|
|
235
|
+
);
|
|
236
|
+
server.registerTool(
|
|
237
|
+
"get_doc_page",
|
|
238
|
+
{
|
|
239
|
+
title: "Get RefineUI doc page",
|
|
240
|
+
description: "Fetch a documentation page by slug, e.g. components/button or foundations/color.",
|
|
241
|
+
inputSchema: z.object({
|
|
242
|
+
slug: z.string().describe("Doc slug or path, e.g. components/button or /foundations/color/")
|
|
243
|
+
})
|
|
244
|
+
},
|
|
245
|
+
async ({ slug }) => {
|
|
246
|
+
const page = getDocPage(slug);
|
|
247
|
+
if (!page) {
|
|
248
|
+
return textResult(`No documentation page found for slug "${normalizeSlug(slug)}".`);
|
|
249
|
+
}
|
|
250
|
+
return jsonResult(page);
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
server.registerTool(
|
|
254
|
+
"list_components",
|
|
255
|
+
{
|
|
256
|
+
title: "List RefineUI components",
|
|
257
|
+
description: "List all component documentation pages in A\u2013Z order.",
|
|
258
|
+
inputSchema: z.object({})
|
|
259
|
+
},
|
|
260
|
+
async () => jsonResult(listPages("components"))
|
|
261
|
+
);
|
|
262
|
+
server.registerTool(
|
|
263
|
+
"list_foundations",
|
|
264
|
+
{
|
|
265
|
+
title: "List RefineUI foundations",
|
|
266
|
+
description: "List foundation documentation pages (tokens, layout, color, \u2026).",
|
|
267
|
+
inputSchema: z.object({})
|
|
268
|
+
},
|
|
269
|
+
async () => jsonResult(listPages("foundations"))
|
|
270
|
+
);
|
|
271
|
+
server.registerTool(
|
|
272
|
+
"get_llm_index",
|
|
273
|
+
{
|
|
274
|
+
title: "Get llm.txt index",
|
|
275
|
+
description: "Return the full RefineUI llm.txt machine-readable documentation index.",
|
|
276
|
+
inputSchema: z.object({})
|
|
277
|
+
},
|
|
278
|
+
async () => textResult(getLlmIndex())
|
|
279
|
+
);
|
|
280
|
+
server.registerTool(
|
|
281
|
+
"get_design_rules",
|
|
282
|
+
{
|
|
283
|
+
title: "Get RefineUI DESIGN.md",
|
|
284
|
+
description: "Return docs/public/DESIGN.md \u2014 Stitch-compatible visual identity and codegen rules for @refineui/*.",
|
|
285
|
+
inputSchema: z.object({})
|
|
286
|
+
},
|
|
287
|
+
async () => textResult(getDesignMd())
|
|
288
|
+
);
|
|
289
|
+
server.registerTool(
|
|
290
|
+
"list_tokens",
|
|
291
|
+
{
|
|
292
|
+
title: "List RefineUI token categories",
|
|
293
|
+
description: "List global token categories and semantic text roles from @refineui/tokens.",
|
|
294
|
+
inputSchema: z.object({})
|
|
295
|
+
},
|
|
296
|
+
async () => jsonResult({
|
|
297
|
+
globalCategories: listTokenCategories(),
|
|
298
|
+
semanticTextRoles: listSemanticTextRoles(),
|
|
299
|
+
docs: "https://ui.pelagornis.com/foundations/design-tokens/"
|
|
300
|
+
})
|
|
301
|
+
);
|
|
302
|
+
server.registerTool(
|
|
303
|
+
"get_index_meta",
|
|
304
|
+
{
|
|
305
|
+
title: "Get docs index metadata",
|
|
306
|
+
description: "Return when the embedded docs index was generated and how many pages it contains.",
|
|
307
|
+
inputSchema: z.object({})
|
|
308
|
+
},
|
|
309
|
+
async () => jsonResult(getIndexMeta())
|
|
310
|
+
);
|
|
311
|
+
server.registerTool(
|
|
312
|
+
"run_doctor",
|
|
313
|
+
{
|
|
314
|
+
title: "Run RefineUI Doctor",
|
|
315
|
+
description: "Read-only RefineUI workspace diagnostics \u2014 setup, stylesheet imports, token contract, composition API, imports.",
|
|
316
|
+
inputSchema: z.object({
|
|
317
|
+
target: z.string().optional().describe("Project root path (default: process.cwd() of MCP server)"),
|
|
318
|
+
workspace: z.string().optional().describe("Monorepo workspace relative path, e.g. apps/web or docs"),
|
|
319
|
+
categories: z.array(
|
|
320
|
+
z.enum([
|
|
321
|
+
"setup",
|
|
322
|
+
"compatibility",
|
|
323
|
+
"foundations",
|
|
324
|
+
"components",
|
|
325
|
+
"library",
|
|
326
|
+
"accessibility"
|
|
327
|
+
])
|
|
328
|
+
).optional().describe("Optional rule categories to run")
|
|
329
|
+
})
|
|
330
|
+
},
|
|
331
|
+
async ({ target, workspace, categories }) => {
|
|
332
|
+
const targetRoot = target ?? process.cwd();
|
|
333
|
+
const workspaces = discoverWorkspaces(targetRoot);
|
|
334
|
+
if (workspaces.length === 0) {
|
|
335
|
+
return textResult("No RefineUI workspaces found. Install @refineui/react or @refineui/tokens first.");
|
|
336
|
+
}
|
|
337
|
+
let selected = workspaces[0];
|
|
338
|
+
if (workspace) {
|
|
339
|
+
const match = workspaces.find((ws) => ws.relativePath === workspace);
|
|
340
|
+
if (!match) {
|
|
341
|
+
return jsonResult({
|
|
342
|
+
error: `Workspace "${workspace}" not found`,
|
|
343
|
+
available: workspaces.map((ws) => ws.relativePath)
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
selected = match;
|
|
347
|
+
}
|
|
348
|
+
const report = runDoctor(targetRoot, selected, { categories });
|
|
349
|
+
return jsonResult({
|
|
350
|
+
summary: reportToSummary(report),
|
|
351
|
+
report,
|
|
352
|
+
workspaces: workspaces.map((ws) => ({
|
|
353
|
+
relativePath: ws.relativePath,
|
|
354
|
+
name: ws.name,
|
|
355
|
+
projectKinds: ws.projectKinds
|
|
356
|
+
}))
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
);
|
|
360
|
+
server.registerTool(
|
|
361
|
+
"inspect_token",
|
|
362
|
+
{
|
|
363
|
+
title: "Inspect RefineUI token",
|
|
364
|
+
description: "Trace a semantic or component token through the dependency graph (foundation \u2192 semantic \u2192 component). Requires built token spec.",
|
|
365
|
+
inputSchema: z.object({
|
|
366
|
+
name: z.string().describe("Token name, e.g. backgroundBrand, button.primary.background, or button")
|
|
367
|
+
})
|
|
368
|
+
},
|
|
369
|
+
async ({ name }) => jsonResult(inspectToken(name))
|
|
370
|
+
);
|
|
371
|
+
server.registerTool(
|
|
372
|
+
"get_component_spec",
|
|
373
|
+
{
|
|
374
|
+
title: "Get RefineUI component spec",
|
|
375
|
+
description: "Return the Component Spec contract (anatomy, states, accessibility, keyboard) \u2014 Contract Layer source of truth.",
|
|
376
|
+
inputSchema: z.object({
|
|
377
|
+
name: z.string().describe("Component id or name, e.g. button, accordion, dialog")
|
|
378
|
+
})
|
|
379
|
+
},
|
|
380
|
+
async ({ name }) => jsonResult(getComponentSpec(name))
|
|
381
|
+
);
|
|
382
|
+
server.registerTool(
|
|
383
|
+
"list_component_specs",
|
|
384
|
+
{
|
|
385
|
+
title: "List RefineUI component specs",
|
|
386
|
+
description: "Return manifest.json \u2014 all components with spec paths and data-refineui identities.",
|
|
387
|
+
inputSchema: z.object({})
|
|
388
|
+
},
|
|
389
|
+
async () => jsonResult(listComponentSpecs())
|
|
390
|
+
);
|
|
391
|
+
server.registerTool(
|
|
392
|
+
"get_component_recipe",
|
|
393
|
+
{
|
|
394
|
+
title: "Get component recipe reference",
|
|
395
|
+
description: "Return recipe id from Component Spec \u2014 visual mapping only, not the contract.",
|
|
396
|
+
inputSchema: z.object({
|
|
397
|
+
name: z.string().describe("Component id, e.g. button or accordion")
|
|
398
|
+
})
|
|
399
|
+
},
|
|
400
|
+
async ({ name }) => jsonResult(getComponentRecipe(name))
|
|
401
|
+
);
|
|
402
|
+
server.registerTool(
|
|
403
|
+
"get_token_spec",
|
|
404
|
+
{
|
|
405
|
+
title: "Get spec index",
|
|
406
|
+
description: "Return Contract Layer index (component spec + token trace manifests).",
|
|
407
|
+
inputSchema: z.object({})
|
|
408
|
+
},
|
|
409
|
+
async () => jsonResult(getTokenSpecIndex() ?? { error: "Spec not built. Run build:tokens and build:react." })
|
|
410
|
+
);
|
|
411
|
+
return server;
|
|
412
|
+
}
|
|
413
|
+
serveStdio(() => createServer());
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@refineui/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for RefineUI docs, components, and design-system rules",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/pelagornis/refineui",
|
|
10
|
+
"directory": "packages/mcp"
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"refineui-mcp": "./lib/server.js"
|
|
14
|
+
},
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./lib/index.d.ts",
|
|
18
|
+
"import": "./lib/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"lib",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build:index": "node scripts/build-docs-index.mjs",
|
|
27
|
+
"build": "node scripts/build-docs-index.mjs && tsup src/server.ts src/index.ts --format esm --dts --clean --out-dir lib",
|
|
28
|
+
"start": "node lib/server.js",
|
|
29
|
+
"dev": "bun run build:index && bun src/server.ts"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@modelcontextprotocol/server": "2.0.0",
|
|
33
|
+
"@refineui/doctor": "0.1.0",
|
|
34
|
+
"@refineui/tokens": "1.0.0",
|
|
35
|
+
"zod": "4.5.4"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^22.0.0",
|
|
39
|
+
"tsup": "^8.0.0",
|
|
40
|
+
"typescript": "^5.0.0"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
}
|
|
48
|
+
}
|