rsbuild-plugin-vue-mcp 0.1.0

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,446 @@
1
+ "use strict";
2
+ const __rslib_import_meta_url__ = /*#__PURE__*/ function() {
3
+ return "u" < typeof document ? new (require('url'.replace('', ''))).URL('file:' + __filename).href : document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href;
4
+ }();
5
+ var __webpack_require__ = {};
6
+ (()=>{
7
+ __webpack_require__.n = (module)=>{
8
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
9
+ __webpack_require__.d(getter, {
10
+ a: getter
11
+ });
12
+ return getter;
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.d = (exports1, getters, values)=>{
17
+ var define = (defs, kind)=>{
18
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
19
+ enumerable: true,
20
+ [kind]: defs[key]
21
+ });
22
+ };
23
+ define(getters, "get");
24
+ define(values, "value");
25
+ };
26
+ })();
27
+ (()=>{
28
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
29
+ })();
30
+ (()=>{
31
+ __webpack_require__.r = (exports1)=>{
32
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
33
+ value: 'Module'
34
+ });
35
+ Object.defineProperty(exports1, '__esModule', {
36
+ value: true
37
+ });
38
+ };
39
+ })();
40
+ var __webpack_exports__ = {};
41
+ __webpack_require__.r(__webpack_exports__);
42
+ __webpack_require__.d(__webpack_exports__, {
43
+ VueMcpPlugin: ()=>VueMcpPlugin
44
+ });
45
+ const external_node_url_namespaceObject = require("node:url");
46
+ const external_node_path_namespaceObject = require("node:path");
47
+ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
48
+ const external_node_fs_namespaceObject = require("node:fs");
49
+ var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
50
+ const external_ws_namespaceObject = require("ws");
51
+ const external_hookable_namespaceObject = require("hookable");
52
+ function createVueMcpContext() {
53
+ return {
54
+ hooks: (0, external_hookable_namespaceObject.createHooks)(),
55
+ rpc: null,
56
+ rpcServer: null
57
+ };
58
+ }
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
+ const external_birpc_namespaceObject = require("birpc");
86
+ const channelCache = new WeakMap();
87
+ function createRPCServer(ws, functions, options = {}) {
88
+ const group = (0, external_birpc_namespaceObject.createBirpcGroup)(functions, ()=>Array.from(ws?.clients || []).map((channel)=>{
89
+ if (channel.readyState === channel.CLOSED) return;
90
+ const cached = channelCache.get(channel);
91
+ if (cached) return cached;
92
+ const options = {
93
+ on: (fn)=>channel.on('message', fn),
94
+ post: (data)=>channel.send(data),
95
+ serialize: (v)=>JSON.stringify(v),
96
+ deserialize: (v)=>JSON.parse(v)
97
+ };
98
+ channelCache.set(channel, options);
99
+ return options;
100
+ }).filter((c)=>!!c), options);
101
+ ws.on('connection', ()=>{
102
+ group.updateChannels();
103
+ });
104
+ return group.broadcast;
105
+ }
106
+ const mcp_js_namespaceObject = require("@modelcontextprotocol/sdk/server/mcp.js");
107
+ var package_namespaceObject = {
108
+ rE: "0.1.0"
109
+ };
110
+ const external_nanoid_namespaceObject = require("nanoid");
111
+ const external_zod_namespaceObject = require("zod");
112
+ function stringify(value) {
113
+ return "string" == typeof value ? value : JSON.stringify(value);
114
+ }
115
+ function createMcpServerDefault(options, ctx) {
116
+ const server = new mcp_js_namespaceObject.McpServer({
117
+ name: "rsbuild-vue-mcp",
118
+ description: 'Rsbuild/Rspack MCP plugin based on Vue DevTools',
119
+ version: package_namespaceObject.rE,
120
+ ...options.mcpServerInfo
121
+ });
122
+ server.registerTool('get-component-tree', {
123
+ description: 'Get the Vue component tree in markdown tree syntax format.'
124
+ }, async ()=>new Promise((resolve, reject)=>{
125
+ const eventName = (0, external_nanoid_namespaceObject.nanoid)();
126
+ ctx.hooks.hookOnce(eventName, (res)=>{
127
+ resolve({
128
+ content: [
129
+ {
130
+ type: 'text',
131
+ text: stringify(res)
132
+ }
133
+ ]
134
+ });
135
+ });
136
+ ctx.rpcServer.getInspectorTree({
137
+ event: eventName
138
+ }).catch((e)=>{
139
+ console.error(e);
140
+ reject(e);
141
+ });
142
+ }));
143
+ server.registerTool('get-component-state', {
144
+ description: 'Get the Vue component state in JSON structure format.',
145
+ inputSchema: {
146
+ componentName: external_zod_namespaceObject.z.string()
147
+ }
148
+ }, async ({ componentName })=>new Promise((resolve, reject)=>{
149
+ const eventName = (0, external_nanoid_namespaceObject.nanoid)();
150
+ ctx.hooks.hookOnce(eventName, (res)=>{
151
+ resolve({
152
+ content: [
153
+ {
154
+ type: 'text',
155
+ text: stringify(res)
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
+ }));
168
+ server.registerTool('edit-component-state', {
169
+ description: 'Edit the Vue component state.',
170
+ inputSchema: {
171
+ componentName: external_zod_namespaceObject.z.string(),
172
+ path: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()),
173
+ value: external_zod_namespaceObject.z.string(),
174
+ valueType: external_zod_namespaceObject.z["enum"]([
175
+ 'string',
176
+ 'number',
177
+ 'boolean',
178
+ 'object',
179
+ 'array'
180
+ ])
181
+ }
182
+ }, async ({ componentName, path, value, valueType })=>new Promise((resolve, reject)=>{
183
+ ctx.rpcServer.editComponentState({
184
+ componentName,
185
+ path,
186
+ value,
187
+ valueType
188
+ }).then(()=>{
189
+ resolve({
190
+ content: [
191
+ {
192
+ type: 'text',
193
+ text: 'ok'
194
+ }
195
+ ]
196
+ });
197
+ }).catch((e)=>{
198
+ console.error(e);
199
+ reject(e);
200
+ });
201
+ }));
202
+ server.registerTool('highlight-component', {
203
+ description: 'Highlight the Vue component.',
204
+ inputSchema: {
205
+ componentName: external_zod_namespaceObject.z.string()
206
+ }
207
+ }, async ({ componentName })=>new Promise((resolve, reject)=>{
208
+ ctx.rpcServer.highlightComponent({
209
+ componentName
210
+ }).then(()=>{
211
+ resolve({
212
+ content: [
213
+ {
214
+ type: 'text',
215
+ text: 'ok'
216
+ }
217
+ ]
218
+ });
219
+ }).catch((e)=>{
220
+ console.error(e);
221
+ reject(e);
222
+ });
223
+ }));
224
+ server.registerTool('get-router-info', {
225
+ description: 'Get the Vue router info in JSON structure format.'
226
+ }, async ()=>new Promise((resolve, reject)=>{
227
+ const eventName = (0, external_nanoid_namespaceObject.nanoid)();
228
+ ctx.hooks.hookOnce(eventName, (res)=>{
229
+ resolve({
230
+ content: [
231
+ {
232
+ type: 'text',
233
+ text: stringify(res)
234
+ }
235
+ ]
236
+ });
237
+ });
238
+ ctx.rpcServer.getRouterInfo({
239
+ event: eventName
240
+ }).catch((e)=>{
241
+ console.error(e);
242
+ reject(e);
243
+ });
244
+ }));
245
+ server.registerTool('get-pinia-state', {
246
+ description: 'Get the Pinia state in JSON structure format.',
247
+ inputSchema: {
248
+ storeName: external_zod_namespaceObject.z.string()
249
+ }
250
+ }, async ({ storeName })=>new Promise((resolve, reject)=>{
251
+ const eventName = (0, external_nanoid_namespaceObject.nanoid)();
252
+ ctx.hooks.hookOnce(eventName, (res)=>{
253
+ resolve({
254
+ content: [
255
+ {
256
+ type: 'text',
257
+ text: stringify(res)
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
+ }));
270
+ server.registerTool('get-pinia-tree', {
271
+ description: 'Get the Pinia tree in JSON structure format.'
272
+ }, async ()=>new Promise((resolve, reject)=>{
273
+ const eventName = (0, external_nanoid_namespaceObject.nanoid)();
274
+ ctx.hooks.hookOnce(eventName, (res)=>{
275
+ resolve({
276
+ content: [
277
+ {
278
+ type: 'text',
279
+ text: stringify(res)
280
+ }
281
+ ]
282
+ });
283
+ });
284
+ ctx.rpcServer.getPiniaTree({
285
+ event: eventName
286
+ }).catch((e)=>{
287
+ console.error(e);
288
+ reject(e);
289
+ });
290
+ }));
291
+ return server;
292
+ }
293
+ const streamableHttp_js_namespaceObject = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
294
+ async function mcpHandlerStateless(server, req, res) {
295
+ try {
296
+ const transport = new streamableHttp_js_namespaceObject.StreamableHTTPServerTransport({
297
+ sessionIdGenerator: void 0
298
+ });
299
+ await server.connect(transport);
300
+ await transport.handleRequest(req, res);
301
+ res.on('close', ()=>{
302
+ transport.close();
303
+ server.close();
304
+ });
305
+ } catch (error) {
306
+ console.error('Error handling MCP request:', error);
307
+ if (!res.headersSent) {
308
+ res.statusCode = 500;
309
+ res.setHeader('content-type', 'application/json');
310
+ res.end(JSON.stringify({
311
+ jsonrpc: '2.0',
312
+ error: {
313
+ code: -32603,
314
+ message: 'Internal server error'
315
+ },
316
+ id: null
317
+ }));
318
+ }
319
+ }
320
+ }
321
+ function setupRspackRoutes(base, getServer, middlewares) {
322
+ middlewares.push({
323
+ name: 'vue-devtools-mcp',
324
+ path: `${base}/mcp`,
325
+ async middleware (req, res) {
326
+ const server = await getServer();
327
+ await mcpHandlerStateless(server, req, res);
328
+ }
329
+ });
330
+ }
331
+ function _define_property(obj, key, value) {
332
+ if (key in obj) Object.defineProperty(obj, key, {
333
+ value: value,
334
+ enumerable: true,
335
+ configurable: true,
336
+ writable: true
337
+ });
338
+ else obj[key] = value;
339
+ return obj;
340
+ }
341
+ function getVueMcpPath() {
342
+ const pluginPath = external_node_path_default().dirname((0, external_node_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
343
+ return pluginPath.replaceAll('\\', '/');
344
+ }
345
+ function getOverlayBootstrapPath() {
346
+ const fileUrl = new URL('./overlay-bootstrap.js', __rslib_import_meta_url__);
347
+ return (0, external_node_url_namespaceObject.fileURLToPath)(fileUrl).replaceAll('\\', '/').replace('/src/', '/dist/');
348
+ }
349
+ const PLUGIN_NAME = "VueMcpPlugin";
350
+ class VueMcpPlugin {
351
+ applyInspector(compiler) {}
352
+ applyHtmlInjection(compiler) {
353
+ compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
354
+ const hooks = compiler.rspack.HtmlRspackPlugin.getCompilationHooks(compilation);
355
+ if (!hooks.alterAssetTags) return;
356
+ hooks.alterAssetTags.tap(PLUGIN_NAME, (data)=>{
357
+ const overlayPath = getOverlayBootstrapPath();
358
+ try {
359
+ const js = external_node_fs_default().readFileSync(overlayPath, {
360
+ encoding: 'utf8'
361
+ });
362
+ data.assetTags.scripts.push({
363
+ tagName: "script",
364
+ voidTag: false,
365
+ attributes: {
366
+ id: 'overlay-bootstrap.js'
367
+ },
368
+ innerHTML: js
369
+ });
370
+ console.log(' ➜ VueDevtools MCP: injection html => overlay-bootstrap.js');
371
+ } catch (e) {}
372
+ return data;
373
+ });
374
+ });
375
+ }
376
+ apply(compiler) {
377
+ if ('production' === compiler.options.mode) return;
378
+ const ctx = createVueMcpContext();
379
+ getVueMcpPath();
380
+ const wsPath = '/__vue-devtools-mcp-ws';
381
+ this.applyInspector(compiler);
382
+ this.applyHtmlInjection(compiler);
383
+ compiler.hooks.environment.tap(PLUGIN_NAME, ()=>{
384
+ if (false === compiler.options.devServer) return;
385
+ compiler.options.devServer ??= {};
386
+ const rawSetupMiddlewares = compiler.options.devServer.setupMiddlewares;
387
+ compiler.options.devServer.setupMiddlewares = (middlewares, devServer)=>{
388
+ if ('function' == typeof rawSetupMiddlewares) middlewares = rawSetupMiddlewares.call(compiler.options.devServer, middlewares, devServer);
389
+ if (!devServer) {
390
+ console.warn('❌ rspack-dev-server is not defined here.');
391
+ return middlewares;
392
+ }
393
+ const httpServer = devServer.server;
394
+ if (!httpServer) {
395
+ console.error('❌ [vue-devtools-mcp] no rspack devServer.server, require @rspack/core >= 1.3');
396
+ return middlewares;
397
+ }
398
+ const wss = new external_ws_namespaceObject.WebSocketServer({
399
+ noServer: true
400
+ });
401
+ wss.on('connection', ()=>{
402
+ console.debug('✅ Client connected to vue-devtools-mcp WebSocket!');
403
+ });
404
+ httpServer.on('upgrade', (request, socket, head)=>{
405
+ const { pathname } = new URL(request.url || '', 'wss://base.url');
406
+ if (pathname !== wsPath) return;
407
+ wss.handleUpgrade(request, socket, head, (client)=>{
408
+ wss.emit('connection', client, request);
409
+ });
410
+ });
411
+ const rpc = createServerRpcFunc(ctx);
412
+ ctx.rpcServer = createRPCServer(wss, rpc, {
413
+ timeout: 3000
414
+ });
415
+ ctx.rpc = rpc;
416
+ const { printUrl = true, mcpPath = '/__mcp' } = this.options;
417
+ setupRspackRoutes(mcpPath, async ()=>{
418
+ let mcp = createMcpServerDefault(this.options, ctx);
419
+ mcp = await this.options.mcpServerSetup?.(mcp, compiler) || mcp;
420
+ return mcp;
421
+ }, middlewares);
422
+ if (printUrl) {
423
+ const port = (compiler.options.devServer || {}).port || 8080;
424
+ const mcpUrl = `http://localhost:${port}${mcpPath}/mcp`;
425
+ setTimeout(()=>{
426
+ if (devServer.logger?.info) devServer.logger.info(` ➜ MCP: Server is running at ${mcpUrl}`);
427
+ else console.log(` ➜ MCP: Server is running at ${mcpUrl}`);
428
+ }, 300);
429
+ }
430
+ return middlewares;
431
+ };
432
+ });
433
+ }
434
+ constructor(options = {}){
435
+ _define_property(this, "name", PLUGIN_NAME);
436
+ _define_property(this, "options", void 0);
437
+ this.options = options;
438
+ }
439
+ }
440
+ exports.VueMcpPlugin = __webpack_exports__.VueMcpPlugin;
441
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
442
+ "VueMcpPlugin"
443
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
444
+ Object.defineProperty(exports, '__esModule', {
445
+ value: true
446
+ });
package/dist/rspack.js ADDED
@@ -0,0 +1,115 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import node_path from "node:path";
3
+ import node_fs from "node:fs";
4
+ import { WebSocketServer } from "ws";
5
+ import { createMcpServerDefault, createVueMcpContext, createRPCServer, createServerRpcFunc, setupRspackRoutes } from "./551.js";
6
+ function _define_property(obj, key, value) {
7
+ if (key in obj) Object.defineProperty(obj, key, {
8
+ value: value,
9
+ enumerable: true,
10
+ configurable: true,
11
+ writable: true
12
+ });
13
+ else obj[key] = value;
14
+ return obj;
15
+ }
16
+ function getVueMcpPath() {
17
+ const pluginPath = node_path.dirname(fileURLToPath(import.meta.url));
18
+ return pluginPath.replaceAll('\\', '/');
19
+ }
20
+ function getOverlayBootstrapPath() {
21
+ const fileUrl = new URL('./overlay-bootstrap.js', import.meta.url);
22
+ return fileURLToPath(fileUrl).replaceAll('\\', '/').replace('/src/', '/dist/');
23
+ }
24
+ const PLUGIN_NAME = "VueMcpPlugin";
25
+ class VueMcpPlugin {
26
+ applyInspector(compiler) {}
27
+ applyHtmlInjection(compiler) {
28
+ compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
29
+ const hooks = compiler.rspack.HtmlRspackPlugin.getCompilationHooks(compilation);
30
+ if (!hooks.alterAssetTags) return;
31
+ hooks.alterAssetTags.tap(PLUGIN_NAME, (data)=>{
32
+ const overlayPath = getOverlayBootstrapPath();
33
+ try {
34
+ const js = node_fs.readFileSync(overlayPath, {
35
+ encoding: 'utf8'
36
+ });
37
+ data.assetTags.scripts.push({
38
+ tagName: "script",
39
+ voidTag: false,
40
+ attributes: {
41
+ id: 'overlay-bootstrap.js'
42
+ },
43
+ innerHTML: js
44
+ });
45
+ console.log(' ➜ VueDevtools MCP: injection html => overlay-bootstrap.js');
46
+ } catch (e) {}
47
+ return data;
48
+ });
49
+ });
50
+ }
51
+ apply(compiler) {
52
+ if ('production' === compiler.options.mode) return;
53
+ const ctx = createVueMcpContext();
54
+ getVueMcpPath();
55
+ const wsPath = '/__vue-devtools-mcp-ws';
56
+ this.applyInspector(compiler);
57
+ this.applyHtmlInjection(compiler);
58
+ compiler.hooks.environment.tap(PLUGIN_NAME, ()=>{
59
+ if (false === compiler.options.devServer) return;
60
+ compiler.options.devServer ??= {};
61
+ const rawSetupMiddlewares = compiler.options.devServer.setupMiddlewares;
62
+ compiler.options.devServer.setupMiddlewares = (middlewares, devServer)=>{
63
+ if ('function' == typeof rawSetupMiddlewares) middlewares = rawSetupMiddlewares.call(compiler.options.devServer, middlewares, devServer);
64
+ if (!devServer) {
65
+ console.warn('❌ rspack-dev-server is not defined here.');
66
+ return middlewares;
67
+ }
68
+ const httpServer = devServer.server;
69
+ if (!httpServer) {
70
+ console.error('❌ [vue-devtools-mcp] no rspack devServer.server, require @rspack/core >= 1.3');
71
+ return middlewares;
72
+ }
73
+ const wss = new WebSocketServer({
74
+ noServer: true
75
+ });
76
+ wss.on('connection', ()=>{
77
+ console.debug('✅ Client connected to vue-devtools-mcp WebSocket!');
78
+ });
79
+ httpServer.on('upgrade', (request, socket, head)=>{
80
+ const { pathname } = new URL(request.url || '', 'wss://base.url');
81
+ if (pathname !== wsPath) return;
82
+ wss.handleUpgrade(request, socket, head, (client)=>{
83
+ wss.emit('connection', client, request);
84
+ });
85
+ });
86
+ const rpc = createServerRpcFunc(ctx);
87
+ ctx.rpcServer = createRPCServer(wss, rpc, {
88
+ timeout: 3000
89
+ });
90
+ ctx.rpc = rpc;
91
+ const { printUrl = true, mcpPath = '/__mcp' } = this.options;
92
+ setupRspackRoutes(mcpPath, async ()=>{
93
+ let mcp = createMcpServerDefault(this.options, ctx);
94
+ mcp = await this.options.mcpServerSetup?.(mcp, compiler) || mcp;
95
+ return mcp;
96
+ }, middlewares);
97
+ if (printUrl) {
98
+ const port = (compiler.options.devServer || {}).port || 8080;
99
+ const mcpUrl = `http://localhost:${port}${mcpPath}/mcp`;
100
+ setTimeout(()=>{
101
+ if (devServer.logger?.info) devServer.logger.info(` ➜ MCP: Server is running at ${mcpUrl}`);
102
+ else console.log(` ➜ MCP: Server is running at ${mcpUrl}`);
103
+ }, 300);
104
+ }
105
+ return middlewares;
106
+ };
107
+ });
108
+ }
109
+ constructor(options = {}){
110
+ _define_property(this, "name", PLUGIN_NAME);
111
+ _define_property(this, "options", void 0);
112
+ this.options = options;
113
+ }
114
+ }
115
+ export { VueMcpPlugin };
@@ -0,0 +1,3 @@
1
+ import type { BirpcGroupReturn, EventOptions } from "birpc";
2
+ import type { WebSocketServer } from "ws";
3
+ export declare function createRPCServer<ClientFunction, ServerFunctions extends object>(ws: WebSocketServer, functions: ServerFunctions, options?: EventOptions<ClientFunction, ServerFunctions>): BirpcGroupReturn<ClientFunction>;
@@ -0,0 +1,3 @@
1
+ import type { RsbuildPlugin, RsbuildPluginAPI } from "@rsbuild/core";
2
+ import type { PluginVueMcpOptions } from "./types.ts";
3
+ export declare const pluginVueMcp: (options?: PluginVueMcpOptions<RsbuildPluginAPI>) => RsbuildPlugin;
@@ -0,0 +1,5 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { RsbuildDevServer } from "@rsbuild/core";
3
+ import type { DevServerMiddleware } from "@rspack/core";
4
+ export declare function setupRoutes<DEV extends RsbuildDevServer>(base: string, getServer: () => Promise<McpServer>, dev: DEV): void;
5
+ export declare function setupRspackRoutes(base: string, getServer: () => Promise<McpServer>, middlewares: DevServerMiddleware[]): void;
@@ -0,0 +1,2 @@
1
+ import type { VueMcpContext } from "../types.ts";
2
+ export declare function createVueMcpContext(): VueMcpContext;
@@ -0,0 +1,2 @@
1
+ import type { RpcFunctions, VueMcpContext } from "../types.ts";
2
+ export declare function createServerRpcFunc(ctx: VueMcpContext): RpcFunctions;
@@ -0,0 +1,5 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { PluginVueMcpOptions, VueMcpContext } from "../types.ts";
3
+ import type { RsbuildPluginAPI } from "@rsbuild/core";
4
+ import type { Compiler as RspackCompiler } from "@rspack/core";
5
+ export declare function createMcpServerDefault<DEV extends RsbuildPluginAPI | RspackCompiler>(options: PluginVueMcpOptions<DEV>, ctx: VueMcpContext): McpServer;
@@ -0,0 +1,10 @@
1
+ import type { Compiler, RspackPluginInstance } from "@rspack/core";
2
+ import type { PluginVueMcpOptions } from "./types.ts";
3
+ export declare class VueMcpPlugin implements RspackPluginInstance {
4
+ readonly name = "VueMcpPlugin";
5
+ private readonly options;
6
+ constructor(options?: PluginVueMcpOptions<Compiler>);
7
+ private applyInspector;
8
+ private applyHtmlInjection;
9
+ apply(compiler: Compiler): void;
10
+ }
@@ -0,0 +1,77 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { Implementation as McpServerInfo } from '@modelcontextprotocol/sdk/types.js';
3
+ import type { Hookable } from "hookable";
4
+ import type { BirpcGroupReturn } from "birpc";
5
+ export type Awaitable<T> = T | Promise<T>;
6
+ export interface RpcFunctions {
7
+ getInspectorTree: (options: {
8
+ event: string;
9
+ componentName?: string;
10
+ }) => void;
11
+ onInspectorTreeUpdated: (event: string, data: string) => void;
12
+ getInspectorState: (options: {
13
+ event: string;
14
+ componentName: string;
15
+ }) => void;
16
+ onInspectorStateUpdated: (event: string, data: string) => void;
17
+ editComponentState: (options: {
18
+ componentName: string;
19
+ path: string[];
20
+ value: string;
21
+ valueType: string;
22
+ }) => void;
23
+ highlightComponent: (options: {
24
+ componentName: string;
25
+ }) => void;
26
+ getRouterInfo: (options: {
27
+ event: string;
28
+ }) => void;
29
+ onRouterInfoUpdated: (event: string, data: string) => void;
30
+ getPiniaState: (options: {
31
+ event: string;
32
+ storeName: string;
33
+ }) => void;
34
+ onPiniaInfoUpdated: (event: string, data: string) => void;
35
+ getPiniaTree: (options: {
36
+ event: string;
37
+ }) => void;
38
+ onPiniaTreeUpdated: (event: string, data: string) => void;
39
+ }
40
+ export interface VueMcpContext {
41
+ hooks: Hookable;
42
+ rpc: RpcFunctions;
43
+ rpcServer: BirpcGroupReturn<RpcFunctions>;
44
+ }
45
+ export interface PluginVueMcpOptions<DEV> {
46
+ /**
47
+ * The host to listen on, default is `localhost`
48
+ */
49
+ host?: string;
50
+ /**
51
+ * Print the MCP server URL in the console
52
+ *
53
+ * @default true
54
+ */
55
+ printUrl?: boolean;
56
+ /**
57
+ * The MCP server info. Ingored when `mcpServer` is provided
58
+ */
59
+ mcpServerInfo?: McpServerInfo;
60
+ /**
61
+ * Setup the MCP server, this is called when the MCP server is created
62
+ * You may also return a new MCP server to replace the default one
63
+ */
64
+ mcpServerSetup?: (server: McpServer, api: DEV) => Awaitable<void | McpServer>;
65
+ /**
66
+ * The path to the MCP server, default is `/__mcp`
67
+ */
68
+ mcpPath?: string;
69
+ /**
70
+ * append an import to the module id ending with `appendTo` instead of adding a script into body
71
+ * useful for projects that do not use html file as an entry
72
+ *
73
+ * WARNING: only set this if you know exactly what it does.
74
+ * @default ''
75
+ */
76
+ appendTo?: string | RegExp;
77
+ }