rsbuild-plugin-vue-mcp 0.1.0 → 0.1.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 +2 -1
- package/README_zh.md +2 -1
- package/dist/396.js +237 -0
- package/dist/index.cjs +121 -173
- package/dist/index.js +3 -5
- package/dist/overlay-bootstrap.js +1 -1
- package/dist/overlay.js +41 -12
- package/dist/rspack.cjs +120 -172
- package/dist/rspack.js +2 -4
- package/dist/types/types.d.ts +9 -20
- package/package.json +2 -4
- package/dist/551.js +0 -287
- package/dist/types/mcp/rpc.d.ts +0 -2
package/README.md
CHANGED
|
@@ -104,9 +104,10 @@ Add that URL to your client's MCP configuration (Cursor, Claude Desktop, VS Code
|
|
|
104
104
|
```json
|
|
105
105
|
{
|
|
106
106
|
"mcpServers": {
|
|
107
|
-
"vue-
|
|
107
|
+
"vue-devtools": {
|
|
108
108
|
"type": "streamable-http",
|
|
109
109
|
"url": "http://localhost:<YourPort>/__mcp/mcp",
|
|
110
|
+
"description": "Vue DevTools MCP - Rsbuild/Rspack MCP plugin based on Vue DevTools",
|
|
110
111
|
"disabled": false
|
|
111
112
|
}
|
|
112
113
|
}
|
package/README_zh.md
CHANGED
|
@@ -101,9 +101,10 @@ MCP 服务(基于 Streamable HTTP 传输)将在 `http://localhost:[port]/__m
|
|
|
101
101
|
```json
|
|
102
102
|
{
|
|
103
103
|
"mcpServers": {
|
|
104
|
-
"vue-
|
|
104
|
+
"vue-devtools": {
|
|
105
105
|
"type": "streamable-http",
|
|
106
106
|
"url": "http://localhost:<YourPort>/__mcp/mcp",
|
|
107
|
+
"description": "Vue DevTools MCP - Rsbuild/Rspack MCP plugin based on Vue DevTools",
|
|
107
108
|
"disabled": false
|
|
108
109
|
}
|
|
109
110
|
}
|
package/dist/396.js
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { createBirpcGroup } from "birpc";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
5
|
+
function createVueMcpContext() {
|
|
6
|
+
return {
|
|
7
|
+
rpcServer: null
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
const channelCache = new WeakMap();
|
|
11
|
+
function createRPCServer(ws, functions, options = {}) {
|
|
12
|
+
const group = createBirpcGroup(functions, ()=>Array.from(ws?.clients || []).map((channel)=>{
|
|
13
|
+
if (channel.readyState === channel.CLOSED) return;
|
|
14
|
+
const cached = channelCache.get(channel);
|
|
15
|
+
if (cached) return cached;
|
|
16
|
+
const options = {
|
|
17
|
+
on: (fn)=>channel.on('message', fn),
|
|
18
|
+
post: (data)=>channel.send(data),
|
|
19
|
+
serialize: (v)=>JSON.stringify(v),
|
|
20
|
+
deserialize: (v)=>JSON.parse(v)
|
|
21
|
+
};
|
|
22
|
+
channelCache.set(channel, options);
|
|
23
|
+
return options;
|
|
24
|
+
}).filter((c)=>!!c), options);
|
|
25
|
+
ws.on('connection', ()=>{
|
|
26
|
+
group.updateChannels();
|
|
27
|
+
});
|
|
28
|
+
return group.broadcast;
|
|
29
|
+
}
|
|
30
|
+
var package_namespaceObject = {
|
|
31
|
+
rE: "0.1.2"
|
|
32
|
+
};
|
|
33
|
+
function stringify(value) {
|
|
34
|
+
return "string" == typeof value ? value : JSON.stringify(value);
|
|
35
|
+
}
|
|
36
|
+
function createMcpServerDefault(options, ctx) {
|
|
37
|
+
const server = new McpServer({
|
|
38
|
+
name: "rsbuild-vue-mcp",
|
|
39
|
+
description: 'Rsbuild/Rspack MCP plugin based on Vue DevTools',
|
|
40
|
+
version: package_namespaceObject.rE,
|
|
41
|
+
...options.mcpServerInfo
|
|
42
|
+
});
|
|
43
|
+
server.registerTool('get-app-record-status', {
|
|
44
|
+
title: 'App Record Status',
|
|
45
|
+
description: "Get the current Devtools App status (appRecords and activeAppRecord). Must be called first before any other MCP tools. An empty content response usually means the user needs to open a web page with an app to debug. If multiple content items are returned, the user has multiple app pages open and should close all but one to avoid interference. If a content contains multiple appRecords, it means multiple Vue App instances exist on the page. `toggle-app` to switch activeAppRecord. "
|
|
46
|
+
}, async ()=>{
|
|
47
|
+
const res = await ctx.rpcServer.getAppRecordStatus();
|
|
48
|
+
return {
|
|
49
|
+
content: res.map((r)=>({
|
|
50
|
+
type: 'text',
|
|
51
|
+
text: stringify(r)
|
|
52
|
+
}))
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
server.registerTool('toggle-app', {
|
|
56
|
+
title: 'Toggle App',
|
|
57
|
+
description: 'Toggle the activeAppRecord by the id of the appRecord. All MCP tool operations on Components, Router, Pinia, etc. are performed based on the activeAppRecord.',
|
|
58
|
+
inputSchema: {
|
|
59
|
+
id: z.string()
|
|
60
|
+
}
|
|
61
|
+
}, async ({ id })=>{
|
|
62
|
+
await ctx.rpcServer.toggleApp({
|
|
63
|
+
id
|
|
64
|
+
});
|
|
65
|
+
return {
|
|
66
|
+
content: [
|
|
67
|
+
{
|
|
68
|
+
type: 'text',
|
|
69
|
+
text: 'ok'
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
server.registerTool('get-component-tree', {
|
|
75
|
+
description: 'Get the Vue component tree in JSON tree syntax format (by Vue DevTools stringify, a two-dimensional serialization format that separates structure from values, replacing nested object references with IDs.).',
|
|
76
|
+
inputSchema: {
|
|
77
|
+
componentName: z.string().optional().describe('query by componentName (the component\'s name, not uid), default query all components')
|
|
78
|
+
}
|
|
79
|
+
}, async ({ componentName })=>{
|
|
80
|
+
const res = await ctx.rpcServer.getInspectorTree({
|
|
81
|
+
componentName
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
content: res.map((r)=>({
|
|
85
|
+
type: 'text',
|
|
86
|
+
text: stringify(r)
|
|
87
|
+
}))
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
server.registerTool('get-component-state', {
|
|
91
|
+
description: 'Get the Vue component state in JSON structure format.',
|
|
92
|
+
inputSchema: {
|
|
93
|
+
componentName: z.string().describe('query by componentName (the component\'s name, not uid)')
|
|
94
|
+
}
|
|
95
|
+
}, async ({ componentName })=>{
|
|
96
|
+
const res = await ctx.rpcServer.getInspectorState({
|
|
97
|
+
componentName
|
|
98
|
+
});
|
|
99
|
+
return {
|
|
100
|
+
content: res.map((r)=>({
|
|
101
|
+
type: 'text',
|
|
102
|
+
text: stringify(r)
|
|
103
|
+
}))
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
server.registerTool('edit-component-state', {
|
|
107
|
+
description: 'Edit the Vue component state.',
|
|
108
|
+
inputSchema: {
|
|
109
|
+
componentName: z.string().describe('by componentName (the component\'s name, not uid)'),
|
|
110
|
+
path: z.array(z.string()),
|
|
111
|
+
value: z.string(),
|
|
112
|
+
valueType: z["enum"]([
|
|
113
|
+
'string',
|
|
114
|
+
'number',
|
|
115
|
+
'boolean',
|
|
116
|
+
'object',
|
|
117
|
+
'array'
|
|
118
|
+
])
|
|
119
|
+
}
|
|
120
|
+
}, async ({ componentName, path, value, valueType })=>{
|
|
121
|
+
await ctx.rpcServer.editComponentState({
|
|
122
|
+
componentName,
|
|
123
|
+
path,
|
|
124
|
+
value,
|
|
125
|
+
valueType
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
content: [
|
|
129
|
+
{
|
|
130
|
+
type: 'text',
|
|
131
|
+
text: 'ok'
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
server.registerTool('highlight-component', {
|
|
137
|
+
description: 'Highlight the Vue component.',
|
|
138
|
+
inputSchema: {
|
|
139
|
+
componentName: z.string().describe('by componentName (the component\'s name, not uid)')
|
|
140
|
+
}
|
|
141
|
+
}, async ({ componentName })=>{
|
|
142
|
+
await ctx.rpcServer.highlightComponent({
|
|
143
|
+
componentName
|
|
144
|
+
});
|
|
145
|
+
return {
|
|
146
|
+
content: [
|
|
147
|
+
{
|
|
148
|
+
type: 'text',
|
|
149
|
+
text: 'ok'
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
server.registerTool('get-router-info', {
|
|
155
|
+
description: 'Get the Vue router info in JSON structure format.'
|
|
156
|
+
}, async ()=>{
|
|
157
|
+
const res = await ctx.rpcServer.getRouterInfo();
|
|
158
|
+
return {
|
|
159
|
+
content: res.map((r)=>({
|
|
160
|
+
type: 'text',
|
|
161
|
+
text: stringify(r)
|
|
162
|
+
}))
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
server.registerTool('get-pinia-state', {
|
|
166
|
+
description: 'Get the Pinia state in JSON structure format.',
|
|
167
|
+
inputSchema: {
|
|
168
|
+
storeName: z.string()
|
|
169
|
+
}
|
|
170
|
+
}, async ({ storeName })=>{
|
|
171
|
+
const res = await ctx.rpcServer.getPiniaState({
|
|
172
|
+
storeName
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
content: res.map((r)=>({
|
|
176
|
+
type: 'text',
|
|
177
|
+
text: stringify(r)
|
|
178
|
+
}))
|
|
179
|
+
};
|
|
180
|
+
});
|
|
181
|
+
server.registerTool('get-pinia-tree', {
|
|
182
|
+
description: 'Get the Pinia tree in JSON structure format.'
|
|
183
|
+
}, async ()=>{
|
|
184
|
+
const res = await ctx.rpcServer.getPiniaTree();
|
|
185
|
+
return {
|
|
186
|
+
content: res.map((r)=>({
|
|
187
|
+
type: 'text',
|
|
188
|
+
text: stringify(r)
|
|
189
|
+
}))
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
return server;
|
|
193
|
+
}
|
|
194
|
+
async function mcpHandlerStateless(server, req, res) {
|
|
195
|
+
try {
|
|
196
|
+
const transport = new StreamableHTTPServerTransport({
|
|
197
|
+
sessionIdGenerator: void 0
|
|
198
|
+
});
|
|
199
|
+
await server.connect(transport);
|
|
200
|
+
await transport.handleRequest(req, res);
|
|
201
|
+
res.on('close', ()=>{
|
|
202
|
+
transport.close();
|
|
203
|
+
server.close();
|
|
204
|
+
});
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error('Error handling MCP request:', error);
|
|
207
|
+
if (!res.headersSent) {
|
|
208
|
+
res.statusCode = 500;
|
|
209
|
+
res.setHeader('content-type', 'application/json');
|
|
210
|
+
res.end(JSON.stringify({
|
|
211
|
+
jsonrpc: '2.0',
|
|
212
|
+
error: {
|
|
213
|
+
code: -32603,
|
|
214
|
+
message: 'Internal server error'
|
|
215
|
+
},
|
|
216
|
+
id: null
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function setupRoutes(base, getServer, dev) {
|
|
222
|
+
dev.middlewares.use(`${base}/mcp`, async (req, res)=>{
|
|
223
|
+
const server = await getServer();
|
|
224
|
+
await mcpHandlerStateless(server, req, res);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
function setupRspackRoutes(base, getServer, middlewares) {
|
|
228
|
+
middlewares.push({
|
|
229
|
+
name: 'vue-devtools-mcp',
|
|
230
|
+
path: `${base}/mcp`,
|
|
231
|
+
async middleware (req, res) {
|
|
232
|
+
const server = await getServer();
|
|
233
|
+
await mcpHandlerStateless(server, req, res);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
export { createMcpServerDefault, createRPCServer, createVueMcpContext, setupRoutes, setupRspackRoutes };
|
package/dist/index.cjs
CHANGED
|
@@ -48,40 +48,11 @@ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_no
|
|
|
48
48
|
const promises_namespaceObject = require("node:fs/promises");
|
|
49
49
|
var promises_default = /*#__PURE__*/ __webpack_require__.n(promises_namespaceObject);
|
|
50
50
|
const external_ws_namespaceObject = require("ws");
|
|
51
|
-
const external_hookable_namespaceObject = require("hookable");
|
|
52
51
|
function createVueMcpContext() {
|
|
53
52
|
return {
|
|
54
|
-
hooks: (0, external_hookable_namespaceObject.createHooks)(),
|
|
55
|
-
rpc: null,
|
|
56
53
|
rpcServer: null
|
|
57
54
|
};
|
|
58
55
|
}
|
|
59
|
-
function createServerRpcFunc(ctx) {
|
|
60
|
-
return {
|
|
61
|
-
getInspectorTree: (_)=>({}),
|
|
62
|
-
onInspectorTreeUpdated: (event, data)=>{
|
|
63
|
-
ctx.hooks.callHook(event, data).finally();
|
|
64
|
-
},
|
|
65
|
-
getInspectorState: (_)=>({}),
|
|
66
|
-
onInspectorStateUpdated: (event, data)=>{
|
|
67
|
-
ctx.hooks.callHook(event, data).finally();
|
|
68
|
-
},
|
|
69
|
-
editComponentState (_) {},
|
|
70
|
-
highlightComponent (_) {},
|
|
71
|
-
getRouterInfo: (_)=>({}),
|
|
72
|
-
onRouterInfoUpdated: (event, data)=>{
|
|
73
|
-
ctx.hooks.callHook(event, data).finally();
|
|
74
|
-
},
|
|
75
|
-
getPiniaTree: (_)=>({}),
|
|
76
|
-
onPiniaTreeUpdated: (event, data)=>{
|
|
77
|
-
ctx.hooks.callHook(event, data).finally();
|
|
78
|
-
},
|
|
79
|
-
getPiniaState: (_)=>({}),
|
|
80
|
-
onPiniaInfoUpdated: (event, data)=>{
|
|
81
|
-
ctx.hooks.callHook(event, data).finally();
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
56
|
const external_birpc_namespaceObject = require("birpc");
|
|
86
57
|
const channelCache = new WeakMap();
|
|
87
58
|
function createRPCServer(ws, functions, options = {}) {
|
|
@@ -105,9 +76,8 @@ function createRPCServer(ws, functions, options = {}) {
|
|
|
105
76
|
}
|
|
106
77
|
const mcp_js_namespaceObject = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
107
78
|
var package_namespaceObject = {
|
|
108
|
-
rE: "0.1.
|
|
79
|
+
rE: "0.1.2"
|
|
109
80
|
};
|
|
110
|
-
const external_nanoid_namespaceObject = require("nanoid");
|
|
111
81
|
const external_zod_namespaceObject = require("zod");
|
|
112
82
|
function stringify(value) {
|
|
113
83
|
return "string" == typeof value ? value : JSON.stringify(value);
|
|
@@ -119,56 +89,73 @@ function createMcpServerDefault(options, ctx) {
|
|
|
119
89
|
version: package_namespaceObject.rE,
|
|
120
90
|
...options.mcpServerInfo
|
|
121
91
|
});
|
|
92
|
+
server.registerTool('get-app-record-status', {
|
|
93
|
+
title: 'App Record Status',
|
|
94
|
+
description: "Get the current Devtools App status (appRecords and activeAppRecord). Must be called first before any other MCP tools. An empty content response usually means the user needs to open a web page with an app to debug. If multiple content items are returned, the user has multiple app pages open and should close all but one to avoid interference. If a content contains multiple appRecords, it means multiple Vue App instances exist on the page. `toggle-app` to switch activeAppRecord. "
|
|
95
|
+
}, async ()=>{
|
|
96
|
+
const res = await ctx.rpcServer.getAppRecordStatus();
|
|
97
|
+
return {
|
|
98
|
+
content: res.map((r)=>({
|
|
99
|
+
type: 'text',
|
|
100
|
+
text: stringify(r)
|
|
101
|
+
}))
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
server.registerTool('toggle-app', {
|
|
105
|
+
title: 'Toggle App',
|
|
106
|
+
description: 'Toggle the activeAppRecord by the id of the appRecord. All MCP tool operations on Components, Router, Pinia, etc. are performed based on the activeAppRecord.',
|
|
107
|
+
inputSchema: {
|
|
108
|
+
id: external_zod_namespaceObject.z.string()
|
|
109
|
+
}
|
|
110
|
+
}, async ({ id })=>{
|
|
111
|
+
await ctx.rpcServer.toggleApp({
|
|
112
|
+
id
|
|
113
|
+
});
|
|
114
|
+
return {
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
type: 'text',
|
|
118
|
+
text: 'ok'
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
};
|
|
122
|
+
});
|
|
122
123
|
server.registerTool('get-component-tree', {
|
|
123
|
-
description: 'Get the Vue component tree in
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}).catch((e)=>{
|
|
139
|
-
console.error(e);
|
|
140
|
-
reject(e);
|
|
141
|
-
});
|
|
142
|
-
}));
|
|
124
|
+
description: 'Get the Vue component tree in JSON tree syntax format (by Vue DevTools stringify, a two-dimensional serialization format that separates structure from values, replacing nested object references with IDs.).',
|
|
125
|
+
inputSchema: {
|
|
126
|
+
componentName: external_zod_namespaceObject.z.string().optional().describe('query by componentName (the component\'s name, not uid), default query all components')
|
|
127
|
+
}
|
|
128
|
+
}, async ({ componentName })=>{
|
|
129
|
+
const res = await ctx.rpcServer.getInspectorTree({
|
|
130
|
+
componentName
|
|
131
|
+
});
|
|
132
|
+
return {
|
|
133
|
+
content: res.map((r)=>({
|
|
134
|
+
type: 'text',
|
|
135
|
+
text: stringify(r)
|
|
136
|
+
}))
|
|
137
|
+
};
|
|
138
|
+
});
|
|
143
139
|
server.registerTool('get-component-state', {
|
|
144
140
|
description: 'Get the Vue component state in JSON structure format.',
|
|
145
141
|
inputSchema: {
|
|
146
|
-
componentName: external_zod_namespaceObject.z.string()
|
|
142
|
+
componentName: external_zod_namespaceObject.z.string().describe('query by componentName (the component\'s name, not uid)')
|
|
147
143
|
}
|
|
148
|
-
}, async ({ componentName })=>
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
});
|
|
160
|
-
ctx.rpcServer.getInspectorState({
|
|
161
|
-
event: eventName,
|
|
162
|
-
componentName
|
|
163
|
-
}).catch((e)=>{
|
|
164
|
-
console.error(e);
|
|
165
|
-
reject(e);
|
|
166
|
-
});
|
|
167
|
-
}));
|
|
144
|
+
}, async ({ componentName })=>{
|
|
145
|
+
const res = await ctx.rpcServer.getInspectorState({
|
|
146
|
+
componentName
|
|
147
|
+
});
|
|
148
|
+
return {
|
|
149
|
+
content: res.map((r)=>({
|
|
150
|
+
type: 'text',
|
|
151
|
+
text: stringify(r)
|
|
152
|
+
}))
|
|
153
|
+
};
|
|
154
|
+
});
|
|
168
155
|
server.registerTool('edit-component-state', {
|
|
169
156
|
description: 'Edit the Vue component state.',
|
|
170
157
|
inputSchema: {
|
|
171
|
-
componentName: external_zod_namespaceObject.z.string(),
|
|
158
|
+
componentName: external_zod_namespaceObject.z.string().describe('by componentName (the component\'s name, not uid)'),
|
|
172
159
|
path: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()),
|
|
173
160
|
value: external_zod_namespaceObject.z.string(),
|
|
174
161
|
valueType: external_zod_namespaceObject.z["enum"]([
|
|
@@ -179,115 +166,78 @@ function createMcpServerDefault(options, ctx) {
|
|
|
179
166
|
'array'
|
|
180
167
|
])
|
|
181
168
|
}
|
|
182
|
-
}, async ({ componentName, path, value, valueType })=>
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
console.error(e);
|
|
199
|
-
reject(e);
|
|
200
|
-
});
|
|
201
|
-
}));
|
|
169
|
+
}, async ({ componentName, path, value, valueType })=>{
|
|
170
|
+
await ctx.rpcServer.editComponentState({
|
|
171
|
+
componentName,
|
|
172
|
+
path,
|
|
173
|
+
value,
|
|
174
|
+
valueType
|
|
175
|
+
});
|
|
176
|
+
return {
|
|
177
|
+
content: [
|
|
178
|
+
{
|
|
179
|
+
type: 'text',
|
|
180
|
+
text: 'ok'
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
};
|
|
184
|
+
});
|
|
202
185
|
server.registerTool('highlight-component', {
|
|
203
186
|
description: 'Highlight the Vue component.',
|
|
204
187
|
inputSchema: {
|
|
205
|
-
componentName: external_zod_namespaceObject.z.string()
|
|
188
|
+
componentName: external_zod_namespaceObject.z.string().describe('by componentName (the component\'s name, not uid)')
|
|
206
189
|
}
|
|
207
|
-
}, async ({ componentName })=>
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
console.error(e);
|
|
221
|
-
reject(e);
|
|
222
|
-
});
|
|
223
|
-
}));
|
|
190
|
+
}, async ({ componentName })=>{
|
|
191
|
+
await ctx.rpcServer.highlightComponent({
|
|
192
|
+
componentName
|
|
193
|
+
});
|
|
194
|
+
return {
|
|
195
|
+
content: [
|
|
196
|
+
{
|
|
197
|
+
type: 'text',
|
|
198
|
+
text: 'ok'
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
};
|
|
202
|
+
});
|
|
224
203
|
server.registerTool('get-router-info', {
|
|
225
204
|
description: 'Get the Vue router info in JSON structure format.'
|
|
226
|
-
}, async ()=>
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
]
|
|
236
|
-
});
|
|
237
|
-
});
|
|
238
|
-
ctx.rpcServer.getRouterInfo({
|
|
239
|
-
event: eventName
|
|
240
|
-
}).catch((e)=>{
|
|
241
|
-
console.error(e);
|
|
242
|
-
reject(e);
|
|
243
|
-
});
|
|
244
|
-
}));
|
|
205
|
+
}, async ()=>{
|
|
206
|
+
const res = await ctx.rpcServer.getRouterInfo();
|
|
207
|
+
return {
|
|
208
|
+
content: res.map((r)=>({
|
|
209
|
+
type: 'text',
|
|
210
|
+
text: stringify(r)
|
|
211
|
+
}))
|
|
212
|
+
};
|
|
213
|
+
});
|
|
245
214
|
server.registerTool('get-pinia-state', {
|
|
246
215
|
description: 'Get the Pinia state in JSON structure format.',
|
|
247
216
|
inputSchema: {
|
|
248
217
|
storeName: external_zod_namespaceObject.z.string()
|
|
249
218
|
}
|
|
250
|
-
}, async ({ storeName })=>
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
});
|
|
262
|
-
ctx.rpcServer.getPiniaState({
|
|
263
|
-
event: eventName,
|
|
264
|
-
storeName
|
|
265
|
-
}).catch((e)=>{
|
|
266
|
-
console.error(e);
|
|
267
|
-
reject(e);
|
|
268
|
-
});
|
|
269
|
-
}));
|
|
219
|
+
}, async ({ storeName })=>{
|
|
220
|
+
const res = await ctx.rpcServer.getPiniaState({
|
|
221
|
+
storeName
|
|
222
|
+
});
|
|
223
|
+
return {
|
|
224
|
+
content: res.map((r)=>({
|
|
225
|
+
type: 'text',
|
|
226
|
+
text: stringify(r)
|
|
227
|
+
}))
|
|
228
|
+
};
|
|
229
|
+
});
|
|
270
230
|
server.registerTool('get-pinia-tree', {
|
|
271
231
|
description: 'Get the Pinia tree in JSON structure format.'
|
|
272
|
-
}, async ()=>
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
]
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
ctx.rpcServer.getPiniaTree({
|
|
285
|
-
event: eventName
|
|
286
|
-
}).catch((e)=>{
|
|
287
|
-
console.error(e);
|
|
288
|
-
reject(e);
|
|
289
|
-
});
|
|
290
|
-
}));
|
|
232
|
+
}, async ()=>{
|
|
233
|
+
const res = await ctx.rpcServer.getPiniaTree();
|
|
234
|
+
return {
|
|
235
|
+
content: res.map((r)=>({
|
|
236
|
+
type: 'text',
|
|
237
|
+
text: stringify(r)
|
|
238
|
+
}))
|
|
239
|
+
};
|
|
240
|
+
});
|
|
291
241
|
return server;
|
|
292
242
|
}
|
|
293
243
|
const streamableHttp_js_namespaceObject = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
@@ -356,7 +306,7 @@ const pluginVueMcp = (options = {})=>({
|
|
|
356
306
|
],
|
|
357
307
|
order: 'pre'
|
|
358
308
|
}, (context)=>{
|
|
359
|
-
if ('dev' !== api.context.action || firstInjected) return context;
|
|
309
|
+
if (api.context.action && 'dev' !== api.context.action || firstInjected) return context;
|
|
360
310
|
let code = context.code;
|
|
361
311
|
if ('string' != typeof code) return context;
|
|
362
312
|
firstInjected = true;
|
|
@@ -398,11 +348,9 @@ const pluginVueMcp = (options = {})=>({
|
|
|
398
348
|
wss.emit('connection', client, request);
|
|
399
349
|
});
|
|
400
350
|
});
|
|
401
|
-
|
|
402
|
-
ctx.rpcServer = createRPCServer(wss, rpc, {
|
|
351
|
+
ctx.rpcServer = createRPCServer(wss, {}, {
|
|
403
352
|
timeout: 3000
|
|
404
353
|
});
|
|
405
|
-
ctx.rpc = rpc;
|
|
406
354
|
const { printUrl = true, mcpPath = '/__mcp' } = options;
|
|
407
355
|
setupRoutes(mcpPath, async ()=>{
|
|
408
356
|
let mcp = createMcpServerDefault(options, ctx);
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { fileURLToPath } from "node:url";
|
|
|
2
2
|
import node_path from "node:path";
|
|
3
3
|
import promises from "node:fs/promises";
|
|
4
4
|
import { WebSocketServer } from "ws";
|
|
5
|
-
import { createMcpServerDefault,
|
|
5
|
+
import { createMcpServerDefault, createRPCServer, createVueMcpContext, setupRoutes } from "./396.js";
|
|
6
6
|
function getVueMcpPath() {
|
|
7
7
|
const pluginPath = node_path.dirname(fileURLToPath(import.meta.url));
|
|
8
8
|
return pluginPath.replaceAll('\\', '/');
|
|
@@ -35,7 +35,7 @@ const pluginVueMcp = (options = {})=>({
|
|
|
35
35
|
],
|
|
36
36
|
order: 'pre'
|
|
37
37
|
}, (context)=>{
|
|
38
|
-
if ('dev' !== api.context.action || firstInjected) return context;
|
|
38
|
+
if (api.context.action && 'dev' !== api.context.action || firstInjected) return context;
|
|
39
39
|
let code = context.code;
|
|
40
40
|
if ('string' != typeof code) return context;
|
|
41
41
|
firstInjected = true;
|
|
@@ -77,11 +77,9 @@ const pluginVueMcp = (options = {})=>({
|
|
|
77
77
|
wss.emit('connection', client, request);
|
|
78
78
|
});
|
|
79
79
|
});
|
|
80
|
-
|
|
81
|
-
ctx.rpcServer = createRPCServer(wss, rpc, {
|
|
80
|
+
ctx.rpcServer = createRPCServer(wss, {}, {
|
|
82
81
|
timeout: 3000
|
|
83
82
|
});
|
|
84
|
-
ctx.rpc = rpc;
|
|
85
83
|
const { printUrl = true, mcpPath = '/__mcp' } = options;
|
|
86
84
|
setupRoutes(mcpPath, async ()=>{
|
|
87
85
|
let mcp = createMcpServerDefault(options, ctx);
|