@starklab/stark-mcp 0.2.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/package.json +1 -1
- package/src/server.js +38 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starklab/stark-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "MCP server exposing the Stark design system catalog, usage rules, prop mappings, and layout conformance checks to any MCP-compatible coding agent — without needing the stark-workspace monorepo checked out.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/src/server.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
|
|
1
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
4
|
import { z } from 'zod';
|
|
3
5
|
|
|
@@ -12,10 +14,10 @@ import {
|
|
|
12
14
|
getGenerationProtocol,
|
|
13
15
|
} from './data.js';
|
|
14
16
|
|
|
15
|
-
const json = value => ({ content: [{ type: 'text', text: JSON.stringify(value, null, 2) }] });
|
|
16
|
-
const error = message => ({ content: [{ type: 'text', text: message }], isError: true });
|
|
17
|
+
const json = (value) => ({ content: [{ type: 'text', text: JSON.stringify(value, null, 2) }] });
|
|
18
|
+
const error = (message) => ({ content: [{ type: 'text', text: message }], isError: true });
|
|
17
19
|
|
|
18
|
-
const wrap = fn => async args => {
|
|
20
|
+
const wrap = (fn) => async (args) => {
|
|
19
21
|
try {
|
|
20
22
|
return json(await fn(args));
|
|
21
23
|
} catch (err) {
|
|
@@ -23,8 +25,16 @@ const wrap = fn => async args => {
|
|
|
23
25
|
}
|
|
24
26
|
};
|
|
25
27
|
|
|
28
|
+
// Read rather than written down: a hand-maintained literal here goes stale on
|
|
29
|
+
// the first release nobody remembers to update it in, and no client ever
|
|
30
|
+
// complains loudly enough to notice — it shipped as 0.1.0 alongside the
|
|
31
|
+
// package's own 0.2.0. cli.js already derives SCANNER_VERSION this way.
|
|
32
|
+
const VERSION = JSON.parse(
|
|
33
|
+
readFileSync(new URL('../package.json', import.meta.url), 'utf-8')
|
|
34
|
+
).version;
|
|
35
|
+
|
|
26
36
|
export function createServer() {
|
|
27
|
-
const server = new McpServer({ name: 'stark-design-system', version:
|
|
37
|
+
const server = new McpServer({ name: 'stark-design-system', version: VERSION });
|
|
28
38
|
|
|
29
39
|
server.registerTool(
|
|
30
40
|
'list_components',
|
|
@@ -46,7 +56,9 @@ export function createServer() {
|
|
|
46
56
|
'Get the dos/donts, prop table, and Figma link for one Stark component. ' +
|
|
47
57
|
'Read this before placing the component in a layout.',
|
|
48
58
|
inputSchema: {
|
|
49
|
-
component: z
|
|
59
|
+
component: z
|
|
60
|
+
.string()
|
|
61
|
+
.describe('Component name, e.g. "Button" or "TextInput" (case-insensitive)'),
|
|
50
62
|
},
|
|
51
63
|
},
|
|
52
64
|
wrap(({ component }) => getComponentUsage(component))
|
|
@@ -71,7 +83,9 @@ export function createServer() {
|
|
|
71
83
|
),
|
|
72
84
|
},
|
|
73
85
|
},
|
|
74
|
-
wrap(({ component, platform, includeTokens }) =>
|
|
86
|
+
wrap(({ component, platform, includeTokens }) =>
|
|
87
|
+
getComponentProps(component, platform, includeTokens)
|
|
88
|
+
)
|
|
75
89
|
);
|
|
76
90
|
|
|
77
91
|
server.registerTool(
|
|
@@ -93,7 +107,7 @@ export function createServer() {
|
|
|
93
107
|
title: 'Get the full layout catalog',
|
|
94
108
|
description:
|
|
95
109
|
'Get every component that can be used as a standalone layout node, with its props ' +
|
|
96
|
-
|
|
110
|
+
"and slots. This is the same catalog Stark's own layout generator (Vecna) is restricted to.",
|
|
97
111
|
inputSchema: {
|
|
98
112
|
platform: z.enum(['web', 'native']).default('web').describe('Target platform'),
|
|
99
113
|
},
|
|
@@ -104,7 +118,7 @@ export function createServer() {
|
|
|
104
118
|
server.registerTool(
|
|
105
119
|
'get_layout_schema',
|
|
106
120
|
{
|
|
107
|
-
title:
|
|
121
|
+
title: "Get one component's layout schema",
|
|
108
122
|
description: 'Get the props/slots schema for a single layout-capable component.',
|
|
109
123
|
inputSchema: {
|
|
110
124
|
component: z.string().describe('Component name, e.g. "Card"'),
|
|
@@ -119,18 +133,28 @@ export function createServer() {
|
|
|
119
133
|
{
|
|
120
134
|
title: 'Validate a generated layout',
|
|
121
135
|
description:
|
|
122
|
-
|
|
136
|
+
"Run Stark's deterministic conformance checks (no LLM) against a LayoutConfig JSON: " +
|
|
123
137
|
'catalog membership, component do/dont rules, guardrails, and prop shape. Returns findings ' +
|
|
124
|
-
|
|
138
|
+
"ranked Critical/Warning/Info. Pass `canvasCases` (your renderer's supported node-type list) " +
|
|
125
139
|
'if you have one — without it, the catalog<->renderer parity check is skipped.',
|
|
126
140
|
inputSchema: {
|
|
127
|
-
layout: z
|
|
128
|
-
|
|
141
|
+
layout: z
|
|
142
|
+
.record(z.string(), z.any())
|
|
143
|
+
.describe('The LayoutConfig JSON, shaped { page: { sections: [...] } }'),
|
|
144
|
+
intent: z
|
|
145
|
+
.record(z.string(), z.any())
|
|
146
|
+
.optional()
|
|
147
|
+
.describe('Intent/guardrails object the layout was generated from'),
|
|
129
148
|
platform: z.enum(['web', 'native']).default('web'),
|
|
130
|
-
canvasCases: z
|
|
149
|
+
canvasCases: z
|
|
150
|
+
.array(z.string())
|
|
151
|
+
.optional()
|
|
152
|
+
.describe('Node types your renderer actually supports'),
|
|
131
153
|
},
|
|
132
154
|
},
|
|
133
|
-
wrap(({ layout, intent, platform, canvasCases }) =>
|
|
155
|
+
wrap(({ layout, intent, platform, canvasCases }) =>
|
|
156
|
+
validateLayout({ layout, intent, platform, canvasCases })
|
|
157
|
+
)
|
|
134
158
|
);
|
|
135
159
|
|
|
136
160
|
server.registerTool(
|