MCP协议说明

MCP 协议说明与接入设计

本文档用于说明 MCP(Model Context Protocol)的基本概念、连接方式、会话机制、认证授权流程,以及工具中心类平台中 MCP 服务的推荐实现方式。

  • API 域名:https://api.example.com
  • MCP 地址:https://api.example.com/mcp
  • API Key:tc_xxxxxxxx
  • 用户 ID:user_id
  • Session ID:mcp_sess_xxxxx

1. MCP 是什么

MCP 全称是 Model Context Protocol,可以理解为一种:

AI 客户端 / Agent 与外部工具服务之间的标准通信协议。

它解决的问题是:

  • 客户端如何发现服务端有哪些工具;
  • 客户端如何知道每个工具需要什么参数;
  • 客户端如何调用工具;
  • 服务端如何按照用户权限只暴露可用工具;
  • 服务端如何将工具执行结果返回给客户端。

在工具中心类平台中,MCP 通常用于让外部 AI 客户端调用平台内的工具,例如:

  • 文本处理工具;
  • 文件解析工具;
  • 视频解析工具;
  • 数据查询工具;
  • 内部自动化工具。

MCP 本身不是某一个简单 REST 接口,而是一套基于 JSON-RPC 的协议规范,常见核心方法包括:

  • initialize
  • tools/list
  • tools/call

此外,很多平台会额外提供一个非标准但很实用的说明接口:

  • GET /mcp/info

2. MCP 与普通 HTTP 工具调用的区别

很多工具平台同时支持两种调用方式:

2.1 普通 HTTP 工具调用

典型调用方式如下:

http 复制代码
POST /tools/run
X-API-Key: tc_xxxxxxxx
Content-Type: application/json

{
  "tool_name": "text_summary",
  "input": {
    "text": "待处理文本"
  }
}

这种方式直观、简单,适合脚本、后端服务、CI/CD 或普通业务系统调用。

2.2 MCP 工具调用

MCP 更偏向 AI 客户端协议化调用。客户端先和服务端建立协议会话,然后通过 JSON-RPC 发现和调用工具。

典型流程是:

text 复制代码
initialize
  ↓
tools/list
  ↓
tools/call

相比普通 HTTP,MCP 更关注:

  • 工具发现;
  • 工具 schema;
  • 客户端能力协商;
  • 会话上下文;
  • Agent 生态兼容。

3. MCP 常见传输方式

MCP 可以运行在不同传输方式上。常见方式包括:

传输方式 说明 常见场景
Stdio 客户端启动本地进程,通过标准输入输出通信 本地工具、本地桌面集成
SSE + HTTP 使用 SSE 建立服务端推送通道,再通过 HTTP 发送消息 早期远程 MCP 实现
Streamable HTTP 新版远程 MCP 推荐方式,通过 HTTP 请求和会话头维持上下文 云端工具服务、Web 服务
WebSocket 通过双向长连接传输 JSON-RPC 消息 实时双向通信场景
Stateless HTTP 每个请求独立携带 API Key,无持久会话 简化实现、调试或兼容模式

对于工具中心类平台,通常推荐:

text 复制代码
Streamable HTTP + 服务端 Session

原因:

  • 适合远程服务;
  • 适合 Nginx / API Gateway 代理;
  • 适合 Docker / Kubernetes 部署;
  • 可通过 Redis 维护 session;
  • 易于横向扩展;
  • 相比 WebSocket,运维复杂度更低。

4. /mcp/info 是什么

GET /mcp/info 通常不是 MCP 标准 JSON-RPC 方法,而是平台提供的辅助说明接口。

它可以用于返回:

  • MCP 服务名称;
  • MCP 服务地址;
  • 支持的传输方式;
  • 认证方式;
  • 客户端配置示例;
  • 协议版本;
  • 能力说明。

示例:

http 复制代码
GET /mcp/info

可能返回:

json 复制代码
{
  "name": "tool-center-mcp",
  "endpoint": "https://api.example.com/mcp",
  "auth": {
    "type": "api_key",
    "header": "X-API-Key"
  },
  "transports": ["streamable-http"],
  "protocolVersion": "2024-11-05"
}

4.1 /mcp/info 是否需要认证

取决于它返回什么内容。

如果只返回通用说明,可以公开:

text 复制代码
可公开访问

如果返回用户相关信息,例如:

  • 当前用户;
  • 当前 API Key;
  • 已订阅工具列表;
  • 账号权限;

则必须校验:

http 复制代码
X-API-Key: tc_xxxxxxxx

推荐做法:

