MCP 面试高频考点:把内部 REST API 封装成可审计 Tools,追问到第几层?

内部系统已经有一批 REST API,团队想把这些能力开放给 AI 应用使用,同时又要求“每一次调用都能审计、能追溯、能兜底”。这正是 MCP 面试里很典型的一道方案题:候选人不能只会说“写个 Server 包一下”,而要讲清楚 Tools、Prompts、结构化输出、容器化部署和审计边界之间的关系。下面以问答形式展开,面试官会根据回答层层追问。

面试场景

面试官:我们有一组内部 REST API,比如订单查询、退款申请、库存调整。现在想让 AI 应用通过 MCP 调用它们,但安全团队要求所有调用可审计。你会怎么设计?

候选人:先给结论:我会做一个独立的远程 MCP Server,用 Streamable HTTP 对外提供,把 REST API 按“业务语义”封装成少量 Tools,用 Prompts 承载需要用户显式选择的标准工作流,所有 Tool 统一走一层审计与授权中间件。容器化只解决部署一致性,不承担安全职责。

具体分工是:Tools 是模型可发起调用的操作,负责真正触达 REST API;Resources 用于暴露只读上下文,比如订单详情文档,但不应把有副作用的操作伪装成 Resource[资料1];Prompts 是用户可显式选择的模板化消息或工作流,适合“退款申请”这种需要固定步骤和话术的场景[资料1]。结构化输出解决的是模型拿到结果后如何稳定解析,而不是替代服务端校验。

基础问题:能力怎么划分

面试官:为什么不把每个 REST 接口一对一映射成 Tool?

候选人:一对一映射会把接口细节泄漏给模型,Tool 数量膨胀,模型选择成本上升,而且 REST 的粒度未必符合业务语义。我的原则是按“用户意图”聚合,比如 query_order、apply_refund、adjust_inventory,每个 Tool 用清晰的名称、描述和输入 schema[资料1][资料2]。schema 只做结构约束,真正的参数校验和授权必须在服务端做,模型传入的文本一律视为不可信输入[资料1]。

面试官:那 Prompts 在这里到底起什么作用?会不会是硬凑?

候选人:不是硬凑。像退款这种流程,用户需要明确触发,并且步骤固定:确认订单、选择原因、预览影响、提交。把这段作为 Prompt 模板由用户显式选择,比让模型自由拼 Tool 调用更可控[资料1]。Prompt 负责“引导流程”,Tool 负责“执行动作”,两者是上下游关系,不是替代关系。

第一轮追问:审计怎么做

面试官:说说审计日志具体记什么。

候选人:记录谁在什么时间调用了哪个 Tool、关键资源范围与结果状态,敏感字段要脱敏[资料1]。我倾向在 Tool 执行层统一埋点,而不是让每个业务函数自己写日志,否则一定漏。日志里记录调用者身份、Tool 名、资源标识、参数摘要(脱敏后)、结果状态和耗时,凭据绝不进日志、不进 Tool 返回值、也不进模型上下文[资料1]。

面试官:如果请求来自 AI 应用,能不能默认它可信?

候选人:不能。服务不应因为请求来自 AI 应用就默认可信[资料1]。远程部署时每次请求都要做授权检查,不能只判断用户是否已登录[资料1]。审计和授权是两件事:审计回答“发生了什么”,授权回答“允不允许发生”。

第二轮追问:异常与安全边界

面试官:如果模型传了一个越权的订单号,或者参数里塞了奇怪的路径、URL,你怎么处理?

候选人:Tool 的 schema 只是结构约束,不能代替服务端校验和授权[资料1]。我会在服务端对资源标识符、URL、路径做白名单和范围约束,越权直接拒绝并记审计。对于高风险或不可逆操作,比如退款、库存调整,要在执行前显示具体影响并要求用户确认[资料1]。这一步不能只靠模型自觉。

面试官:如果下游 REST API 超时或返回异常呢?

候选人:Tool 要返回结构化的错误结果,区分“参数错误”“无权限”“下游不可用”“部分成功”,让模型能据此决定是否重试或告知用户。重试次数、超时值不能拍脑袋,要按业务 SLA、风险和压测结果确定,并且重试要幂等,否则退款这类操作可能重复执行。这也是容易踩坑的细节:把“可重试的查询”和“不可重试的写操作”用同一套重试策略处理。

方案设计与结构化输出

面试官:结构化输出在这里怎么落地?

候选人:Tool 的返回值要稳定可解析,比如统一返回状态、业务数据、错误码和审计追踪号,而不是一段自由文本。这样 Host 侧能可靠判断成功与否,审计也能用追踪号关联上下游。注意结构化输出不等于把内部字段全暴露,返回字段要按最小必要原则裁剪。

面试官:容器化部署要注意什么?

候选人:Docker 保证环境一致和可复制部署,但远程部署的真正难点在认证、授权、会话管理、限流和超时[资料1]。stdio 适合 Host 本机启动子进程的场景,远程服务用 Streamable HTTP 更合适;如果用 stdio,标准输出只能走协议消息,调试日志必须写标准错误,否则会破坏通信[资料1]。这是很容易被忽略的坑。

下面用版本无关的伪代码表达审计中间件的接口设计,不绑定具体 SDK:

handle(toolName, rawArgs, caller):
    identity = authorize(caller, toolName, rawArgs)   // 每次请求都校验
    if not identity.allowed: audit(reject); return error(PERMISSION_DENIED)
    args = validateAndConstrain(rawArgs)              // 服务端校验,非仅 schema
    if toolName in HIGH_RISK and not confirmed: return needConfirm(impact)
    traceId = newTraceId()
    audit(start, identity, toolName, mask(args), traceId)
    result = callRestApi(toolName, args)
    audit(end, status(result), traceId)
    return structured(result, traceId)

面试官点评

考察点:是否理解 Tools、Resources、Prompts 的语义分工,是否把审计、授权、校验放在正确层次,是否识别容器化和传输方式的真实边界。

合格回答:能说明 Tools 是模型可发起调用的操作、Prompts 是用户显式选择的工作流[资料1][资料2],审计记录调用者、Tool、资源范围和结果状态并脱敏[资料1],服务端不信任模型输入[资料1]。

加分项:指出 schema 不能替代授权、高风险操作需确认、stdio 下日志写标准错误、重试要区分读写幂等,并明确超时和重试参数应由 SLA 与压测决定而非拍数字。

总结

这道题的核心不是“会不会写 MCP Server”,而是能否把业务语义、安全边界和可观测性放在一起权衡。Tools 承担执行,Prompts 承担受控流程,结构化输出保证可解析,审计中间件统一兜底;容器化只是部署手段。适用边界是:当 REST API 有副作用、需要权限和追溯时,这套分层才必要;如果只是只读资料检索,用 Resource 或检索型 Tool 更轻。关键取舍在于聚合粒度与可控性之间的平衡,最容易踩的坑是把 schema 当校验、把登录当授权、把日志写进标准输出。

参考资料

  • MCP 基础知识
  • Tools(MCP 规范):https://modelcontextprotocol.io/specification/2026-07-28/server/tools
  • MCP Python SDK:https://github.com/modelcontextprotocol/python-sdk
  • MCP Java SDK:https://github.com/modelcontextprotocol/java-sdk
Logo

更多推荐