大厂 MCP 面试实录:将内部 REST API 封装为可审计 MCP Tools 的设计与实践
本文采用模拟面试形式,复盘企业级场景下将内部 REST API 封装为可审计 MCP Tools 的核心考察点与落地实践。
面试官:今天的业务场景是:公司内部有上百个稳定的业务 REST API,需要封装成 MCP Tools 供给内部 AI 助手调用,要求满足权限可控、操作可审计、传输安全,技术栈限定 Java MCP SDK、OAuth 2.1、stdio 传输,你先聊聊整体的架构设计思路?
候选人:整体可以分成三层:第一层是 MCP Server 层,基于 Spring AI MCP Server Starter 搭建,它是对 Java MCP SDK 的 Spring 生态扩展,能简化 Tool 的声明、配置和安全集成资料1;第二层是能力映射层,每个内部 REST API 对应一个 MCP Tool,通过注解或动态配置的方式声明 Tool 的名称、描述、输入参数 schema,将模型的调用请求转发为上游 REST API 请求;第三层是安全审计层,用 OAuth 2.1 做身份认证和权限校验,所有调用日志落地到审计系统,满足合规要求。传输用 stdio 是因为 AI 助手的 Host 会和 MCP Server 部署在同一台宿主机,Host 启动子进程运行 Server,符合 stdio 传输的适用场景资料2。
面试官(追问1:技术选型灵活性):你提到用 Spring AI MCP 的注解声明 Tool,如果上游 REST API 的参数是嵌套结构、包含动态枚举,甚至接口经常迭代,静态注解能不能满足?动态生成 Tool schema 的方案有没有考虑过?
候选人:首先 Spring AI MCP 的注解支持用 Java 复杂类型(嵌套 POJO、List、枚举)作为 Tool 参数,会自动生成符合规范的 JSON Schema,大部分静态接口场景足够用。如果上游 API 经常迭代,或者参数有动态枚举(比如根据用户权限返回不同的可选值),可以在 Server 启动阶段调用上游的 OpenAPI 文档,动态生成 Tool 的参数 schema 和描述,避免硬编码。不过动态生成需要额外处理 schema 的版本对齐,比如上游接口升级后要保证生成的 schema 不会出现不兼容的变更,必要时可以加 schema 校验步骤,确保和上游接口的契约一致。另外不管用静态注解还是动态生成,MCP Server 都必须做服务端参数校验------Tool 的参数 schema 只是结构约束,不能代替服务端的合法性校验,比如模型可能传入非法的枚举值、超长的字符串,必须拦截这类请求资料2。
面试官(追问2:安全边界细节):OAuth 2.1 的 token 在 stdio 传输下是怎么传递的?你之前提到调用上游 API 要用独立的 token,能不能说下具体逻辑?会不会有 token 泄露的风险?
候选人 :stdio 是本地进程间通信,Host 会在 MCP 会话初始化阶段,把 OAuth 2.1 的 access token 放在初始化请求的元数据中传给 Server,不需要在网络中传输,避免了窃听风险。同时 Host 请求 token 时会携带 resource 参数,明确指定 MCP Server 是目标资源,避免 token 被跨服务滥用资料4。Server 收到请求后会先校验 token 的合法性:包括签名校验、过期时间校验、权限范围(scope)校验,校验通过才会处理后续的 Tool 调用请求。调用上游 REST API 时,Server 会作为 OAuth 客户端,用客户端凭证模式向内部 IdP 申请独立的 access token,绝对不能透传从 MCP Client 收到的 token------这是 MCP 安全规范的强制要求,避免不同服务的 token 互相滥用资料4。审计日志中只会记录从 token 中解析出的用户 ID、调用时间、Tool 名称、脱敏后的参数、结果状态,不会记录任何完整的 token 内容,避免敏感信息泄露。
面试官(追问3:异常处理与可观测性):如果上游 REST API 超时或者返回 5xx 错误,Server 怎么处理?审计日志要记录哪些内容?怎么保证可观测性?
候选人:首先上游调用会配置超时时间,具体数值需要根据内部 API 的 SLA 和业务风险压测确定,超时后 Server 会直接返回错误响应给 Host,不会无限阻塞 MCP 会话。如果上游返回 5xx 错误,会返回结构化的错误信息,比如错误码、重试建议,不会把上游的堆栈、内部服务地址等敏感信息暴露给模型。审计日志需要记录五个核心要素:调用者用户 ID、调用时间戳、调用的 Tool 标识、脱敏后的关键参数、调用结果状态(成功/失败/超时/权限拒绝),同时所有日志必须输出到标准错误(stderr),不能输出到标准输出(stdout),否则会破坏 MCP 的 stdio 协议通信资料2。可观测性方面,除了审计日志,还可以暴露 Prometheus 指标,统计每个 Tool 的调用量、成功率、平均耗时、上游错误率,方便运维快速排查问题。
面试官(追问4:场景化方案设计):现在有个需求:删除类的 REST API 需要用户二次确认才能调用,同时不同用户的权限粒度不一样,有的用户只能查询,有的能修改,你怎么实现?这个方案有什么适用边界和容易踩坑的地方?
候选人:首先高风险操作(比如删除、修改数据)的 Tool,可以在元数据中标记需要用户确认的属性,Host 侧检测到该标记后,会弹出确认框给用户,用户确认后才将请求转发给 Server 执行。权限粒度方面,OAuth 2.1 的 token 会携带用户的权限范围(scope),Server 在认证阶段就会校验用户的 scope 是否包含当前 Tool 所需的权限,如果没有直接拒绝调用,不需要走到上游 API 的校验,减少不必要的请求。这个方案的适用边界是:MCP Server 和 Host 部署在同一台宿主机,适合内部工具场景;如果需要远程部署,就需要换成 Streamable HTTP 传输,额外处理会话管理、限流、跨域等问题资料2。容易踩坑的地方有两个:一是很多开发者会把调试日志输出到 stdout,直接破坏 MCP 的通信协议,导致会话建立失败;二是容易犯 token 透传的错误,把 Host 传过来的 token 直接用来调用上游 API,违反安全规范资料4。另外如果封装的上百个 API 都注册为 Tool,模型可能无法在上下文里承载所有 Tool 的描述,导致调用准确率下降,这时候需要做 Tool 的动态加载,根据用户的 query 只返回相关的 Tool,而不是全量注册。
面试官点评
- 考察点:1. 对 MCP 核心架构、传输方式适用场景的理解;2. 对 Java MCP SDK/Spring AI MCP 的落地能力;3. 对 MCP 安全边界(尤其是 OAuth token 处理、输入校验)的掌握;4. 对可审计、可观测、异常处理的工程化思维。
- 合格回答:能清晰说明三层架构,知道 stdio 传输的适用场景,了解 OAuth 的基本流程,知道日志不能输出到 stdout,能说出服务端参数校验的必要性。
- 加分项:能提到 token 不能透传的安全规范,能想到 Tool 过多时的动态加载方案,能明确审计日志的核心要素,能区分静态注解和动态生成 schema 的适用场景,能说明方案的适用边界和取舍。
总结
将内部 REST API 封装为 MCP Tools 的核心不是简单的协议转换,而是要做好能力映射的灵活性、安全边界的合规性、审计日志的完整性,避免把 MCP 当成普通的 API 网关,忽略协议特有的安全要求和传输规范。
参考资料
- MCP Java SDK, https://github.com/modelcontextprotocol/java-sdk
- MCP 基础知识
- MCP Python SDK, https://github.com/modelcontextprotocol/python-sdk
- Authorization Security Considerations, https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/security-considerations