text 复制代码
/mcp/info 默认只返回通用说明;
带 API Key 时可额外返回当前 Key 可访问的摘要信息。

5. MCP 三个核心方法

MCP 的常见协议流程主要包含三个核心方法:

  1. initialize
  2. tools/list
  3. tools/call

5.1 initialize

initialize 是 MCP 会话的初始化方法。

客户端通过它告诉服务端:

  • 客户端名称;
  • 客户端版本;
  • 支持的协议版本;
  • 客户端能力。

示例请求:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": {
      "name": "example-client",
      "version": "1.0.0"
    }
  }
}

示例响应:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "tools": {}
    },
    "serverInfo": {
      "name": "tool-center",
      "version": "1.0.0"
    }
  }
}

initialize 的作用不是调用工具,而是建立协议上下文。


5.2 tools/list

tools/list 用于获取当前会话可访问的工具列表。

请求示例:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}

服务端应根据当前 session 对应的用户和 API Key 查询权限,只返回该用户已订阅、且当前可用的工具。

响应示例:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "text_summary",
        "description": "对文本内容进行摘要",
        "inputSchema": {
          "type": "object",
          "properties": {
            "text": {
              "type": "string",
              "description": "需要摘要的文本"
            }
          },
          "required": ["text"]
        }
      }
    ]
  }
}

注意:

text 复制代码
tools/list 不能返回用户未订阅的工具。

5.3 tools/call

tools/call 用于调用某个具体工具。

请求示例:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "text_summary",
    "arguments": {
      "text": "这是一段需要摘要的文本。"
    }
  }
}

服务端处理逻辑:

text 复制代码
1. 根据 session 获取 user_id / api_key_id;
2. 检查 API Key 是否仍然有效;
3. 检查用户是否订阅 params.name 对应工具;
4. 检查工具是否 active;
5. 校验 arguments 是否符合工具 schema;
6. 执行工具;
7. 返回结果。

响应示例:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "摘要结果..."
      }
    ]
  }
}

如果未订阅工具,应返回权限错误,例如:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32003,
    "message": "当前用户未订阅该工具"
  }
}

6. 推荐执行顺序

严格来说,/mcp/info 不属于 MCP 会话本身,它是辅助信息接口。

推荐整体顺序如下:

text 复制代码
可选:GET /mcp/info
  ↓
连接或请求 /mcp,携带 X-API-Key
  ↓
initialize
  ↓
tools/list
  ↓
tools/call

更完整地说:

text 复制代码
1. 用户在控制台创建 API Key;
2. 用户将 API Key 配置到 MCP 客户端;
3. 客户端访问 /mcp/info 或直接连接 /mcp;
4. 服务端验证 X-API-Key;
5. 服务端创建或恢复 MCP session;
6. 客户端发送 initialize;
7. 服务端返回协议能力;
8. 客户端发送 tools/list;
9. 服务端返回当前用户已订阅工具;
10. 客户端发送 tools/call;
11. 服务端校验权限并执行工具。

7. MCP Session 是什么

MCP session 可以理解为一次客户端与 MCP 服务端之间的协议会话。

它保存的是:

  • 当前连接属于哪个用户;
  • 当前连接使用哪个 API Key;
  • 是否已初始化;
  • 客户端信息;
  • 协议版本;
  • 会话创建时间;
  • 最后活跃时间。

示例结构:

json 复制代码
{
  "session_id": "mcp_sess_xxxxx",
  "user_id": 10001,
  "api_key_id": 20001,
  "api_key_prefix": "tc_abcd",
  "initialized": true,
  "client_info": {
    "name": "example-client",
    "version": "1.0.0"
  },
  "protocol_version": "2024-11-05",
  "created_at": "2026-01-01T00:00:00Z",
  "last_seen_at": "2026-01-01T00:10:00Z"
}

注意:

text 复制代码
session 不是浏览器登录 session,也不是 JWT。

它是 MCP 协议层的服务端上下文。


8. Session 由谁维护

MCP session 的核心状态应由 服务端维护

客户端通常只保存:

  • session_id
  • 或保持连接本身;
  • 或保存 Mcp-Session-Id
  • 或保存请求 ID 用于匹配响应。

服务端保存:

  • user_id
  • api_key_id
  • 是否已认证;
  • 是否已初始化;
  • 客户端信息;
  • 权限上下文;
  • 会话 TTL;
  • 长连接对象(如果是 SSE / WebSocket)。

不能把用户身份和权限完全交给客户端保存,因为客户端不可信。


9. 不同传输方式下的 Session 维护

9.1 SSE + HTTP

常见流程:

