MCP 通信

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 端点,和一个用于客户端发送消息 的常规 HTTP POST 端点。
  • 消息协议 (JSON-RPC 2.0):所有传输的消息都遵循 JSON-RPC 2.0 规范,主要有以下三种类型。

    • 请求 (Request) :客户端发起的调用,包含唯一的 id,服务端必须对此做出响应(Response)。
    • 通知 (Notification) :客户端发起的消息,没有 id 字段,服务端不需要做出响应。
    • 响应 (Response) :服务端对"请求"的回复,包含与请求相同的 id 和执行结果或错误信息。

📡 核心生命周期与接口详解

MCP 的生命周期通常包含以下几个阶段,我会在每个阶段都给出清晰的接口定义和调用示例。

1. 连接与初始化 (Initialization)

这是会话建立的"握手"阶段,目的是让客户端和服务端互相认识,并就协议版本、能力等信息达成一致。

触发时点:当 MCP 客户端首次连接到 MCP 服务端时。

1.1 客户端发现服务端点 (SSE 模式独有)

如果是 SSE 模式 ,客户端首先会向服务端的 SSE 端点发起 GET 请求。服务端响应后,会通过一个名为 endpoint 的 SSE 事件,将用于后续通信的 POST 端点地址告诉客户端。

  • Client → Server (SSE GET)

    http 复制代码
    GET /sse HTTP/1.1
    Host: your-spring-boot-server.com
  • Server → Client (SSE endpoint event)

    json 复制代码
    event: 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 消息来驱动。

相关推荐
MicrosoftReactor2 小时前
技术速递|以 Token 经济学驱动的架构:混合模型、AI Runway、AKS Kata MicroVM 与 MCP
人工智能·ai·架构·copilot·mcp
不剪发的Tony老师3 小时前
DBHub:一款免费开源的数据库MCP服务器
数据库·mcp
特长腿特长3 小时前
Cherry Studio 通过 MCP 接口操作 Obsidian 完全指南
ai·obsidian·mcp
Python私教4 小时前
AI 代理只会在本地打转?我用 MCP 给它接上手脚,3 步接通第一个外部服务
agent·ai编程·mcp
心之伊始21 小时前
Spring AI MCP Client 实战:让 Java 后端通过 stdio 调用本地工具服务
java·spring boot·agent·spring ai·mcp
winlife_1 天前
全程用 AI 做一款商业级手游 · EP9 收尾与复盘:做到了哪,没做到哪,边界在哪
java·开发语言·人工智能·unity·ai编程·游戏开发·mcp
用户788157868331 天前
MCP Server 自动发现:/.well-known/mcp.json 新标准详解
mcp
winlife_1 天前
全程用 AI 做一款商业级手游 · EP7 表现层与手感:从“能跑“到“摸起来爽“
java·开发语言·人工智能·unity·ai编程·游戏开发·mcp
花酒锄作田2 天前
DeepAgents - 配置MCP Server
mcp·deepagents