主题
高频面试题
如何将已有的应用转换成 MCP 服务?
已有应用接 MCP 不是“把所有 API 包成 tools”,而是把应用能力重新整理成适合 Agent 发现、调用、审计和授权的接口。
面试官角度分析,想考什么
转 MCP 服务的第一步是什么?
考能力盘点:先按读上下文、执行动作、任务模板拆 resources、tools、prompts,而不是原样暴露 API。工具粒度和鉴权怎么设计?
考面向任务的抽象、身份透传和最小权限。副作用、安全和上线怎么验证?
考审批、幂等、审计,以及契约测试、trace 和灰度。
可直接抄走的 30 秒参考答案
text
我会先盘点已有应用能力,把只读上下文做成 resources,把模型需要主动执行的查询或动作做成 tools,把可复用任务流程做成 prompts。工具不要一比一照搬底层 API,而要按 Agent 任务设计清晰粒度、稳定 schema、可控返回和错误语义。然后接入原应用的认证授权,做到用户身份、tenant、scope 和审计可追溯。高风险写操作要 preview、用户确认、幂等和回滚。最后用 MCP inspector 或集成测试验证协议契约、权限、注入、大结果、超时和日志。面试回答详解,知其所以然
这道题考的是“产品能力如何变成 Agent 可用能力”。MCP Server 可以包一层已有 REST API、GraphQL、CLI、数据库或本地应用,但真正难的是设计边界:哪些能力可以被模型调用,哪些只能由用户选择,哪些必须审批。
1. 先做能力盘点和风险分级
不要从代码开始,先盘点已有应用的能力:
- 只读查询:查订单、查 issue、读文档、查报表。
- 有副作用操作:创建记录、修改状态、删除文件、发送消息。
- 长任务操作:导出报表、跑构建、生成批处理任务。
- 上下文数据:项目配置、文档、日志、数据库 schema、用户选择的对象。
- 可复用流程:日报模板、故障排查步骤、PR review 提示。
再按风险分级:
- 低风险:只读、可公开、结果可截断。
- 中风险:读取敏感数据、访问内部系统、消耗配额。
- 高风险:写生产、删数据、发通知、付款、改权限。
这个分级决定后面的 tool 设计、权限、审批和审计。
2. 映射 MCP primitive:不是所有 API 都是 tool
MCP Server 主要暴露三类 primitive:
- Resources:适合“读上下文”。例如
project://config、file://docs/readme、db://schema/orders。通常由 Host 或用户选择后放进上下文。 - Tools:适合“执行动作或按需查询”。例如
search_orders、create_ticket、run_report。模型可以在任务中选择调用。 - Prompts:适合“可复用任务模板”。例如
review_pr、triage_incident、write_release_notes。
判断口诀:
text
用户/Host 主动选择的上下文 -> Resource
模型需要决策是否执行的动作 -> Tool
可复用工作流入口 -> Prompt例如已有知识库应用里,“读取某篇文档”可以是 resource;“按关键词搜索文档”可以是 tool;“根据文档生成 FAQ”可以是 prompt。
3. 设计工具粒度:面向任务,不面向底层接口
常见错误是把每个 REST endpoint 直接变成一个 tool。这样会导致工具太多、参数太底层、模型选择困难。
更好的设计:
- 用业务动词命名:
search_customer_orders比GET /v1/orders更适合模型。 - 工具粒度适中:一个工具完成一个清晰任务,不做万能
call_api。 - 参数少而明确:优先枚举、布尔、日期范围、分页 cursor,少用自由文本大对象。
- 输入 schema 写约束:必填字段、格式、最小最大值、枚举值。
- 返回结构稳定:成功、失败、可重试、需要用户确认要区分。
- 高风险工具拆成两段:
preview_change/apply_change。
示例链路:
text
用户说“帮我找上周失败的构建并建跟进任务”
-> search_failed_builds(project, date_range)
-> summarize_build_failures(build_ids)
-> create_tracking_ticket(summary, assignee) 需要确认4. 适配已有应用的几种方式
- 包 REST / GraphQL API:最常见,MCP Server 内部调用已有 HTTP 接口。
- 包 SDK:复用官方 SDK,减少认证、分页和错误处理成本。
- 包 CLI:适合已有命令行工具,但要严控参数、工作目录和输出大小。
- 直接连数据库:适合内部只读查询,生产中要使用只读账号和 SQL allowlist。
- 嵌入应用进程:适合桌面、本地 IDE、浏览器状态,但要格外注意权限和稳定性。
不管哪种方式,对外都应该暴露稳定的 MCP 能力,而不是泄露内部实现细节。
5. 认证授权:把用户身份和工具权限接起来
已有应用通常已经有用户、组织、角色和权限。转换成 MCP Server 时要决定身份模型:
- 本地个人工具:使用本机 token、系统密钥链、配置文件或 OAuth 登录。
- 企业 SaaS:优先 OAuth,让每个用户以自己的身份访问。
- 内部平台:可以用服务账号 + 细粒度授权,但要把最终用户和请求来源写入审计。
- 多租户服务:每次请求都带 tenant、user、project scope,并做服务端校验。
重要原则:
- token 不进入模型上下文。
- 不要让 MCP Server 用超级管理员权限服务所有请求。
- Host 看到的是工具和结果,不应该看到可复用密钥。
- 需要支持撤销授权、刷新 token 和权限变更。
6. 安全和副作用控制
写操作一定要设计成可检查、可确认、可追溯。
- 高风险工具提供 dry-run 或 preview。
delete_*、send_*、purchase_*、grant_*等工具默认需要确认。- 对重复请求使用 idempotency key。
- 对外部系统写入保留 request id 和 audit log。
- 返回结果说明“改了什么、没改什么、下一步是什么”。
- 失败要可恢复:重试、安全取消、补偿动作或人工接管。
面试中可以主动补一句:MCP Server 暴露给模型后,错误参数不再只是 API 调用失败,还可能变成真实业务事故。
7. 上线验证和可观测性
上线前至少验证四类东西:
- 协议契约:initialize、tools/list、tools/call、resources/read、错误返回符合 MCP 规范。
- 工具质量:schema 清楚、描述不误导、参数边界明确、返回结构稳定。
- 安全策略:越权、注入、路径穿越、敏感信息泄露、危险动作审批。
- 运行质量:超时、限流、重试、分页、大结果截断、日志和 trace。
生产指标可以看:
- tool call 成功率和失败类型。
- 模型选错工具比例。
- 需要人工确认的调用比例。
- 平均延迟和 token 成本。
- 被策略拦截的危险调用数量。
面试官追问3个问题
追问一:为什么不能直接暴露一个 call_api(path, method, body)?
- 考察点:工具抽象能力和安全意识。
- 回答方向:万能 API 工具让模型承担底层协议决策,schema 太松,越权和误操作风险大,也很难审计。更好的做法是封装成业务级工具,参数和权限都受控。
追问二:读取详情应该做 tool 还是 resource?
- 考察点:MCP primitive 边界。
- 回答方向:如果详情由用户或 Host 明确选择并加入上下文,更像 resource;如果模型需要在任务过程中按条件决定读哪个对象,可以做 tool。很多系统会两者都提供,但职责不同。
追问三:已有应用是内部系统,没有 OAuth 怎么办?
- 考察点:现实工程适配。
- 回答方向:可以用服务账号或内部网关,但必须把最终用户、tenant、project scope 带进请求并在服务端校验;高风险动作加审批;审计记录不能只记服务账号。
扩展知识
一个实用迁移流程
text
能力盘点
-> primitive 映射
-> tool/resource schema 设计
-> auth 和 scope 接入
-> 安全策略与审批
-> 测试和 inspector 验证
-> 灰度上线和 trace 观测REST API 到 MCP 的映射不是一比一
- 列表型 API:通常封装成带过滤条件和分页 cursor 的 search tool。
- 详情型 API:如果由用户选择对象,适合 resource;如果由模型按需读取,可做 tool。
- 写操作 API:最好拆成 preview / apply,并加入确认。
- 批处理 API:返回 job id,再提供
get_job_status和cancel_job。 - 管理型 API:默认不开放,除非有明确权限和审批场景。
MCP Server 的版本兼容
已有应用会演进,MCP Server 也要有版本策略:
- 工具 schema 增字段时保持向后兼容。
- 删除或改语义前保留 deprecated 期。
- 返回结构稳定,不要让模型每周重新学习。
- 重大权限变化要同步 Host 配置和用户授权。