大厂 MCP 面试实录:基于 OpenTelemetry 与 OAuth 2.1 的可重复集成测试方案设计
本文为 MCP 后端开发岗位模拟面试复盘,围绕「为内部文档查询 MCP 服务编写可重复执行的集成测试」业务场景展开,考察候选人对 MCP 协议、安全规范、可观测性与测试工程化的综合理解。
面试过程
开场:场景引入
面试官:你好,今天我们团队正在基于 Spring AI MCP 开发一个面向内部员工的文档查询 MCP Server,该服务暴露了查询内部知识库、下载审批附件两类 Tool,采用 Streamable HTTP 传输方式对外提供服务,现在需要你设计一套可重复执行的集成测试方案,要求覆盖正常调用、权限拦截、异常降级三个核心场景,且测试结果可追溯。你先说说整体的设计思路?
候选人:我的整体设计分为三层:测试基础设施层、测试用例层、可观测校验层。首先测试基础设施层用 MCP 测试客户端模拟 Host 侧的 MCP Client,避免依赖真实的大模型;用容器化技术启动 MCP Server 的依赖(知识库数据库、缓存等),保证每次测试的环境一致性;集成 OpenTelemetry 采集全链路调用数据,作为测试断言的核心依据。测试用例层分为三类:正常功能用例、权限拦截用例、异常降级用例,分别覆盖三类核心场景。可观测校验层则用 traceId 关联每个测试用例的请求和链路数据,既校验返回值,也校验链路是否符合预期。这套方案的核心思路是通用的,如果团队用其他语言栈的 MCP SDK,只需要替换对应语言的客户端、OpenTelemetry 采集器和测试框架即可,逻辑完全复用。
第一轮追问:可观测性与异常处理
面试官:你提到用 OpenTelemetry 作为断言依据,具体怎么设计?如果测试过程中链路数据丢失怎么办?和传统的只校验返回值的方案比,有什么取舍?
候选人 :具体设计是每个测试用例发起请求前生成唯一的 traceId,注入到 MCP 请求的上下文里,测试结束后直接查询内存导出器中对应 traceId 的所有 Span 做断言。比如正常调用知识库查询 Tool 的用例,会断言链路包含「MCP Client → MCP Server → 知识库数据库」三层 Span,且所有 Span 的状态码都是 OK,没有错误标签;权限拦截的用例会断言链路在 MCP Server 层就终止,不会触发下游知识库的 Span,且 MCP Server 的 Span 上有 auth.error=insufficient_scope 的标签。
如果链路数据丢失,首先会先检查测试环境的 OpenTelemetry SDK 是否正确注入,有没有因为测试并发导致 Span 被丢弃,然后设置兜底的超时断言:如果超过业务约定的阈值还没返回结果,就直接判定测试失败,同时打印当时的 Span 列表辅助排错。和传统只校验返回值的方案比,优势是不仅能校验返回值是否正确,还能校验链路是否按预期执行,比如会不会出现权限绕过的漏洞(比如没有权限的请求触发了下游数据库调用);劣势是增加了 OpenTelemetry 的接入成本,对于简单的 MCP 工具来说有点重,所以我们会在核心场景用链路断言,非核心场景可以简化成返回值校验。
第二轮追问:安全场景覆盖
面试官:OAuth 2.1 在测试中怎么模拟不同权限?你提到要覆盖权限拦截场景,具体怎么设计用例?如果 mock Token 校验逻辑和真实服务端不一致会有什么问题?
候选人 :我们会在测试环境启动一个轻量的 OAuth 2.1 测试授权服务,预置三类测试用户:普通员工(仅拥有 knowledge:read 权限)、审批员(拥有 attachment:download 权限)、未授权用户(无任何权限)。每个测试用例执行前会先调用授权服务的 Token 端点获取对应权限的 access token,再放到 MCP 请求的 Authorization 头里。比如权限拦截用例会用普通员工的 token 调用附件下载 Tool,预期服务返回 401/403,同时链路中存在权限校验失败的 Span。
这里必须用真实的授权服务而不是 mock 校验逻辑,因为 MCP 规范要求服务端必须校验 Token 的受众(audience)字段、是否支持 PKCE 等安全要求资料2资料3,mock 的话很容易漏掉这些校验逻辑,导致生产环境出现安全漏洞。当然,非核心的权限用例也可以用 mock 来提升测试速度,但核心的权限校验逻辑必须用真实的服务端验证。另外,我们的测试授权服务会配置支持 PKCE,因为 MCP 客户端必须校验授权服务是否支持 PKCE,否则会拒绝授权流程资料3。
第三轮追问:异常处理与可重复性
面试官:如果测试过程中 MCP Server 抛出未捕获的异常,比如调用知识库时数据库超时,你的方案怎么处理?如何保证测试的可重复性?
候选人 :首先我们会给 MCP Server 的测试实例配置降级策略:比如知识库调用超过约定阈值就返回「服务暂时不可用」的友好提示,同时 OpenTelemetry 会记录这个异常 Span,状态码为 ERROR,错误标签为 knowledge_db.timeout。测试用例会断言:异常场景下不会返回堆栈信息给客户端,只会返回预设的降级提示,同时链路中存在对应的错误 Span。
为了保证可重复性,我们用容器化技术启动所有依赖中间件,每个测试用例运行前都会重置测试数据:比如清空知识库的测试文档表,插入固定的测试文档,保证每个用例的输入输出完全一致,不会因为脏数据导致结果波动。这里有一个容易踩坑的点:MCP 的 stdio 传输模式下,Server 的标准输出不能打印调试日志,否则会破坏 JSON-RPC 通信资料4,所以我们的测试环境会把日志输出重定向到标准错误或文件,同时通过 OpenTelemetry 的日志采集把日志和 Span 关联,方便排错。
第四轮追问:跨场景适配
面试官:你提到的方案是基于 Java 技术栈的,如果团队用的是 Python 的 MCP SDK,你的方案怎么调整?有没有什么通用的设计原则?
候选人:核心思路完全通用,只需要替换对应语言栈的组件即可:Python 场景下用官方 MCP SDK 的测试客户端模拟 MCP Client,用 Python OpenTelemetry SDK 采集链路数据,导出到和 Java 测试用例共用的链路存储实例,断言逻辑还是通过 traceId 查询 Span;OAuth 2.1 的部分可以用 Authlib 启动轻量的测试授权服务,逻辑和 Java 版本一致。
通用的设计原则有三条:一是用容器化保证测试环境的隔离和一致性,避免依赖本地环境;二是用链路数据作为核心断言依据,覆盖黑盒测试看不到的逻辑分支;三是核心安全场景必须用真实的依赖服务验证,不要用 mock 替代,避免漏掉安全漏洞。
可落地示例(伪代码)
注:下述代码为版本无关的接口设计示意,非可直接运行代码,具体实现需参考对应语言 MCP SDK 的测试文档资料1。
java
@Test
void testNormalKnowledgeQuery() {
// 1. 获取具备知识库查询权限的测试 Token
String accessToken = oauthTestServer.issueToken("user_001", Set.of("knowledge:read"));
// 2. 构造 MCP 工具调用请求
McpRequest request = McpRequest.builder()
.method("tools/call")
.param("name", "query_internal_knowledge")
.param("arguments", Map.of("keyword", "年假规则"))
.header("Authorization", "Bearer " + accessToken)
.build();
// 3. 发送请求并获取响应
McpResponse response = mcpTestClient.dispatch(request);
// 4. 断言返回值符合预期
assertTrue(response.getResult().contains("年假上限10天"));
// 5. 断言 OpenTelemetry 链路符合预期
List<Span> traceSpans = otelExporter.getSpans(response.getTraceId());
assertEquals(3, traceSpans.size()); // Client → Server → 知识库
assertTrue(traceSpans.stream().allMatch(s -> s.getStatus().isSuccess()));
}
面试官点评
考察点:这道题考察三个层次的能力:第一层是基础认知,是否理解 MCP 的客户端-服务端架构、三类能力、安全边界与传输方式的特点;第二层是工程能力,能否把 OpenTelemetry、OAuth 2.1 技术与 MCP 测试场景真实结合,而不是生硬堆砌概念;第三层是风险意识,是否考虑到异常处理、可重复性、安全合规等生产环境的实际问题。
合格回答:需要覆盖测试的分层设计、核心技术的选型理由、异常处理的兜底方案,能说出 OpenTelemetry 和 OAuth 2.1 在场景中的具体作用,而不是泛泛而谈概念。
加分项:能说出 MCP 规范中的具体安全要求(如 audience 校验、PKCE 支持)、能区分不同场景的技术取舍、能识别出 stdio 传输的日志坑、能给出跨语言栈的适配方案。
总结
这套方案的核心是把 MCP 集成测试从传统的黑盒返回值校验,升级为链路级全场景校验:OpenTelemetry 解决了可观测性与可追溯性的问题,OAuth 2.1 测试授权服务解决了安全场景的覆盖问题,容器化解决了环境一致性的问题。
适用边界:面向需要远程部署、有严格权限控制、可观测性要求高的 MCP 服务;如果是本地 stdio 传输的轻量 MCP 工具,不需要权限控制,可以简化掉 OAuth 和 OpenTelemetry 的部分,直接做单元测试即可。
关键取舍:真实授权服务能覆盖更多安全场景但启动成本高,适合核心权限用例;内存导出器适合单机测试但无法支持分布式场景,需要根据团队的实际需求选择。
容易踩坑的细节:一是忽略 MCP 规范要求的 Token 受众校验,导致生产环境出现 Token 混淆漏洞资料2;二是 stdio 传输的 Server 打印日志到标准输出破坏通信资料4;三是测试数据未重置导致用例之间相互影响,结果不可重复。
参考资料
- 资料1 MCP Java SDK: https://github.com/modelcontextprotocol/java-sdk
- 资料2 Authorization: https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization
- 资料3 Authorization Security Considerations: https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/security-considerations
- 资料4 MCP 基础知识