cq-mcp-server 0.3.0 → 0.3.1

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.
Files changed (2) hide show
  1. package/dist/index.js +37 -24
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -331,41 +331,54 @@ if (MCP_TRANSPORT === "http") {
331
331
  // session_id → transport 映射,支持多用户并发
332
332
  const sessions = new Map();
333
333
  const httpServer = createServer(async (req, res) => {
334
+ // 允许跨域(Dify 可能从不同域访问)
335
+ res.setHeader("Access-Control-Allow-Origin", "*");
336
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
337
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, mcp-session-id");
338
+ res.setHeader("Access-Control-Expose-Headers", "mcp-session-id");
339
+ if (req.method === "OPTIONS") {
340
+ res.writeHead(204).end();
341
+ return;
342
+ }
334
343
  if (!req.url?.startsWith("/mcp")) {
335
344
  res.writeHead(404).end("Not Found");
336
345
  return;
337
346
  }
338
- // 每个新 session(首次 initialize 请求)创建独立的 server + transport
339
347
  const sessionId = req.headers["mcp-session-id"];
340
- if (!sessionId) {
341
- // session:为该用户创建独立实例
342
- const transport = new StreamableHTTPServerTransport({
343
- sessionIdGenerator: () => randomUUID(),
344
- });
345
- const server = createMcpServer();
346
- await server.connect(transport);
347
- transport.onclose = () => {
348
- const sid = transport.sessionId;
349
- if (sid) {
350
- sessions.delete(sid);
351
- log.info(`Session 关闭: ${sid},当前活跃: ${sessions.size}`);
352
- }
353
- };
354
- await transport.handleRequest(req, res);
355
- // handleRequest 后 sessionId 已生成,存入 map
356
- if (transport.sessionId) {
357
- sessions.set(transport.sessionId, transport);
358
- log.info(`新 Session: ${transport.sessionId},当前活跃: ${sessions.size}`);
359
- }
360
- }
361
- else {
362
- // 已有 session:路由到对应 transport
348
+ if (sessionId) {
349
+ // 已有 session:路由到对应 transport(GET/POST/DELETE 均转发)
363
350
  const transport = sessions.get(sessionId);
364
351
  if (!transport) {
365
352
  res.writeHead(404).end("Session not found");
366
353
  return;
367
354
  }
368
355
  await transport.handleRequest(req, res);
356
+ return;
357
+ }
358
+ // 无 session ID:只允许 POST initialize 创建新 session
359
+ if (req.method !== "POST") {
360
+ res.writeHead(400).end("Missing mcp-session-id");
361
+ return;
362
+ }
363
+ // 新 session:为该用户创建独立实例
364
+ const transport = new StreamableHTTPServerTransport({
365
+ sessionIdGenerator: () => randomUUID(),
366
+ });
367
+ const mcpServer = createMcpServer();
368
+ await mcpServer.connect(transport);
369
+ transport.onclose = () => {
370
+ const sid = transport.sessionId;
371
+ if (sid) {
372
+ sessions.delete(sid);
373
+ log.info(`Session 关闭: ${sid},当前活跃: ${sessions.size}`);
374
+ }
375
+ };
376
+ // handleRequest 前先存入 map,防止 GET 请求在 POST 完成前到来
377
+ // sessionId 在 handleRequest 内部生成后会写入 response header
378
+ await transport.handleRequest(req, res);
379
+ if (transport.sessionId) {
380
+ sessions.set(transport.sessionId, transport);
381
+ log.info(`新 Session: ${transport.sessionId},当前活跃: ${sessions.size}`);
369
382
  }
370
383
  });
371
384
  httpServer.listen(MCP_PORT, () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cq-mcp-server",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "MCP Server for CloudQuery platform — list databases, list tables, inspect columns, and execute SQL via MCP tools.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",