MCP 面试高频考点:给远程 Server 加日志、指标、追踪,OAuth 与 JSON Schema 怎么落地
面试场景
候选人正在面试一个偏平台工程的 AI 应用基础设施岗位,岗位要求能设计并落地可观测、可安全接入的 MCP Server。前面已经聊过 MCP 的客户端—服务端架构、Tools/Resources/Prompts 的区别,以及 stdio 与 Streamable HTTP 传输方式。面试官把问题收敛到一个具体场景:你们要把一个原本只在本机通过 stdio 跑的 MCP Server 改造成可远程访问的服务,用 Docker 部署,前面还要接统一身份体系。请你把日志、指标、分布式追踪、鉴权和参数校验一起设计出来。
基础问题:先把可观测性边界说清楚
面试官:如果让你给这个 MCP Server 加日志、指标和分布式追踪,你会怎么分层?SDK、业务代码、容器平台分别负责什么?
候选人:我会先分三层。第一层是协议与 SDK 层,第二层是业务能力层,也就是 Tools、Resources、Prompts 的实现,第三层是部署与接入层。
先说结论:日志要默认可靠输出,但不把日志后端绑死在 SDK 里;指标和追踪要和主流可观测框架对接,但不要让 MCP SDK 自己强依赖某个实现。以 Java 生态为例,MCP Java SDK 的公共 API 只通过 SLF4J 打日志,不内置日志后端,也不自带 metrics 或 tracing 实现;可观测元数据会沿着响应式流水线传递,这样可以和 Micrometer、OpenTelemetry 这类框架无缝集成,并在异步边界保留 correlation ID 和 tracing 状态 [资料1]。这很重要,因为远程 MCP 调用通常有流式响应、异步线程切换,如果 trace context 在边界断掉,排障会非常痛苦。
业务层要补充语义化信息:哪个 Tool 被调用、输入参数里哪些字段敏感需要脱敏、调用了哪个下游资源、结果是成功还是业务失败。这里不能只打“收到请求”这种通用日志,而要把审计需要的信息补齐。按照 MCP 的安全要求,审计日志至少要记录谁在什么时间调用了哪个 Tool、关键资源范围和结果状态,同时敏感字段必须脱敏;凭据不能出现在日志、Tool 返回值或模型上下文中 [资料2]。
部署层用 Docker 时,我会让应用日志走标准输出/标准错误,方便容器运行时和日志采集器统一收集。如果是 stdio 模式,调试日志必须写到 stderr,不能写到 stdout,因为 stdout 承载的是协议消息,混入会破坏通信 [资料2]。远程 HTTP 模式虽然没有这个协议级冲突,但保持容器化的十二要素输出方式仍然更稳妥。
面试官点评:考察点是是否理解“SDK 提供扩展点、业务提供语义、平台负责采集”这三层边界。合格回答要提到 SDK 不内置 metrics/tracing 实现,而是通过上下文传递支持集成 [资料1];同时能区分 stdio 与远程部署对日志输出的不同要求 [资料2]。加分项是主动提到审计日志脱敏和凭据保护。
第一轮追问:鉴权不是“登录了就行”,怎么和可观测性协作?
面试官:你提到远程部署。如果这个 Server 通过 Streamable HTTP 暴露,认证鉴权你准备怎么做?OAuth 放在哪一层?如果授权失败,日志和追踪里记什么,不记什么?
候选人:远程 MCP Server 必须做逐请求授权,不能只判断用户是否已经登录 [资料2]。我会按规范走 OAuth 2.1。MCP 授权服务器必须实现 OAuth 2.1,并对机密客户端和公共客户端都采取合适的安全措施 [资料3]。在架构上,MCP Server 作为资源服务器,前面可以有网关做令牌透传和基础校验,但真正的资源级授权要在 Server 内完成,因为不同 Tool、不同 Resource URI 的权限差异只有业务知道。
具体分工是:网关或 HTTP 接入层负责 TLS、基础限流、提取访问令牌、把身份信息转换成应用内 principal;MCP Server 在每个 Tool/Resource/Prompt 处理前做授权检查,包括 scope、资源归属、租户边界和操作风险。OAuth 2.1 的授权服务器发现机制由 MCP 规范定义,Server 需要告诉 Client 去哪里拿令牌、怎么完成授权 [资料3]。Docker 部署时,我不会把长期凭据打进镜像,而是通过环境变量或密钥挂载注入短期凭据;规范也提到客户端和服务端可以从环境读取凭据 [资料4],但生产里要配合密钥轮换。
可观测性和鉴权要联动,但不能泄露敏感信息。日志里记录用户标识的哈希或内部主体 ID、client ID、请求 ID、trace ID、Tool 名称、资源范围、授权结果和拒绝原因类别,比如“scope 不足”“资源越权”“令牌过期”;但绝不能记录原始 access token、refresh token、完整 Authorization 头,也不能把用户传入的高敏感参数原样打印 [资料2]。追踪系统里的 span attribute 也要遵守同样规则,可以记录rpc.method、mcp.tool.name、auth.result,但不能把令牌放进 tag。
如果授权失败,我会返回明确但不过度详细的错误给 Client,同时在审计日志里保留足够信息供排障和安全审计。这里的取舍是:给调用方的错误信息要足够让其知道是缺权限还是令牌问题,但不能暴露内部资源布局;给安全团队的日志要足够追溯,但不能成为凭据泄露源。
面试官:为什么不能只在网关鉴权?
候选人:因为 MCP 的能力粒度不是“能不能访问 /mcp”这么粗。Tool 可能有副作用,Resource 可能按 URI 分权限,Prompt 可能涉及不同工作流。JSON Schema 只能约束参数结构,不能代替服务端校验和授权 [资料2]。网关通常只能做到粗粒度路由级控制,细粒度的“这个用户能不能对这个资源执行这个 Tool”必须在 Server 内结合业务状态判断。
面试官点评:考察点是远程 MCP 的安全边界、OAuth 2.1 的定位,以及鉴权与审计日志的协作。合格回答要明确“每次请求授权”[资料2]、授权服务器必须实现 OAuth 2.1 [资料3]、凭据不能进日志 [资料2]。加分项是区分网关粗粒度鉴权与 Server 细粒度授权,并解释为什么 JSON Schema 不能替代授权。
第二轮追问:JSON Schema 在这里到底做什么,异常链路怎么观测?
面试官:你提到 JSON Schema 不能替代授权,那它在这个方案里负责什么?如果参数校验失败、Tool 执行抛异常、下游超时,日志、指标、追踪分别怎么记?
候选人:JSON Schema 在 MCP 里是协议级和能力级的结构描述与校验基础。MCP 规范里有从 TypeScript 源自动生成的 JSON Schema,作为各种自动化工具使用的校验依据 [资料4];Tool 也应该提供清晰的名称、描述和输入 schema [资料2]。我的结论是:JSON Schema 负责“结构和基本类型是否正确”,服务端校验负责“语义是否合法”,授权负责“是否允许”,三者不能互相替代。
落地时,每个 Tool 的输入都要声明 JSON Schema,比如字段类型、必填项、枚举范围、字符串模式;但服务端仍然要把模型传入的文本视为不可信输入,对文件路径、URL、SQL、Shell 参数和资源标识符做约束 [资料2]。比如一个检索 Tool,schema 可以要求query是字符串、topK是整数,但topK是否超过当前租户配额、resourceUri是否属于当前用户,这些不是 schema 能判断的。
异常链路我会分成四类处理。
第一类是协议或传输错误,比如 JSON-RPC 消息格式错误、HTTP 流中断。这类错误由接入层和 SDK 层记录,trace 要标记到入口 span,指标按协议错误码计数,日志保留请求 ID,但不要打印完整敏感报文。
第二类是 schema 校验失败。这类错误应在进入业务逻辑前快速失败,返回给 Client 的错误要指出哪个字段不符合 schema;指标上单独记validation_failed,trace 上记录失败字段路径,日志里记录 Tool 名和校验错误摘要,避免把用户输入全文打进日志。
第三类是授权失败。前面说过,要审计但不泄露令牌。指标里要区分unauthenticated和permission_denied,这样才能看出是令牌配置问题还是权限模型问题。
第四类是业务执行异常和下游依赖故障。Tool 执行必须被一个明确的 span 包裹,span 名称可使用 Tool 名,并记录结果状态;对下游 HTTP、数据库、检索服务的调用创建子 span,保持 trace context 跨异步边界传递 [资料1]。日志不要只打堆栈,要带上 trace ID、Tool 名、资源范围和业务操作摘要;指标至少要有请求量、成功率、延迟分布、外部依赖错误率。
一个容易踩坑的细节是:stdio 模式下如果把调试日志写到 stdout,会直接破坏协议消息流 [资料2];远程模式虽然没有这个问题,但很多框架在异常时会自动打印完整请求体,如果请求里带 token、身份证号、数据库连接串,就会违规。所以日志配置里必须对敏感字段做统一脱敏,异常处理器也要避免把原始请求原样输出。
另一个取舍是:是否把所有 Tool 输入都打到 span attribute。我的建议是默认不打全量参数,只打字段存在性、长度、枚举值等低风险元数据;确需排障时通过采样或受控调试开关开启,避免高基数和敏感信息泄露。具体超时、重试、采样率和缓存时长,我不会拍脑袋定固定值,而要根据业务 SLA、下游风险和压测结果确定。
方案设计:一个可落地的接入切面
面试官:如果让你给这个 Server 设计一个统一的可观测与安全拦截层,你会怎么组织?
候选人:我会做一个围绕 MCP 能力调用的服务端拦截层,逻辑顺序是:
- 从传输层提取请求 ID、trace context、访问令牌,建立入口 span;如果是 Java 生态,利用 SDK 在 Reactor 流水线中传递 observability metadata,确保异步边界不丢 correlation ID 和 tracing state [资料1]。
- 做 OAuth 2.1 令牌校验和主体解析,得到 principal、scope、租户信息。
- 根据请求路由到具体 Tool/Resource/Prompt,先做 JSON Schema 结构校验。MCP 本身使用 JSON Schema 做协议校验 [资料4],Tool 输入 schema 也应纳入统一校验链路。
- 做细粒度授权:判断该 principal 是否能访问目标 Resource、是否能执行该 Tool、参数中的资源标识是否越权。高风险或不可逆操作还要标记“需用户确认”,不能因为请求来自 AI 应用就默认可信 [资料2]。
- 执行业务逻辑,对下游调用创建子 span,记录依赖耗时与错误;审计日志记录调用者、时间、Tool、资源范围、结果状态,并脱敏 [资料2]。
- 统一异常处理:区分协议错误、校验错误、鉴权错误、业务错误、依赖错误,分别映射到合适的 JSON-RPC/HTTP 错误、指标标签和 trace status。
Docker 部署上,镜像只包含应用和最小运行时依赖;配置通过环境变量或挂载注入,不写入镜像;日志输出到 stdout/stderr,由平台侧采集;SDK 默认使用轻量传输实现,例如 Java SDK 默认用 JDK HttpClient 以减少额外依赖 [资料1],这也让镜像更可控。
面试官点评:考察点是能否把 OAuth 2.1、JSON Schema、可观测性和部署方式串成一个真实链路,而不是孤立列概念。合格回答要体现“先认证、再校验、后授权、再执行业务”的顺序,并解释每一步的边界。加分项是主动提到高风险操作确认、敏感字段脱敏、异步上下文透传,以及 Docker 镜像最小化与配置外置。
总结
这场面试的核心不是背出 MCP 有哪些能力,而是判断候选人能否在远程部署场景下把几件事同时做对:
- 可观测性分层清晰:SDK 提供日志与上下文传递,不绑定 metrics/tracing 后端;业务层补充语义和审计;平台层负责采集。Java SDK 通过 SLF4J 输出日志,并支持与 Micrometer、OpenTelemetry 等框架集成 [资料1]。
- 安全边界不混淆:OAuth 2.1 解决身份与授权接入 [资料3],JSON Schema 解决结构校验 [资料4],服务端校验和授权解决语义与权限问题,三者缺一不可 [资料2]。
- 异常与审计可追溯:每类错误要有不同指标、trace 标记和日志级别;审计日志能追溯“谁、何时、调用什么、影响什么、结果如何”,但不能泄露凭据和敏感参数 [资料2]。
- 部署细节不踩坑:stdio 下日志不能写 stdout [资料2];远程 HTTP 下要处理会话、限流、超时和逐请求授权;Docker 中避免把凭据打进镜像。
如果只回答“加个 Logback、接一下 OTel、OAuth 放网关”,通常只能算入门;能讲清楚上下文透传、审计脱敏、细粒度授权、schema 与服务端校验的边界,才是更接近工程落地的回答。
参考资料
- MCP Java SDK
- [MCP 基础知识]
- Authorization
- Overview