基于TypeScript的MCP Server:Streamable HTTP

半兽人 发表于: 2025-07-10   最后更新时间: 2025-12-02 13:54:54  
{{totalSubscript}} 订阅, 98 游览

开发要求

  • Node.js ≥ 18.0.0
  • npm ≥ 9.0.0
  • TypeScript ≥ 5.0.0

session-server.ts

import express from "express";
import { randomUUID } from "node:crypto";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";

const app = express();
app.use(express.json());

// 会话ID与传输层映射表
const transports: { [sessionId: string]: StreamableHTTPServerTransport } = {};

// 处理客户端请求
app.post('/mcp', async (req, res) => {

    const sessionId = req.headers['mcp-session-id'] as string | undefined;
    let transport: StreamableHTTPServerTransport;

    console.log("收到请求:", JSON.stringify(req.body, null, 2));
    console.log("sessionId:", sessionId);

    if (sessionId && transports[sessionId]) {
        // 复用现有会话
        transport = transports[sessionId];
    } else if (!sessionId && isInitializeRequest(req.body)) {
        // 新建会话
        transport = new StreamableHTTPServerTransport({
            sessionIdGenerator: () => randomUUID(),
            onsessioninitialized: (sessionId) => {
                transports[sessionId] = transport;
            }
        });

        // 清理会话
        transport.onclose = () => {
            if (transport.sessionId) delete transports[transport.sessionId];
        };

        const server = new McpServer({
            name: "示例服务器",
            version: "1.0.0"
        });

        // ... 配置服务器资源、工具和提示 ...
        // Add an addition tool
        server.tool("add", 'Add two numbers', { a: z.number(), b: z.number() },
            async ({ a, b }) => ({
                content: [{ type: "text", text: String(a + b) }]
            })
        );

        await server.connect(transport);
    } else {
        res.status(400).json({
            jsonrpc: '2.0',
            error: {
                code: -32000,
                message: '错误请求:无效的会话ID'
            }
        });
        return;
    }

    await transport.handleRequest(req, res, req.body);
});

// 处理GET/DELETE请求
const handleSessionRequest = async (req: express.Request, res: express.Response) => {
    const sessionId = req.headers['mcp-session-id'] as string | undefined;
    if (!sessionId || !transports[sessionId]) {
        res.status(400).send('无效或缺失的会话ID');
        return;
    }
    await transports[sessionId].handleRequest(req, res);
};

app.get('/mcp', handleSessionRequest);
app.delete('/mcp', handleSessionRequest);

app.listen(3000);

测试

初始化

curl -i -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 0,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-06-18",
      "capabilities": {
        "sampling": {},
        "roots": {
          "listChanged": true
        }
      },
      "clientInfo": {
        "name": "curl-test",
        "version": "0.1"
      }
    }
  }'

返回

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
mcp-session-id: e9c34a54-35af-4da9-a78c-6c91faf82414
Date: Thu, 10 Jul 2025 11:02:32 GMT
Transfer-Encoding: chunked

event: message
data: {"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{"listChanged":true}},"serverInfo":{"name":"示例服务器","version":"1.0.0"}},"jsonrpc":"2.0","id":0}

获取功能列表:

curl -i -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "mcp-session-id: cb8aa83e-f06a-4c73-9714-5ead68afbae1" \
  -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {
    "_meta": {
      "progressToken": 1
    }
  }
}'

调用其中的功能:

curl -i -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "mcp-session-id: cb8aa83e-f06a-4c73-9714-5ead68afbae1" \
  -d '{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "_meta": {
      "progressToken": 3
    },
    "name": "add",
    "arguments": {
      "a": 10,
      "b": 20
    }
  }
}'
MCP
更新于 2025-12-02

查看MCP更多相关的文章或提一个关于MCP的问题,也可以与我们一起分享文章