关于 MCP Server Auth Template
MCP Server Auth Template 是面向远程 MCP 授权实现者的 Python 资源服务器参考项目,展示 OAuth 2.1/OIDC 验证、按范围授权及无状态 MCP。它还包含仅记录元数据的追踪设计。
主要功能
- 01OAuth 2.1 与 OIDC 验证
- 02Entra ID 和通用 OIDC 配置
- 03基于范围的工具授权
- 04基于 Streamable HTTP 的无状态 MCP
- 05仅含元数据的 OpenTelemetry 追踪
适用场景
- 01实现受保护的远程 MCP 服务
- 02测试令牌受众与范围校验
- 03评估无状态 MCP 授权流程
MCP 相关
该服务通过 Streamable HTTP 向 MCP 客户端提供受保护工具,采用 OAuth Bearer 令牌准入、按主体授权和无状态 MCP 行为。它发布受保护资源元数据以供授权发现。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm -e MCP_SERVER_RESOURCE_SERVER_URL -e MCP_SERVER_AUTH_PROVIDER -e MCP_SERVER_REQUIRED_SCOPES -e MCP_SERVER_TRANSPORT_ALLOWED_HOSTS -e MCP_SERVER_ENTRA_TENANT_ID -e MCP_SERVER_ENTRA_AUDIENCE -e MCP_SERVER_ENTRA_APPLICATION_ID_URI -e MCP_SERVER_GENERIC_ISSUER_URL -e MCP_SERVER_GENERIC_AUDIENCE -e MCP_SERVER_GENERIC_JWKS_ALLOWED_ORIGINS ghcr.io/brunovicco/mcp-server-auth-template:v0.7.0MCP_SERVER_RESOURCE_SERVER_URLProtected-resource URL advertised by this deploymentMCP_SERVER_AUTH_PROVIDER密钥Authorization-server adapter to useMCP_SERVER_REQUIRED_SCOPESJSON array of baseline delegated OAuth scopesMCP_SERVER_TRANSPORT_ALLOWED_HOSTSAdditional exact Host values accepted by the local container transportMCP_SERVER_ENTRA_TENANT_IDRequired when MCP_SERVER_AUTH_PROVIDER=entraMCP_SERVER_ENTRA_AUDIENCERequired when MCP_SERVER_AUTH_PROVIDER=entraMCP_SERVER_ENTRA_APPLICATION_ID_URIRequired when MCP_SERVER_AUTH_PROVIDER=entraMCP_SERVER_GENERIC_ISSUER_URLRequired when MCP_SERVER_AUTH_PROVIDER=genericMCP_SERVER_GENERIC_AUDIENCERequired when MCP_SERVER_AUTH_PROVIDER=genericMCP_SERVER_GENERIC_JWKS_ALLOWED_ORIGINSOptional JSON array of explicitly trusted cross-origin JWKS origins本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/brunovicco/mcp-server-auth-template:v0.7.0Streamable HTTP工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mcp-server-auth-template
面向生产环境的 OAuth 2.1 远程 MCP 资源服务参考实现:支持 Microsoft Entra ID 和通用 OIDC、精确的令牌与资源验证、失败时默认拒绝的授权、渐进式作用域质询、无状态 MCP
2026-07-28,以及仅包含元数据的 OpenTelemetry 证据。
当你面对的难题不是“如何公开 MCP 工具?”,而是如何在不削弱身份、授权、传输和可观测性边界的前提下公开工具时,可以使用此仓库。此服务可与 mcp-client-auth-template 配合,提供使用合成身份且无需生产凭据的可执行端到端参考实现。
此仓库验证的内容
配套的可执行路径会验证真实的资源服务行为,而非仅验证配置声明:
- ✅ 资源服务会发布 RFC 9728 受保护资源元数据
- ✅ RFC 8707 资源绑定会成为精确的 JWT 受众边界
- ✅ 颁发者、签名、有效期、算法与密钥兼容性以及调用方类型验证均会在失败时默认拒绝
- ✅ 委派作用域与 Entra 应用程序角色是相互独立的授权概念
- ✅ 渐进式授权会在分发前返回
403 insufficient_scope - ✅ 受众错误的令牌会被拒绝并返回
401;明确的令牌资源策略不依赖 MCP SDK 默认设置 - ✅
tools/list会按主体进行筛选,并且只携带范围受限的private缓存提示 - ✅ 受保护的工具不会出现在匿名目录发现中
- ✅ MCP
2026-07-28保持无状态,且不会生成Mcp-Session-Id - ✅ 通用 OIDC 与 Microsoft Entra ID 共用同一个应用边界,不会泄露提供方信息
- ✅ W3C 跟踪上下文会传递到服务端,同时 OAuth/MCP 敏感值不会进入遥测数据
- ✅ 发布制品、容器证据、SBOM 和来源证明均通过可执行门禁验证
如需逐项了解配套 OAuth/MCP 行为的要求,包括明确的证据缺口,以及 MCP Authorization Interest Group / Tool Scopes Working Group 的讨论主题,请参阅授权实施者报告。
架构
flowchart LR
Client["MCP client"] -->|"OAuth 2.1 / OIDC"| AS["Authorization server<br/>Entra ID or generic OIDC"]
Client -->|"MCP 2026-07-28<br/>resource-bound bearer"| Admission["Transport admission"]
Admission --> AuthN["Token verification"]
AuthN --> AuthZ["Tool authorization"]
AuthZ --> Tools["MCP tools"]
Server["This resource server"] --- Admission
Server -->|"OIDC discovery + cached JWKS"| AS
Server -.->|"W3C trace context + OTLP"| Collector["OpenTelemetry Collector"]
Collector --> Tempo["Tempo"]
Tempo --> Grafana["Grafana"]
授权服务负责登录、许可、客户端注册和令牌签发。本仓库负责受保护资源:传输准入、元数据发布、访问令牌验证、请求级主体构建、工具授权与分发。
如需了解各层边界和详细授权流程,请参阅架构。
5 分钟验证
配套客户端负责跨仓库可执行的参考流程。将两个仓库克隆到同级目录后,可直接从源码验证此服务:
cd ../mcp-client-auth-template
./scripts/run_reference_demo.sh \
--server-root ../mcp-server-auth-template
该流程会从当前检出内容启动真实服务,并配合确定性的本地 OIDC 提供方,验证 CIMD 优先的 Authorization Code + PKCE、经过身份验证的 whoami、有界范围的权限提升、错误受众拒绝以及无状态 MCP 行为。
要验证已发布镜像的可观测性:
cd ../mcp-client-auth-template
./scripts/run_observability_demo.sh --keep
可观测性流程会验证客户端和服务之间的一条分布式跟踪、Collector 成功接收、Tempo 检索、Grafana 配置以及遥测隐私断言。
确切的证据边界请参阅验证指南。
可视化证明
以下终端证明来自源码级配对参考流程:

