从一个实际需求理解 MCP
假设你要开发一个库存助手。用户问“键盘还有多少库存”,你希望 AI 查询业务系统,再根据结果回答。
这需要解决几个问题:应用怎样知道有哪些工具?工具接受什么参数?调用结果以什么格式返回?MCP(Model Context Protocol,模型上下文协议)为 AI 应用与外部工具、数据之间的通信提供了统一约定。它负责交换上下文和能力信息,应用仍需自行组织模型调用与业务流程。(modelcontextprotocol.io)
没有统一约定时,每接一个系统,你可能都要重新设计工具描述、参数封装和结果处理。MCP 的价值是让这些连接方式可以复用:服务端按协议提供能力,支持 MCP 的应用按协议接入。实际接入仍要确认双方支持的功能和传输方式。(modelcontextprotocol.io)
先分清三个角色和三类能力
MCP 中有三个主要角色:
- Host,宿主应用:用户使用的 AI 应用,负责组织模型、上下文和交互。
- Client,客户端:宿主内部负责 MCP 通信的组件。
- Server,服务端:对外提供工具或数据的程序,可以运行在本机,也可以部署在远程。(modelcontextprotocol.io)
服务端常见的能力包括三类:
| 能力 | 用途 | 例子 |
|---|---|---|
| Tools | 执行可调用的操作 | 查询库存、创建工单 |
| Resources | 提供可读取的上下文 | 文档内容、数据库结构 |
| Prompts | 提供可复用的提示模板 | 按固定格式整理报告 |
通常,工具由模型根据任务选择使用,资源由应用组织并加载,提示模板由用户主动选择。具体交互形式由宿主决定;一个入门服务只提供工具也可以。(py.sdk.modelcontextprotocol.io)
一次工具调用怎样完成
以查询库存为例,一条典型链路是:
- 宿主通过客户端连接服务端,确认协议兼容性和可用能力。
- 客户端发送
tools/list,获得工具名称、说明和参数结构。 - 宿主把适用的工具描述交给模型。
- 模型提出调用某个工具及其参数,宿主检查后,由客户端发送
tools/call。 - 服务端查询库存并返回结果,宿主把结果交给模型,生成面向用户的回答。(modelcontextprotocol.io)
这里要分清两件事:模型提出调用,应用执行调用。开发自己的 Agent 时,你需要把 MCP 工具接入模型的工具调用流程,并处理权限、异常和结果回填;连接服务端只是其中一步。(modelcontextprotocol.io)
用库存查询做一个最小例子
建议先做一个只读工具。下面是 Python 伪代码,用于说明结构,不能直接运行;MCPServer 的导入和启动方式需按所选 SDK 文档补齐。
server = MCPServer("inventory-demo")
stock = {"keyboard": 12, "mouse": 30}
@server.tool()
def get_stock(sku: str) -> dict:
"""按商品编码查询库存;只读,不修改数据。"""
if sku not in stock:
return {"found": False, "sku": sku}
return {
"found": True,
"sku": sku,
"quantity": stock[sku],
}
server.run(transport="stdio")
这个结构对应 SDK 中的常见写法:创建服务、注册函数、启动传输。工具名称、说明和参数类型构成调用接口,应明确表达用途和输入要求。(py.sdk.modelcontextprotocol.io)
接入时,可以分三步完成。
第一步,选择传输方式。 本地练习可选 stdio,由宿主启动服务进程,通过标准输入输出通信。远程部署通常使用 Streamable HTTP,由客户端访问服务端地址。(py.sdk.modelcontextprotocol.io)
第二步,配置并测试连接。 本地接入需要给宿主提供启动命令、脚本路径及必要的环境变量。建议使用解释器和脚本的绝对路径,减少工作目录差异。先用 MCP Inspector 检查工具是否能被发现,再传入 {"sku": "keyboard"},确认返回数量为 12。Inspector 可以启动本地服务并测试通信。(py.sdk.modelcontextprotocol.io)
第三步,接入模型。 如果使用已有宿主,按其配置方式启用服务;如果自己写 Agent,则需要获取工具列表、转换为模型接口接受的工具定义,并将模型提出的调用转发给 MCP 服务。把返回结果加入对话后,再让模型生成回答。(modelcontextprotocol.io)
接通之后,留意这些坑
工具说明太含糊。 query 很难表达用途。建议使用 get_stock 这样的名称,并写清商品编码格式、返回字段和失败含义。工具描述与参数结构是模型选择和调用工具的重要依据。(modelcontextprotocol.io)
日志混进协议输出。 stdio 使用标准输出传递协议消息。应把日志写入标准错误,避免启动脚本、导入代码等输出干扰通信。(py.sdk.modelcontextprotocol.io)
把“可调用”当成“已授权”。 服务端仍要验证参数和访问权限。删除数据、发送消息等有副作用的操作,应设置明确的确认机制,并让用户能拒绝调用。(modelcontextprotocol.io)
只测试成功路径。 对这个库存例子,至少再测不存在的商品、错误参数和服务不可用。建议让错误结果清楚区分“查不到”和“查询失败”,避免应用把失败解释成库存为零。
小结与下一步
入门练习可以围绕一个验收目标展开:工具能被发现,参数能被正确传入,结果能回到模型,失败能够被识别。
先完成上面的只读库存查询,再把演示字典换成真实业务接口。随后逐步加入权限控制、超时处理和调用记录,每次增加一种复杂性,更容易找到问题发生在哪一层。
参考来源
- 选题参考:小林面试笔记 · 同主题文章(本文为本站原创撰写,未转载原文)