Skip to main content
Glama

MCPDemo - Visual SQL Chat Platform

by Ayi456
mcpRoutes.ts6.09 kB
import express from 'express'; import { randomUUID } from 'node:crypto'; import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js'; import { CloudFunctionMCPHandler } from '../CloudFunctionMCPHandler.js'; import { authenticateUser } from '../middleware/authentication.js'; import { UserManager } from '../UserManager.js'; import { User } from '../types.js'; /** * 设置 MCP 协议相关路由 */ export function setupMcpRoutes( app: express.Application, mcpServer: Server | null, mcpTransports: { [sessionId: string]: StreamableHTTPServerTransport }, sessionUserMap: Map<string, User>, userManager: UserManager ) { // MCP 协议端点 - POST 请求处理客户端到服务器的通信 app.post(['/mcp', '/mcp/'], async (req, res) => { if (!mcpServer) { return res.status(503).json({ jsonrpc: '2.0', error: { code: -32000, message: 'MCP Server not initialized' }, id: null }); } // 尝试验证用户身份(保持向后兼容) const authResult = await authenticateUser(req, userManager); const authenticatedUser = authResult.user; const isInitRequest = req.body?.method === 'initialize'; // 检测云函数环境 const isCloudFunction = !!( process.env.SERVERLESS || process.env.SCF_RUNTIME_API || process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.TENCENTCLOUD_RUNENV || process.env.SCF_NAMESPACE || process.env._SCF_SERVER_PORT || req.headers['x-scf-request-id'] || req.headers['x-scf-region'] || process.env.FORCE_CLOUD_FUNCTION === 'true' ); if (isCloudFunction) { // 云函数环境:使用专门的处理器 const cloudHandler = new CloudFunctionMCPHandler(mcpServer); return await cloudHandler.handleMCPRequest(req, res); } // 本地环境:使用传统的会话管理 try { // 修复 Accept 头部 if (!req.headers.accept || !req.headers.accept.includes('text/event-stream')) { req.headers.accept = 'application/json, text/event-stream'; } // 检查现有会话ID const sessionId = req.headers['mcp-session-id'] as string | undefined; let transport: StreamableHTTPServerTransport; if (!isCloudFunction && sessionId && mcpTransports[sessionId]) { transport = mcpTransports[sessionId]; } else if (isInitializeRequest(req.body) || isCloudFunction) { transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID(), onsessioninitialized: (sessionId) => { if (!isCloudFunction) { mcpTransports[sessionId] = transport; } // 存储认证用户信息 const pendingUser = req.pendingUser; if (pendingUser) { sessionUserMap.set(sessionId, pendingUser); console.log('待处理用户信息已存储到新会话:', { sessionId, userId: pendingUser.id }); delete req.pendingUser; } } }); // 传输关闭时清理 if (!isCloudFunction) { transport.onclose = () => { if (transport.sessionId) { console.log('Cleaning up transport for session:', transport.sessionId); delete mcpTransports[transport.sessionId]; sessionUserMap.delete(transport.sessionId); } }; } // 连接到 MCP 服务器 await mcpServer.connect(transport); } else { const errorDetails = { hasSessionId: !!sessionId, sessionIdExists: sessionId ? !!mcpTransports[sessionId] : false, isInitialize: isInitializeRequest(req.body), requestMethod: req.body?.method, requestId: req.body?.id }; console.log('Invalid MCP request:', errorDetails); return res.status(400).json({ jsonrpc: '2.0', error: { code: -32000, message: `Bad Request: ${!sessionId ? 'No session ID provided and not an initialize request' : 'Invalid session ID'}`, data: errorDetails }, id: req.body?.id || null }); } // 将认证用户信息存储到会话中 if (authenticatedUser) { let currentSessionId = sessionId; if (!currentSessionId && isInitRequest) { req.pendingUser = authenticatedUser; } else if (currentSessionId) { sessionUserMap.set(currentSessionId, authenticatedUser); console.log('用户信息已存储到会话:', { sessionId: currentSessionId, userId: authenticatedUser.id }); } } await transport.handleRequest(req, res, req.body); } catch (error) { console.error('MCP 请求处理错误:', error); if (!res.headersSent) { res.status(500).json({ jsonrpc: '2.0', error: { code: -32603, message: 'Internal server error' }, id: null }); } } }); // MCP 协议端点 - GET 请求处理服务器到客户端的通知(SSE) app.get(['/mcp', '/mcp/'], async (req, res) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; if (!sessionId || !mcpTransports[sessionId]) { return res.status(400).send('Invalid or missing session ID'); } const transport = mcpTransports[sessionId]; await transport.handleRequest(req, res); }); // MCP 协议端点 - DELETE 请求处理会话终止 app.delete(['/mcp', '/mcp/'], async (req, res) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; if (!sessionId || !mcpTransports[sessionId]) { return res.status(400).send('Invalid or missing session ID'); } const transport = mcpTransports[sessionId]; await transport.handleRequest(req, res); }); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Ayi456/visual-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server