ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

MCP vs Function Calling vs OpenAPI:协议对比与选型

MCP vs Function Calling vs OpenAPI:协议对比与选型 摘要MCP、Function Calling、OpenAPI三种AI工具调用方式的深度对比从协议规范、架构模型、通信方式、跨厂商复用、双向交互等八个维度逐项拆解附选型决策表。MCP vs Function Calling vs OpenAPI 协议对比与选型上周有个同事问我给模型接外部工具到底该用 Function Calling、OpenAPI 还是 MCP。我让他把同一个天气查询工具用三种方式各写一遍写完他自己就明白了。这篇把这个对比做透从协议规范到开发体验逐项拆解最后给一张选型表让你面对新项目能快速判断。三种方式各是什么Function Calling 是大模型厂商提供的原生能力。你在对话请求里塞一段工具的 JSON Schema模型判断需要调用时直接吐出结构化的函数名和参数你的代码拿到后去执行再把结果喂回模型。它没有独立的服务端概念工具定义和调用都揉在一次对话请求里绑定具体厂商的 API 格式。OpenAPI 是描述 REST API 的业界规范本来跟大模型没关系。一个 OpenAPI 文档把 HTTP 接口的路径、方法、参数、响应写清楚任何 HTTP 客户端都能照着调用。现在很多 Agent 框架会把 OpenAPI 文档自动转成模型能理解的工具定义让模型直接调用现成的 REST 接口。MCP 是专为 LLM 设计的开放协议。它定义了客户端和服务端的架构服务端独立运行暴露工具、资源、提示三类原语客户端动态发现并调用。MCP 有完整的生命周期、传输层抽象和双向通信能力服务端写一次可以被任意 MCP 客户端复用。多维度对比下面这张表从八个维度横向对比三者。维度Function CallingOpenAPIMCP协议性质厂商私有能力REST 描述规范面向 HTTP面向 LLM 的开放协议架构模型模型内嵌无服务端HTTP 端点无状态客户端-服务端独立进程工具定义JSON Schema 塞进请求OpenAPI 文档运行时动态发现list_tools通信方式单次请求响应HTTP 请求响应双向支持通知、流式、采样状态管理无状态无状态REST有会话和生命周期跨厂商复用差格式各家不同好但需转换层好一次实现多客户端复用双向交互不支持不支持支持服务端可反向请求客户端长任务进度无无有进度通知生态成熟度各厂商各自实现极成熟工具链丰富新生态增长快安全模型客户端自行实现标准 HTTP 安全能力协商加传输层安全加 Origin 校验扩展方式改 prompt 改 schema改文档服务端独立扩展客户端无感几条关键差异展开说。复用性上 Function Calling 最弱OpenAI 和 Anthropic 的工具定义格式细节不同换模型经常要改。MCP 最强服务端跟模型解耦Claude、Cursor、自研客户端都能接同一个服务端。双向交互是 MCP 独有的服务端能通过采样反向让客户端的模型干活Function Calling 和 OpenAPI 都做不到。长任务进度上报也只有 MCP 原生支持另外两者要自己在外部加一套机制。开发体验上三者各有脾性。Function Calling 上手最快一个请求里塞 schema 就能跑但工具多了请求体会膨胀调试也全靠看模型输出的 JSON。OpenAPI 有成熟的编辑器和文档工具写接口顺手可它本来是给人看的转成模型工具时要裁剪参数和描述转换层得自己维护。MCP 配合 FastMCP 装饰器写普通函数就能发布工具schema 自动生成还自带 Inspector 可视化调试工具多了也不乱。学习曲线 MCP 稍陡要理解客户端服务端和生命周期这些概念但换来的是后续扩展省心。同一个工具的三种写法我用一个天气查询工具做对照三种方式各写一遍差异一目了然。完整代码先装依赖。pipinstallopenai httpx fastmcpFunction Calling 方式用 OpenAI SDK 把工具定义塞进请求。# weather_function_calling.py# Function Calling 方式工具定义揉在对话请求里importjsonfromopenaiimportOpenAI# 初始化客户端API key 从环境变量读clientOpenAI()# 工具定义JSON Schema 格式绑定 OpenAI 的 tools 字段tools[{type:function,function:{name:get_weather,description:查询指定城市的天气,# 参数 schema模型据此生成参数parameters:{type:object,properties:{city:{type:string,description:城市名},},required:[city],},},}]defget_weather(city:str)-str:本地实现真实项目换成调用气象 API。# 简化实现返回固定字符串returnf{city}今天晴25 度defmain():# 第一轮对话把工具定义一起发过去responseclient.chat.completions.create(modelgpt-4o-mini,messages[{role:user,content:北京天气怎么样}],toolstools,)msgresponse.choices[0].message# 模型决定调用工具时tool_calls 里会有调用信息ifmsg.tool_calls:callmsg.tool_calls[0]# 解析模型生成的参数argsjson.loads(call.function.arguments)# 本地执行工具resultget_weather(args[city])# 把结果喂回模型做第二轮followclient.chat.completions.create(modelgpt-4o-mini,messages[{role:user,content:北京天气怎么样},msg,{role:tool,tool_call_id:call.id,content:result},],)print(follow.choices[0].message.content)else:print(msg.content)if__name____main__:main()OpenAPI 方式先用 FastAPI 起一个带 OpenAPI 文档的 HTTP 服务再用 httpx 照着文档调用。# weather_openapi_server.py# OpenAPI 方式工具就是一个标准 REST 接口fromfastapiimportFastAPI appFastAPI(titleWeather API)app.get(/weather,summary查询城市天气)defweather(city:str):GET 接口FastAPI 自动生成 OpenAPI 文档。# 真实项目换成气象 API 调用return{city:city,condition:晴,temperature:25}# 启动后访问 /openapi.json 能拿到完整 OpenAPI 文档# uvicorn weather_openapi_server:app --port 8000# weather_openapi_client.py# OpenAPI 方式的客户端照着文档调 HTTP 接口importhttpxdefmain():# 直接按文档定义的路径和方法调用# Agent 框架会读 /openapi.json 自动转成模型工具withhttpx.Client()asclient:respclient.get(http://127.0.0.1:8000/weather,params{city:北京},)# 解析 JSON 响应dataresp.json()print(f{data[city]}{data[condition]}{data[temperature]}度)if__name____main__:main()MCP 方式用 FastMCP 把工具包成独立服务端。# weather_mcp_server.py# MCP 方式工具作为独立服务端运行可被任意 MCP 客户端复用fromfastmcpimportFastMCP# 创建服务端工具定义由装饰器自动生成mcpFastMCP(WeatherServer)mcp.tooldefget_weather(city:str)-str:查询指定城市的天气。 Args: city: 城市名 # 真实项目换成气象 API 调用returnf{city}今天晴25 度if__name____main__:# 默认 stdio 传输Claude Desktop 等客户端可直接接入mcp.run()# weather_mcp_client.py# MCP 方式的客户端动态发现并调用工具importasynciofromfastmcpimportClientasyncdefmain():# 连接服务端自动走 stdioasyncwithClient(weather_mcp_server.py)asclient:# 动态列出可用工具不需要预先知道有哪些toolsawaitclient.list_tools()print(发现工具:,[t.namefortintools])# 调用天气工具resultawaitclient.call_tool(get_weather,{city:北京})print(result.data)if__name____main__:asyncio.run(main())选型建议不同场景的选型我整理成一张表。场景推荐方案理由单一模型、少量简单工具Function Calling零额外架构最快上线已有大量 REST API 想给模型用OpenAPI 加转换层复用现有接口不用重写多模型多客户端、要共享工具MCP一次实现多方复用解耦模型长任务需要进度上报MCP原生支持进度通知需要服务端反向调用模型采样MCP独有双向能力纯本地工具、桌面集成MCPstdio标准化、安全可控快速原型验证Function Calling门槛最低企业级多团队工具市场MCP服务端独立部署、便于统一管理实际项目里三者经常组合用。用 MCP 做工具服务端的统一出口内部工具可以是 Function Calling 风格的封装也可以是包了一层的 OpenAPI 接口。MCP 服务端充当适配层对上屏蔽模型差异对下兼容遗留接口。三者可以共存按需混搭。常见问题与避坑1. Function Calling 换模型工具定义要重写。OpenAI 的 tools 字段、Anthropic 的 tool_use、Gemini 的 functionDeclarations 格式细节都不同必填字段和枚举处理也有差异。我有个项目从 GPT 迁到 Claude工具定义改了一整天。用 MCP 把工具抽到服务端模型侧只管调 MCP 客户端迁移成本就低多了。2. OpenAPI 文档直接喂模型 token 爆炸。一个中型项目的 OpenAPI 文档动辄几万字全塞进上下文既贵又乱。实际用要先按需筛选端点再做参数裁剪只暴露模型用得上的接口。别图省事把整个文档丢给模型。3. MCP 服务端被多客户端复用时工具命名冲突。不同服务端的工具可能撞名比如都叫 search。客户端聚合多个服务端时加前缀区分FastMCP 的多服务端配置会自动加服务端名前缀自己拼要注意。4. Function Calling 没有资源概念文件类上下文只能塞 prompt。想让模型读一个大文件Function Calling 只能把内容拼进消息token 占用高。MCP 用资源原语让模型按需读取配合分页能省大量 token。5. OpenAPI 做不了长任务进度。REST 是无状态请求响应长任务只能轮询或靠 WebSocket 自己造一套。MCP 的进度通知是协议内置的省掉自己造轮子。小结Function Calling 适合单一模型快速上手OpenAPI 适合复用现成 REST 接口MCP 适合多模型多客户端共享工具生态和需要双向交互的场景。三者可以混搭MCP 常作为统一出口把另外两者整合进来。选型核心看复用性、双向交互和长任务需求这三个点。下一篇进入 Python MCP SDK 的实操看 FastMCP 怎么把服务端开发做到几行代码搞定。相关推荐MCP协议全景Host、Client、Server架构详解Tools原语深度解析从定义到调用全流程MCP是什么为什么2026年每个AI开发者都需要了解它
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进