嘿,大家好,我是老码小张。
混迹技术圈有些年头了,相比追逐各种花里胡哨的新名词,我可能更喜欢钻研技术背后的那点儿门道,琢磨怎么用这些技术实实在在地解决点问题。最近 AI Agent 这阵风刮得挺猛,OpenAI 也推出了自家的 Agents SDK,我自然也去扒拉了一下,发现里面有个叫 MCP 的东西,挺有意思,今天就想跟大家唠唠这个。

你想啊,咱们现在用的大语言模型(LLM),像 GPT-4 这些,脑子确实聪明,能聊天能写文能写代码。但它们本质上还是被关在一个“数字黑箱”里,跟咱们现实世界或者具体的软件系统是隔离开的。你想让它帮你查查今天本地天气怎么样?或者去你的项目管理软件里更新个任务状态?直接跟它说,它大概率只能摊摊手,表示“臣妾做不到啊”。
为啥?因为它没有“手”和“脚”啊!它需要一些工具(Tools)或者说能力,才能跟外部世界互动。
过去我们怎么做呢?通常是在应用代码里写一堆特定的函数,然后通过各种提示工程(Prompt Engineering)或者特定的 API 调用方式,告诉 LLM:“嘿,当你需要查天气时,就调用这个 get_weather(city)
函数;当你需要读文件时,就用这个 read_file(path)
函数。”
这种方法不是不行,但有几个问题:
-
1. 定制化太强:每个应用都得自己写一套工具对接逻辑,有点像给每个电器都配一个专用插头,换个地方可能就用不了了。 -
2. 不够灵活:如果别人已经做了一个很牛的查数据库工具,你想用,可能还得自己重新封装一遍,适配你的 Agent 框架。 -
3. 标准缺失:各家搞各家的,没个统一的“说法”,交流和复用都挺麻烦。
这时候,MCP 就登场了。
MCP:AI 应用的“USB-C 接口”
MCP 全称是 Model Context Protocol,模型上下文协议。官方文档打了个很形象的比方:MCP 就像是 AI 应用的 USB-C 接口。
想想 USB-C:一个标准接口,能充电、能传数据、能接显示器、能连各种外设。不管你是苹果、安卓还是 Windows 电脑,只要支持 USB-C,很多配件都能通用。
MCP 想做的,就是为 AI 模型(特别是 LLM)提供一个标准化的方式来连接不同的数据源和工具。
有了这个标准协议,理论上:
-
• 工具开发者可以开发符合 MCP 规范的工具服务(比如一个专门操作 Notion 的服务,或者一个控制智能家居的服务),而不用太关心这个服务最终会被哪个具体的 AI 应用或 Agent 框架使用。 -
• AI 应用开发者(比如咱们用 OpenAI Agents SDK 的人)可以方便地接入各种现成的 MCP 工具服务,给自己的 Agent “插上”各种能力,而不需要为每种工具都写一堆定制的对接代码。
听起来是不是有点小激动?这就像给你的 AI Agent 配上了一个万能插座,以后想加什么新功能,只要找到支持 MCP 的“电器”(工具服务),插上就行了。
OpenAI Agents SDK 怎么玩转 MCP?
好消息是,OpenAI 的 Agents SDK 已经内置了对 MCP 的支持。这意味着咱们可以直接在创建 Agent 的时候,把 MCP 服务给“挂载”上去。
那么,MCP 服务具体长啥样呢?目前 MCP 规范定义了两种类型的服务,主要是通信方式不同:
-
1. stdio 服务器 (stdio servers):这种服务通常是作为一个子进程在你的应用程序内部运行的,可以理解为“本地运行”。通信方式是通过标准输入/输出(stdin/stdout)。 -
2. HTTP over SSE 服务器 (HTTP over SSE servers):这种服务是远程运行的,你需要通过一个 URL 去连接它。通信方式是基于 HTTP 和 Server-Sent Events (SSE)。
OpenAI Agents SDK 提供了两个对应的类来连接这两种服务器:MCPServerStdio
和 MCPServerSse
。
举个例子,假设你想让你的 Agent 能操作本地文件系统(读文件、写文件、列目录等)。正好,MCP 官方提供了一个基于 stdio 的文件系统服务。你可以这样把它跑起来并连接到你的 Python 代码里(这里用了 npx
,通常是 Node.js 环境下的工具,它会帮你下载并运行 @modelcontextprotocol/server-filesystem
这个包):
import os
from openai_agents.mcp import MCPServerStdio
# 假设你的项目里有个叫 samples_dir 的目录
samples_dir = "./my_agent_files"
# 确保这个目录存在
os.makedirs(samples_dir, exist_ok=True)
asyncdefrun_mcp_example():
# 配置并启动 MCP 文件系统服务
# command 指定用 npx
# args 告诉 npx 去执行 @modelcontextprotocol/server-filesystem,
# 并且把 samples_dir 作为工作目录传给它
# -y 参数是告诉 npx 自动确认安装
mcp_server_filesystem = MCPServerStdio(
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", samples_dir],
}
)
# 使用 async with 确保服务在退出时能被正确关闭
asyncwith mcp_server_filesystem as server:
print("MCP 文件系统服务已启动...")
# 我们可以尝试手动列出它提供的工具
tools = await server.list_tools()
print("文件系统服务提供的工具:")
for tool in tools:
print(f"- {tool.function.name}: {tool.function.description}")
# 这里只是演示如何启动和列出工具,
# 后面会展示如何把它集成到 Agent 中
# 如果你在异步环境运行,可以直接 await run_mcp_example()
# 如果在同步环境,可以用 asyncio.run(run_mcp_example())
import asyncio
asyncio.run(run_mcp_example())
上面这段代码干了啥?
-
1. 引入了 MCPServerStdio
。 -
2. 定义了要跑的命令: npx -y @modelcontextprotocol/server-filesystem ./my_agent_files
。这行命令会启动一个本地的 MCP 服务,专门用来操作./my_agent_files
这个目录下的文件。 -
3. 用 async with
来管理这个服务的生命周期,确保程序退出时服务也能干净地关掉。 -
4. 在 with
块里,我们调用了server.list_tools()
,这个方法会通过 stdio 去问那个子进程:“嘿,你能干啥呀?把你所有的工具(能力)都报上来。” -
5. 然后我们把获取到的工具列表打印出来看看。
跑起来之后,你可能会看到类似这样的输出:
MCP 文件系统服务已启动...
文件系统服务提供的工具:
- filesystem.readFile: Reads the content of a file.
- filesystem.writeFile: Writes content to a file.
- filesystem.listFiles: Lists files and directories in a given path.
... (可能还有其他工具)
看,这个文件系统服务告诉我们,它能读文件 (readFile
)、写文件 (writeFile
)、列文件 (listFiles
) 等。
把 MCP 服务“插”给 Agent
光启动服务还不够,关键是怎么让 Agent 用起来。在 OpenAI Agents SDK 里,这事儿很简单。你只需要在创建 Agent
对象的时候,把刚才创建的 mcp_server_filesystem
实例(或者其他 MCP 服务实例)放进 mcp_servers
列表里就行了:
from openai_agents.agents import Agent
# (假设 mcp_server_filesystem 已经在前面定义好了)
# 假设还有另一个 MCP 服务叫 mcp_server_other
# 创建 Agent 时,把 MCP 服务列表传进去
my_agent = Agent(
name="文件小助手",
instructions="请使用提供的工具来完成任务。",
# 把所有想让这个 Agent 使用的 MCP 服务都放在这个列表里
mcp_servers=[mcp_server_filesystem,
# mcp_server_other # 如果有其他服务,也加进来
]
)
# 接下来就可以运行这个 Agent 了
# result = await my_agent.run("请帮我读取 my_agent_files 目录下的 welcome.txt 文件内容。")
# print(result.get_text())
当 my_agent
运行时,Agents SDK 会自动干几件事:
-
1. 询问能力:它会去找 mcp_servers
列表里的每个服务,调用它们的list_tools()
方法,把所有可用的工具都收集起来。 -
2. 告知 LLM:在构建给 LLM 的提示(Prompt)时,SDK 会把这些从 MCP 服务收集来的工具信息(名称、描述、参数等)一并告诉 LLM。 -
3. 执行调用:如果 LLM 在思考后决定要使用某个来自 MCP 服务的工具(比如决定调用 filesystem.readFile
),Agents SDK 会捕捉到这个意图,然后调用对应 MCP 服务的call_tool()
方法,并把 LLM 指定的参数传过去。 -
4. 返回结果:MCP 服务执行完工具调用后,会把结果返回给 SDK,SDK 再把这个结果喂给 LLM,让它继续下一步思考或生成最终回复。
整个过程对我们开发者来说是比较透明的,我们只需要把 MCP 服务“注册”给 Agent 就行了,底层的通信和调用细节 SDK 都帮你处理了。

这个图清晰地展示了从用户发出指令,到 SDK 如何协调 LLM 和 MCP 服务,最终完成任务的整个流程。
性能小贴士:工具列表缓存
你可能注意到了,每次运行 Agent 时,SDK 都会调用 list_tools()
。如果你的 MCP 服务是个远程服务(HTTP over SSE 类型),或者 list_tools()
本身比较耗时,这可能会带来一点延迟。
如果你的 MCP 服务提供的工具列表是相对固定的(比如那个文件系统服务,它的能力基本不会变),你可以在创建 MCPServerStdio
或 MCPServerSse
对象时,加上 cache_tools_list=True
这个参数:
mcp_server_filesystem = MCPServerStdio(
params={...},
cache_tools_list=True # 开启工具列表缓存
)
这样设置后,SDK 只会在第一次运行时调用 list_tools()
,之后就会直接使用缓存的结果,能省下不少时间。
当然,如果你知道 MCP 服务的工具列表发生了变化(比如服务更新了,增加了新工具),你需要手动让缓存失效,可以调用服务对象的 invalidate_tools_cache()
方法。
MCP vs. 直接写 Python 工具函数
你可能会问,既然 OpenAI Agents SDK 本身也支持直接定义 Python 函数作为工具,为啥还要搞个 MCP 呢?它们有啥区别?
简单做个对比:
|
|
|
实现方式 |
|
|
语言/环境 |
|
|
复用性 |
|
|
标准化 |
|
|
开发/接入成本 |
|
|
解耦性 |
|
|
怎么选?
-
• 如果你的工具逻辑比较简单,只在当前 Python 应用中使用,或者需要访问应用内部的状态,那么直接定义 Python 函数可能更直接方便。 -
• 如果你需要接入一个已有的、用其他语言编写的、或者需要独立部署维护的功能服务,并且希望这个服务能被多个不同的 AI 应用(可能用了不同的 Agent 框架)复用,那么 MCP 是一个非常理想的选择。 -
• 如果你想构建一个通用的工具平台,让别人能方便地接入你的能力,实现 MCP 协议是个不错的方向。
调试与追踪
当你用了 MCP 服务后,如果 Agent 运行出了问题,怎么排查呢?别担心,OpenAI Agents SDK 的追踪(Tracing)功能也考虑到了 MCP。它会自动记录跟 MCP 相关的操作,比如:
-
• 调用 list_tools()
的过程。 -
• 当 LLM 决定调用某个 MCP 工具时,相关的函数调用信息(调了哪个工具,传了什么参数,返回了什么结果)。
这些追踪信息能帮你搞清楚在 SDK、LLM 和 MCP 服务之间到底发生了什么,定位问题会方便很多。
说了这么多
好啦,关于 OpenAI Agents SDK 里的 MCP,今天就先跟大家聊这么多。
简单来说,MCP 就是想做 AI 应用连接外部工具和数据源的那个“通用标准接口”,有点像我们硬件世界的 USB-C。OpenAI Agents SDK 对 MCP 的支持,让我们可以更方便地把各种符合规范的“能力插件”(MCP 服务)集成到我们的 Agent 里,不管是本地跑的还是远程调用的。这为构建功能更强大、更灵活、也更开放的 AI Agent 打开了一扇新的大门。
当然,MCP 还是个相对较新的东西,生态也还在发展中。但我觉得这个方向是对的,未来可能会看到越来越多基于 MCP 的工具服务涌现出来。
如果你对这个感兴趣,不妨去看看 OpenAI Agents SDK 文档里关于 MCP 的更多细节,或者直接去 examples/mcp
目录下跑跑官方提供的完整示例代码。亲自上手试一试,感觉会更真切!
我是老码小张,一个喜欢扒拉技术细节的普通技术人。希望今天的分享对你有启发!下次有机会再跟大家聊聊其他有意思的技术话题。回见!