从一个实际需求理解 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)

一次工具调用怎样完成

以查询库存为例,一条典型链路是:

  1. 宿主通过客户端连接服务端,确认协议兼容性和可用能力。
  2. 客户端发送 tools/list,获得工具名称、说明和参数结构。
  3. 宿主把适用的工具描述交给模型。
  4. 模型提出调用某个工具及其参数,宿主检查后,由客户端发送 tools/call。
  5. 服务端查询库存并返回结果,宿主把结果交给模型,生成面向用户的回答。(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)

只测试成功路径。 对这个库存例子,至少再测不存在的商品、错误参数和服务不可用。建议让错误结果清楚区分“查不到”和“查询失败”,避免应用把失败解释成库存为零。

小结与下一步

入门练习可以围绕一个验收目标展开:工具能被发现,参数能被正确传入,结果能回到模型,失败能够被识别。

先完成上面的只读库存查询,再把演示字典换成真实业务接口。随后逐步加入权限控制、超时处理和调用记录,每次增加一种复杂性,更容易找到问题发生在哪一层。

参考来源