@wot-ui/cli 0.0.1-beta.2
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 +93 -0
- package/README.zh-CN.md +74 -0
- package/data/v2.json +19827 -0
- package/data/versions.json +10 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +416 -0
- package/dist/scanner-BFHnD5iE.mjs +199 -0
- package/dist/server-HjZltXBO.mjs +248 -0
- package/package.json +49 -0
- package/skills/wot-ui/SKILL.md +18 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { a as resolveVersion, i as listComponents, n as lintProject, o as loadMetadataFile, r as findComponent } from "./scanner-BFHnD5iE.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 }) => {
|
|
35
|
+
return { content: [{
|
|
36
|
+
type: "text",
|
|
37
|
+
text: jsonText({ components: listComponents(version) })
|
|
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 }) => {
|
|
53
|
+
const result = findComponent(component, version);
|
|
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 }) => {
|
|
79
|
+
const result = findComponent(component, version);
|
|
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 }) => {
|
|
106
|
+
const result = findComponent(component, version);
|
|
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 }) => {
|
|
144
|
+
if (!component) return { content: [{
|
|
145
|
+
type: "text",
|
|
146
|
+
text: jsonText({ components: listComponents(version).map((item) => ({
|
|
147
|
+
name: item.name,
|
|
148
|
+
cssVars: item.cssVars
|
|
149
|
+
})) })
|
|
150
|
+
}] };
|
|
151
|
+
const result = findComponent(component, version);
|
|
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, component }) => {
|
|
180
|
+
return { content: [{
|
|
181
|
+
type: "text",
|
|
182
|
+
text: jsonText({ entries: (loadMetadataFile(resolveVersion(version)).changelog ?? []).filter((entry) => {
|
|
183
|
+
const versionMatches = version ? entry.version === version || `v${entry.version}` === version : 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 }) => {
|
|
202
|
+
return { content: [{
|
|
203
|
+
type: "text",
|
|
204
|
+
text: jsonText(lintProject(dir ?? process.cwd(), version))
|
|
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: "0.0.0"
|
|
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,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wot-ui/cli",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.1-beta.2",
|
|
5
|
+
"description": "CLI, MCP and skills toolkit for wot-ui",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/wot-ui/open-wot#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/wot-ui/open-wot.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": "https://github.com/wot-ui/open-wot/issues",
|
|
13
|
+
"main": "./dist/index.mjs",
|
|
14
|
+
"module": "./dist/index.mjs",
|
|
15
|
+
"types": "./dist/index.d.mts",
|
|
16
|
+
"bin": {
|
|
17
|
+
"wot": "dist/index.mjs"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"data",
|
|
21
|
+
"dist",
|
|
22
|
+
"skills"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=20.0.0"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsdown",
|
|
29
|
+
"dev": "tsdown --watch",
|
|
30
|
+
"extract": "tsx scripts/extract.ts",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"test:watch": "vitest",
|
|
33
|
+
"typecheck": "tsc --noEmit"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@cfworker/json-schema": "catalog:cli",
|
|
37
|
+
"@modelcontextprotocol/server": "catalog:cli",
|
|
38
|
+
"@vue/compiler-sfc": "catalog:cli",
|
|
39
|
+
"commander": "catalog:cli",
|
|
40
|
+
"zod": "catalog:cli"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "catalog:types",
|
|
44
|
+
"tsdown": "catalog:cli",
|
|
45
|
+
"tsx": "catalog:cli",
|
|
46
|
+
"typescript": "catalog:cli",
|
|
47
|
+
"vitest": "catalog:testing"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wot-ui
|
|
3
|
+
description: Query wot-ui component knowledge before generating or refactoring UI code.
|
|
4
|
+
summary: Query wot-ui component knowledge before generating code.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Use the local `wot` CLI before generating or refactoring wot-ui based code.
|
|
8
|
+
|
|
9
|
+
Recommended workflow:
|
|
10
|
+
1. Run `wot list` to find the target component.
|
|
11
|
+
2. Run `wot info <Component>` to inspect props, events, slots, and CSS variables.
|
|
12
|
+
3. Run `wot doc <Component>` when you need the markdown documentation.
|
|
13
|
+
4. Run `wot token <Component>` when theme customization is involved.
|
|
14
|
+
|
|
15
|
+
Current limitations:
|
|
16
|
+
- Only wot-ui v2 is supported.
|
|
17
|
+
- Bundled data is still a seed dataset until `pnpm extract` is run against the full wot-ui source repository.
|
|
18
|
+
- `usage` and `lint` currently focus on `.vue` files.
|