
做 AI 应用时MCP 和 Function Calling 经常被当成同一件事。“MCP 就是高级版 Function Calling”“有了 MCP 就不需要 Function Calling 了”这两种说法其实都忽略了它们在调用链中的位置。要真正分清边界最直接的办法是让 MCP Host 的模型请求先走一次 TaoTokenhttps://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 然后在真实响应里观察两段转折——模型返回的“工具调用意图”以及 Host 发出的 tools/call 请求。前者是 Function Calling 的边界后者是 MCP 的边界。如果不把这两层分开工具一多就会出现两种典型症状要么把工具描述全塞进系统提示词提示词越来越长模型却越来越不会选要么手写一套私有工具调用协议换 Host 就全部作废。这篇文章会把一个 MCP Host 的模型 API 直接指向 TaoToken用 queryStudentStats 这个工具跑一遍让边界在响应里自然显形顺便给出可复制的配置和排障方法。1. 先把调用链画对两个边界不在同一层同时使用 Function Calling 和 MCP 的典型链路可以压缩成下面这条横线用户 → LLM →模型返回 queryStudentStats(studentName张三)→ MCP Host →MCP Client 发送 tools/call→ MCP Server → 数据库 / 业务 API这张图里有两个完全不同的边界。第一个边界在 LLM 与 AI 应用之间模型并不直接执行任何代码它只是通过 Function Calling 返回一个结构化请求告诉应用“我想调用 queryStudentStats参数是张三”。第二个边界在 AI 应用与 MCP Server 之间应用里的 MCP Client 收到模型意图后把参数整理成 tools/call 消息通过协议发给 ServerServer 真正执行查询再返回结果。一个是“模型怎么表达我想做的事”一个是“应用怎么按照统一规矩去把事做了”。这两个边界不是串在一起的同一条线而是两层独立的协作关系。如果不用 MCPAI 应用完全可以把 Function Calling 返回的请求映射成本地 Java 方法、REST API 或者一段 SQL如果不用 Function Calling应用也可以根据用户点击某个按钮、执行固定工作流或业务规则主动去调用 MCP Tool甚至直接读取 MCP Resource。所以更准确的说法是两者经常协作但彼此都不是对方的前置条件。“决定调用”“传输调用”“执行调用”这三件事不应该被混成一层。2. Function Calling 和 MCP 各管哪一段先看 Function Calling。它是模型 API 提供的一种工具调用接口应用先把工具的名称、描述和参数结构发给模型。下面是一份典型的工具定义{ type: function, function: { name: queryStudentStats, description: 查询指定学生的作业提交和成绩统计, parameters: { type: object, properties: { studentName: { type: string, description: 学生姓名 } }, required: [studentName] } } }当用户问“张三最近成绩怎么样”时模型大概率不会直接生成“他去查了数据库”这种话而是返回一段结构化调用请求{ name: queryStudentStats, arguments: { studentName: 张三 } }这里最容易误解的一点模型通常只生成调用请求并不会去执行你的 Java 方法或数据库查询。后续步骤仍然由应用负责把可用的工具和用户问题一起发给模型接收模型返回的工具调用请求校验参数执行本地代码或转发给外部系统把工具结果交还给模型模型基于结果生成最终回答或者继续请求下一个工具。Function Calling 更像是模型和应用之间的一种“结构化协作接口”它回答的是“模型是否需要工具、选哪个工具、参数是什么”至于工具位于当前 JVM、另一个微服务还是第三方平台它并不关心。MCP 再往后走一层。它全称 Model Context Protocol是一套建立在 JSON-RPC 2.0 之上的开放协议采用 Host、Client、Server 三层架构。MCP Host 是承载 AI 体验的应用负责权限、上下文和模型集成MCP Client 是 Host 中负责连接某个 MCP Server 的协议组件MCP Server 则按统一格式向外暴露能力。MCP Server 暴露的不只是 Tool还包括 Resources可读取的文件、数据库记录、Git 历史和 Prompts可复用的提示模板。以 Tool 为例MCP Client 先通过 tools/list 发现可用工具{jsonrpc: 2.0, id: 1, method: tools/list, params: {}}再通过 tools/call 发起调用{jsonrpc: 2.0, id: 2, method: tools/call, params: {name: queryStudentStats, arguments: {studentName: 张三}}}上面的示例为了突出核心字段省略了 MCP 规范要求的 _meta 元数据。MCP 当前定义了两种标准传输stdio 是 Host 启动本地子进程后通过标准输入输出交换消息Streamable HTTP 则通过统一 HTTP 端点传输并可用请求级 SSE 流返回结果。所以 MCP Server 不一定是远程微服务也可以是一个本机子进程。MCP 的核心价值不是“把一次方法调用改成 HTTP”而是让不同 Host 和不同能力提供方共享一套可发现、可组合、可替换的接入协议。3. 把 TaoToken 接进 MCP Host让边界在响应里显形概念讲完了要让“边界”这个抽象词变成能观察的东西就需要一个可以动手的实验环境。接下来把 MCP Host 的模型请求改走 TaoToken用实际响应区分模型层的 Function Calling 和工具层的 MCP。3.1 准备材料一把 Key 和一个 MCP Server先去 TaoToken 注册并创建 API Key。创建好之后会得到一把形如sk-...的密钥下文统一用YOUR_API_KEY占位。具体的模型 ID 不要凭记忆填去 TaoToken 官网的模型广场看当时的列表以模型广场为准。再准备一个暴露queryStudentStats工具的 MCP Server。如果你手上已经有现成的 MCP Server直接复用如果没有用 MCP 官方 SDK 的最小模板写一个即可Server 本身不是这篇文章的重点重点是通过它观察调用链。3.2 用 Claude Code 当 MCP HostBase URL 指向 TaoTokenMCP Host 有很多选择这里用 Claude Code 做实验最直接因为它原生支持 MCP 协议同时模型接入只需要配置环境变量。先设置模型请求的 Base URL 和 Keyexport ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_AUTH_TOKENYOUR_API_KEY export ANTHROPIC_MODELMODEL_ID其中MODEL_ID以 TaoToken 模型广场当天的列表为准。也可以把配置写进~/.claude/settings.json{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY, ANTHROPIC_MODEL: MODEL_ID } }这里有两个容易踩的地方第一Base URL 一定是https://taotoken.net/api末尾不要加/v1不要加 UTM也不要填成官网首页第二官网落地页只用来注册、创建 Key、看模型广场和用量不能填进工具的 Base URL。那把 Key 也不要写死在代码里用环境变量或本地配置文件加载。3.3 跑一次 queryStudentStats拆开六个环节把 MCP Server 接到 Claude Codeclaude mcp add school-stats -- node /path/to/school-stats-server.js然后在 Claude Code 里问一句“张三最近成绩怎么样”这条对话会依次走六个环节MCP Client 启动时通过tools/list拿到queryStudentStats的工具定义。Host 把工具的名称、描述和输入 Schema 转成模型 API 能识别的 function schema发给模型。模型通过 Function Calling 返回“我想调用 queryStudentStats参数是张三”的意图。Host 中的 MCP Client 把这个意图转换成tools/call请求发送给 MCP Server。MCP Server 校验权限和参数执行查询按 MCP Tool Result 格式返回结果。Host 把工具结果交还给模型模型基于结果生成最终回答。仔细观察这六步第 1、2、3、6 步围绕“模型与应用”展开属于 Function Calling 的职责范围第 4、5 步围绕“应用与 Server”展开属于 MCP 的职责范围。TaoToken 在整条链路里只负责转发模型 API 请求不介入工具执行。所以当调试日志里先出现“模型返回了 queryStudentStats 的调用请求”后又出现“MCP Server 返回了执行结果”时函数选择和工具执行之间的边界就自然显现了。拿到同一把 Key 后你也可以把它配到其他 OpenAI 兼容的 MCP Host 里对比不同 Host 在 tools/list 和模型请求格式上的差异。4. 核心区别对照边界、职责、观察点维度Function CallingMCP在 TaoToken 实验里怎么看所在边界模型 ↔ 应用MCP Client ↔ MCP Server模型返回 arguments 时是 FC 层Host 发 tools/call 时是 MCP 层核心问题模型如何表达工具调用请求能力如何被统一发现、连接、调用一个问“选谁”一个问“怎么接”工具来源应用提交给模型 APIServer 通过 tools/list 暴露改工具 Schema 影响 FC改 Server 暴露影响 MCP谁选择工具通常由模型也可由应用限制协议本身不负责模型决策模型不返回调用意图时先怀疑 FC 侧谁执行工具应用或平台执行/转发MCP Server 接收 tools/call 后执行Server 无响应时先怀疑 MCP 侧传输方式取决于模型提供商 APIstdio、Streamable HTTP 或自定义传输Base URL 和协议版本决定能否连通能否独立使用可以不依赖 MCP可以不要求模型自动选工具单独改任何一层都不影响另一层表格里“所在边界”是最重要的一行。很多人分不清了多半是把“模型选择工具”和“应用执行工具”压成了一件事。实际上Function Calling 的产物是一张由模型填写的“调用单”MCP 的产物是一次发生在 Host 与 Server 之间的“标准协议调用”。模型填好调用单之后应用可以在本地执行也可以走 REST更可以把它映射为 MCP 的 tools/call。这才是两者真正的关系。5. 三个最常见的误区从“谁是谁的升级版”说起第一个误区MCP 是 Function Calling 的升级版。升级关系意味着新方案覆盖旧方案的职责但 MCP 并不替模型决定调用哪个工具它解决的是另一层的标准化接入问题。Function Calling 管“模型想说啥”MCP 管“应用怎么接”两者干的事不一样谈不上升级。第二个误区有了 MCP 就不需要 Function Calling。如果希望模型根据自然语言自主选择 MCP Tool模型侧仍然需要某种 Tool Calling 能力。有些模型平台原生支持 MCP把中间的适配过程封装起来了会让“不需要 FC”的错觉其实只是被屏蔽了。第三个误区用了 Function Calling 加手写 HTTP 就等于 MCP。Function Calling 之后当然可以手写 HTTP 请求但那是你自己的适配方式MCP 还规定了工具发现、Schema、结果结构、版本兼容、传输和授权等共同约定。“能远程调用”不等于“实现了 MCP”。另外还有个更实际的坑用了 MCP 并不代表可以不好好写工具描述。Tool 的 name、description 和 inputSchema 会直接影响模型能不能选对工具、填对参数MCP 省掉的是各 Host 与 Server 重复定义接入协议的成本不是工具语义设计的成本。6. 什么时候只用 Function Calling什么时候引入 MCP只用 Function Calling 通常就够了工具只服务于一个应用工具和编排代码位于同一个项目里工具数量少且变化不频繁不需要接入其他 MCP Host 或复用外部 MCP Server直接调用本地方法或既有 REST API 已经足够清晰。比如在一个单体应用里直接持有几个 Tool 对象去发模型请求就没必要为了“看起来更 Agent”额外引入 MCP。引入 MCP 更有价值的场景则相反同一套能力要被多个 AI 应用复用Host 与工具由不同项目或团队维护希望接入现有 MCP Server 生态既想提供 Tools 也想提供 Resources 或 Prompts或者希望模型与框架可替换而能力服务保持稳定。判断标准不是“工具超过几个”或者“团队超过几个人”而是你是否真的需要一个稳定、可复用、跨实现的能力边界。MCP 不是免费午餐引入后仍然要处理 Schema 演进、权限控制、超时重试、工具重名、日志审计和提示注入防护。如果只是几个本地方法硬套 MCP 反而会多出一层运维成本。7. 跑通之后怎么用报错反推是哪一层出问题实验跑起来后如果报错可以根据错误特征快速判断问题出在 FC 层、MCP 层还是接入层。返回 401 Unauthorized先查接入层API Key 是否正确、有没有在 TaoToken 控制台创建、是否把YOUR_API_KEY占位符当成了真实 Key 填进去。返回 404 Not Found先查 Base URL正确写法是https://taotoken.net/api末尾不加/v1不要带上 UTM更不要把官网首页地址填进环境变量。模型没有返回调用意图直接回复“我查不了”问题可能出在 FC 侧工具描述写得模糊、必填参数没标、当前模型本身不支持 function calling。这时候去模型广场换一个更合适的模型或者重新组织工具描述。MCP 工具一直没有执行先看 MCP 侧用claude mcp list确认 Server 注册成功再确认 Server 有没有通过tools/list暴露queryStudentStats。如果看到的是旧教程里的 initialize、Mcp-Session-Id、HTTP SSE 这类字眼那是 2026-07-28 之前的 MCP 协议版本当前规范已改为无状态模型请求自带协议版本和 Client Capabilities代码不一定是写错了是协议版本迭代了。8. 记住三句话再动手验证一次Function Calling 是模型侧的工具调用接口模型表达调用意图应用处理调用闭环。MCP 是应用侧的能力接入协议统一发现、连接和调用 Tools、Resources、Prompts。两者可以组合但谁也不是谁的升级版。想自己动手观察这条链路先去 TaoToken 模型对话 用同一把 Key 发一条测试消息确认模型 ID 和 Base URL 没填错要长期写代码可以在 Coding Plan 看套餐是否够用Key 在 控制台 API Keys 创建。Claude Code 的环境变量对照和完整接入步骤见 Claude Code 接入文档。