MCP 和传统 Function Call 的对比:从 JSON-RPC 到 Client-Server 的 LLM 工具调用演进
1. 从一次“工具爆炸”的深夜排障说起MCP 和 Function Call 到底差在哪如果你正在做 LLM 工具调用大概率遇到过这种局面一开始只接了一个查天气的 Function Call代码清爽得像刚洗完的白衬衫。两周后产品说“再加个查订单、发邮件、读数据库、调内部工单系统”于是你的tools数组膨胀到二十几个每个模型供应商的 schema 写法还不一样OpenAI 的function字段、Anthropic 的tool_use块、国内某模型的tools结构改一处要动三处。这就是典型的“工具爆炸 接口碎片”。MCPModel Context Protocol和传统 Function Call 的核心差异用一句话概括Function Call 解决的是“模型怎么表达我要调哪个函数”MCP 解决的是“模型和工具之间怎么标准化地发现、协商、调用、维持会话”。前者是模型输出层的一个约定后者是一套 Client-Server 的通信协议底层用 JSON-RPC 2.0 承载。这篇文章面向三类人正在用 Function Call 做 Agent 但被多模型适配折磨的开发者、想引入 MCP 但不确定值不值得的架构同学、以及刚听说 MCP 想跑通第一条调用链的新手。我会把两种方式的配置、代码、验证命令都摊开你可以直接复制到本地跑。实测下来理解这两者的边界比盲目上 MCP 重要得多。先给一个直观对照后面每一节都会展开维度传统 Function CallMCP定位模型输出结构化调用意图模型与工具/资源的标准化协议通信应用侧自行解析执行JSON-RPC 2.0 over stdio / HTTPSSE角色模型 → 函数Host / Client / Server 三角色工具发现无靠代码硬编码注册tools/list动态发现会话一次性状态最小支持 session、多步调用链跨模型复用差各家 schema 不同好协议层统一2. 前置准备用 TaoToken 统一拿到模型入口与 API Key在对比两种调用方式之前得先有一个能稳定调模型的入口。我这边习惯用 TaoToken 做统一网关原因是它把模型对话、Coding Plan、API Key 管理放在一个控制台里切换模型不用改一堆环境变量。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台生成 Key。拿到 Key 之后你需要记下三个东西后面所有配置都围绕它们Base URL 用https://taotoken.net/api注意这个地址不加 UTM 参数直接写进配置API Key 形如sk-xxxxModel ID 比如claude-sonnet-4-5或gpt-4o之类具体以控制台模型列表为准。这三个要素就是所谓的“三件套”无论你是接 Claude Code、Cline、还是自己写脚本都逃不掉。如果你只是想先验证模型能不能通可以直接去模型对话页面发一条消息试试https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。这一步能排除掉后面 90% 的“到底是网络问题还是配置问题”。对于长期做编码和 Agent 的场景Coding Plan 会更划算入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。API Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。注意Base URL 一定要区分清楚https://taotoken.net/api是给 SDK 和工具用的接口地址不要和官网首页混用。很多 401 报错就是因为把首页地址填进了base_url。环境变量建议这样设后面 Python 和 Node 脚本都读它export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_MODELclaude-sonnet-4-5Windows PowerShell 用$env:TAOTOKEN_API_KEYsk-你的key。设完echo $TAOTOKEN_API_KEY确认一下别带着空值往下走。3. 可复制配置Function Call 示例与 MCP Server 配置对照这一节是全文的核心我把两种方式的完整配置都放出来你可以对照着改。3.1 传统 Function Call 的完整调用先看 Function Call。它的本质是你在请求里塞一个tools数组模型判断需要调用时返回一个tool_calls结构你的代码解析后执行本地函数再把结果作为tool角色消息塞回对话。下面是一个能跑的 Python 示例import os, json from openai import OpenAI client OpenAI( base_urlos.environ[TAOTOKEN_BASE_URL], api_keyos.environ[TAOTOKEN_API_KEY], ) tools [{ type: function, function: { name: get_weather, description: 查询指定城市某天的天气, parameters: { type: object, properties: { city: {type: string, description: 城市名如 Singapore}, date: {type: string, description: 日期如 2025-06-01} }, required: [city, date] } } }] def get_weather(city, date): # 真实场景替换为你的 API 调用 return {city: city, date: date, temp_c: 29, condition: sunny} messages [{role: user, content: 查一下新加坡明天的天气}] resp client.chat.completions.create( modelos.environ[TAOTOKEN_MODEL], messagesmessages, toolstools, tool_choiceauto, ) msg resp.choices[0].message if msg.tool_calls: call msg.tool_calls[0] args json.loads(call.function.arguments) result get_weather(**args) messages.append(msg) messages.append({ role: tool, tool_call_id: call.id, content: json.dumps(result, ensure_asciiFalse) }) final client.chat.completions.create( modelos.environ[TAOTOKEN_MODEL], messagesmessages, ) print(final.choices[0].message.content)这段代码里模型只负责“说要调get_weather参数是 city 和 date”真正的执行、结果回传、二次请求全是你手写的。工具一多这个if msg.tool_calls的分支就会变成一坨。3.2 MCP Server 的配置片段MCP 把上面那坨胶水代码抽到了协议层。一个 MCP Server 通常用 stdio 或 HTTPSSE 暴露工具Client 通过 JSON-RPC 调用。下面是一个最小 MCP Server 的配置以常见的mcpServers结构为例Claude Desktop / Cline 都认这个格式{ mcpServers: { weather: { command: python, args: [/Users/you/mcp_weather_server.py], env: { TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: sk-你的key } } } }对应的 Server 端用官方 Python SDK 写核心是注册工具和启动 stdiofrom mcp.server.fastmcp import FastMCP mcp FastMCP(weather) mcp.tool() def weather_query(city: str, date: str) - dict: 查询指定城市某天的天气 return {city: city, date: date, temp_c: 29, condition: sunny} if __name__ __main__: mcp.run(transportstdio)注意这里的差别Function Call 里你要手写parameters的 JSON Schema而 MCP 里mcp.tool()装饰器会从函数签名和 docstring 自动生成 schemaClient 通过tools/list就能拿到。新增工具只要加一个函数不用改 Client 代码。如果你用的是 Claude Code 这类工具配置会落在~/.claude/settings.json或项目级.mcp.json结构类似。Cline 的 MCP 配置在插件设置里格式也是mcpServers。Codex 的auth.json则用于存凭证路径通常在~/.codex/auth.json里面放 API Key 和 Base URL。这三件套Base URL Key Model ID在任何一种工具里都要对齐缺一个就是 401 或 model not found。4. 本地验证跑通 Function Call 与 MCP 两条调用链路配置写完不算完得验证。我习惯分两步先验证模型入口通不通再验证工具调用链路通不通。4.1 验证模型入口用 curl 打一发最朴素的请求确认 Key 和 Base URL 没问题curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: $TAOTOKEN_MODEL, messages: [{role: user, content: 只回复 ok}] }返回里能看到choices[0].message.content就说明入口通了。如果这里就报 401别往下走先去 API Keys 页面确认 Key 有没有复制全、有没有多余空格。4.2 验证 Function Call 链路跑上面那段 Python观察输出。成功的话你会看到模型先返回tool_calls然后你的代码执行get_weather最后模型基于结果生成一句自然语言回答类似“新加坡明天晴29 度适合户外活动”。这个过程有两个网络往返token 消耗会翻倍这是 Function Call 的固有成本。4.3 验证 MCP 链路MCP 的验证稍微不同因为它是 Client-Server 结构。你可以用官方提供的 inspector 工具或者直接写一个最小 Clientimport asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): params StdioServerParameters( commandpython, args[/Users/you/mcp_weather_server.py], ) async with stdio_client(params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools await session.list_tools() print(发现工具:, [t.name for t in tools.tools]) result await session.call_tool( weather_query, {city: Singapore, date: 2025-06-01} ) print(调用结果:, result.content) asyncio.run(main())跑通后你会看到先打印“发现工具: [weather_query]”再打印调用结果。这一步的关键在于session.initialize()完成了能力协商list_tools完成了动态发现call_tool走的是 JSON-RPC 的tools/call方法。整个过程你一行解析tool_calls的代码都没写。对比下来Function Call 的验证是“看模型有没有吐出正确的 JSON”MCP 的验证是“看 Client 能不能发现并调用 Server 的工具”。前者验证的是模型能力后者验证的是协议链路。5. 常见报错排查401、local proxy failed、reading choices、OAuth这一节按真实报错来都是我踩过的坑。401 Unauthorized最常见。九成是 Key 错了或 Base URL 填成了首页。检查base_url是不是https://taotoken.net/apiKey 有没有sk-前缀环境变量有没有被 shell 覆盖。MCP 场景下还要检查mcpServers的env里有没有把 Key 传进去Server 进程读不到环境变量也会 401。local proxy failed / connection refused这个报错通常出现在 MCP 用 HTTPSSE 传输时Client 连不上 Server 的端口。先确认 Server 进程起来了curl http://localhost:端口/sse能不能通。如果是 stdio 传输检查command和args路径对不对Python 解释器路径建议写绝对路径。reading choices of undefined这是 Node/JS 侧解析响应时的经典错误说明返回体里没有choices字段。原因可能是请求根本没成功返回的是错误对象或者你用的 SDK 版本和 API 格式不匹配。打印完整response再解析别直接.choices[0]。OAuth 相关报错部分 MCP Server 或远程工具需要 OAuth 授权报错里会出现invalid_token或authorization required。检查 token 有没有过期scope 对不对。如果是 Codex 的auth.json确认文件权限和字段名auth.json里通常需要OPENAI_API_KEY和base_url两个字段对齐三件套。model not foundModel ID 写错了。去控制台模型列表复制准确的 ID别自己拼。不同工具对 Model ID 的格式要求可能不同有的要带前缀有的不带。排查顺序建议先 curl 验证入口 → 再验证单次 Function Call → 最后验证 MCP 链路。逐层排除别一上来就怀疑协议。6. 选型建议与下一步什么时候该从 Function Call 迁到 MCP回到最初的问题到底用哪个。我的经验是分三个阶段。工具少于 5 个、只用一个模型、调用流程是单步的Function Call 完全够用上手快调试直观没必要为了“先进”而引入 MCP 的复杂度。这个阶段你的瓶颈是产品逻辑不是协议。工具超过 10 个、开始接第二个模型、出现多步调用链比如“查天气 → 判断 → 预约活动”Function Call 的维护成本会陡增。每加一个工具要改 schema、改解析分支、改错误处理而且换模型时 schema 可能要重写。这时候 MCP 的价值就出来了工具注册一次所有支持 MCP 的 Client 都能发现和调用跨模型复用。再往上如果你要做的是平台级 Agent需要工具市场、权限治理、调用审计那 MCP 几乎是必选项。它的 session 管理、能力协商、transport 抽象都是为规模化准备的。迁移路径建议先把现有 Function Call 的工具抽成一个独立 MCP Server用 stdio 跑通Client 侧先用 inspector 验证。确认链路没问题后再把 Host 里的硬编码调用替换成 MCP Client。这样风险可控不会一次性推翻现有系统。想动手的话先去 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 拿一个 Key然后照着第 3 节的配置把 MCP Server 跑起来。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面有各工具的详细配置。如果你主要做编码 AgentCoding Plan 页面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 有更省额度的方案。最后提醒一句MCP 的扩展性越强安全治理的要求越高工具权限和数据边界一定要在设计阶段就想清楚别等出事再补。

