大厂 MCP 面试实录:本地 Server 远程化改造与提示注入防护设计
本文为 MCP 技术岗模拟面试复盘,围绕「本地 Java MCP Server 远程化改造」业务场景展开,覆盖基础认知、架构设计、安全防护、异常处理等核心考察点。
面试开场
面试官:候选人你好,今天我们考察的核心场景是:你之前维护的基于 Java MCP SDK 开发的本地业务 MCP Server,现在需要改造为可被企业内网多个 AI 应用远程调用的服务,请你先说说改造的整体思路,以及你会优先考虑哪些问题?
候选人:我的整体思路是优先替换传输层实现,同时分层构建安全防护体系,优先保障协议兼容性和基础安全能力。具体来说:首先,本地 MCP Server 原本使用 stdio 传输,仅支持本机子进程调用,远程场景下 stdio 无法跨机器通信,因此我会优先替换为 Streamable HTTP 传输,这是 MCP 协议官方推荐的远程传输方案,支持双向 JSON-RPC 通信,适配 AI 应用的调用模式,同时可以很方便的集成限流、超时、会话管理能力,满足远程部署的通用要求资料1资料2。其次,远程暴露后安全风险陡增,我会把安全防护拆分为传输层授权、参数层校验、内容层过滤三层,避免单一防护失效。最后,我会补充审计日志和监控能力,满足可观测性要求。优先考虑的两个核心问题是:一是改造后要尽可能保留原有 Tool/Resource/Prompt 的能力兼容,避免业务逻辑重构;二是要解决远程暴露后的未授权访问、提示注入、数据泄露三类核心风险。
第一轮追问:传输方案选型
面试官:你提到选择 Streamable HTTP 传输,为什么不用 SSE 或者 Netty 这类其他传输方案?改造过程中需要保留原有本地调用的能力吗?不同选型的取舍是什么?
候选人:SSE 是单向事件推送传输,仅支持服务端向客户端推送消息,而 MCP 的 Tool 调用需要客户端向服务端发起请求、服务端返回结果的双向交互,因此 SSE 无法满足核心调用需求,仅适合做资源推送类的补充场景。Netty 传输虽然性能更高,但需要额外实现 MCP 协议的 JSON-RPC 编解码、会话管理逻辑,开发成本高,且企业内部场景下 HTTP 传输的性能完全能满足需求,因此不优先选择。 关于本地调用能力的保留:如果业务确实需要同时支持本地和远程调用,我可以同时暴露 stdio 和 HTTP 两个传输端口,通过配置区分调用方式;但如果仅需要远程调用,我会关闭 stdio 端口,只暴露 HTTP 端点,减少攻击面。关键取舍是:同时暴露两个端口会提升使用灵活性,但会扩大安全防护范围,增加配置复杂度,因此需要根据业务实际需求判断,如果本地调用场景已经很少,优先选择只暴露 HTTP 端口。
第二轮追问:提示注入与安全边界
面试官:现在 Server 远程暴露后,模型传入的参数可能包含提示注入攻击,比如在 Tool 参数中夹带恶意指令,试图让 Server 执行额外操作,或者窃取数据。你提到要分层防护,具体怎么实现?要注意 MCP 的安全边界有哪些要求?
候选人 :首先,MCP 的安全边界明确要求:Tool 的参数 Schema 只是结构约束,不能代替服务端校验和授权,Server 必须把所有模型传入的文本视为不可信输入资料1,不能因为请求来自 AI 应用就默认其可信资料3。具体防护分三层: 第一层是传输层授权,基于 Java MCP SDK 提供的可插拔授权钩子资料2,集成 Spring Security 的 JWT 校验逻辑,每次请求不仅要校验用户是否登录,还要校验用户是否有调用对应 Tool 的权限,比如普通用户不能调用删除类的高风险 Tool,授权信息不通过直接返回 403,不进入后续逻辑。 第二层是参数层校验,除了 SDK 自动根据 JSON Schema 做的结构校验外,还要做业务层面的校验:比如文件路径类参数要禁止包含 .. 等跳转字符,避免路径遍历;SQL、Shell 类参数要严格限制字符集,避免注入。 第三层是内容层防护,一方面要过滤 Tool 返回内容中的潜在恶意指令,避免把注入内容带回模型上下文,覆盖系统规则资料1;如果 Tool 封装了 RAG 检索能力,检索到的外部文档内容也属于不可信输入,其中的潜在恶意指令不能直接返回给模型资料1。另一方面要对审计日志中的敏感字段脱敏,比如用户 ID、文件路径、查询关键词的哈希值,避免凭据和敏感数据泄露资料3。另外,高风险 Tool 比如删除、修改类操作,要在执行前向用户展示具体影响,要求用户显式确认,避免不可逆操作被恶意调用。
第三轮追问:异常处理与可观测性
面试官:如果出现参数注入攻击、授权校验失败这类异常,你的系统怎么处理?可观测性方面要做哪些设计?有没有非常容易踩坑的细节?
候选人:异常处理上会做分级响应:参数校验失败、授权失败这类低风险异常,直接返回对应的错误码(400/403),不执行业务逻辑,记录轻量审计日志;如果检测到明确的提示注入攻击,直接拒绝请求,返回错误提示,同时触发安全告警,通知管理员。 可观测性方面,核心是审计日志和监控指标:审计日志必须记录「谁(用户ID)、什么时间、调用了哪个 Tool、关键参数范围、结果状态」,同时敏感字段必须脱敏,不能记录完整参数和返回内容;监控指标要覆盖请求量、错误率、授权失败率、提示注入拦截率,异常情况下触发告警。 这里有一个非常容易踩坑的细节:MCP 的 stdio 传输要求调试日志写到标准错误,否则会破坏协议通信,而 HTTP 传输下如果直接把调试日志打到标准输出,会和 JSON-RPC 响应消息混在一起,导致客户端解析失败,因此所有日志都必须输出到独立的日志系统,不能直接写到标准输出流资料1。
第四轮追问:方案落地与取舍
面试官:你能不能给出一个基于 Java MCP SDK 的可落地示例?要说明方案的适用边界和关键取舍。
候选人:这个方案适用于企业内部基于 Spring 生态的 Java 服务,Spring AI 2.0+ 已经提供了 MCP 的 WebMVC 服务端传输实现资料2,可以直接基于该能力开发。适用边界是:仅支持企业内部内网访问,不需要公网暴露的场景,如果需要对公网提供服务,还需要额外增加限流、WAF 等防护。关键取舍有两个:一是提示注入过滤的粒度,如果规则太严,会把正常包含"删除""执行"等关键词的业务查询误判为注入,影响正常使用,因此我只会拦截包含明确注入特征的内容(比如"忽略之前指令""执行系统命令"等),普通关键词查询不做拦截;二是审计日志的详细程度,如果记录完整参数,会有数据泄露风险,因此只记录参数的哈希值和关键业务字段,方便排错的同时避免敏感数据泄露。以下是基于公开信息设计的伪代码示例,没有依赖未公开的 SDK API:
java
// 伪代码,基于 Spring AI 2.0+ 公开的 MCP WebMVC 传输能力,引用资料2
@Configuration
public class RemoteMcpServerConfig {
// 暴露 Streamable HTTP 端点,路径为 /mcp
@Bean
public McpServerTransport mcpTransport() {
return new WebMvcMcpServerTransport("/mcp");
}
// 集成可插拔授权钩子,对接 Spring Security
@Bean
public McpAuthorizationHook authHook() {
return (request, context) -> {
// 从请求头提取 JWT,校验用户身份和 Tool 调用权限
Authentication auth = jwtAuthProvider.authenticate(request.getHeaders());
if (auth == null || !authzService.hasPermission(auth.getName(), context.getToolName())) {
throw new AccessDeniedException("无权调用该 Tool");
}
context.setUserId(auth.getName());
return CompletableFuture.completedFuture(null);
};
}
}
// 业务 Tool 示例,包含参数校验和注入防护
@McpTool(name = "queryCustomerOrder", description = "查询客户订单信息")
public String queryCustomerOrder(@McpParam(name = "customerId", description = "客户ID") String customerId,
@McpParam(name = "keyword", description = "查询关键词") String keyword) {
// 业务参数校验
if (!customerId.matches("\\d+")) {
throw new IllegalArgumentException("客户ID格式非法");
}
// 提示注入检测
if (PromptInjectionDetector.isInjection(keyword)) {
auditLog("提示注入拦截", getUserId(), "queryCustomerOrder", Map.of("customerId", customerId, "keyword", sha256(keyword)));
throw new SecurityException("参数包含非法内容,请求已拒绝");
}
// 执行业务逻辑
String result = orderService.query(customerId, keyword);
// 返回内容过滤,避免注入内容回流到模型上下文
return OutputSanitizer.sanitize(result);
}
这个方案不需要修改原有业务 Tool 的核心逻辑,只需要在传输层和参数层增加防护代码,改造成本较低。
面试官点评
本次考察的核心点有三个:第一是对 MCP 传输方案选型的理解,能否结合双向交互、开发成本、攻击面等维度做合理选型;第二是对 MCP 安全边界的认知,是否知道参数 Schema 不能代替服务端校验,是否理解远程暴露后的授权、提示注入、数据泄露三类核心风险;第三是落地能力,能否把抽象的安全要求转化为可实现的代码,同时明确方案的适用边界和取舍。 - 合格回答 :需要覆盖传输选型的原因、分层安全防护的思路、至少一个容易踩坑的细节; - 加分项:能说出 stdio 和 HTTP 并存的取舍、能明确提示注入过滤的粒度权衡、能基于公开的 SDK 能力给出落地方案,而不是空泛的概念描述。
总结
本地 MCP Server 远程化改造的核心是选型匹配、安全分层、可观测性兜底。Streamable HTTP 传输是当前远程场景的最优解,但需要根据业务需求判断是否保留本地调用能力;提示注入防护是远程暴露后的核心风险,需要结合传输授权、参数校验、内容过滤三层能力,同时注意日志输出、返回内容过滤这类容易踩坑的细节。所有安全方案都需要结合业务 SLA 和风险等级做取舍,不能为了绝对安全牺牲业务可用性。
参考资料
- MCP 基础知识
- MCP Java SDK,公开链接:https://github.com/modelcontextprotocol/java-sdk
- Security Best Practices,公开链接:https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices
- MCP Python SDK,公开链接:https://github.com/modelcontextprotocol/python-sdk