以下跟踪截图来自一次成功的可观测性运行,重点展示
mcp-server-auth-template 跨度:


身份验证配置
| 配置 | 适用场景 | 关键行为 |
|---|---|---|
| Entra 委托 | 企业交互式用户 | 验证 scp、租户/应用程序标识符、颁发者、受众和主体 |
| Entra 应用程序 | 特定提供方的纯应用部署 | 要求显式设置 idtyp=app;将 roles 与委托范围分开处理 |
| 通用 OIDC 委托 | 基于标准的交互式客户端 | 验证颁发者/受众/签名/过期时间和 OAuth 范围 |
| 通用 OIDC 客户端凭据 | 确定性配对配置文件中的无人值守服务 | 接受预先注册的机器令牌和渐进式 OAuth 范围 |
设置 MCP_SERVER_AUTH_PROVIDER=entra 或 generic 即可切换适配器。示例 whoami 工具会返回经过验证的调用方身份;health 需要额外的 mcp:tools:health 范围,并演示调度前的 403 insufficient_scope 挑战。
快速开始
前置条件:Python 3.13 或 3.14,以及
uv。
git clone https://github.com/brunovicco/mcp-server-auth-template.git
cd mcp-server-auth-template
cp .env.example .env
uv sync --frozen --all-groups
uv run uvicorn mcp_server_auth_template.entrypoints.mcp_server:create_app --factory --reload
在 .env 中配置 Entra 或通用 OIDC 配置块,然后将 MCP 客户端指向
http://localhost:8000/mcp。
| 端点 | 用途 | 身份验证 |
|---|---|---|
/mcp | MCP Streamable HTTP | Bearer 令牌 |
/.well-known/oauth-protected-resource | 授权服务器发现元数据 | 公开 |
/livez | 进程存活状态 | 公开,最小化响应 |
/readyz | MCP 生命周期就绪状态 | 公开,最小化响应 |
要以生产风格运行:
uv run python -m mcp_server_auth_template.entrypoints.serve
在将服务暴露到环回地址之外之前,请参阅生产运维。
官方 MCP 注册表
此服务已发布到官方 MCP 注册表,条目为:
io.github.brunovicco/[email protected]
server.json 将公开的 GHCR 镜像描述为使用真实
streamable-http 传输的 OCI 软件包;它不会声称存在托管的 remotes 端点。发布流程受安全发布流水线和专用注册表工作流控制;该工作流会在发布前验证不可变镜像、所有权元数据和已持久化的注册表响应。
请参阅官方 MCP 注册表和 授权实施者报告。
安全属性
此实现有意采用默认拒绝策略:
- 精确验证签发方和受众、限制时钟偏差、校验算法与密钥兼容性,并缓存 JWKS 刷新结果;
- 明确采用
validate_token_resource=False策略:由令牌验证器强制校验提供方受众(Entra API 客户端 ID、api://标识符),而非通过 SDK URL 字符串相等来校验 (ADR-0027); - 依赖主体的发现结果绝不会跨授权上下文共享 (ADR-0028);
- 加固发现/JWKS 出站流量,防范不安全协议、重定向、压缩、超大响应体、私有/保留目的地、混合 DNS 解析结果和 DNS 重绑定;
- 在身份验证和工具分发之前,对 Host、Origin、请求头、封装、请求体大小和并发进行准入控制;
- 委托身份与应用身份保持区分;扩展协商本身绝不授予授权;
- 持有者令牌和解码后的声明仅在请求内使用,绝不记录或持久化;
- 跟踪不包含凭据、任意请求头和 URL、MCP 参数/结果、请求体、baggage 或异常文本。
这是一个透明的参考实现,并非安全认证。改造该边界之前,请阅读隐私和数据处理以及 docs/adr/ 下的架构决策记录。
MCP 2026-07-28
基线:MCP 规范 2026-07-28 和 MCP Python SDK >=2.2,<3。
配套模板将现代无状态配置作为可执行行为进行验证:
server/discover和每个请求中的_meta携带协议版本、客户端身份和能力,无需旧版initialize/initialized握手;- 现代请求使用
MCP-Protocol-Version、Mcp-Method和Mcp-Name; - 响应不会生成
Mcp-Session-Id; - 受保护资源元数据用于驱动授权服务器发现;
- RFC 8707
resource会精确绑定访问令牌受众; server/discover和tools/list携带 SEP-2549 缓存提示(ttlMs=30000、cacheScope=private);- 运行时的
403 insufficient_scope会保留之前的授权,并且仅允许对尚未分发的操作进行一次有限重放; - 机器对机器访问需通过
io.modelcontextprotocol/oauth-client-credentials显式启用。
请参阅兼容性以及配套客户端的跨仓库 E2E 证据。
可观测性
a2a-otel-kit 会在 MCP ASGI 边界延续 W3C 跟踪上下文。只有在配置了 A2A_OTEL_ENABLED=true 和完整的 OTLP 跟踪端点时才会进行导出,否则不会产生网络流量。Span 仅包含元数据,位于加固的 HTTP 准入层内,但处于身份验证和工具分发层之外。
请参阅 LLM 和应用可观测性。
工程验证
- 确定性质量门禁,涵盖 lint、格式化、严格的 Mypy、架构、测试/覆盖率、Bandit、依赖项审计、供应链控制、治理和 vendored 合约验证;
- GitHub Actions 均固定到 SHA,默认仅具备只读权限,并将发布授权隔离;
- CycloneDX 源码/运行时清单、完整漏洞证据和默认拒绝的例外策略;
- 采用许可清单、可重复构建的 Python 发布制品,附带 SHA-256 清单和 GitHub 构建来源证明;
- 经策略批准发布到 GHCR,并提供不可变摘要、来源证明和 SBOM 证明;
- Python 3.13/3.14 搭配 MCP SDK 2.2.0 和最新兼容的 2.x 版本;将 MCP SDK 弃用警告升级为测试失败,以便尽早发现 MCP 3 兼容性问题;
- 使用本地密钥和合成身份的离线 JWT 测试夹具;
- ADR 记录安全、协议、运维、兼容性、可观测性和供应链决策。
演示与生产环境
| 参考实现证据 | 生产环境采用方式 |
|---|---|
| 配套演示中使用合成的本地 OIDC | 经过审核注册和授权同意流程的企业授权服务器 |
| 回环/本地参考网络 | 受 TLS 保护的服务网络和明确的代理所有权 |
| 本地 Collector/Tempo/Grafana | 由组织管理的遥测管道和保留策略 |
| 合成签名密钥和身份 | 托管密钥、机密和提供商专属控制 |
参考 whoami / health 工具 | 具有明确授权策略和副作用控制的领域工具 |
参考设置用于验证边界,并非生产默认设置。
仓库结构
src/ resource-server implementation
tests/ unit, contract and security evidence
scripts/ quality, governance and release automation
docs/ architecture, operations, privacy and security
examples/ deployment/reference configuration
.github/workflows/ CI, compatibility and release workflows
本地编辑器和编码 Agent 状态有意排除在公共仓库之外。
文档
| 文档 | 用途 |
|---|---|
| 验证 | 源码级和可观察的配对证明 |
| 架构 | 上下文、分层、依赖规则和请求顺序 |
| 兼容性 | 支持的版本以及可执行的客户端/服务端契约 |
| 运维 | 预检、探针、关闭、容器和 Kubernetes |
| 隐私 | 数据清单、保留、日志记录、跟踪和外部处理器 |
| 供应链 | 依赖策略、CI 信任边界、威胁和例外 |
| 可观测性 | OpenTelemetry 和可选的 Langfuse 配置 |
| 开发 | 本地环境、检查和容器工作流 |
| 架构决策 | 重要决策背后的理由和权衡 |
测试与质量
uv lock --check
uv sync --frozen --all-groups
uv run pytest
uv run python scripts/quality_gate.py
质量门禁就是完成标准。它涵盖 lint、格式、架构、严格类型检查、测试/覆盖率、Bandit、依赖审计、供应链控制、治理以及供应的契约验证。
范围与生产环境采用
本仓库是参考模板,而非托管身份服务。具体部署仍必须提供 TLS 终止、不可变镜像发布、机密交付、提供商专属注册、网络策略、容量规划、监控责任归属和实时 IdP 验证。已提交的 .invalid 和全零值均为占位符,无法通过生产预检。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。