@wot-ui/cli 0.0.1-beta.10
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/LICENSE.md +21 -0
- package/README.md +189 -0
- package/data/v2.json +19827 -0
- package/data/versions.json +10 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +414 -0
- package/dist/scanner-_isnOGJK.mjs +203 -0
- package/dist/server-BLoIUV7u.mjs +248 -0
- package/package.json +82 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { a as resolveVersion, i as listComponents, n as lintProject, o as loadMetadataFile, r as findComponent, s as version } from "./scanner-_isnOGJK.mjs";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { McpServer, StdioServerTransport } from "@modelcontextprotocol/server";
|
|
4
|
+
import * as z from "zod/v4";
|
|
5
|
+
|
|
6
|
+
//#region src/mcp/prompts.ts
|
|
7
|
+
const WOT_EXPERT_PROMPT = [
|
|
8
|
+
"You are a wot-ui expert assistant.",
|
|
9
|
+
"Always query component metadata before generating code.",
|
|
10
|
+
"Prefer using wot_list, wot_info, wot_doc, and wot_token before writing UI code.",
|
|
11
|
+
"Assume only wot-ui v2 is supported by this server."
|
|
12
|
+
].join(" ");
|
|
13
|
+
const WOT_PAGE_GENERATOR_PROMPT = [
|
|
14
|
+
"Generate wot-ui pages by first collecting every relevant component API and CSS variable.",
|
|
15
|
+
"Prefer existing wd-* components and documented props over ad-hoc custom markup.",
|
|
16
|
+
"When theme customization is involved, inspect CSS variables with wot_token first."
|
|
17
|
+
].join(" ");
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/mcp/tools.ts
|
|
21
|
+
function jsonText(value) {
|
|
22
|
+
return JSON.stringify(value, null, 2);
|
|
23
|
+
}
|
|
24
|
+
function registerMcpTools(server) {
|
|
25
|
+
server.registerTool("wot_list", {
|
|
26
|
+
description: "List available wot-ui components.",
|
|
27
|
+
inputSchema: z.object({ version: z.string().optional() }),
|
|
28
|
+
annotations: {
|
|
29
|
+
readOnlyHint: true,
|
|
30
|
+
destructiveHint: false,
|
|
31
|
+
idempotentHint: true,
|
|
32
|
+
openWorldHint: false
|
|
33
|
+
}
|
|
34
|
+
}, async ({ version: version$1 }) => {
|
|
35
|
+
return { content: [{
|
|
36
|
+
type: "text",
|
|
37
|
+
text: jsonText({ components: listComponents(version$1) })
|
|
38
|
+
}] };
|
|
39
|
+
});
|
|
40
|
+
server.registerTool("wot_info", {
|
|
41
|
+
description: "Get props, events, slots, and CSS variables for a component.",
|
|
42
|
+
inputSchema: z.object({
|
|
43
|
+
component: z.string(),
|
|
44
|
+
version: z.string().optional()
|
|
45
|
+
}),
|
|
46
|
+
annotations: {
|
|
47
|
+
readOnlyHint: true,
|
|
48
|
+
destructiveHint: false,
|
|
49
|
+
idempotentHint: true,
|
|
50
|
+
openWorldHint: false
|
|
51
|
+
}
|
|
52
|
+
}, async ({ component, version: version$1 }) => {
|
|
53
|
+
const result = findComponent(component, version$1);
|
|
54
|
+
if (!result) return {
|
|
55
|
+
isError: true,
|
|
56
|
+
content: [{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: `Component not found: ${component}`
|
|
59
|
+
}]
|
|
60
|
+
};
|
|
61
|
+
return { content: [{
|
|
62
|
+
type: "text",
|
|
63
|
+
text: jsonText(result)
|
|
64
|
+
}] };
|
|
65
|
+
});
|
|
66
|
+
server.registerTool("wot_doc", {
|
|
67
|
+
description: "Get component markdown documentation.",
|
|
68
|
+
inputSchema: z.object({
|
|
69
|
+
component: z.string(),
|
|
70
|
+
version: z.string().optional()
|
|
71
|
+
}),
|
|
72
|
+
annotations: {
|
|
73
|
+
readOnlyHint: true,
|
|
74
|
+
destructiveHint: false,
|
|
75
|
+
idempotentHint: true,
|
|
76
|
+
openWorldHint: false
|
|
77
|
+
}
|
|
78
|
+
}, async ({ component, version: version$1 }) => {
|
|
79
|
+
const result = findComponent(component, version$1);
|
|
80
|
+
if (!result?.doc) return {
|
|
81
|
+
isError: true,
|
|
82
|
+
content: [{
|
|
83
|
+
type: "text",
|
|
84
|
+
text: `Documentation not found: ${component}`
|
|
85
|
+
}]
|
|
86
|
+
};
|
|
87
|
+
return { content: [{
|
|
88
|
+
type: "text",
|
|
89
|
+
text: result.doc
|
|
90
|
+
}] };
|
|
91
|
+
});
|
|
92
|
+
server.registerTool("wot_demo", {
|
|
93
|
+
description: "Get component demo code or list demos.",
|
|
94
|
+
inputSchema: z.object({
|
|
95
|
+
component: z.string(),
|
|
96
|
+
demo: z.string().optional(),
|
|
97
|
+
version: z.string().optional()
|
|
98
|
+
}),
|
|
99
|
+
annotations: {
|
|
100
|
+
readOnlyHint: true,
|
|
101
|
+
destructiveHint: false,
|
|
102
|
+
idempotentHint: true,
|
|
103
|
+
openWorldHint: false
|
|
104
|
+
}
|
|
105
|
+
}, async ({ component, demo, version: version$1 }) => {
|
|
106
|
+
const result = findComponent(component, version$1);
|
|
107
|
+
if (!result) return {
|
|
108
|
+
isError: true,
|
|
109
|
+
content: [{
|
|
110
|
+
type: "text",
|
|
111
|
+
text: `Component not found: ${component}`
|
|
112
|
+
}]
|
|
113
|
+
};
|
|
114
|
+
if (!demo) return { content: [{
|
|
115
|
+
type: "text",
|
|
116
|
+
text: jsonText({ demos: result.demos ?? [] })
|
|
117
|
+
}] };
|
|
118
|
+
const matched = result.demos?.find((item) => item.name.toLowerCase() === demo.toLowerCase());
|
|
119
|
+
if (!matched) return {
|
|
120
|
+
isError: true,
|
|
121
|
+
content: [{
|
|
122
|
+
type: "text",
|
|
123
|
+
text: `Demo not found: ${demo}`
|
|
124
|
+
}]
|
|
125
|
+
};
|
|
126
|
+
return { content: [{
|
|
127
|
+
type: "text",
|
|
128
|
+
text: jsonText(matched)
|
|
129
|
+
}] };
|
|
130
|
+
});
|
|
131
|
+
server.registerTool("wot_token", {
|
|
132
|
+
description: "Get component CSS variables.",
|
|
133
|
+
inputSchema: z.object({
|
|
134
|
+
component: z.string().optional(),
|
|
135
|
+
version: z.string().optional()
|
|
136
|
+
}),
|
|
137
|
+
annotations: {
|
|
138
|
+
readOnlyHint: true,
|
|
139
|
+
destructiveHint: false,
|
|
140
|
+
idempotentHint: true,
|
|
141
|
+
openWorldHint: false
|
|
142
|
+
}
|
|
143
|
+
}, async ({ component, version: version$1 }) => {
|
|
144
|
+
if (!component) return { content: [{
|
|
145
|
+
type: "text",
|
|
146
|
+
text: jsonText({ components: listComponents(version$1).map((item) => ({
|
|
147
|
+
name: item.name,
|
|
148
|
+
cssVars: item.cssVars
|
|
149
|
+
})) })
|
|
150
|
+
}] };
|
|
151
|
+
const result = findComponent(component, version$1);
|
|
152
|
+
if (!result) return {
|
|
153
|
+
isError: true,
|
|
154
|
+
content: [{
|
|
155
|
+
type: "text",
|
|
156
|
+
text: `Component not found: ${component}`
|
|
157
|
+
}]
|
|
158
|
+
};
|
|
159
|
+
return { content: [{
|
|
160
|
+
type: "text",
|
|
161
|
+
text: jsonText({
|
|
162
|
+
name: result.name,
|
|
163
|
+
cssVars: result.cssVars
|
|
164
|
+
})
|
|
165
|
+
}] };
|
|
166
|
+
});
|
|
167
|
+
server.registerTool("wot_changelog", {
|
|
168
|
+
description: "Get changelog entries for the supported v2 dataset.",
|
|
169
|
+
inputSchema: z.object({
|
|
170
|
+
version: z.string().optional(),
|
|
171
|
+
component: z.string().optional()
|
|
172
|
+
}),
|
|
173
|
+
annotations: {
|
|
174
|
+
readOnlyHint: true,
|
|
175
|
+
destructiveHint: false,
|
|
176
|
+
idempotentHint: true,
|
|
177
|
+
openWorldHint: false
|
|
178
|
+
}
|
|
179
|
+
}, async ({ version: version$1, component }) => {
|
|
180
|
+
return { content: [{
|
|
181
|
+
type: "text",
|
|
182
|
+
text: jsonText({ entries: (loadMetadataFile(resolveVersion(version$1)).changelog ?? []).filter((entry) => {
|
|
183
|
+
const versionMatches = version$1 ? entry.version === version$1 || `v${entry.version}` === version$1 : true;
|
|
184
|
+
const componentMatches = component ? (entry.components ?? []).some((item) => item.toLowerCase() === component.toLowerCase()) : true;
|
|
185
|
+
return versionMatches && componentMatches;
|
|
186
|
+
}) })
|
|
187
|
+
}] };
|
|
188
|
+
});
|
|
189
|
+
server.registerTool("wot_lint", {
|
|
190
|
+
description: "Lint a local project for wot-ui related issues.",
|
|
191
|
+
inputSchema: z.object({
|
|
192
|
+
dir: z.string().optional(),
|
|
193
|
+
version: z.string().optional()
|
|
194
|
+
}),
|
|
195
|
+
annotations: {
|
|
196
|
+
readOnlyHint: true,
|
|
197
|
+
destructiveHint: false,
|
|
198
|
+
idempotentHint: true,
|
|
199
|
+
openWorldHint: true
|
|
200
|
+
}
|
|
201
|
+
}, async ({ dir, version: version$1 }) => {
|
|
202
|
+
return { content: [{
|
|
203
|
+
type: "text",
|
|
204
|
+
text: jsonText(lintProject(dir ?? process.cwd(), version$1))
|
|
205
|
+
}] };
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
//#endregion
|
|
210
|
+
//#region src/mcp/server.ts
|
|
211
|
+
async function startMcpServer() {
|
|
212
|
+
const server = new McpServer({
|
|
213
|
+
name: "wot-ui",
|
|
214
|
+
version
|
|
215
|
+
}, {
|
|
216
|
+
instructions: "Use wot-ui component tools before generating UI code. Only wot-ui v2 metadata is available in this server.",
|
|
217
|
+
capabilities: { logging: {} }
|
|
218
|
+
});
|
|
219
|
+
registerMcpTools(server);
|
|
220
|
+
server.registerPrompt("wot-expert", { description: "General wot-ui expert workflow." }, async () => ({ messages: [{
|
|
221
|
+
role: "assistant",
|
|
222
|
+
content: {
|
|
223
|
+
type: "text",
|
|
224
|
+
text: WOT_EXPERT_PROMPT
|
|
225
|
+
}
|
|
226
|
+
}] }));
|
|
227
|
+
server.registerPrompt("wot-page-generator", {
|
|
228
|
+
description: "Workflow for generating a wot-ui page.",
|
|
229
|
+
argsSchema: z.object({ goal: z.string().optional() })
|
|
230
|
+
}, async ({ goal }) => ({ messages: [{
|
|
231
|
+
role: "assistant",
|
|
232
|
+
content: {
|
|
233
|
+
type: "text",
|
|
234
|
+
text: goal ? `${WOT_PAGE_GENERATOR_PROMPT} Goal: ${goal}` : WOT_PAGE_GENERATOR_PROMPT
|
|
235
|
+
}
|
|
236
|
+
}] }));
|
|
237
|
+
const transport = new StdioServerTransport();
|
|
238
|
+
await server.connect(transport);
|
|
239
|
+
const shutdown = async () => {
|
|
240
|
+
await server.close();
|
|
241
|
+
process.exit(0);
|
|
242
|
+
};
|
|
243
|
+
process.on("SIGINT", shutdown);
|
|
244
|
+
process.on("SIGTERM", shutdown);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
//#endregion
|
|
248
|
+
export { startMcpServer };
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wot-ui/cli",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.1-beta.10",
|
|
5
|
+
"description": "面向 wot-ui 的 CLI、MCP 与数据提取工具集",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"funding": "https://github.com/sponsors/antfu",
|
|
8
|
+
"homepage": "https://github.com/wot-ui/open-wot#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/wot-ui/open-wot.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": "https://github.com/wot-ui/open-wot/issues",
|
|
14
|
+
"keywords": [],
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./dist/index.mjs",
|
|
18
|
+
"./package.json": "./package.json"
|
|
19
|
+
},
|
|
20
|
+
"main": "./dist/index.mjs",
|
|
21
|
+
"module": "./dist/index.mjs",
|
|
22
|
+
"types": "./dist/index.d.mts",
|
|
23
|
+
"bin": {
|
|
24
|
+
"wot": "dist/index.mjs"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"data",
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20.0.0"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@cfworker/json-schema": "^4.1.1",
|
|
35
|
+
"@modelcontextprotocol/server": "^2.0.0-alpha.2",
|
|
36
|
+
"@vue/compiler-sfc": "^3.5.13",
|
|
37
|
+
"commander": "^14.0.0",
|
|
38
|
+
"zod": "^4.1.12"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@antfu/eslint-config": "^6.6.1",
|
|
42
|
+
"@antfu/ni": "^28.0.0",
|
|
43
|
+
"@antfu/utils": "^9.3.0",
|
|
44
|
+
"@types/node": "^25.0.1",
|
|
45
|
+
"@vitest/coverage-v8": "4.0.15",
|
|
46
|
+
"baseline-browser-mapping": "^2.10.18",
|
|
47
|
+
"bumpp": "^10.3.2",
|
|
48
|
+
"eslint": "^9.39.2",
|
|
49
|
+
"lint-staged": "^16.2.7",
|
|
50
|
+
"publint": "^0.3.16",
|
|
51
|
+
"simple-git-hooks": "^2.13.1",
|
|
52
|
+
"tinyexec": "^1.0.2",
|
|
53
|
+
"tsdown": "^0.17.3",
|
|
54
|
+
"tsx": "^4.21.0",
|
|
55
|
+
"typescript": "^5.9.3",
|
|
56
|
+
"vitest": "^4.0.15",
|
|
57
|
+
"vitest-package-exports": "^0.1.1",
|
|
58
|
+
"yaml": "^2.8.2"
|
|
59
|
+
},
|
|
60
|
+
"simple-git-hooks": {
|
|
61
|
+
"pre-commit": "pnpm i --frozen-lockfile --ignore-scripts --offline && npx lint-staged"
|
|
62
|
+
},
|
|
63
|
+
"lint-staged": {
|
|
64
|
+
"*": "eslint --fix --no-warn-ignored"
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsdown",
|
|
68
|
+
"dev": "tsdown --watch",
|
|
69
|
+
"extract": "tsx scripts/extract.ts",
|
|
70
|
+
"extract:cli": "pnpm extract",
|
|
71
|
+
"extract:clone": "rm -rf /tmp/open-wot-wot-ui && git clone --depth 1 https://github.com/wot-ui/wot-ui.git /tmp/open-wot-wot-ui && pnpm extract --wot-dir /tmp/open-wot-wot-ui --output data/v2.json",
|
|
72
|
+
"lint": "eslint",
|
|
73
|
+
"release": "bumpp",
|
|
74
|
+
"start": "tsx src/index.ts",
|
|
75
|
+
"test": "vitest run",
|
|
76
|
+
"test:coverage": "vitest run --coverage --coverage.reporter=lcov --coverage.reporter=text",
|
|
77
|
+
"test:watch": "vitest",
|
|
78
|
+
"typecheck": "tsc --noEmit",
|
|
79
|
+
"typecheck:all": "pnpm typecheck",
|
|
80
|
+
"typecheck:cli": "pnpm typecheck"
|
|
81
|
+
}
|
|
82
|
+
}
|