text 复制代码
Client --GET /mcp/sse--> Server
Client --POST /mcp/messages?session_id=xxx--> Server
Server --SSE event--> Client

Session 维护方式:

内容 维护方
session 状态 服务端
session_id 客户端保存并携带
SSE 连接对象 服务端保存
用户身份与权限 服务端

9.2 Streamable HTTP

常见流程:

text 复制代码
第一次请求:
POST /mcp
X-API-Key: tc_xxxxxxxx

后续请求:
POST /mcp
Mcp-Session-Id: mcp_sess_xxxxx

第一次请求后,服务端返回:

http 复制代码
Mcp-Session-Id: mcp_sess_xxxxx

Session 维护方式:

内容 维护方
session 数据 服务端
Mcp-Session-Id 客户端保存并携带
用户身份与权限 服务端
请求/响应 每次 HTTP 请求

9.3 WebSocket

常见流程:

text 复制代码
Client --WebSocket /mcp--> Server
headers: X-API-Key

WebSocket 连接本身就是会话载体。

服务端通常会在 socket 上保存上下文:

json 复制代码
{
  "session_id": "mcp_sess_xxxxx",
  "user_id": 10001,
  "api_key_id": 20001,
  "initialized": true
}

Session 维护方式:

内容 维护方
WebSocket 连接 双方保持
session 状态 服务端
用户身份与权限 服务端
请求 ID 客户端生成,双方匹配

9.4 Stateless HTTP

如果没有实现 session,也可以每次请求都携带 API Key:

http 复制代码
POST /mcp
X-API-Key: tc_xxxxxxxx

服务端每次请求都验证 API Key。

优点:

  • 实现简单;
  • 无需 session 存储;
  • 请求天然无状态。

缺点:

  • 不易维护 initialized 状态;
  • 不容易记录客户端信息;
  • 不完全符合会话型 MCP 语义;
  • 对复杂客户端兼容性较差。

10. 认证与授权

工具中心类平台通常有两套凭证:

场景 凭证 请求头
管理控制台 JWT Authorization: Bearer <token>
工具调用 / MCP API Key X-API-Key: tc_xxxxxxxx

原则:

text 复制代码
管理台使用 JWT;
工具调用和 MCP 使用 API Key;
不要把 JWT 交给 MCP 客户端;
不要把 API Key 当成前端登录态使用。

11. API Key 应该在哪一步验证

11.1 /mcp/info

如果只返回通用服务说明,可以不验证。

如果返回用户相关信息,必须验证 API Key。


11.2 建立 /mcp 会话时

必须验证:

http 复制代码
X-API-Key: tc_xxxxxxxx

服务端应检查:

text 复制代码
1. API Key 是否存在;
2. API Key 是否 active;
3. API Key 是否过期;
4. API Key 所属用户是否 active;
5. 是否允许创建 MCP session。

验证成功后创建 session。


11.3 initialize

如果 session 已在连接入口创建,initialize 可复用 session 上下文。

它主要负责协议协商,不应承担主要权限判断。


11.4 tools/list

必须基于当前 session 的用户身份进行授权过滤。

逻辑:

text 复制代码
session.user_id
  ↓
查询 active subscriptions
  ↓
只返回已订阅且 active 的工具

11.5 tools/call

必须再次进行实时授权校验。

即使 tools/list 已经过滤过工具,tools/call 仍不能信任客户端。

服务端应检查:

text 复制代码
1. session 是否存在;
2. API Key 是否仍 active;
3. API Key 是否过期;
4. 用户是否仍 active;
5. 用户是否订阅 params.name 对应工具;
6. 工具是否 active;
7. arguments 是否符合工具 schema。

原因:

  • 用户可能手写 tools/call
  • 用户可能绕过 tools/list
  • 订阅可能在 session 存活期间被取消;
  • API Key 可能在 session 存活期间被吊销;
  • 工具可能临时下线。

12. 推荐的 Session 存储方案

12.1 单实例开发环境

可以使用进程内内存:

text 复制代码
Map<string, McpSession>

优点:

  • 简单;
  • 性能高;
  • 易调试。

缺点:

  • 服务重启 session 丢失;
  • 多实例无法共享;
  • 不适合生产横向扩容。

12.2 生产环境

推荐使用 Redis:

text 复制代码
mcp:session:mcp_sess_xxxxx -> JSON

推荐 TTL:

text 复制代码
30 分钟 ~ 2 小时

每次请求刷新 TTL。

Redis Value 示例:

