MCP 面试高频考点:远程 Tool 调用的认证、授权与最小权限怎么落地?
面试场景
某团队把内部知识库和工单系统封装成远程 MCP Server,通过 Streamable HTTP 暴露给多个 AI 应用。上线前评审时,安全团队提出三个问题:不同部门的人能不能调同一个 Tool?Tool 参数里的资源 ID 能不能越权?出了问题怎么追溯?面试官围绕这个场景,逐步追问认证、授权、最小权限、审计和 Prompt 设计的分工。
第一轮:基础认知
面试官:这个场景里,认证和授权分别在解决什么问题?为什么不能只做登录校验?
候选人:结论是认证解决"你是谁",授权解决"你能做什么",两者缺一不可。
MCP 采用客户端---服务端架构,Host 中的 MCP Client 与 Server 建立会话,Server 通过 Tools、Resources、Prompts 暴露能力 资料1。Streamable HTTP 适合远程服务,远程部署必须考虑认证、授权、会话管理、限流和超时 资料1。所以只判断用户已登录是不够的,Server 要对每次请求执行授权检查 资料1。规范层面,MCP 的授权能力位于传输层,面向 HTTP 传输定义授权流程;stdio 传输则应从环境变量获取凭据,而不是走这套 HTTP 授权流程 资料2。
面试官:那 SDK 是不是自带一套授权实现,直接开启就行?
候选人:不是。以 MCP Java SDK 为例,它提供的是可插拔的授权钩子,没有内置授权实现;授权集成在服务端传输层,具体策略交给 Spring Security、MicroProfile JWT 或自研方案 资料3。
这样设计的原因很实际:不同环境的身份体系差异大,SDK 绑定某一种会限制选型。代价是团队要自己承担策略正确性,不能指望"开了开关就安全"。
第二轮追问:Tool 层的授权怎么做
面试官:登录和传输层授权都做了,为什么还要在 Tool 内部再判一次?
候选人:因为传输层只知道"这个请求来自某个已授权客户端",不知道"这次调用的资源范围是否合法"。Tool 的参数 schema 只是结构约束,不能代替服务端校验和授权 资料1。
具体做法是:每个 Tool 声明所需权限,服务端在执行前根据调用者身份、Tool 名和参数中的资源范围做判定。例如查询工单的 Tool,除了校验 ticketId 格式,还要确认该工单属于调用者可见的项目。模型传入的文本必须视为不可信输入,对文件路径、URL、SQL、Shell 参数和资源标识符做约束 资料1。
面试官:如果参数里的资源 ID 被改成别的部门的,你的校验放在哪一层?
候选人:放在 Tool 执行入口,而不是只放在参数反序列化层。 结构校验通过不代表语义合法。我会把"身份 + 资源归属"的判定做成统一拦截逻辑,所有 Tool 复用,避免每个实现各写一套漏掉。这里有个容易踩坑的细节:只校验顶层参数不够,嵌套结构里的资源标识符同样要递归约束,否则模型可以构造深层参数绕过。
面试官:那最小权限具体体现在哪些地方?
候选人:三个层面。 一是 Tool 粒度,只暴露业务真正需要的操作,只读资料不该设计成有副作用的 Tool 资料1;二是资源粒度,判定到具体资源范围而非"有该 Tool 权限即可";三是凭据粒度,下游系统调用使用受限凭据,凭据不出现在日志、Tool 返回值或模型上下文中 资料1。安全实践也强调对代理进程使用最小权限、必要时做进程级隔离 资料4。
第三轮追问:异常、审计与可观测性
面试官:如果授权服务本身超时或不可用,Tool 调用应该放行还是拒绝?
候选人:默认拒绝,这是安全默认值。 授权判定失败属于"无法确认合法",不能当作通过。同时要把失败原因区分为"无权限"和"依赖不可用",前者返回明确的拒绝语义,后者返回可重试的临时错误,避免模型误判后反复重试。超时和重试的具体阈值没有通用答案,要按业务 SLA 和风险等级定,不能拍脑袋写死。
面试官:审计日志记什么?怎么避免日志本身成为泄露源?
候选人:记录谁在什么时间调用了哪个 Tool、关键资源范围与结果状态,并对敏感字段脱敏 资料1。 关键是"关键资源范围"而不是完整参数原文,否则日志里可能带出凭据或隐私数据。日志还要覆盖拒绝事件,因为越权尝试往往比成功调用更有排查价值。
面试官:Prompt 在这个方案里起什么作用?是不是和安全无关?
候选人:Prompt 不是安全控制,但影响安全边界。 Prompts 是用户可显式选择的模板化消息或工作流 资料1。对于高风险或不可逆操作,应在执行前显示具体影响并要求用户确认 资料1。可以把"确认影响范围"的交互设计成 Prompt 模板的一部分,让用户明确看到将要操作哪些资源。但要分清:Prompt 是引导和确认,真正的拦截必须落在服务端授权上,不能靠提示词约束模型行为。
方案设计:三者如何协作
面试官:把认证、Tool 授权、审计和 Prompt 串成一个完整调用链。
候选人:
- 传输层:Streamable HTTP 入口完成身份认证,SDK 的授权钩子接入团队既有身份体系 资料2资料3。
- Tool 入口:统一拦截器根据身份、Tool 名、参数中的资源范围做授权判定,递归校验嵌套资源标识符。
- 执行层:使用最小权限的下游凭据,高风险操作经 Prompt 模板向用户展示影响并确认。
- 审计层:成功与拒绝都记录,敏感字段脱敏,作为可观测性的一部分。
伪代码示意(版本无关的接口设计):
text
handleToolCall(call):
identity = authenticate(request) // 传输层
if identity == null: reject(401)
decision = authorize(identity, call.tool, extractScopes(call.args))
if decision == UNAVAILABLE: audit(...); return retryableError()
if decision == DENIED: audit(...); return forbidden()
result = execute(call, leastPrivilegeCredential(identity))
audit(identity, call.tool, scopes, result.status) // 脱敏
return result
面试官:适用边界呢?
候选人: 这套方案适用于远程、多租户、资源有归属关系的场景。如果是本机 stdio 启动的 Server,按规范应从环境变量取凭据而非走 HTTP 授权流程 资料2,重点转向沙箱和文件系统访问限制 资料4。另外,如果业务本身没有细粒度资源归属,强行做资源级授权只会增加复杂度,收益有限。
面试官点评
考察点:能否区分认证与授权、是否理解 schema 不等于授权、能否把传输层、Tool 层、审计和 Prompt 摆到正确位置,以及异常时的安全默认值。
合格回答:说清每次请求都要授权、参数是不可信输入、审计要脱敏、凭据不进日志和模型上下文。
加分项:指出 SDK 只提供授权钩子而非实现 资料3;区分"无权限"和"依赖不可用"两类失败;说明 Prompt 是确认手段而非安全控制;明确 stdio 与 Streamable HTTP 在授权路径上的差异 资料2。
总结
这道题的核心不是背概念,而是回答"授权检查放在哪、失败时怎么默认、出问题怎么追溯"。传输层认证、Tool 级授权、最小权限凭据、脱敏审计和 Prompt 确认各司其职,任何一环缺位都会让"已登录"变成"可越权"。超时、重试、日志保留等具体数值应结合业务 SLA、风险等级和压测结果确定,而不是套用固定值。
参考资料
- MCP 基础知识
- Authorization: https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization
- MCP Java SDK: https://github.com/modelcontextprotocol/java-sdk
- Security Best Practices: https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices