@xiaou66/vite-plugin-vue-mcp-next 0.0.2 → 0.0.3

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/index.js CHANGED
@@ -809,18 +809,39 @@ function createMcpServer(ctx, vite) {
809
809
 
810
810
  // src/mcp/transport.ts
811
811
  import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
812
- function setupMcpTransport(base, server, vite) {
812
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
813
+ function setupMcpTransport(base, createServer, vite) {
813
814
  const transports = /* @__PURE__ */ new Map();
814
815
  vite.middlewares.use(`${base}/sse`, (_req, res) => {
815
816
  const transport = new SSEServerTransport(`${base}/messages`, res);
816
- transports.set(transport.sessionId, transport);
817
+ const server = createServer();
818
+ transports.set(transport.sessionId, { server, transport });
817
819
  res.on("close", () => {
818
820
  transports.delete(transport.sessionId);
821
+ void server.close();
819
822
  });
820
823
  void server.connect(transport).catch((error) => {
821
824
  res.destroy(error instanceof Error ? error : new Error(String(error)));
822
825
  });
823
826
  });
827
+ vite.middlewares.use(`${base}/mcp`, (req, res) => {
828
+ if (req.method !== "POST") {
829
+ res.statusCode = 405;
830
+ res.end("Method Not Allowed");
831
+ return;
832
+ }
833
+ const transport = new StreamableHTTPServerTransport({
834
+ sessionIdGenerator: void 0
835
+ });
836
+ const server = createServer();
837
+ res.on("close", () => {
838
+ void transport.close();
839
+ void server.close();
840
+ });
841
+ void server.connect(transport).then(() => transport.handleRequest(req, res)).catch((error) => {
842
+ res.destroy(error instanceof Error ? error : new Error(String(error)));
843
+ });
844
+ });
824
845
  vite.middlewares.use(`${base}/messages`, (req, res) => {
825
846
  if (req.method !== "POST") {
826
847
  res.statusCode = 405;
@@ -834,13 +855,13 @@ function setupMcpTransport(base, server, vite) {
834
855
  res.end("Bad Request");
835
856
  return;
836
857
  }
837
- const transport = transports.get(sessionId);
838
- if (!transport) {
858
+ const entry = transports.get(sessionId);
859
+ if (!entry) {
839
860
  res.statusCode = 404;
840
861
  res.end("Not Found");
841
862
  return;
842
863
  }
843
- void transport.handlePostMessage(req, res).catch((error) => {
864
+ void entry.transport.handlePostMessage(req, res).catch((error) => {
844
865
  res.destroy(error instanceof Error ? error : new Error(String(error)));
845
866
  });
846
867
  });
@@ -1216,7 +1237,7 @@ function replaceOrAppendOwnedBlock(current, options) {
1216
1237
  const block = createCodexServerBlock(options);
1217
1238
  const matcher = createOwnedBlockMatcher(options.serverName);
1218
1239
  if (matcher.test(current)) {
1219
- return current.replace(matcher, block);
1240
+ return ensureTrailingNewline(current);
1220
1241
  }
1221
1242
  const separator = current.trim() ? "\n\n" : "";
1222
1243
  return `${trimEndNewline(current)}${separator}${block}`;
@@ -1258,6 +1279,10 @@ async function readOptionalTextFile(filePath) {
1258
1279
  function trimEndNewline(value) {
1259
1280
  return value.replace(/\n+$/u, "");
1260
1281
  }
1282
+ function ensureTrailingNewline(value) {
1283
+ return value.endsWith("\n") ? value : `${value}
1284
+ `;
1285
+ }
1261
1286
  function escapeRegExp(value) {
1262
1287
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1263
1288
  }
@@ -1279,7 +1304,10 @@ async function updateJsonMcpClientConfig(options) {
1279
1304
  return;
1280
1305
  }
1281
1306
  const mcpServers = isPlainRecord(config.mcpServers) ? config.mcpServers : {};
1282
- mcpServers[options.serverName] = { url: options.mcpUrl };
1307
+ if (Object.hasOwn(mcpServers, options.serverName)) {
1308
+ return;
1309
+ }
1310
+ mcpServers[options.serverName] = { type: "sse", url: options.mcpUrl };
1283
1311
  config.mcpServers = mcpServers;
1284
1312
  await fs3.mkdir(path3.dirname(options.configPath), { recursive: true });
1285
1313
  await fs3.writeFile(
@@ -1324,7 +1352,7 @@ function isNodeError2(error) {
1324
1352
  }
1325
1353
 
1326
1354
  // src/plugin/mcpClientConfig/index.ts
1327
- async function updateMcpClientConfigs(root, mcpUrl, options) {
1355
+ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options) {
1328
1356
  const serverName = options.serverName;
1329
1357
  const jobs = [];
1330
1358
  if (options.cursor) {
@@ -1332,7 +1360,7 @@ async function updateMcpClientConfigs(root, mcpUrl, options) {
1332
1360
  updateJsonMcpClientConfig({
1333
1361
  clientName: "Cursor",
1334
1362
  configPath: path4.join(root, ".cursor", "mcp.json"),
1335
- mcpUrl,
1363
+ mcpUrl: sseUrl,
1336
1364
  serverName
1337
1365
  })
1338
1366
  );
@@ -1341,7 +1369,7 @@ async function updateMcpClientConfigs(root, mcpUrl, options) {
1341
1369
  jobs.push(
1342
1370
  updateCodexMcpClientConfig({
1343
1371
  configPath: path4.join(root, ".codex", "config.toml"),
1344
- mcpUrl,
1372
+ mcpUrl: streamableHttpUrl,
1345
1373
  serverName
1346
1374
  })
1347
1375
  );
@@ -1351,7 +1379,7 @@ async function updateMcpClientConfigs(root, mcpUrl, options) {
1351
1379
  updateJsonMcpClientConfig({
1352
1380
  clientName: "Claude Code",
1353
1381
  configPath: path4.join(root, ".mcp.json"),
1354
- mcpUrl,
1382
+ mcpUrl: sseUrl,
1355
1383
  serverName
1356
1384
  })
1357
1385
  );
@@ -1361,7 +1389,7 @@ async function updateMcpClientConfigs(root, mcpUrl, options) {
1361
1389
  updateJsonMcpClientConfig({
1362
1390
  clientName: "Trae",
1363
1391
  configPath: path4.join(root, ".trae", "mcp.json"),
1364
- mcpUrl,
1392
+ mcpUrl: sseUrl,
1365
1393
  serverName
1366
1394
  })
1367
1395
  );
@@ -1397,8 +1425,11 @@ function vueMcpNext(userOptions = {}) {
1397
1425
  timeout: -1
1398
1426
  }
1399
1427
  );
1400
- const mcpServer = createMcpServer(ctx, server);
1401
- setupMcpTransport(options.mcpPath, mcpServer, server);
1428
+ setupMcpTransport(
1429
+ options.mcpPath,
1430
+ () => createMcpServer(ctx, server),
1431
+ server
1432
+ );
1402
1433
  server.ws.on(
1403
1434
  "vite-plugin-vue-mcp-next:page-connected",
1404
1435
  (payload) => {
@@ -1425,12 +1456,21 @@ function vueMcpNext(userOptions = {}) {
1425
1456
  }
1426
1457
  );
1427
1458
  const port = String(server.config.server.port || 5173);
1428
- const mcpUrl = `http://${options.host}:${port}${options.mcpPath}/sse`;
1459
+ const mcpSseUrl = `http://${options.host}:${port}${options.mcpPath}/sse`;
1460
+ const mcpStreamableHttpUrl = `http://${options.host}:${port}${options.mcpPath}/mcp`;
1429
1461
  const root = searchForWorkspaceRoot(server.config.root);
1430
- await updateMcpClientConfigs(root, mcpUrl, options.mcpClients);
1462
+ await updateMcpClientConfigs(
1463
+ root,
1464
+ mcpSseUrl,
1465
+ mcpStreamableHttpUrl,
1466
+ options.mcpClients
1467
+ );
1431
1468
  if (options.printUrl) {
1432
1469
  setTimeout(() => {
1433
- console.log(` \u279C MCP: Server is running at ${mcpUrl}`);
1470
+ console.log(` \u279C MCP: SSE server is running at ${mcpSseUrl}`);
1471
+ console.log(
1472
+ ` \u279C MCP: Streamable HTTP server is running at ${mcpStreamableHttpUrl}`
1473
+ );
1434
1474
  }, 300);
1435
1475
  }
1436
1476
  server.httpServer?.once("close", () => {