vite-plugin-swagger-mcp 0.0.16 → 0.0.19

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/dist/cjs/index.js CHANGED
@@ -25,8 +25,15 @@ __export(src_exports, {
25
25
  module.exports = __toCommonJS(src_exports);
26
26
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
27
27
  var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
28
+ var import_types = require("@modelcontextprotocol/sdk/types");
28
29
  var import_node_crypto = require("node:crypto");
29
- var import_zod = require("zod");
30
+ var import_v4 = require("zod/v4");
31
+ async function readJsonBody(req) {
32
+ let body = "";
33
+ for await (const chunk of req)
34
+ body += chunk;
35
+ return JSON.parse(body || "{}");
36
+ }
30
37
  var SwaggerMcpServer = class {
31
38
  constructor(swaggerUrl, token) {
32
39
  this.swaggerUrl = swaggerUrl;
@@ -144,130 +151,90 @@ function vitePluginSwaggerMcp({
144
151
  enforce: "pre",
145
152
  async configureServer(server) {
146
153
  var _a, _b;
147
- try {
148
- let transport = new import_streamableHttp.StreamableHTTPServerTransport({
149
- sessionIdGenerator: () => (0, import_node_crypto.randomUUID)(),
150
- onsessioninitialized: (sessionId) => {
151
- transports[sessionId] = transport;
152
- }
153
- });
154
- transport.onclose = () => {
155
- if (transport.sessionId) {
156
- delete transports[transport.sessionId];
157
- }
158
- };
159
- const swaggerServer = new SwaggerMcpServer(swaggerUrl, token);
154
+ const swaggerServer = new SwaggerMcpServer(swaggerUrl, token);
155
+ const createNewServer = () => {
160
156
  const mcpServer = new import_mcp.McpServer({
161
157
  name: "swagger-mcp-server",
162
158
  version: "0.1.0"
163
159
  });
164
160
  mcpServer.tool("getModules", "获取模块列表", async () => {
165
161
  const res = await swaggerServer.getModules();
166
- return {
167
- content: [
168
- {
169
- type: "text",
170
- text: JSON.stringify(res)
171
- }
172
- ]
173
- };
162
+ return { content: [{ type: "text", text: JSON.stringify(res) }] };
174
163
  });
175
164
  mcpServer.tool(
176
165
  "getModuleApis",
177
- "获取特定模块下的所有接口及返回值类型",
178
- {
179
- module: import_zod.z.string().describe("模块名称")
180
- },
166
+ "获取特定模块下的所有接口",
167
+ { module: import_v4.z.string().describe("模块名称") },
181
168
  async ({ module: module2 }) => {
182
- if (!module2) {
183
- return {
184
- content: [
185
- {
186
- type: "text",
187
- text: JSON.stringify({ error: "模块名称不能为空" })
188
- }
189
- ]
190
- };
191
- }
192
169
  const res = await swaggerServer.getModuleApis(module2);
193
- return {
194
- content: [{ type: "text", text: JSON.stringify(res) }]
195
- };
170
+ return { content: [{ type: "text", text: JSON.stringify(res) }] };
196
171
  }
197
172
  );
198
173
  mcpServer.tool(
199
174
  "getApiTypes",
200
175
  "获取特定接口的参数及返回值类型",
201
- { path: import_zod.z.string(), method: import_zod.z.string() },
176
+ { path: import_v4.z.string(), method: import_v4.z.string() },
202
177
  async (args) => ({
203
- content: [
204
- {
205
- type: "text",
206
- text: JSON.stringify(
207
- await swaggerServer.getApiTypes(args.path, args.method)
208
- )
209
- }
210
- ]
178
+ content: [{ type: "text", text: JSON.stringify(await swaggerServer.getApiTypes(args.path, args.method)) }]
211
179
  })
212
180
  );
213
- await mcpServer.connect(transport);
214
- console.log(
215
- "MCP server connected:",
216
- `http://localhost:${(_b = (_a = server.config) == null ? void 0 : _a.server) == null ? void 0 : _b.port}/_mcp/sse/swagger`
217
- );
218
- server.middlewares.use("/_mcp/sse/swagger", async (req, res) => {
219
- var _a2;
181
+ return mcpServer;
182
+ };
183
+ const ENDPOINT = "/_mcp/sse/swagger";
184
+ server.middlewares.use(ENDPOINT, async (req, res, next) => {
185
+ try {
186
+ const url = new URL(req.url || "", `http://${req.headers.host}`);
187
+ const sessionId = req.headers["mcp-session-id"] || url.searchParams.get("sessionId");
220
188
  if (req.method === "POST") {
221
- const sessionId = req.headers["mcp-session-id"];
222
- let body = "";
223
- for await (const chunk of req)
224
- body += chunk;
225
- const json = JSON.parse(body);
226
- console.log("post request received");
227
- console.log("body: ", json);
228
- try {
229
- if (sessionId && transports[sessionId]) {
230
- transport = transports[sessionId];
231
- await transport.handleRequest(req, res, json);
232
- return;
233
- }
234
- if (!sessionId) {
235
- await transport.handleRequest(req, res, json);
236
- const sessionId2 = transport.sessionId;
237
- if (sessionId2) {
238
- transports[sessionId2] = transport;
189
+ const json = await readJsonBody(req);
190
+ let transport;
191
+ if (sessionId && transports[sessionId]) {
192
+ transport = transports[sessionId];
193
+ } else if (!sessionId && (0, import_types.isInitializeRequest)(json)) {
194
+ transport = new import_streamableHttp.StreamableHTTPServerTransport({
195
+ sessionIdGenerator: () => (0, import_node_crypto.randomUUID)(),
196
+ // 如果你的编辑器不支持 SSE 只能接收 JSON 响应,可以设为 true
197
+ // 但大多数现代编辑器建议保持默认(false)以支持标准流
198
+ enableJsonResponse: false,
199
+ onsessioninitialized: (sid) => {
200
+ transports[sid] = transport;
201
+ console.log(`[MCP] Session initialized: ${sid}`);
239
202
  }
240
- return;
241
- }
203
+ });
204
+ transport.onclose = () => {
205
+ if (transport.sessionId)
206
+ delete transports[transport.sessionId];
207
+ console.log(`[MCP] Session closed: ${transport.sessionId}`);
208
+ };
209
+ const mcpServer = createNewServer();
210
+ await mcpServer.connect(transport);
211
+ } else {
242
212
  res.statusCode = 400;
243
- res.end("Bad Request: invalid session ID or method.");
244
- return;
245
- } catch (error) {
246
- console.error("Error handling MCP request:", error);
247
- res.statusCode = 500;
248
- res.end("Internal server error.");
249
- return;
213
+ return res.end(JSON.stringify({ error: "Invalid session or not an initialize request" }));
250
214
  }
215
+ await transport.handleRequest(req, res, json);
216
+ return;
251
217
  }
252
218
  if (req.method === "GET") {
253
- if (!((_a2 = req.headers.accept) == null ? void 0 : _a2.includes("text/event-stream"))) {
254
- res.writeHead(405);
255
- return res.end();
219
+ if (!sessionId || !transports[sessionId]) {
220
+ const initTransport = new import_streamableHttp.StreamableHTTPServerTransport();
221
+ await initTransport.handleRequest(req, res);
222
+ return;
256
223
  }
257
- res.writeHead(200, {
258
- "Content-Type": "text/event-stream",
259
- "Cache-Control": "no-cache",
260
- Connection: "keep-alive"
261
- });
262
- transport.onmessage = (message) => {
263
- res.write(message);
264
- };
224
+ await transports[sessionId].handleRequest(req, res);
265
225
  return;
266
226
  }
267
- });
268
- } catch (error) {
269
- console.log("MCP server error", error);
270
- }
227
+ res.statusCode = 405;
228
+ res.end("Method Not Allowed");
229
+ } catch (error) {
230
+ console.error("[MCP Error]", error);
231
+ if (!res.headersSent) {
232
+ res.statusCode = 500;
233
+ res.end("Internal Server Error");
234
+ }
235
+ }
236
+ });
237
+ console.log(`✅ MCP Swagger Server mounted at http://localhost:${(_b = (_a = server.config) == null ? void 0 : _a.server) == null ? void 0 : _b.port}${ENDPOINT}`);
271
238
  }
272
239
  };
273
240
  }
package/dist/esm/index.js CHANGED
@@ -2,20 +2,88 @@ 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
16
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
17
+ import { isInitializeRequest } from "@modelcontextprotocol/sdk/types";
17
18
  import { randomUUID } from "node:crypto";
18
- import { z } from "zod";
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
+ }
19
87
  export var SwaggerMcpServer = /*#__PURE__*/function () {
20
88
  function SwaggerMcpServer(swaggerUrl, token) {
21
89
  _classCallCheck(this, SwaggerMcpServer);
@@ -180,7 +248,7 @@ export var SwaggerMcpServer = /*#__PURE__*/function () {
180
248
  }
181
249
  }, _callee3, this);
182
250
  }));
183
- function getModuleApis(_x) {
251
+ function getModuleApis(_x2) {
184
252
  return _getModuleApis.apply(this, arguments);
185
253
  }
186
254
  return getModuleApis;
@@ -219,7 +287,7 @@ export var SwaggerMcpServer = /*#__PURE__*/function () {
219
287
  }
220
288
  }, _callee4, this);
221
289
  }));
