MCP(模型上下文协议)的底层交互是一个精巧的流程,核心是通过 JSON-RPC 2.0 格式在预定义的通道上交换标准化的消息。
下面的内容会为你完整拆解这个过程。同时,为了让整个流程更清晰,我会引入一个具体的场景:假设你的 Spring Boot 服务里有一个 get_weather 工具,而客户端程序(比如一个AI应用)需要调用它来获取天气信息。
🔌 核心架构概览
整个架构由几个关键部分组成:
-
MCP 客户端 (MCP Client):AI 应用(如 Claude Desktop)内部的组件,负责发起所有请求。
-
MCP 服务端 (MCP Server):你的 Spring Boot 服务,负责响应请求并执行业务逻辑。
-
传输层 (Transport):客户端与服务端通信的方式,MCP 协议主要定义了两种标准传输机制。
- 标准输入/输出 (stdio):用于本地通信,客户端将服务端作为子进程启动,通过标准输入(stdin)和标准输出(stdout)交换消息。消息之间通过换行符分隔。
- HTTP with Server-Sent Events (SSE) :用于网络通信,客户端通过 HTTP 与服务端交互。服务端必须提供两个端点:一个用于客户端接收消息 的 SSE
GET端点,和一个用于客户端发送消息 的常规 HTTPPOST端点。
-
消息协议 (JSON-RPC 2.0):所有传输的消息都遵循 JSON-RPC 2.0 规范,主要有以下三种类型。
- 请求 (Request) :客户端发起的调用,包含唯一的
id,服务端必须对此做出响应(Response)。 - 通知 (Notification) :客户端发起的消息,没有
id字段,服务端不需要做出响应。 - 响应 (Response) :服务端对"请求"的回复,包含与请求相同的
id和执行结果或错误信息。
- 请求 (Request) :客户端发起的调用,包含唯一的
📡 核心生命周期与接口详解
MCP 的生命周期通常包含以下几个阶段,我会在每个阶段都给出清晰的接口定义和调用示例。
1. 连接与初始化 (Initialization)
这是会话建立的"握手"阶段,目的是让客户端和服务端互相认识,并就协议版本、能力等信息达成一致。
触发时点:当 MCP 客户端首次连接到 MCP 服务端时。
1.1 客户端发现服务端点 (SSE 模式独有)
如果是 SSE 模式 ,客户端首先会向服务端的 SSE 端点发起 GET 请求。服务端响应后,会通过一个名为 endpoint 的 SSE 事件,将用于后续通信的 POST 端点地址告诉客户端。
-
Client → Server (SSE GET)
httpGET /sse HTTP/1.1 Host: your-spring-boot-server.com -
Server → Client (SSE endpoint event)
jsonevent: endpoint data: /message?sessionId=abc123
1.2 客户端发送初始化请求
客户端向服务端发送 initialize 请求,告知自己的协议版本、客户端信息和支持的能力。
-
Client → Server (Request)
json{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "0.1.0", "capabilities": { "roots": { "listChanged": true } }, "clientInfo": { "name": "my-ai-client", "version": "1.0.0" } } }
1.3 服务端响应并返回自身能力
服务端收到后,会返回自己的协议信息、能力和服务端信息。
-
Server → Client (Response)
json{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "0.1.0", "capabilities": { "tools": { "listChanged": true } }, "serverInfo": { "name": "my-spring-mcp-server", "version": "1.0.0" } } }
1.4 客户端发送初始化完成通知(必须发送,否则工具发现请求会卡住!!!)
客户端收到成功响应后,发送一个 initialized 通知,表示自己已完成初始化,通信通道正式建立。
-
Client → Server (Notification)
json{ "jsonrpc": "2.0", "method": "notifications/initialized" }
2. 工具发现 (Tool Discovery)
让客户端能从服务端"拉取"一份可用工具的清单,包括工具的名称、描述和输入参数定义(JSON Schema)。这是 MCP 实现"即插即用"的关键。
触发时点:在初始化阶段完成之后,由客户端主动发起。这也是服务端向外"介绍"自己能力的方式。
-
Client → Server (Request)
json{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" } -
Server → Client (Response)
json{ "jsonrpc": "2.0", "id": 2, "result": { "tools": [ { "name": "get_weather", "description": "获取指定城市的当前天气信息", "inputSchema": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称,例如:北京" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "温度单位" } }, "required": ["city"] } } ] } }
3. 工具调用 (Tool Call)
这是最重要的业务交互阶段。客户端根据 tools/list 返回的元数据,构造并发送 tools/call 请求,服务端执行后返回结果。
触发时点:当 AI 模型决定使用某个工具时,由 MCP 客户端代理发起此请求。
-
Client → Server (Request)
json{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "get_weather", "arguments": { "city": "杭州", "unit": "celsius" } } } -
Server → Client (Response)
json{ "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "text", "text": "杭州当前天气:晴,25°C" } ], "isError": false } }
补充说明:协议也支持服务端通过 SSE 流式返回结果,这种方式对于需要长时间处理的任务特别有用。例如,可以先返回一个进度通知,最后再返回最终结果。
4. 关闭会话 (Shutdown & Exit)
当 AI 应用与 MCP 服务端的交互结束时,需要优雅地关闭连接。
触发时点:由客户端发起,表示会话结束。
-
Client → Server (Request)
json{ "jsonrpc": "2.0", "id": 4, "method": "shutdown" } -
Server → Client (Response)
json{ "jsonrpc": "2.0", "id": 4, "result": {} } -
Client → Server (Notification)
json{ "jsonrpc": "2.0", "method": "exit" }
总的来说,MCP 的整个工作流程可以看作是一个结构化的对话,由"握手"(初始化)开始,接着"展示菜单"(工具发现),然后"点菜"(工具调用),最后"结账离开"(关闭会话)。每一步都有明确的 JSON-RPC 消息来驱动。