理解 MCP:统一工具连接方式
认识 Host、Client 和 Server,读懂工具发现与调用过程。
学完这一课,你将能够
- 说清 MCP 的三个角色
- 区分 tools、resources 和 prompts
- 校验工具调用并处理协议错误
学习目标
- 解释 Host、Client、Server 各自承担的角色。
- 区分工具、资源和提示词三类能力。
- 读懂工具发现与调用中的消息结构。
前置要求:HTTP、JSON 和工具分发器。 本节演示离线消息处理,不声称实现完整 MCP 服务端。
MCP 解决什么问题
如果每个 AI 应用都为每个数据源写一套私有连接方式,维护成本会快速增加。 Model Context Protocol 为应用与能力提供方定义共同的连接与消息约定。 它帮助应用发现和调用工具、访问资源、获取可复用提示词。
MCP 不是模型,也不是 Agent 的完整控制循环。 应用仍要决定调用哪些能力、如何管理上下文以及何时需要用户确认。 协议一致不代表任何服务端都可信或拥有相同质量。
三个角色
| 角色 | 职责 | 例子 |
|---|---|---|
| Host | 组织 AI 体验,管理权限与多个连接 | 你的 Agent 应用 |
| Client | 与一个 Server 建立协议连接 | 应用内的 MCP 客户端 |
| Server | 暴露工具、资源或提示词 | 文档搜索服务 |
Host 可以管理多个 Client;每个连接对接一个 Server。 Server 可以连接数据库或外部 API,但应用不应因此直接继承它全部权限。
三类能力分别是什么
Tools 表达可执行操作,如搜索文档或查询库存。 Resources 表达可读取的上下文数据,如文件内容或数据库结构。 Prompts 表达可复用的交互模板,由应用或用户选择使用。
协议还包含生命周期、能力协商和其他机制。 建立连接时应先初始化并协商版本与能力,再使用支持的方法。 本地常见传输是标准输入输出;远程服务可使用规范定义的 HTTP 传输。
离线观察发现和调用
保存为 mcp_messages.py 并运行。
下面只演示 JSON-RPC 请求的两个方法,省略初始化、传输、通知和完整规范校验。
不要直接把它作为生产 MCP Server。
import json
TOOL = {
"name": "lookup_stock",
"description": "按商品 ID 查询库存,只读。",
"inputSchema": {
"type": "object",
"properties": {"product_id": {"type": "string"}},
"required": ["product_id"], "additionalProperties": False,
},
}
def handle(request):
response = {"jsonrpc": "2.0", "id": request["id"]}
if request["method"] == "tools/list":
response["result"] = {"tools": [TOOL]}
elif request["method"] == "tools/call":
params = request.get("params", {})
if params.get("name") != TOOL["name"]:
response["error"] = {"code": -32602, "message": "Unknown tool"}
else:
args = params.get("arguments", {})
valid = args == {"product_id": "python-book"}
text = '{"stock":3}' if valid else "商品不存在或参数无效"
response["result"] = {
"content": [{"type": "text", "text": text}],
"isError": not valid,
}
else:
response["error"] = {"code": -32601, "message": "Method not found"}
return response
requests = [
{"jsonrpc": "2.0", "id": 1, "method": "tools/list"},
{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {
"name": "lookup_stock", "arguments": {"product_id": "python-book"},
}},
{"jsonrpc": "2.0", "id": 3, "method": "missing_method"},
]
for request in requests:
print(json.dumps(handle(request), ensure_ascii=False, indent=2))观察响应 ID 如何对应请求 ID。
未知协议方法返回 JSON-RPC 错误;已知工具中的执行问题可以通过工具结果的 isError 表达。
两者代表不同层面的失败,客户端应按规范区分处理。
接入一个真实 Server 前
先读它暴露哪些能力、如何认证、访问哪些数据,以及如何更新版本。 只启用任务需要的工具,并在 Host 侧检查输入和操作影响。 外部服务返回的文本依旧是数据,不会因为通过 MCP 传输就自动成为可信指令。
如果工具清单发生变化,应刷新发现结果并重新检查权限。 对连接失败、工具超时和服务端错误分别记录,避免全部显示为“模型出错”。
练习与验收
新增一个未知工具请求和一个无效商品请求,比较两类响应。 画出你的应用连接文档服务时的三个角色。
- 能指出例子省略了哪些生产协议步骤。
- 能通过 ID 把响应映射回请求。
- 能区分协议错误和工具执行错误。
- 能解释 MCP 为什么不能代替执行层权限检查。
延伸阅读
下一课把人工确认嵌入工作流,并讨论多 Agent 何时值得使用。
让这一课,真正成为你的收获
完成练习后标记完成,也可以随时回来复习。
笔记与进度保存在当前浏览器,无需登录