222
- function getApiTypes(_x2, _x3) {
290
+ function getApiTypes(_x3, _x4) {
223
291
  return _getApiTypes.apply(this, arguments);
224
292
  }
225
293
  return getApiTypes;
@@ -228,7 +296,7 @@ export var SwaggerMcpServer = /*#__PURE__*/function () {
228
296
  return SwaggerMcpServer;
229
297
  }();
230
298
 
231
- // Map to store transports by session ID
299
+ // 存储会话 ID 对应的 Transport 实例
232
300
  var transports = {};
233
301
  export default function vitePluginSwaggerMcp(_ref) {
234
302
  var swaggerUrl = _ref.swaggerUrl,
@@ -238,281 +306,218 @@ export default function vitePluginSwaggerMcp(_ref) {
238
306
  enforce: "pre",
239
307
  configureServer: function configureServer(server) {
240
308
  return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9() {
241
- var _server$config, transport, swaggerServer, mcpServer;
309
+ var _server$config;
310
+ var swaggerServer, createNewServer, ENDPOINT;
242
311
  return _regeneratorRuntime().wrap(function _callee9$(_context9) {
243
312
  while (1) switch (_context9.prev = _context9.next) {
244
313
  case 0:
245
- _context9.prev = 0;
246
- transport = new StreamableHTTPServerTransport({
247
- sessionIdGenerator: function sessionIdGenerator() {
248
- return randomUUID();
249
- },
250
- onsessioninitialized: function onsessioninitialized(sessionId) {
251
- // Store the transport by session ID
252
- transports[sessionId] = transport;
253
- }
254
- }); // Clean up transport when closed
255
- transport.onclose = function () {
256
- if (transport.sessionId) {
257
- delete transports[transport.sessionId];
258
- }
259
- };
260
- swaggerServer = new SwaggerMcpServer(swaggerUrl, token); // 实例化 MCP Server
261
- mcpServer = new McpServer({
262
- name: "swagger-mcp-server",
263
- version: "0.1.0"
264
- }); // 注册工具
265
- /***
266
- * 获取模块列表
267
- */
268
- mcpServer.tool("getModules", "获取模块列表", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
269
- var res;
270
- return _regeneratorRuntime().wrap(function _callee5$(_context5) {
271
- while (1) switch (_context5.prev = _context5.next) {
272
- case 0:
273
- _context5.next = 2;
274
- return swaggerServer.getModules();
275
- case 2:
276
- res = _context5.sent;
277
- return _context5.abrupt("return", {
278
- content: [{
279
- type: "text",
280
- text: JSON.stringify(res)
281
- }]
282
- });
283
- case 4:
284
- case "end":
285
- return _context5.stop();
286
- }
287
- }, _callee5);
288
- })));
314
+ swaggerServer = new SwaggerMcpServer(swaggerUrl, token); // --- 辅助函数:创建并配置一个新的 MCP Server 实例 ---
315
+ createNewServer = function createNewServer() {
316
+ var mcpServer = new McpServer({
317
+ name: "swagger-mcp-server",
318
+ version: "0.1.0"
319
+ });
289
320
 
290
- /***
291
- * 获取特定模块下的所有接口及返回值类型
292
- */
293
- mcpServer.tool("getModuleApis", "获取特定模块下的所有接口及返回值类型", {
294
- module: z.string().describe("模块名称")
295
- }, /*#__PURE__*/function () {
296
- var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(_ref3) {
297
- var module, res;
298
- return _regeneratorRuntime().wrap(function _callee6$(_context6) {
299
- while (1) switch (_context6.prev = _context6.next) {
321
+ // 注册所有工具
322
+ mcpServer.tool("getModules", "获取模块列表", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
323
+ var res;
324
+ return _regeneratorRuntime().wrap(function _callee5$(_context5) {
325
+ while (1) switch (_context5.prev = _context5.next) {
300
326
  case 0:
301
- module = _ref3.module;
302
- if (module) {
303
- _context6.next = 3;
304
- break;
305
- }
306
- return _context6.abrupt("return", {
307
- content: [{
308
- type: "text",
309
- text: JSON.stringify({
310
- error: "模块名称不能为空"
311
- })
312
- }]
313
- });
314
- case 3:
315
- _context6.next = 5;
316
- return swaggerServer.getModuleApis(module);
317
- case 5:
318
- res = _context6.sent;
319
- return _context6.abrupt("return", {
327
+ _context5.next = 2;
328
+ return swaggerServer.getModules();
329
+ case 2:
330
+ res = _context5.sent;
331
+ return _context5.abrupt("return", {
320
332
  content: [{
321
333
  type: "text",
322
334
  text: JSON.stringify(res)
323
335
  }]
324
336
  });
325
- case 7:
337
+ case 4:
326
338
  case "end":
327
- return _context6.stop();
339
+ return _context5.stop();
328
340
  }
329
- }, _callee6);
330
- }));
331
- return function (_x4) {
332
- return _ref4.apply(this, arguments);
333
- };
334
- }());
335
-
336
- /***
337
- * 获取特定接口的参数及返回值类型
338
- */
339
- mcpServer.tool("getApiTypes", "获取特定接口的参数及返回值类型", {
340
- path: z.string(),
341
- method: z.string()
342
- }, /*#__PURE__*/function () {
343
- var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(args) {
344
- return _regeneratorRuntime().wrap(function _callee7$(_context7) {
345
- while (1) switch (_context7.prev = _context7.next) {
346
- case 0:
347
- _context7.t0 = JSON;
348
- _context7.next = 3;
349
- return swaggerServer.getApiTypes(args.path, args.method);
350
- case 3:
351
- _context7.t1 = _context7.sent;
352
- _context7.t2 = _context7.t0.stringify.call(_context7.t0, _context7.t1);
353
- _context7.t3 = {
354
- type: "text",
355
- text: _context7.t2
356
- };
357
- _context7.t4 = [_context7.t3];
358
- return _context7.abrupt("return", {
359
- content: _context7.t4
360
- });
361
- case 8:
362
- case "end":
363
- return _context7.stop();
364
- }
365
- }, _callee7);
366
- }));
367
- return function (_x5) {
368
- return _ref5.apply(this, arguments);
369
- };
370
- }());
371
- _context9.next = 10;
372
- return mcpServer.connect(transport);
373
- case 10:
374
- // Connect to the MCP mcpServer
375
- console.log("MCP server connected:", "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, "/_mcp/sse/swagger"));
376
- server.middlewares.use('/_mcp/sse/swagger', /*#__PURE__*/function () {
377
- var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(req, res) {
378
- var _sessionId, body, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, chunk, json, _sessionId2, _req$headers$accept;
341
+ }, _callee5);
342
+ })));
343
+ mcpServer.tool("getModuleApis", "获取特定模块下的所有接口", {
344
+ module: z.string().describe("模块名称")
345
+ }, /*#__PURE__*/function () {
346
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(_ref3) {
347
+ var module, res;
348
+ return _regeneratorRuntime().wrap(function _callee6$(_context6) {
349
+ while (1) switch (_context6.prev = _context6.next) {
350
+ case 0:
351
+ module = _ref3.module;
352
+ _context6.next = 3;
353
+ return swaggerServer.getModuleApis(module);
354
+ case 3:
355
+ res = _context6.sent;
356
+ return _context6.abrupt("return", {
357
+ content: [{
358
+ type: "text",
359
+ text: JSON.stringify(res)
360
+ }]
361
+ });
362
+ case 5:
363
+ case "end":
364
+ return _context6.stop();
365
+ }
366
+ }, _callee6);
367
+ }));
368
+ return function (_x5) {
369
+ return _ref4.apply(this, arguments);
370
+ };
371
+ }());
372
+ mcpServer.tool("getApiTypes", "获取特定接口的参数及返回值类型", {
373
+ path: z.string(),
374
+ method: z.string()
375
+ }, /*#__PURE__*/function () {
376
+ var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(args) {
377
+ return _regeneratorRuntime().wrap(function _callee7$(_context7) {
378
+ while (1) switch (_context7.prev = _context7.next) {
379
+ case 0:
380
+ _context7.t0 = JSON;
381
+ _context7.next = 3;
382
+ return swaggerServer.getApiTypes(args.path, args.method);
383
+ case 3:
384
+ _context7.t1 = _context7.sent;
385
+ _context7.t2 = _context7.t0.stringify.call(_context7.t0, _context7.t1);
386
+ _context7.t3 = {
387
+ type: "text",
388
+ text: _context7.t2
389
+ };
390
+ _context7.t4 = [_context7.t3];
391
+ return _context7.abrupt("return", {
392
+ content: _context7.t4
393
+ });
394
+ case 8:
395
+ case "end":
396
+ return _context7.stop();
397
+ }
398
+ }, _callee7);
399
+ }));
400
+ return function (_x6) {
401
+ return _ref5.apply(this, arguments);
402
+ };
403
+ }());
404
+ return mcpServer;
405
+ };
406
+ ENDPOINT = "/_mcp/sse/swagger";
407
+ server.middlewares.use(ENDPOINT, /*#__PURE__*/function () {
408
+ var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(req, res, next) {
409
+ var url, _sessionId, json, transport, mcpServer, initTransport;
379
410
  return _regeneratorRuntime().wrap(function _callee8$(_context8) {
380
411
  while (1) switch (_context8.prev = _context8.next) {
381
412
  case 0:
382
- if (!(req.method === 'POST')) {
383
- _context8.next = 57;
413
+ _context8.prev = 0;
414
+ url = new URL(req.url || "", "http://".concat(req.headers.host));
415
+ _sessionId = req.headers["mcp-session-id"] || url.searchParams.get("sessionId");
416
+ /* ================= POST 请求处理 ================= */
417
+ if (!(req.method === "POST")) {
418
+ _context8.next = 24;
384
419
  break;
385
420
  }
386
- _sessionId = req.headers["mcp-session-id"];
387
- body = '';
388
- _iteratorAbruptCompletion = false;
389
- _didIteratorError = false;
390
- _context8.prev = 5;
391
- _iterator = _asyncIterator(req);
392
- case 7:
393
- _context8.next = 9;
394
- return _iterator.next();
395
- case 9:
396
- if (!(_iteratorAbruptCompletion = !(_step = _context8.sent).done)) {
397
- _context8.next = 15;
421
+ _context8.next = 6;
422
+ return readJsonBody(req);
423
+ case 6:
424
+ json = _context8.sent;
425
+ if (!(_sessionId && transports[_sessionId])) {
426
+ _context8.next = 11;
398
427
  break;
399
428
  }
400
- chunk = _step.value;
401
- body += chunk;
402
- case 12:
403
- _iteratorAbruptCompletion = false;
404
- _context8.next = 7;
405
- break;
406
- case 15:
429
+ transport = transports[_sessionId];
407
430
  _context8.next = 21;
408
431
  break;
409
- case 17:
410
- _context8.prev = 17;
411
- _context8.t0 = _context8["catch"](5);
412
- _didIteratorError = true;
413
- _iteratorError = _context8.t0;
414
- case 21:
415
- _context8.prev = 21;
416
- _context8.prev = 22;
417
- if (!(_iteratorAbruptCompletion && _iterator.return != null)) {
418
- _context8.next = 26;
432
+ case 11:
433
+ if (!(!_sessionId && isInitializeRequest(json))) {
434
+ _context8.next = 19;
419
435
  break;
420
436
  }
421
- _context8.next = 26;
422
- return _iterator.return();
423
- case 26:
424
- _context8.prev = 26;
425
- if (!_didIteratorError) {
426
- _context8.next = 29;
427
- break;
428
- }
429
- throw _iteratorError;
430
- case 29:
431
- return _context8.finish(26);
432
- case 30:
433
- return _context8.finish(21);
434
- case 31:
435
- json = JSON.parse(body);
436
- console.log("post request received");
437
- console.log("body: ", json);
438
- _context8.prev = 34;
439
- if (!(_sessionId && transports[_sessionId])) {
440
- _context8.next = 40;
441
- break;
442
- }
443
- transport = transports[_sessionId];
444
- _context8.next = 39;
437
+ transport = new StreamableHTTPServerTransport({
438
+ sessionIdGenerator: function sessionIdGenerator() {
439
+ return randomUUID();
440
+ },
441
+ // 如果你的编辑器不支持 SSE 只能接收 JSON 响应,可以设为 true
442
+ // 但大多数现代编辑器建议保持默认(false)以支持标准流
443
+ enableJsonResponse: false,
444
+ onsessioninitialized: function onsessioninitialized(sid) {
445
+ transports[sid] = transport;
446
+ console.log("[MCP] Session initialized: ".concat(sid));
447
+ }
448
+ });
449
+ transport.onclose = function () {
450
+ if (transport.sessionId) delete transports[transport.sessionId];
451
+ console.log("[MCP] Session closed: ".concat(transport.sessionId));
452
+ };
453
+
454
+ // 为这个 Transport 绑定一个新的 Server 实例,防止 "Already initialized"
455
+ mcpServer = createNewServer();
456
+ _context8.next = 17;
457
+ return mcpServer.connect(transport);
458
+ case 17:
459
+ _context8.next = 21;
460
+ break;
461
+ case 19:
462
+ res.statusCode = 400;
463
+ return _context8.abrupt("return", res.end(JSON.stringify({
464
+ error: "Invalid session or not an initialize request"
465
+ })));
466
+ case 21:
467
+ _context8.next = 23;
445
468
  return transport.handleRequest(req, res, json);
446
- case 39:
469
+ case 23:
447
470
  return _context8.abrupt("return");
448
- case 40:
449
- if (_sessionId) {
450
- _context8.next = 46;
471
+ case 24:
472
+ if (!(req.method === "GET")) {
473
+ _context8.next = 33;
451
474
  break;
452
475
  }
453
- _context8.next = 43;
454
- return transport.handleRequest(req, res, json);
455
- case 43:
456
- // session ID will only be available (if in not Stateless-Mode)
457
- // after handling the first request
458
- _sessionId2 = transport.sessionId;
459
- if (_sessionId2) {
460
- transports[_sessionId2] = transport;
476
+ if (!(!_sessionId || !transports[_sessionId])) {
477
+ _context8.next = 30;
478
+ break;
461
479
  }
480
+ // 如果是初次连接请求且没有 sessionId,让 transport 处理以发送 endpoint 事件
481
+ // 这里创建一个临时的 transport 来引导客户端
482
+ initTransport = new StreamableHTTPServerTransport();
483
+ _context8.next = 29;
484
+ return initTransport.handleRequest(req, res);
485
+ case 29:
462
486
  return _context8.abrupt("return");
463
- case 46:
464
- res.statusCode = 400;
465
- res.end("Bad Request: invalid session ID or method.");
466
- return _context8.abrupt("return");
467
- case 51:
468
- _context8.prev = 51;
469
- _context8.t1 = _context8["catch"](34);
470
- console.error('Error handling MCP request:', _context8.t1);
471
- res.statusCode = 500;
472
- res.end("Internal server error.");
487
+ case 30:
488
+ _context8.next = 32;
489
+ return transports[_sessionId].handleRequest(req, res);
490
+ case 32:
473
491
  return _context8.abrupt("return");
474
- case 57:
475
- if (!(req.method === 'GET')) {
476
- _context8.next = 64;
477
- break;
478
- }
479
- if ((_req$headers$accept = req.headers.accept) !== null && _req$headers$accept !== void 0 && _req$headers$accept.includes('text/event-stream')) {
480
- _context8.next = 61;
481
- break;
492
+ case 33:
493
+ res.statusCode = 405;
494
+ res.end("Method Not Allowed");
495
+ _context8.next = 41;
496
+ break;
497
+ case 37:
498
+ _context8.prev = 37;
499
+ _context8.t0 = _context8["catch"](0);
500
+ console.error("[MCP Error]", _context8.t0);
501
+ if (!res.headersSent) {
502
+ res.statusCode = 500;
503
+ res.end("Internal Server Error");
482
504
  }
483
- res.writeHead(405);
484
- return _context8.abrupt("return", res.end());
485
- case 61:
486
- res.writeHead(200, {
487
- 'Content-Type': 'text/event-stream',
488
- 'Cache-Control': 'no-cache',
489
- Connection: 'keep-alive'
490
- });
491
- transport.onmessage = function (message) {
492
- res.write(message);
493
- };
494
- return _context8.abrupt("return");
495
- case 64:
505
+ case 41:
496
506
  case "end":
497
507
  return _context8.stop();
498
508
  }
499
- }, _callee8, null, [[5, 17, 21, 31], [22,, 26, 30], [34, 51]]);
509
+ }, _callee8, null, [[0, 37]]);
500
510
  }));
501
- return function (_x6, _x7) {
511
+ return function (_x7, _x8, _x9) {
502
512
  return _ref6.apply(this, arguments);
503
513
  };
504
514
  }());
505
- _context9.next = 17;
506
- break;
507
- case 14:
508
- _context9.prev = 14;
509
- _context9.t0 = _context9["catch"](0);
510
- console.log("MCP server error", _context9.t0);
511
- case 17:
515
+ 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));
516
+ case 5:
512
517
  case "end":
513
518
  return _context9.stop();
514
519
  }
515
- }, _callee9, null, [[0, 14]]);
520
+ }, _callee9);
516
521
  }))();
517
522
  }
518
523
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-swagger-mcp",
3
- "version": "0.0.16",
3
+ "version": "0.0.19",
4
4
  "description": "vite plugin for swagger mcp",
5
5
  "homepage": "https://github.com/mmdctjj/vite-plugin-swagger-mcp",
6
6
  "repository": {