@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.
@@ -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.