UNPKG

bc_resource_mcp

Version:

MCP server for Baichuan resource

102 lines (101 loc) 4.06 kB
import express from "express"; import cors from "cors"; import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js"; import { createMcpServer } from "./server.js"; import { Logger } from "../utils/logger.js"; import { loadConfig } from "../utils/config.js"; // 将服务器启动逻辑封装到函数中 export async function startSseServer() { const config = loadConfig(); const app = express(); app.use(cors({ origin: config.allowedOrigins, methods: ["GET", "POST"], allowedHeaders: ["Content-Type", "Authorization"], })); const transports = {}; app.get("/health", (req, res) => { res.status(200).json({ status: "ok", version: config.version, uptime: process.uptime(), timestamp: new Date().toISOString(), connections: transports.size, }); }); app.get("/sse", async (req, res) => { const transport = new SSEServerTransport("/messages", res); const moduleId = req.headers["moduleid"]; Logger.debug("收到 SSE 连接请求", { headers: req.headers }); if (!moduleId) { Logger.error("缺少必要的 moduleId"); res.status(400).json({ error: "Missing moduleId" }); return; } const sessionId = transport.sessionId; Logger.info(`新的 SSE 连接建立: ${sessionId}`); transports[sessionId] = transport; req.on("close", () => { Logger.info(`SSE 连接关闭: ${sessionId}`); delete transports[sessionId]; }); const mcpServer = createMcpServer(moduleId); await mcpServer.connect(transport); Logger.info(`MCP 服务器连接成功: ${sessionId}`); }); app.post("/messages", async (req, res) => { try { Logger.debug("收到客户端消息", req.query); const sessionId = req.query.sessionId; if (Object.keys(transports).length === 0) { throw new Error(`没有活跃的SSE连接`); } const transport = transports[sessionId]; if (!transport) { throw new Error(`没有找到会话ID为 ${sessionId} 的SSE连接`); } await transport.handlePostMessage(req, res); } catch (error) { Logger.error("处理客户端消息失败", error); res.status(500).json({ error: "处理消息失败", message: error.message }); } }); async function closeAllConnections() { Logger.info(`关闭所有连接 (${Object.keys(transports).length}个)`); for (const [sessionId, transport] of Object.entries(transports)) { try { await transport.close(); Logger.info(`已关闭连接:${sessionId}`); } catch (error) { Logger.error(`关闭连接失败:${sessionId}`, error); } } for (const sessionId in transports) { delete transports[sessionId]; } } app.use((error, req, res, next) => { Logger.error("未处理的异常", error); res.status(500).json({ error: "服务器内部错误", message: error.message }); }); process.on("SIGINT", async () => { Logger.info("收到SIGINT信号,正在关闭服务器..."); await closeAllConnections(); process.exit(0); }); process.on("SIGTERM", async () => { Logger.info("收到SIGTERM信号,正在关闭服务器..."); await closeAllConnections(); process.exit(0); }); const port = config.port; const server = app.listen(port, () => { Logger.info(`BC Resource MCP 服务器已启动,监听端口:${port}`); Logger.info(`- SSE 连接端点: http://localhost:${port}/sse`); Logger.info(`- SSE 消息处理端点: http://localhost:${port}/messages`); Logger.info(`- 健康检查端点: http://localhost:${port}/health`); }); return server; }