vite-plugin-swagger-mcp 0.0.17 → 0.0.20

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.
@@ -1,5 +1,6 @@
1
1
  import type { Plugin } from "vite";
2
2
  import { SchemaObject } from "./type";
3
+ export declare const isInitializeRequest: (value: unknown) => boolean;
3
4
  export declare class SwaggerMcpServer {
4
5
  private swaggerUrl;
5
6
  private token?;
@@ -42,7 +43,7 @@ export declare class SwaggerMcpServer {
42
43
  method: string;
43
44
  }>;
44
45
  }
45
- export default function vitePluginSwaggerMcp(options: {
46
+ export default function vitePluginSwaggerMcp({ swaggerUrl, token, }: {
46
47
  swaggerUrl: string;
47
48
  token?: string;
48
49
  }): Plugin;
package/dist/cjs/index.js CHANGED
@@ -1,8 +1,6 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
4
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
5
  var __export = (target, all) => {
8
6
  for (var name in all)
@@ -16,28 +14,28 @@ var __copyProps = (to, from, except, desc) => {
16
14
  }
17
15
  return to;
18
16
  };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
18
 
29
19
  // src/index.ts
30
20
  var src_exports = {};
31
21
  __export(src_exports, {
32
22
  SwaggerMcpServer: () => SwaggerMcpServer,
33
- default: () => vitePluginSwaggerMcp
23
+ default: () => vitePluginSwaggerMcp,
24
+ isInitializeRequest: () => isInitializeRequest
34
25
  });
35
26
  module.exports = __toCommonJS(src_exports);
36
27
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
37
- var import_node_crypto = require("node:crypto");
38
- var z = __toESM(require("zod"));
39
- var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp");
28
+ var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
40
29
  var import_types = require("@modelcontextprotocol/sdk/types");
30
+ var import_node_crypto = require("node:crypto");
31
+ var import_v4 = require("zod/v4");
32
+ async function readJsonBody(req) {
33
+ let body = "";
34
+ for await (const chunk of req)
35
+ body += chunk;
36
+ return JSON.parse(body || "{}");
37
+ }
38
+ var isInitializeRequest = (value) => import_types.InitializeRequestParamsSchema.safeParse(value).success;
41
39
  var SwaggerMcpServer = class {
42
40
  constructor(swaggerUrl, token) {
43
41
  this.swaggerUrl = swaggerUrl;
@@ -145,122 +143,105 @@ var SwaggerMcpServer = class {
145
143
  };
146
144
  }
147
145
  };
148
- function vitePluginSwaggerMcp(options) {
149
- const transports = {};
146
+ var transports = {};
147
+ function vitePluginSwaggerMcp({
148
+ swaggerUrl,
149
+ token
150
+ }) {
150
151
  return {
151
152
  name: "vite-plugin-swagger-mcp",
152
- configureServer(vite) {
153
- var _a;
154
- const swaggerServer = new SwaggerMcpServer(
155
- options.swaggerUrl,
156
- options.token
157
- );
158
- const createMcpServer = () => {
159
- const server = new import_mcp.McpServer({
153
+ enforce: "pre",
154
+ async configureServer(server) {
155
+ var _a, _b;
156
+ const swaggerServer = new SwaggerMcpServer(swaggerUrl, token);
157
+ const createNewServer = () => {
158
+ const mcpServer = new import_mcp.McpServer({
160
159
  name: "swagger-mcp-server",
161
160
  version: "0.1.0"
162
161
  });
163
- server.tool("getModules", "获取模块列表", async () => {
162
+ mcpServer.tool("getModules", "获取模块列表", async () => {
164
163
  const res = await swaggerServer.getModules();
165
- return {
166
- content: [
167
- {
168
- type: "text",
169
- text: JSON.stringify(res)
170
- }
171
- ]
172
- };
164
+ return { content: [{ type: "text", text: JSON.stringify(res) }] };
173
165
  });
174
- server.tool(
166
+ mcpServer.tool(
167
+ "getModuleApis",
168
+ "获取特定模块下的所有接口",
169
+ { module: import_v4.z.string().describe("模块名称") },
170
+ async ({ module: module2 }) => {
171
+ const res = await swaggerServer.getModuleApis(module2);
172
+ return { content: [{ type: "text", text: JSON.stringify(res) }] };
173
+ }
174
+ );
175
+ mcpServer.tool(
175
176
  "getApiTypes",
176
177
  "获取特定接口的参数及返回值类型",
177
- { path: z.string(), method: z.string() },
178
+ { path: import_v4.z.string(), method: import_v4.z.string() },
178
179
  async (args) => ({
179
- content: [
180
- {
181
- type: "text",
182
- text: JSON.stringify(
183
- await swaggerServer.getApiTypes(args.path, args.method)
184
- )
185
- }
186
- ]
180
+ content: [{ type: "text", text: JSON.stringify(await swaggerServer.getApiTypes(args.path, args.method)) }]
187
181
  })
188
182
  );
189
- server.registerTool(
190
- "getApiTypes",
191
- {
192
- description: "获取接口类型定义",
193
- inputSchema: {
194
- path: z.string(),
195
- method: z.string()
196
- }
197
- },
198
- async ({ path, method }) => ({
199
- content: [
200
- {
201
- type: "text",
202
- text: JSON.stringify(await swaggerServer.getApiTypes(path, method))
203
- }
204
- ]
205
- })
206
- );
207
- return server;
183
+ return mcpServer;
208
184
  };
209
- vite.middlewares.use("/_mcp/swagger", async (req, res) => {
210
- const sessionId = req.headers["mcp-session-id"];
211
- if (req.method === "POST") {
212
- let body = "";
213
- for await (const chunk of req)
214
- body += chunk;
215
- const json = JSON.parse(body);
216
- try {
185
+ const ENDPOINT = "/_mcp/sse/swagger";
186
+ server.middlewares.use(ENDPOINT, async (req, res, next) => {
187
+ try {
188
+ const url = new URL(req.url || "", `http://${req.headers.host}`);
189
+ const sessionId = req.headers["mcp-session-id"] || url.searchParams.get("sessionId");
190
+ if (req.method === "POST") {
191
+ const json = await readJsonBody(req);
217
192
  let transport;
218
193
  if (sessionId && transports[sessionId]) {
219
194
  transport = transports[sessionId];
220
- } else if (!sessionId && (0, import_types.isInitializeRequest)(json)) {
195
+ } else if (!sessionId && isInitializeRequest(json)) {
221
196
  transport = new import_streamableHttp.StreamableHTTPServerTransport({
222
197
  sessionIdGenerator: () => (0, import_node_crypto.randomUUID)(),
223
- onsessioninitialized(id) {
224
- transports[id] = transport;
198
+ // 如果你的编辑器不支持 SSE 只能接收 JSON 响应,可以设为 true
199
+ // 但大多数现代编辑器建议保持默认(false)以支持标准流
200
+ enableJsonResponse: false,
201
+ onsessioninitialized: (sid) => {
202
+ transports[sid] = transport;
203
+ console.log(`[MCP] Session initialized: ${sid}`);
225
204
  }
226
205
  });
227
206
  transport.onclose = () => {
228
- if (transport.sessionId) {
207
+ if (transport.sessionId)
229
208
  delete transports[transport.sessionId];
230
- }
209
+ console.log(`[MCP] Session closed: ${transport.sessionId}`);
231
210
  };
232
- const mcpServer = createMcpServer();
211
+ const mcpServer = createNewServer();
233
212
  await mcpServer.connect(transport);
234
213
  } else {
235
214
  res.statusCode = 400;
236
- return res.end("Bad Request");
215
+ return res.end(JSON.stringify({ error: "Invalid session or not an initialize request" }));
237
216
  }
238
217
  await transport.handleRequest(req, res, json);
239
- } catch (err) {
240
- console.error(err);
241
- res.statusCode = 500;
242
- res.end("Internal Error");
218
+ return;
243
219
  }
244
- return;
245
- }
246
- if (req.method === "GET") {
247
- if (!sessionId || !transports[sessionId]) {
248
- res.statusCode = 400;
249
- return res.end("Missing session");
220
+ if (req.method === "GET") {
221
+ if (!sessionId || !transports[sessionId]) {
222
+ const initTransport = new import_streamableHttp.StreamableHTTPServerTransport();
223
+ await initTransport.handleRequest(req, res);
224
+ return;
225
+ }
226
+ await transports[sessionId].handleRequest(req, res);
227
+ return;
228
+ }
229
+ res.statusCode = 405;
230
+ res.end("Method Not Allowed");
231
+ } catch (error) {
232
+ console.error("[MCP Error]", error);
233
+ if (!res.headersSent) {
234
+ res.statusCode = 500;
235
+ res.end("Internal Server Error");
250
236
  }
251
- await transports[sessionId].handleRequest(req, res);
252
- return;
253
237
  }
254
- res.statusCode = 405;
255
- res.end();
256
238
  });
257
- console.log(
258
- `Swagger MCP ready: http://localhost:${(_a = vite.config.server) == null ? void 0 : _a.port}/_mcp/swagger`
259
- );
239
+ console.log(`✅ MCP Swagger Server mounted at http://localhost:${(_b = (_a = server.config) == null ? void 0 : _a.server) == null ? void 0 : _b.port}${ENDPOINT}`);
260
240
  }
261
241
  };
262
242
  }
263
243
  // Annotate the CommonJS export names for ESM import in node:
264
244
  0 && (module.exports = {
265
- SwaggerMcpServer
245
+ SwaggerMcpServer,
246
+ isInitializeRequest
266
247
  });
@@ -1,5 +1,6 @@
1
1
  import type { Plugin } from "vite";
2
2
  import { SchemaObject } from "./type";
3
+ export declare const isInitializeRequest: (value: unknown) => boolean;
3
4
  export declare class SwaggerMcpServer {
4
5
  private swaggerUrl;
5
6
  private token?;
@@ -42,7 +43,7 @@ export declare class SwaggerMcpServer {
42
43
  method: string;
43
44
  }>;
44
45
  }
45
- export default function vitePluginSwaggerMcp(options: {
46
+ export default function vitePluginSwaggerMcp({ swaggerUrl, token, }: {
46
47
  swaggerUrl: string;
47
48
  token?: string;
48
49
  }): Plugin;
package/dist/esm/index.js CHANGED
@@ -2,24 +2,91 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
5
- function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
6
- function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
7
5
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8
6
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
9
7
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
10
8
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
9
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
12
10
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
11
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
12
+ function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
13
13
  function _asyncIterator(r) { var n, t, o, e = 2; for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) { if (t && null != (n = r[t])) return n.call(r); if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r)); t = "@@asyncIterator", o = "@@iterator"; } throw new TypeError("Object is not async iterable"); }
14
14
  function AsyncFromSyncIterator(r) { function AsyncFromSyncIteratorContinuation(r) { if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object.")); var n = r.done; return Promise.resolve(r.value).then(function (r) { return { value: r, done: n }; }); } return AsyncFromSyncIterator = function AsyncFromSyncIterator(r) { this.s = r, this.n = r.next; }, AsyncFromSyncIterator.prototype = { s: null, n: null, next: function next() { return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); }, return: function _return(r) { var n = this.s.return; return void 0 === n ? Promise.resolve({ value: r, done: !0 }) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); }, throw: function _throw(r) { var n = this.s.return; return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); } }, new AsyncFromSyncIterator(r); }
15
15
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
16
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
17
+ import { InitializeRequestParamsSchema } from "@modelcontextprotocol/sdk/types";
16
18
  import { randomUUID } from "node:crypto";
17
- import * as z from "zod";
18
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp";
19
- import { isInitializeRequest } from "@modelcontextprotocol/sdk/types";
20
- /* =========================
21
- * Swagger MCP Server
22
- * ========================= */
19
+ import { z } from "zod/v4";
20
+ // --- 辅助函数:解析 JSON Body ---
21
+ function readJsonBody(_x) {
22
+ return _readJsonBody.apply(this, arguments);
23
+ }
24
+ function _readJsonBody() {
25
+ _readJsonBody = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10(req) {
26
+ var body, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, chunk;
27
+ return _regeneratorRuntime().wrap(function _callee10$(_context10) {
28
+ while (1) switch (_context10.prev = _context10.next) {
29
+ case 0:
30
+ body = "";
31
+ _iteratorAbruptCompletion = false;
32
+ _didIteratorError = false;
33
+ _context10.prev = 3;
34
+ _iterator = _asyncIterator(req);
35
+ case 5:
36
+ _context10.next = 7;
37
+ return _iterator.next();
38
+ case 7:
39
+ if (!(_iteratorAbruptCompletion = !(_step = _context10.sent).done)) {
40
+ _context10.next = 13;
41
+ break;
42
+ }
43
+ chunk = _step.value;
44
+ body += chunk;
45
+ case 10:
46
+ _iteratorAbruptCompletion = false;
47
+ _context10.next = 5;
48
+ break;
49
+ case 13:
50
+ _context10.next = 19;
51
+ break;
52
+ case 15:
53
+ _context10.prev = 15;
54
+ _context10.t0 = _context10["catch"](3);
55
+ _didIteratorError = true;
56
+ _iteratorError = _context10.t0;
57
+ case 19:
58
+ _context10.prev = 19;
59
+ _context10.prev = 20;
60
+ if (!(_iteratorAbruptCompletion && _iterator.return != null)) {
61
+ _context10.next = 24;
62
+ break;
63
+ }
64
+ _context10.next = 24;
65
+ return _iterator.return();
66
+ case 24:
67
+ _context10.prev = 24;
68
+ if (!_didIteratorError) {
69
+ _context10.next = 27;
70
+ break;
71
+ }
72
+ throw _iteratorError;
73
+ case 27:
74
+ return _context10.finish(24);
75
+ case 28:
76
+ return _context10.finish(19);
77
+ case 29:
78
+ return _context10.abrupt("return", JSON.parse(body || "{}"));
79
+ case 30:
80
+ case "end":
81
+ return _context10.stop();
82
+ }
83
+ }, _callee10, null, [[3, 15, 19, 29], [20,, 24, 28]]);
84
+ }));
85
+ return _readJsonBody.apply(this, arguments);
86
+ }
87
+ export var isInitializeRequest = function isInitializeRequest(value) {
88
+ return InitializeRequestParamsSchema.safeParse(value).success;
89
+ };
23
90
  export var SwaggerMcpServer = /*#__PURE__*/function () {
24
91
  function SwaggerMcpServer(swaggerUrl, token) {
25
92
  _classCallCheck(this, SwaggerMcpServer);
@@ -184,7 +251,7 @@ export var SwaggerMcpServer = /*#__PURE__*/function () {
184
251
  }
185
252
  }, _callee3, this);
186
253
  }));
187
- function getModuleApis(_x) {
254
+ function getModuleApis(_x2) {
188
255
  return _getModuleApis.apply(this, arguments);
189
256
  }
190
257
  return getModuleApis;
@@ -223,7 +290,7 @@ export var SwaggerMcpServer = /*#__PURE__*/function () {
223
290
  }
224
291
  }, _callee4, this);
225
292
  }));
226
- function getApiTypes(_x2, _x3) {
293
+ function getApiTypes(_x3, _x4) {
227
294
  return _getApiTypes.apply(this, arguments);
228
295
  }
229
296
  return getApiTypes;
@@ -232,269 +299,229 @@ export var SwaggerMcpServer = /*#__PURE__*/function () {
232
299
  return SwaggerMcpServer;
233
300
  }();
234
301
 
235
- /* =========================
236
- * Vite Plugin
237
- * ========================= */
238
-
239
- export default function vitePluginSwaggerMcp(options) {
240
- var transports = {};
302
+ // 存储会话 ID 对应的 Transport 实例
303
+ var transports = {};
304
+ export default function vitePluginSwaggerMcp(_ref) {
305
+ var swaggerUrl = _ref.swaggerUrl,
306
+ token = _ref.token;
241
307
  return {
242
308
  name: "vite-plugin-swagger-mcp",
243
- configureServer: function configureServer(vite) {
244
- var _vite$config$server;
245
- var swaggerServer = new SwaggerMcpServer(options.swaggerUrl, options.token);
246
-
247
- /** 创建 MCP Server(每个 session 共享一个 definition) */
248
- var createMcpServer = function createMcpServer() {
249
- var server = new McpServer({
250
- name: "swagger-mcp-server",
251
- version: "0.1.0"
252
- });
253
-
254
- /***
255
- * 获取模块列表
256
- */
257
- server.tool("getModules", "获取模块列表", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
258
- var res;
259
- return _regeneratorRuntime().wrap(function _callee5$(_context5) {
260
- while (1) switch (_context5.prev = _context5.next) {
261
- case 0:
262
- _context5.next = 2;
263
- return swaggerServer.getModules();
264
- case 2:
265
- res = _context5.sent;
266
- return _context5.abrupt("return", {
267
- content: [{
268
- type: "text",
269
- text: JSON.stringify(res)
270
- }]
309
+ enforce: "pre",
310
+ configureServer: function configureServer(server) {
311
+ return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9() {
312
+ var _server$config;
313
+ var swaggerServer, createNewServer, ENDPOINT;
314
+ return _regeneratorRuntime().wrap(function _callee9$(_context9) {
315
+ while (1) switch (_context9.prev = _context9.next) {
316
+ case 0:
317
+ swaggerServer = new SwaggerMcpServer(swaggerUrl, token); // --- 辅助函数:创建并配置一个新的 MCP Server 实例 ---
318
+ createNewServer = function createNewServer() {
319
+ var mcpServer = new McpServer({
320
+ name: "swagger-mcp-server",
321
+ version: "0.1.0"
271
322
  });
272
- case 4:
273
- case "end":
274
- return _context5.stop();
275
- }
276
- }, _callee5);
277
- })));
278
323
 
279
- /***
280
- * 获取特定接口的参数及返回值类型
281
- */
282
- server.tool("getApiTypes", "获取特定接口的参数及返回值类型", {
283
- path: z.string(),
284
- method: z.string()
285
- }, /*#__PURE__*/function () {
286
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(args) {
287
- return _regeneratorRuntime().wrap(function _callee6$(_context6) {
288
- while (1) switch (_context6.prev = _context6.next) {
289
- case 0:
290
- _context6.t0 = JSON;
291
- _context6.next = 3;
292
- return swaggerServer.getApiTypes(args.path, args.method);
293
- case 3:
294
- _context6.t1 = _context6.sent;
295
- _context6.t2 = _context6.t0.stringify.call(_context6.t0, _context6.t1);
296
- _context6.t3 = {
297
- type: "text",
298
- text: _context6.t2
324
+ // 注册所有工具
325
+ mcpServer.tool("getModules", "获取模块列表", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
326
+ var res;
327
+ return _regeneratorRuntime().wrap(function _callee5$(_context5) {
328
+ while (1) switch (_context5.prev = _context5.next) {
329
+ case 0:
330
+ _context5.next = 2;
331
+ return swaggerServer.getModules();
332
+ case 2:
333
+ res = _context5.sent;
334
+ return _context5.abrupt("return", {
335
+ content: [{
336
+ type: "text",
337
+ text: JSON.stringify(res)
338
+ }]
339
+ });
340
+ case 4:
341
+ case "end":
342
+ return _context5.stop();
343
+ }
344
+ }, _callee5);
345
+ })));
346
+ mcpServer.tool("getModuleApis", "获取特定模块下的所有接口", {
347
+ module: z.string().describe("模块名称")
348
+ }, /*#__PURE__*/function () {
349
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(_ref3) {
350
+ var module, res;
351
+ return _regeneratorRuntime().wrap(function _callee6$(_context6) {
352
+ while (1) switch (_context6.prev = _context6.next) {
353
+ case 0:
354
+ module = _ref3.module;
355
+ _context6.next = 3;
356
+ return swaggerServer.getModuleApis(module);
357
+ case 3:
358
+ res = _context6.sent;
359
+ return _context6.abrupt("return", {
360
+ content: [{
361
+ type: "text",
362
+ text: JSON.stringify(res)
363
+ }]
364
+ });
365
+ case 5:
366
+ case "end":
367
+ return _context6.stop();
368
+ }
369
+ }, _callee6);
370
+ }));
371
+ return function (_x5) {
372
+ return _ref4.apply(this, arguments);
299
373
  };
300
- _context6.t4 = [_context6.t3];
301
- return _context6.abrupt("return", {
302
- content: _context6.t4
303
- });
304
- case 8:
305
- case "end":
306
- return _context6.stop();
307
- }
308
- }, _callee6);
309
- }));
310
- return function (_x4) {
311
- return _ref2.apply(this, arguments);
312
- };
313
- }());
314
- server.registerTool("getApiTypes", {
315
- description: "获取接口类型定义",
316
- inputSchema: {
317
- path: z.string(),
318
- method: z.string()
319
- }
320
- }, /*#__PURE__*/function () {
321
- var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(_ref3) {
322
- var path, method;
323
- return _regeneratorRuntime().wrap(function _callee7$(_context7) {
324
- while (1) switch (_context7.prev = _context7.next) {
325
- case 0:
326
- path = _ref3.path, method = _ref3.method;
327
- _context7.t0 = JSON;
328
- _context7.next = 4;
329
- return swaggerServer.getApiTypes(path, method);
330
- case 4:
331
- _context7.t1 = _context7.sent;
332
- _context7.t2 = _context7.t0.stringify.call(_context7.t0, _context7.t1);
333
- _context7.t3 = {
334
- type: "text",
335
- text: _context7.t2
374
+ }());
375
+ mcpServer.tool("getApiTypes", "获取特定接口的参数及返回值类型", {
376
+ path: z.string(),
377
+ method: z.string()
378
+ }, /*#__PURE__*/function () {
379
+ var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(args) {
380
+ return _regeneratorRuntime().wrap(function _callee7$(_context7) {
381
+ while (1) switch (_context7.prev = _context7.next) {
382
+ case 0:
383
+ _context7.t0 = JSON;
384
+ _context7.next = 3;
385
+ return swaggerServer.getApiTypes(args.path, args.method);
386
+ case 3:
387
+ _context7.t1 = _context7.sent;
388
+ _context7.t2 = _context7.t0.stringify.call(_context7.t0, _context7.t1);
389
+ _context7.t3 = {
390
+ type: "text",
391
+ text: _context7.t2
392
+ };
393
+ _context7.t4 = [_context7.t3];
394
+ return _context7.abrupt("return", {
395
+ content: _context7.t4
396
+ });
397
+ case 8:
398
+ case "end":
399
+ return _context7.stop();
400
+ }
401
+ }, _callee7);
402
+ }));
403
+ return function (_x6) {
404
+ return _ref5.apply(this, arguments);
336
405
  };
337
- _context7.t4 = [_context7.t3];
338
- return _context7.abrupt("return", {
339
- content: _context7.t4
340
- });
341
- case 9:
342
- case "end":
343
- return _context7.stop();
344
- }
345
- }, _callee7);
346
- }));
347
- return function (_x5) {
348
- return _ref4.apply(this, arguments);
349
- };
350
- }());
351
- return server;
352
- };
406
+ }());
407
+ return mcpServer;
408
+ };
409
+ ENDPOINT = "/_mcp/sse/swagger";
410
+ server.middlewares.use(ENDPOINT, /*#__PURE__*/function () {
411
+ var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(req, res, next) {
412
+ var url, _sessionId, json, transport, mcpServer, initTransport;
413
+ return _regeneratorRuntime().wrap(function _callee8$(_context8) {
414
+ while (1) switch (_context8.prev = _context8.next) {
415
+ case 0:
416
+ _context8.prev = 0;
417
+ url = new URL(req.url || "", "http://".concat(req.headers.host));
418
+ _sessionId = req.headers["mcp-session-id"] || url.searchParams.get("sessionId");
419
+ /* ================= POST 请求处理 ================= */
420
+ if (!(req.method === "POST")) {
421
+ _context8.next = 24;
422
+ break;
423
+ }
424
+ _context8.next = 6;
425
+ return readJsonBody(req);
426
+ case 6:
427
+ json = _context8.sent;
428
+ if (!(_sessionId && transports[_sessionId])) {
429
+ _context8.next = 11;
430
+ break;
431
+ }
432
+ transport = transports[_sessionId];
433
+ _context8.next = 21;
434
+ break;
435
+ case 11:
436
+ if (!(!_sessionId && isInitializeRequest(json))) {
437
+ _context8.next = 19;
438
+ break;
439
+ }
440
+ transport = new StreamableHTTPServerTransport({
441
+ sessionIdGenerator: function sessionIdGenerator() {
442
+ return randomUUID();
443
+ },
444
+ // 如果你的编辑器不支持 SSE 只能接收 JSON 响应,可以设为 true
445
+ // 但大多数现代编辑器建议保持默认(false)以支持标准流
446
+ enableJsonResponse: false,
447
+ onsessioninitialized: function onsessioninitialized(sid) {
448
+ transports[sid] = transport;
449
+ console.log("[MCP] Session initialized: ".concat(sid));
450
+ }
451
+ });
452
+ transport.onclose = function () {
453
+ if (transport.sessionId) delete transports[transport.sessionId];
454
+ console.log("[MCP] Session closed: ".concat(transport.sessionId));
455
+ };
353
456
 
354
- /* =========================
355
- * MCP HTTP Endpoint
356
- * ========================= */
357
-
358
- vite.middlewares.use("/_mcp/swagger", /*#__PURE__*/function () {
359
- var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(req, res) {
360
- var sessionId, body, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, chunk, json, transport, mcpServer;
361
- return _regeneratorRuntime().wrap(function _callee8$(_context8) {
362
- while (1) switch (_context8.prev = _context8.next) {
363
- case 0:
364
- sessionId = req.headers["mcp-session-id"];
365
- /* ---------- POST (JSON-RPC) ---------- */
366
- if (!(req.method === "POST")) {
367
- _context8.next = 57;
368
- break;
369
- }
370
- body = "";
371
- _iteratorAbruptCompletion = false;
372
- _didIteratorError = false;
373
- _context8.prev = 5;
374
- _iterator = _asyncIterator(req);
375
- case 7:
376
- _context8.next = 9;
377
- return _iterator.next();
378
- case 9:
379
- if (!(_iteratorAbruptCompletion = !(_step = _context8.sent).done)) {
380
- _context8.next = 15;
381
- break;
382
- }
383
- chunk = _step.value;
384
- body += chunk;
385
- case 12:
386
- _iteratorAbruptCompletion = false;
387
- _context8.next = 7;
388
- break;
389
- case 15:
390
- _context8.next = 21;
391
- break;
392
- case 17:
393
- _context8.prev = 17;
394
- _context8.t0 = _context8["catch"](5);
395
- _didIteratorError = true;
396
- _iteratorError = _context8.t0;
397
- case 21:
398
- _context8.prev = 21;
399
- _context8.prev = 22;
400
- if (!(_iteratorAbruptCompletion && _iterator.return != null)) {
401
- _context8.next = 26;
402
- break;
403
- }
404
- _context8.next = 26;
405
- return _iterator.return();
406
- case 26:
407
- _context8.prev = 26;
408
- if (!_didIteratorError) {
409
- _context8.next = 29;
410
- break;
411
- }
412
- throw _iteratorError;
413
- case 29:
414
- return _context8.finish(26);
415
- case 30:
416
- return _context8.finish(21);
417
- case 31:
418
- json = JSON.parse(body);
419
- _context8.prev = 32;
420
- if (!(sessionId && transports[sessionId])) {
421
- _context8.next = 37;
422
- break;
423
- }
424
- transport = transports[sessionId];
425
- _context8.next = 47;
426
- break;
427
- case 37:
428
- if (!(!sessionId && isInitializeRequest(json))) {
429
- _context8.next = 45;
430
- break;
431
- }
432
- transport = new StreamableHTTPServerTransport({
433
- sessionIdGenerator: function sessionIdGenerator() {
434
- return randomUUID();
435
- },
436
- onsessioninitialized: function onsessioninitialized(id) {
437
- transports[id] = transport;
438
- }
439
- });
440
- transport.onclose = function () {
441
- if (transport.sessionId) {
442
- delete transports[transport.sessionId];
443
- }
457
+ // 为这个 Transport 绑定一个新的 Server 实例,防止 "Already initialized"
458
+ mcpServer = createNewServer();
459
+ _context8.next = 17;
460
+ return mcpServer.connect(transport);
461
+ case 17:
462
+ _context8.next = 21;
463
+ break;
464
+ case 19:
465
+ res.statusCode = 400;
466
+ return _context8.abrupt("return", res.end(JSON.stringify({
467
+ error: "Invalid session or not an initialize request"
468
+ })));
469
+ case 21:
470
+ _context8.next = 23;
471
+ return transport.handleRequest(req, res, json);
472
+ case 23:
473
+ return _context8.abrupt("return");
474
+ case 24:
475
+ if (!(req.method === "GET")) {
476
+ _context8.next = 33;
477
+ break;
478
+ }
479
+ if (!(!_sessionId || !transports[_sessionId])) {
480
+ _context8.next = 30;
481
+ break;
482
+ }
483
+ // 如果是初次连接请求且没有 sessionId,让 transport 处理以发送 endpoint 事件
484
+ // 这里创建一个临时的 transport 来引导客户端
485
+ initTransport = new StreamableHTTPServerTransport();
486
+ _context8.next = 29;
487
+ return initTransport.handleRequest(req, res);
488
+ case 29:
489
+ return _context8.abrupt("return");
490
+ case 30:
491
+ _context8.next = 32;
492
+ return transports[_sessionId].handleRequest(req, res);
493
+ case 32:
494
+ return _context8.abrupt("return");
495
+ case 33:
496
+ res.statusCode = 405;
497
+ res.end("Method Not Allowed");
498
+ _context8.next = 41;
499
+ break;
500
+ case 37:
501
+ _context8.prev = 37;
502
+ _context8.t0 = _context8["catch"](0);
503
+ console.error("[MCP Error]", _context8.t0);
504
+ if (!res.headersSent) {
505
+ res.statusCode = 500;
506
+ res.end("Internal Server Error");
507
+ }
508
+ case 41:
509
+ case "end":
510
+ return _context8.stop();
511
+ }
512
+ }, _callee8, null, [[0, 37]]);
513
+ }));
514
+ return function (_x7, _x8, _x9) {
515
+ return _ref6.apply(this, arguments);
444
516
  };
445
- mcpServer = createMcpServer();
446
- _context8.next = 43;
447
- return mcpServer.connect(transport);
448
- case 43:
449
- _context8.next = 47;
450
- break;
451
- case 45:
452
- res.statusCode = 400;
453
- return _context8.abrupt("return", res.end("Bad Request"));
454
- case 47:
455
- _context8.next = 49;
456
- return transport.handleRequest(req, res, json);
457
- case 49:
458
- _context8.next = 56;
459
- break;
460
- case 51:
461
- _context8.prev = 51;
462
- _context8.t1 = _context8["catch"](32);
463
- console.error(_context8.t1);
464
- res.statusCode = 500;
465
- res.end("Internal Error");
466
- case 56:
467
- return _context8.abrupt("return");
468
- case 57:
469
- if (!(req.method === "GET")) {
470
- _context8.next = 64;
471
- break;
472
- }
473
- if (!(!sessionId || !transports[sessionId])) {
474
- _context8.next = 61;
475
- break;
476
- }
477
- res.statusCode = 400;
478
- return _context8.abrupt("return", res.end("Missing session"));
479
- case 61:
480
- _context8.next = 63;
481
- return transports[sessionId].handleRequest(req, res);
482
- case 63:
483
- return _context8.abrupt("return");
484
- case 64:
485
- res.statusCode = 405;
486
- res.end();
487
- case 66:
488
- case "end":
489
- return _context8.stop();
490
- }
491
- }, _callee8, null, [[5, 17, 21, 31], [22,, 26, 30], [32, 51]]);
492
- }));
493
- return function (_x6, _x7) {
494
- return _ref5.apply(this, arguments);
495
- };
496
- }());
497
- console.log("Swagger MCP ready: http://localhost:".concat((_vite$config$server = vite.config.server) === null || _vite$config$server === void 0 ? void 0 : _vite$config$server.port, "/_mcp/swagger"));
517
+ }());
518
+ console.log("\u2705 MCP Swagger Server mounted at http://localhost:".concat((_server$config = server.config) === null || _server$config === void 0 || (_server$config = _server$config.server) === null || _server$config === void 0 ? void 0 : _server$config.port).concat(ENDPOINT));
519
+ case 5:
520
+ case "end":
521
+ return _context9.stop();
522
+ }
523
+ }, _callee9);
524
+ }))();
498
525
  }
499
526
  };
500
527
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-swagger-mcp",
3
- "version": "0.0.17",
3
+ "version": "0.0.20",
4
4
  "description": "vite plugin for swagger mcp",
5
5
  "homepage": "https://github.com/mmdctjj/vite-plugin-swagger-mcp",
6
6
  "repository": {