首先本文的面向对象是开发人员,所以直接聚焦 MCP 的运行交互逻辑,跳过产品方向的功能解释。
MCP的存在意义
MCP作为一个双端交互协议,其核心在于通过jsonrpc机制,使LLM的客户端能够清晰地了解服务器所具备的各项能力。
运行逻辑四步走
1. 初始化
在初始化阶段,客户端会向服务端发送一个initialize请求,该请求中包含了客户端的相关能力信息。服务端在接收到该请求后,会回复一个包含服务端能力信息的报文。对于 http 请求还会额外通过 header 返回 mcp-session-id。此后的所有请求,客户端都需要在 header 中携带这个mcp-session-id参数。
- 入参示例:
{
"jsonrpc": "2.0",
"id": 0,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"sampling": {},
"roots": {
"listChanged": true
}
},
"clientInfo": {
"name": "mcp-inspector",
"version": "0.11.0"
}
}
} - 返回示例:
{
"id": 0,
"jsonrpc": "2.0",
"result": {
"capabilities": {
"tools": {
"listChanged": false
}
},
"protocolVersion": "2024-11-05",
"serverInfo": {
"name": "小助手",
"version": "1.0.0"
}
}
}
2. 初始化完成通知
客户端在成功接收到服务端的初始化回复后,会向服务端发送一个notifications/initialized通知,告知服务端初始化已完成。此步骤的回复通常为一个简单的状态码(如202),不需要包含消息体。
- 入参示例:
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
} - 回复:202(无需消息体)
3. 加载工具列表
客户端接下来会向服务端发送一个tools/list请求,以获取服务端提供的工具列表。服务端在接收到该请求后,会返回一个包含工具详细信息的报文。
- 入参示例:
{
"jsonrpc": "2.0",
"method": "tools/list",
"params": {},
"id": "123"
} - 返回示例:
{
"id": "123",
"jsonrpc": "2.0",
"result": {
"tools": [
{
"annotations": {
"title": "xx"
},
"description": "xxx",
"inputSchema": {
"properties": {
"param1": {
"description": "xxx",
"type": "string"
}
},
"required": [
"param1"
],
"type": "object"
},
"name": "tool_name_xxxxx"
}
]
}
}
4. 执行方法调用
最后,客户端会根据需要调用某个具体的工具,发送一个tools/call请求。服务端在接收到该请求后,会执行相应的工具,并返回一个包含执行结果的报文。
- 入参示例:
{
"method": "tools/call",
"params": {
"name": "tool_name_xxxxx",
"arguments": {
"param1": "北京"
}
},
"jsonrpc": "2.0",
"id": 21
} - 返回示例:
{
"id": 21,
"jsonrpc": "2.0",
"result": {
"content": [
{
"text": "xxxxxxxxxxxxxxx",
"type": "text"
}
]
}
}到这一个最简单模型的交互流程就完成了,只要服务端按上面的格式返回就是可用的。
关于MCP交互协议
MCP一共三种交互协议,出入参的报文规划一致,只在具体的交互方式上存在差异:
- stdio:入参和出参分别对应输入、输出流。
- sse(Server-Sent Events):入参通过POST请求提交,返回结果通过SSE获取。不过,这种协议目前已不推荐使用。
- streamHTTP:通过普通的HTTP请求和响应进行交互,是综合最优的选择,既便于客户端接入,也便于服务端进行扩展。
对于VO(View Object)对应的字段和详细解释,可以参考MCP的官方schema文档。
对于其它协议细节可以参考MCP官方文档
发表回复