你可能遇到过这种场面:脚本里已经把 REST 接口调通了,老板又让你接一个 MCP 服务器,文档里说的是「工具」「资源」「上下文」,跟原来的路径加参数完全不是一套说法。这篇不重复协议兼容层和客户端配置,只从工程落地角度对比两边的调用模型、失败方式和运维成本,给一套能照着走的判断顺序。
先把场景说清楚:你手上已经有一套跑通的 REST 调用,路径、参数、鉴权都摸熟了,现在要接一个 MCP 服务器,文档里蹦出来的是「工具」「资源」「上下文」,跟原来的 URL 加 query 完全是两套说法。别急着找协议兼容层,先搞清楚这两种调用在工程上根本不是一个模型,接法、错法、运维方式都不一样。
这篇只对比落地层面的差别:请求怎么发起、契约从哪来、权限怎么划、失败长什么样、日志记什么、上线后怎么改。协议细节和客户端配置不在这里展开,那些去站内指南中心看相关条目。看完你应该能做两件事:给定一个能力,判断该做成 API 还是 MCP 工具;已经接了 MCP,知道出问题时先翻哪一层。
两种调用在脑子里长什么样
API 调用的心智模型很简单:你的代码主动发一个带路径和参数的请求,调用方和被调方是写死的一对一关系,谁调谁、调几次、什么顺序,全在你代码里。MCP 调用不是这样——调用方不写在代码里,写在服务器声明的工具清单里,由会话里的模型去挑一个用。你写的不是「调 A」,而是「告诉模型有 A、B、C 可用」。
- 入参来源
- API 的入参由接口文档规定,你照着填;MCP 的入参由模型自己生成,你只能约束它别乱填
- 调用方身份
- API 的调用方是确定的代码路径;MCP 的调用方是会话里的一次决策,同一段代码不一定走同一个工具
- 关系稳定性
- API 是固定配对,改一端要通知另一端;MCP 是清单匹配,服务器加个工具,模型的行为分布就可能变
有个关键差别容易被忽略:API 的入参错了,通常是客户端拼错,改代码就行;MCP 的入参错了,是模型生成的,你改不了模型,只能改工具描述让它少犯错。所以参数校验的严格程度要提一档。
契约从哪来:接口文档 vs 工具清单
API 侧的契约是文档加版本号,改字段要发版、要通知调用方、要留迁移期。MCP 侧的契约是服务器运行时暴露出来的工具描述,模型读到什么就按什么调,没有版本号这一说。这就带来一个实际后果:描述写得糊,模型就会瞎调,而且报错不会告诉你「是你描述写错了」。
- 先看参数类型写没写清打开工具描述,确认每个参数的 type、必填项、取值范围都在里面。类型是 string 还是 integer、能不能为空,写不清模型就会猜
- 再看实际传了什么翻会话里的工具选择记录,把模型真实传入的参数跟描述对照。经常能看到描述里说可选、模型却传了个空字符串,或者类型对不上
- 最后才怀疑实现描述和入参都对,工具返回却不对,才去查服务器实现。顺序反了会浪费大量时间在没问题的代码上
不适用的情况也说一下:如果只是内部单人用的短期脚本,没必要为一个工具专门写精细描述,跑通就行。但只要这个工具会被别人用、或者会被放进多步流程里,描述就是契约,值得当文档写。
| 对比项 | API 侧 | MCP 侧 |
|---|---|---|
| 契约载体 | 接口文档 + 版本号 | 服务器运行时暴露的工具描述 |
| 变更方式 | 发版、通知、迁移期 | 改描述即生效,无版本概念 |
| 出错归因 | 改客户端代码 | 改工具描述或加校验层 |
| 多步组合 | 代码里写死调用顺序 | 模型自己决定先调哪个 |
鉴权与权限边界怎么划
API 的 Key 通常绑在一个账号或项目上,权限范围由服务端配置决定,你越权一般会收到明确的错误码,好定位。MCP 的权限更容易被忽略:模型能调到的工具集合,就是它的权限面。你给清单里加一个写操作工具,等于在会话里放了一个口子,而且这个口子是通过自然语言触发的,不像改代码那样显眼。
- 把工具按读写分级:读类工具可以放开,写类工具加确认步骤或走人工审批
- 清单里的每个工具都要能回答「最坏情况下模型用它干了什么」
- 别一次性把所有内部接口都挂成工具,先挂最小可用集合,按需再加
- 给高风险工具加参数范围限制,比在服务端事后发现更省事
- 定期回看工具清单,下线几个月没人用的工具也是缩小权限面
什么情况下可以放宽:全部工具都是只读查询,且数据本身不敏感,比如查公开文档、查天气这类。一旦涉及写、涉及钱、涉及用户数据,分级和确认就不能省。
失败表现完全不同,排错顺序也不同
API 失败信号很清晰:状态码、错误体、超时,基本能定位到是网络、鉴权还是参数。MCP 失败常常是「模型没调」或者「调错工具」,没有 HTTP 状态码可看,你面对的是一段会话记录。这就决定了排错顺序要反过来,先确认请求有没有真的发出去,再谈别的。
- 请求发出去了吗先看会话里有没有对应的工具调用记录,没有的话问题在模型选择层,不在你的接口
- 参数合法吗有调用记录就看入参,跟工具描述对照,缺必填、类型错都会在这一层暴露
- 工具返回了吗看服务器有没有返回、返回体是不是空、是不是超时,这一步跟调 API 类似
- 返回被读懂了吗模型拿到返回但没按预期继续,往往是返回结构太复杂或字段名看不懂,简化返回比改模型有用
有个反直觉的情况:当你把 MCP 服务器的调用日志完整打出来时,排错反而比 API 简单,因为决策链和结果在同一个地方,你能看到模型为什么选这个工具。前提是日志真的打全了。
| 失败类型 | 典型表现 | 先动哪里 |
|---|---|---|
| 模型没调工具 | 会话里没调用记录 | 改工具描述、检查清单是否暴露 |
| 选错工具 | 调了 A 但该用 B | 补描述里的使用场景、区分同类工具 |
| 参数不合法 | 工具报参数错 | 在描述里收紧类型和必填 |
| 工具本身报错 | 有调用、服务端返回错 | 查服务器实现,跟 API 排错一样 |
| 返回没被用上 | 调了、返回了、流程没继续 | 简化返回结构,检查字段命名 |
日志和观测该记什么
API 侧的日志套路大家都熟:请求 ID、端点、状态码、耗时、重试次数。MCP 侧要在这个基础上多记几样,因为你要还原的不只是一次网络请求,而是一次决策。被选中的工具名、入参原文、工具返回原文、以及模型有没有用上这个返回,这几项缺一样就还原不了现场。
- 请求 ID 和会话 ID 都要带,方便把一次决策链串起来
- 入参和返回都记原文,别只记摘要,摘要会丢掉类型信息
- 记录模型有没有引用返回内容,判断工具是否真的起作用
- 重试次数单独记,MCP 场景里重试可能表现为换个工具重试,跟 API 的原地重试不一样
- 耗时按「模型选择耗时」和「工具执行耗时」分开统计,混在一起看不出瓶颈
两边都要能回答三个问题:这次调用为什么发生、花了多少、失败后有没有重试。什么情况下可以少记:纯本地实验环境,日志随手写写就行,但一旦上生产就别省这几行,MCP 的问题一旦没法复现,日志是唯一的线索。
上线后改动和运维的差别
API 改动本质上是版本迁移问题:双跑、灰度、下线老版本,套路成熟。MCP 改动是能力面变化问题:新增或下线一个工具,模型的行为分布会跟着变,原来走 A 路径的可能改走 B 了。你改的是清单,动的是模型的决策空间,这两件事的回归成本不一样。
- 给工具清单加变更记录谁在什么时候加了哪个工具、改了什么描述,记在一个地方,跟代码变更一样对待
- 准备固定用例挑几条典型提问,跑一遍看模型还会不会走原来的路径,路径变了就要评估是不是可接受
- 小流量先放新工具先只对一部分会话可见,观察决策是否稳定,稳了再全量
- 下线也走流程直接删工具可能让模型找不到原路径而乱试,先标记废弃、观察一段时间再移除
不适用的情况:工具集合稳定、模型固定且用量很小的内部场景,可以不做回归,改完自己点几下确认就行。用量一上来,回归成本就没法省了。
选哪种:一张判断清单
判断顺序可以简化为一句:这个能力是人来触发还是模型来触发。模型需要在对话里自主选择、组合、多步串起来,优先 MCP;需要被代码在固定流程里精确调用、严格控制参数和时序,优先普通 API。两者都要的情况很常见,做法一般是底层保留 API 保证稳定,上面挂一层工具声明给模型用。
| 你的诉求 | 优先选 | 理由 |
|---|---|---|
| 模型自主选、多步组合 | MCP | 调用方是模型决策,写不进固定代码 |
| 固定流程、精确参数 | API | 时序和参数可控,失败可定位 |
| 既要稳定又要灵活 | API 打底 + MCP 包一层 | 底层稳,上层让模型挑 |
| 纯单人短期脚本 | API 就行 | 没必要为一次性需求写工具描述 |
兜底原则:别为了「用上 MCP」而把本来就该写死的调用改成工具。模型决策是有成本的,能确定的事让代码确定下来更省心。价格和用量相关的数字,不同中转和官方口径不一样,去站内价格追踪页面核对当时的数字更靠谱。
怎么验证接得对不对
验收到最后还是要落到用例上。准备一组固定场景:正常参数、缺必填、类型写错、工具返回空,看 API 和 MCP 两边的反应是否符合预期。MCP 这边还要额外看一件事——模型在失败之后是换工具重试还是直接放弃,这个行为决定了你要不要加护栏。
- 给调用设步数上限,避免模型在多个工具之间反复试出不来
- 设总耗时上限,长会话里单次工具调用拖太久会拖垮整体体验
- 把每次失败归类成「选错工具」「参数不合法」「工具本身报错」三类,分别改描述、改校验、改实现
- 固定几条回归用例,每次改工具清单后跑一遍,观察路径有没有漂移
还有一点容易被跳过:确认工具返回的内容本身是可读的。返回一个嵌套很深的 JSON,模型很可能抓不到关键字段,这时候简化返回比调整提示词有效。反过来,如果你发现模型总是忽略某个工具,先怀疑描述里没说清它什么时候该用,而不是模型不行。
下一步如果这篇帮你分清了两种调用的边界,接下来该看具体服务的真实数据了:各家官方 API 的当前价格、支持模型和中转站可信度都在站内持续更新,接之前先去核对当时的数字,比听别人转述靠谱。→常见问题
MCP 是不是就是把 API 包装了一层?
不完全是。包装只解决了「能调」,MCP 还要解决「模型知道什么时候该调」和「参数由模型生成」。如果你的场景里调用时机和参数都是代码写死的,那确实只是包装,用普通 API 更省事。只有需要模型自主选择工具时,这层才有实际价值。
我原来的 API 能不能直接给 MCP 用?
可以,但通常要重写一层描述:把端点、参数类型、必填项、返回结构翻译成模型能读懂的工具说明,并在实现里补上参数校验。直接透传的话,模型很容易传错类型或漏必填,最后要靠服务端报错来兜底,体验很差。
两边并发和限流要怎么一起考虑?
MCP 上游还是打到同一批接口,所以限流要看底层接口的额度,而不是看 MCP 服务器。模型一次性发起多个工具调用时会叠加并发,建议给工具层设一个总并发上限并排队。具体额度到站内页面按当时的数字核对,别按经验估。
调用失败了怎么快速判断是哪一层的问题?
先看底层接口有没有收到请求:没收到就是工具选择或参数构造的问题;收到了但报错就看错误类型;返回正常但模型答非所问,就是返回内容没被正确解读。这三步能把问题圈到具体一层,避免到处改。
小团队有没有必要一上来就上 MCP?
看模型要不要自己决定调什么。五个人以内、流程固定的工具链,用普通 API 加一点提示词通常够了,维护成本更低。等出现「同一批工具要按不同任务灵活组合」的需求时再引入,迁移代价并不大。