json 复制代码
{
  "session_id": "mcp_sess_xxxxx",
  "user_id": 10001,
  "api_key_id": 20001,
  "api_key_prefix": "tc_abcd",
  "initialized": true,
  "client_info": {
    "name": "example-client",
    "version": "1.0.0"
  },
  "protocol_version": "2024-11-05",
  "created_at": "2026-01-01T00:00:00Z",
  "last_seen_at": "2026-01-01T00:10:00Z"
}

13. 推荐实现:Streamable HTTP + Redis Session

推荐架构:

text 复制代码
MCP Client
  ↓ HTTPS
API Gateway / Nginx
  ↓
MCP Server
  ↓
Redis: MCP Session
  ↓
Database: User / API Key / Subscription / Service
  ↓
Tool Worker

推荐流程:

text 复制代码
GET /mcp/info
  ↓
返回 MCP 服务说明

POST /mcp initialize + X-API-Key
  ↓
验证 API Key
  ↓
创建 Redis session
  ↓
返回 Mcp-Session-Id

POST /mcp tools/list + Mcp-Session-Id
  ↓
读取 Redis session
  ↓
查询用户已订阅服务
  ↓
返回工具列表

POST /mcp tools/call + Mcp-Session-Id
  ↓
读取 Redis session
  ↓
实时校验 API Key / 订阅 / 工具状态
  ↓
执行工具
  ↓
返回结果

14. 客户端配置示例

json 复制代码
{
  "mcpServers": {
    "tool-center": {
      "url": "https://api.example.com/mcp",
      "headers": {
        "X-API-Key": "tc_xxxxxxxx"
      }
    }
  }
}

说明:

  1. url 指向 MCP 入口;
  2. X-API-Key 使用用户在控制台创建的 API Key;
  3. 用户必须先订阅工具;
  4. tools/list 只返回已订阅工具;
  5. tools/call 调用未订阅工具应返回权限错误。

15. Nginx 代理注意事项

如果使用远程 MCP,需要确保代理支持长连接或流式响应。

示例:

nginx 复制代码
location /mcp {
    proxy_pass         http://backend_api;
    proxy_http_version 1.1;
    proxy_set_header   Host              $host;
    proxy_set_header   X-Real-IP         $remote_addr;
    proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;
    proxy_set_header   Upgrade           $http_upgrade;
    proxy_set_header   Connection        "upgrade";
    proxy_buffering    off;
    proxy_cache        off;
    proxy_read_timeout 86400s;
    proxy_send_timeout 86400s;
    chunked_transfer_encoding off;
}

注意:

  • SSE / Streamable HTTP 通常需要关闭 buffering;
  • 长连接需要较长 proxy_read_timeout
  • 如果不使用 WebSocket,Upgrade 头不是必须,但保留通常不影响;
  • 如果使用多实例,session 应放 Redis,不应只放本地内存。

16. 常见错误与处理

16.1 API Key 无效

建议返回:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32001,
    "message": "API Key 无效或已过期"
  }
}

HTTP 状态可使用:

text 复制代码
401 Unauthorized

16.2 未订阅工具

建议返回:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32003,
    "message": "当前用户未订阅该工具"
  }
}

HTTP 状态可使用:

text 复制代码
403 Forbidden

16.3 工具不存在

建议返回:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32602,
    "message": "工具不存在或不可用"
  }
}

16.4 参数错误

建议返回:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32602,
    "message": "工具参数不合法"
  }
}

17. 安全建议

  1. API Key 只展示一次

    • 创建成功时展示完整 Key;
    • 后续只展示前缀;
    • 不在前端持久化完整 Key。
  2. MCP 不使用 JWT

    • JWT 用于管理控制台;
    • MCP / 工具调用使用 API Key。
  3. tools/list 按订阅过滤

    • 不暴露未订阅工具;
    • 不暴露内部工具。
  4. tools/call 必须实时校验权限

    • 不能因为 session 已认证就跳过权限检查。
  5. Session 设置 TTL

    • 推荐 30 分钟到 2 小时;
    • 每次请求刷新 TTL。
  6. API Key 吊销应尽快生效

    • tools/call 时检查 API Key 状态;
    • 可在吊销 Key 时清理相关 MCP session。
  7. 记录审计日志

    • 记录调用时间;
    • 记录 API Key 前缀;
    • 记录用户 ID;
    • 记录工具名称;
    • 记录成功/失败状态;
    • 不记录完整 API Key。

18. 推荐后端伪代码

18.1 初始化 session