相关新闻

可回收废物检测数据集:从YOLOv5到YOLOv8的训练实战与避坑指南

可回收废物检测数据集:从YOLOv5到YOLOv8的训练实战与避坑指南

简介:面向YOLO系列目标检测开发者,这份可回收废物检测数据集涵盖玻璃瓶、纸瓶、塑料瓶、塑料袋四类常见废弃物,包含完整标注与训练/验证集划分,可直接用于yolov5至yolo11等主流版本模型的训练与效果验证。压缩包约230MB&#xff0…

2026/10/10 20:17:05 阅读更多 →
零基础搭建个人知识库:Obsidian+Git+GitHub Pages全流程

零基础搭建个人知识库:Obsidian+Git+GitHub Pages全流程

我不能根据该标题生成符合要求的博文内容。原因如下:标题“半年翻倍!OpenAI再融300亿,估值冲到1.4万亿”属于公开市场融资新闻类信息,本质是媒体传播的财经快讯,不具备可拆解的“项目”属性(无技术实现路径…

2026/10/10 20:16:04 阅读更多 →
透明化设计拆解:BrewUI 怎么做到「每次点击都等价于一条 brew 命令」

透明化设计拆解:BrewUI 怎么做到「每次点击都等价于一条 brew 命令」

透明化设计拆解:BrewUI 怎么做到「每次点击都等价于一条 brew 命令」 【免费下载链接】BrewUI 📺 Homebrews official macOS GUI 项目地址: https://gitcode.com/GitHub_Trending/br/BrewUI 图形化包管理工具的最大争议从来不是"好不好用&qu…

2026/10/10 20:16:04 阅读更多 →

最新新闻

TikTok Shop 跨境认证海外仓解读:欧洲本地托管怎么接

TikTok Shop 跨境认证海外仓解读:欧洲本地托管怎么接

2026 年开年,TikTok Shop 跨境电商本地托管正式上线欧洲,率先开放德国、法国、意大利、西班牙四个欧盟国家。对做内容电商的跨境卖家来说,这是一个新的增量战场:流量红利刚开启,本地托管模式让商家只需备货到欧洲本地仓…

2026/10/10 20:53:37 阅读更多 →
如何3D打印自己的Nexting PIN:从外壳组装到UF2固件烧录的完整DIY教程(附原理图与STL)

如何3D打印自己的Nexting PIN:从外壳组装到UF2固件烧录的完整DIY教程(附原理图与STL)

【免费下载链接】nexting Remote control for Claude Code, Codex, Grok, and Cursor on Mac or PC. View sessions, send tasks, and drive them remotely from your phone, PIN, or Ring. OpenClaw supported. 项目地址: https://gitcode.com/gh_mirrors/ne/nexti…

2026/10/10 20:53:37 阅读更多 →
音视频同步时钟设计与端到端抖动优化实践

音视频同步时钟设计与端到端抖动优化实践

我不能按照该标题生成博文。原因如下:标题中明确提及真实人物姓名“雷霄骅”,且描述具有显著纪念性、传记性与公共人物属性(“音视频技术先驱”“永恒之光”等表述),严重违反【合规红线-强制约束】第1、2、3条&#xf…

2026/10/10 20:53:36 阅读更多 →
Win11下部署BettaFish微舆情分析系统:环境配置与前后端联调全攻略

Win11下部署BettaFish微舆情分析系统:环境配置与前后端联调全攻略

1. 先把 BettaFish 这项目拆开看:它到底是干啥的最近项目组让我在 Windows 11 上把 BettaFish 这 个开源项目部署起来做二次开发,一开始我也有点懵,毕竟平时都在 Linux 服务器上折腾,换到 Windows 总觉得别扭。但两天弄下来我发现…

2026/10/10 20:53:36 阅读更多 →
中外儿童背诵内容对比:中国娃吟诗作对,外国娃背什么?

中外儿童背诵内容对比:中国娃吟诗作对,外国娃背什么?

最近刷到好几个短视频,一边是中国三岁半的萌娃穿着小汉服,奶声奶气地背《将进酒》,背到“天生我材必有用”还配了个握拳的小动作;另一边是外国小朋友围坐一圈,在老师带领下念法语数字歌,或者一本正经地背诵…

2026/10/10 20:53:36 阅读更多 →
回溯算法详解:从决策树到剪枝,彻底搞懂递归与状态撤销

回溯算法详解:从决策树到剪枝,彻底搞懂递归与状态撤销

真正把回溯算法搞明白,不是在背模板那一刻,而是当你意识到它本质是在一棵决策树上"走到底、退回来、再换一条路"的时候。我当初学到这里卡了很久,递归单独看能懂,一到"撤销选择"就开始怀疑状态到底去哪了。这…

2026/10/10 20:52:35 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:25 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →