本文目录
一句话:第 3 篇的 Function Calling 解决了"模型怎么调工具",但每接一个工具都要自己写胶水代码。MCP 把接入接口标准化了;客户端、服务端还要匹配协议版本、传输方式、能力和权限。
MCP 解决什么(一句话讲清)
MCP(Model Context Protocol,模型上下文协议)是一个开放标准,规定了"AI 应用"和"外部能力(工具 / 数据 / 提示)"之间怎么对话。
类比一下:MCP 之于 AI 工具,就像 USB-C 之于设备。以前每个工具配一根专用线(每个 Agent 自己写一套对接);有了 MCP 这个统一接口,你把工具做成一个 MCP Server,支持对应能力的 MCP Client 可以按同一协议接入,减少为不同客户端重复编写适配代码。
MCP Server 能暴露三类东西:
- Tools(工具):能执行的动作(查数据库、发请求、跑脚本)——最常用。
- Resources(资源):能读取的数据(文件、记录)。
- Prompts(提示模板):可复用的提示词模板。
亲手暴露一个工具
本例使用官方 Python SDK 1.x 的 FastMCP 接口和 Python 3.10+。在第 2 篇的虚拟环境里运行 python -m pip install "mcp>=1,<2",将代码保存为 weather_server.py;不要把文件命名为 mcp.py。工具返回演示假数据。
# 已安装官方SDK 1.x:python -m pip install "mcp>=1,<2"
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather") # 起个名
@mcp.tool() # 这个装饰器就把函数变成了 MCP 工具
def get_weather(city: str) -> str:
"""查询某个城市今天的天气。""" # 文档字符串 = 给模型看的工具说明
fake = {"北京": "晴 26℃", "上海": "多云 24℃"}
return fake.get(city, "暂无数据")
if __name__ == "__main__":
mcp.run() # 默认用 stdio 传输,跑起来等客户端连接关键点:
@mcp.tool()自动把函数签名 + docstring 转成模型能懂的工具 schema(还记得第 3 篇手写的那一大段 JSON 吗?这里自动生成了)。- 本例默认使用 stdio,由客户端启动 Python 子进程并通过标准输入输出通信。现代 MCP 标准传输是 stdio 与 Streamable HTTP;旧 HTTP+SSE 是兼容旧版本的方式,SSE 也可以作为 Streamable HTTP 的流式响应形式。
- 客户端需配置本虚拟环境的 Python 可执行文件和 weather_server.py 的绝对路径。启动后完成初始化与 tools/list,确认能发现 get_weather,再调用工具验证;各客户端的配置字段以其当前文档为准。
它和 Function Calling 什么关系
- Function Calling 是"模型↔工具"在单个应用内的调用机制(第 3 篇)。
- MCP 是"工具↔任意客户端"的跨应用标准:你封装一次,到处能用。
客户端可以把模型原生工具调用或自己的编排结果转换成 MCP 请求。MCP 规定工具与资源如何发现、调用和交换消息,不限定必须使用哪一种模型 API。
常见坑
- 工具 docstring 写得烂:和第 3 篇一样,描述含糊,模型就不知道何时调。
- 不做权限 / 校验:能成功连接并被授权的客户端才应调用工具;危险操作(写数据、删文件)必须加确认和权限。
- stdio 里乱 print:stdio 传输下,往标准输出打日志会污染协议消息——日志走 stderr。
- 以为 MCP 会让模型更聪明:不会。它只是"接线标准",决策能力还在模型本身。
关联面试题
- 「MCP 是什么?和 Function Calling 有什么区别和联系?」
- 「怎么给 Agent 安全地接入外部工具?」
👉 去 题库 搜 MCP / 工具调用 / Agent 工程。
训练营延伸
工业级的工具接入,要的是统一工具网关 + 多级沙箱(子进程 / 容器 / microVM)+ 容错与权限分级——是训练营的集群 Agent 那条线在做的事,把"接一个工具"升级成"安全地接一整套工具体系"。