python 复制代码
async def handle_initialize(request):
    api_key = request.headers.get("X-API-Key")
    key_info = verify_api_key(api_key)

    if not key_info:
        return jsonrpc_error(request.id, -32001, "API Key 无效或已过期")

    session_id = create_session_id()
    session = {
        "session_id": session_id,
        "user_id": key_info.user_id,
        "api_key_id": key_info.id,
        "initialized": True,
        "client_info": request.params.get("clientInfo"),
        "protocol_version": request.params.get("protocolVersion"),
    }

    await redis.setex(f"mcp:session:{session_id}", 7200, json.dumps(session))

    return response_with_header(
        jsonrpc_result(request.id, {
            "protocolVersion": "2024-11-05",
            "capabilities": {"tools": {}},
            "serverInfo": {"name": "tool-center", "version": "1.0.0"},
        }),
        headers={"Mcp-Session-Id": session_id},
    )

18.2 获取工具列表

python 复制代码
async def handle_tools_list(request):
    session = await get_session(request.headers.get("Mcp-Session-Id"))
    if not session:
        return jsonrpc_error(request.id, -32002, "MCP session 不存在或已过期")

    subscriptions = get_active_subscriptions(session["user_id"])
    tools = build_tools_from_subscriptions(subscriptions)

    return jsonrpc_result(request.id, {"tools": tools})

18.3 调用工具

python 复制代码
async def handle_tools_call(request):
    session = await get_session(request.headers.get("Mcp-Session-Id"))
    if not session:
        return jsonrpc_error(request.id, -32002, "MCP session 不存在或已过期")

    tool_name = request.params["name"]
    arguments = request.params.get("arguments", {})

    if not is_api_key_active(session["api_key_id"]):
        return jsonrpc_error(request.id, -32001, "API Key 已失效")

    if not has_active_subscription(session["user_id"], tool_name):
        return jsonrpc_error(request.id, -32003, "当前用户未订阅该工具")

    validate_tool_arguments(tool_name, arguments)
    result = await run_tool(tool_name, arguments)

    return jsonrpc_result(request.id, {
        "content": [
            {"type": "text", "text": result}
        ]
    })

19. 最佳实践总结

推荐设计:

text 复制代码
传输方式:Streamable HTTP
认证方式:X-API-Key
Session 存储:Redis
Session 标识:Mcp-Session-Id
工具权限:基于用户订阅实时判断

推荐流程:

text 复制代码
GET /mcp/info
  可选,用于查看服务说明

POST /mcp initialize + X-API-Key
  验证 API Key
  创建 session
  返回 Mcp-Session-Id

POST /mcp tools/list + Mcp-Session-Id
  使用 session.user_id
  返回已订阅工具

POST /mcp tools/call + Mcp-Session-Id
  使用 session.user_id / api_key_id
  再次校验 API Key 和订阅
  执行工具

核心原则:

text 复制代码
身份认证可复用 session;
关键操作授权必须实时校验。

20. 一句话说明

MCP 是 AI 客户端与工具服务之间的标准协议。对于远程工具平台,推荐使用 Streamable HTTP,通过 X-API-Key 完成首次认证,通过服务端 session 维持上下文,通过 tools/list 暴露已订阅工具,通过 tools/call 调用工具,并在每次关键操作时实时校验 API Key、订阅和工具状态。

相关推荐
小锋java12343 小时前
【技术专题】LangChain4j 开发Java Agent智能体 - 会话记忆
java·人工智能
青岛前景互联信息技术有限公司3 小时前
AI驱动的消防通信指挥系统:实现风险预警与智能接处警的秒级响应
大数据·人工智能·物联网
美团技术团队3 小时前
报名|ACL'26 美团中稿精选:从能力评测到推理优化,构建生成新范式
人工智能
Legend NO243 小时前
非结构化数据治理全解:从合规痛点、中台架构到 AI 智能化分类落地
大数据·人工智能·架构
闻道参看3 小时前
智能搜索生态驱动的流量卡位实操:中小微入局者的 GEO 优化 服务选型全维度实证分析
大数据·人工智能
Bruce_Liuxiaowei4 小时前
当Windows成为Agent的监狱-操作系统级Agent安全架构深度解读
人工智能·windows·安全·安全架构·智能体
王_teacher4 小时前
ResNet-18网络模型+原理解析+Pytorch实现+手写模型
人工智能·cnn·卷积神经网络
树谷-胡老师4 小时前
2024年中国大型数据中心空间分布及环境属性数据集
人工智能·机器学习
小马哥crazymxm4 小时前
自动驾驶“跨化身”!Sensor2Sensor用4D高斯泼溅+扩散模型,把网络行车记录仪变成高精度LiDAR真数据
人工智能·机器学习·自动驾驶