Entra ID保护的MCP服务器
受Microsoft Entra ID(前Azure AD)认证保护的Model Context Protocol(MCP)服务器
具有Microsoft Entra ID访问令牌验证功能的FastMCP服务器。提供认证用户的索赔信息检索、Azure资源管理、Microsoft Graph API集成、基于角色的访问控制(RBAC)等功能。
✨ 主要功能
- 🔐 Microsoft Entra ID认证:JWT令牌签名验证、audience/issuer验证、作用域或角色验证
- 👤 获取用户信息:从访问令牌中提取详细的用户索赔信息
- ☁️ 空气资源整合:通过On-Bahalf-Of(OBO)流获取Azure Virtual Machines一览表
- 📊 Microsoft Graph统合:检索和优化用户简档信息的查询
- 🎭 基于角色的访问控制:基于令牌roles索赔的阶段性信息访问控制
- 🔧 可扩展设计:可轻松添加新MCP工具的模块结构
📑 目次
技术栈
- python: 3.12+
- MCP框架: FastMCP 2.14.5+
- 认证:
- python-jose - JWT検证 - msal –OBO流 - cryptography - 暗号化処理
- Azure SDK/微软图形SDK:
- azure-mgmt-compute - Azure VM 管理 - msgraph-sdk -Microsoft Graph API客户端
- 包管理: 紫外线
机能概要
🔐 认证机能
- 全面验证Microsoft Entra ID的JWT令牌
- 签名验证(使用JWKS) - aud (audience)和 iss (issuer)的验证 - 所需作用域(ENTRA_REQUIRED_SCOPES)或必需角色(ENTRA_REQUIRED_ROLES),模板名称将采用不同的格式 - 验证成功时,将通过哪个scope/role输出到INFO日志
- 基于快速MCP的MCP服务器
- 默认值: streamable-http 通过传输 localhost:8000 等待 - 灵活的环境变量设置
🛠️ 交付工具
用户信息
get_user_info:获取已认证用户的索赔信息
- subject, tenant_id, user_principal_name, email, name, roles, scopes 等等
Azure统合
list_azure_vms: Azure Virtual Machines 一覧取得
- 在OBO流中更换为Azure资源管理器的标记 - 返回指定预订中的虚拟机信息
Microsoft Graph统合
get_graph_me:获取用户的完整基本信息
- 在OBO流中更换为Graph API用令牌
get_graph_me_with_select_query:优化的字段检索
- $select 仅检索查询所需的字段 - 优化网络效率和响应速度
基于角色的访问控制(RBAC)
get_company_info:按角色逐步提供企业信息
- 无角色:基本发布信息 - 用户角色:详细的发布信息 - 审计角色:包括审计信息 - 管理员角色:包括机密信息的所有信息
get_sensitive_data:管理员角色专用敏感数据
- 仅管理员角色所有者可访问 - 权限不足时 AuthenticationError 发生
list_available_resources:可访问资源列表
- 列出当前用户角色可访问的资源 - 便于权限确认
目录配置
entra-id-protected-mcp-server/
├── .vscode/
│ ├── launch.json # VS Code デバッグ設定
│ └── settings.json # VS Code エディタ設定
├── src/
│ ├── main.py # エントリーポイント
│ ├── auth/ # 認証関連
│ │ ├── __init__.py
│ │ ├── entra_auth_provider.py # Microsoft Entra ID トークン検証
│ │ ├── obo_client.py # On-Behalf-Of フロー実装
│ │ └── claims_helpers.py # クレーム情報抽出ヘルパー
│ ├── common/ # 共通ユーティリティ
│ │ ├── __init__.py
│ │ ├── config.py # 環境変数設定
│ │ ├── logging_config.py # ログ設定管理
│ │ └── utils.py # ヘルパー関数
│ └── tools/ # MCP ツール
│ ├── __init__.py # ツール自動登録
│ ├── userinfo.py # ユーザー情報ツール
│ ├── azure_vm.py # Azure VM 管理ツール
│ ├── graph_user.py # Graph API ツール
│ └── role_based_info.py # RBAC ツール
├── .env.example # 環境変数テンプレート
├── LOGGING_GUIDE.md # ログ設定の詳細ガイド
├── pyproject.toml # プロジェクト設定と依存関係
├── uv.lock # uv のロックファイル
└── README.md # このファイル主要模块角色
|模块|角色| |----------|------| | main.py 初始化和启动快速MCP服务器。读取配置、设置认证提供程序、注册工具 | auth/entra_auth_provider.py |JWT令牌的验证。获取JWKS并执行签名验证、audience/issuer/范围或角色检查 | auth/obo_client.py 使用MSAL实现On-Behalf-Of流。将用户令牌更换为服务令牌 | auth/claims_helpers.py 从访问令牌中提取用户信息角色作用域的辅助函数组 | common/config.py |环境变量的集中管理。提供Microsoft Entra ID设置、日志级别和MCP服务器设置 | common/logging_config.py 用于单独控制3种日志级别(应用程序认证MCP服务器)的设置类 | common/utils.py 范围透视、Graph模型序列化等辅助函数 | tools/__init__.py 自动检测和注册工具。tools/ 动态加载下属的模块 | tools/userinfo.py |用户信息获取工具(get_user_info) | | tools/azure_vm.py |Azure VM管理工具(list_azure_vms) | | tools/graph_user.py |Microsoft Graph工具(get_graph_me, get_graph_me_with_select_query) | | tools/role_based_info.py RBAC工具(get_company_info, get_sensitive_data, list_available_resources) |
必要要件
- python: 3.12 以降
- 微软Entra ID租户
- API应用程序注册 - 可发行访问令牌的环境(SPA/Web应用/CLI等)
- 包管理器: 紫外线 (推奨)
安装,安装
1.Microsoft Entra ID的应用程序登录和作用域/应用程序角色制作
在使用此服务器之前,必须使用Microsoft Entra ID注册应用程序。此服务器包含Microsoft Entra ID v2.0令牌(requestedAccessTokenVersion=2),模板名称将采用不同的格式。
1-1.在Azure门户注册应用程序
- Azure门户→ “微软Entra ID” → “注册应用程序” → 「新规登録」
- 设置任意名称「登録」 来修改标记元素的显示属性
- 请记住以下信息(稍后)
.env文件):
- 目录(租户)标识 -稍后 ENTRA_TENANT_ID 设置为 - 应用程序(客户端)标识 -稍后 ENTRA_APP_CLIENT_ID 设置为
1-2.将访问标记版本设置为v2.0
- 对象应用程序的 “宣言” 打开菜单
requestedAccessTokenVersion的2的明细栏样式中定义的设置
{
"requestedAccessTokenVersion": 2
}1-3.设置应用程序标识URI
- 公开API 移到
- “设置” 或 设置应用程序标识URI 来修改标记元素的显示属性
- 设置URI(例如:
api://) - 记下此值(稍后)
ENTRA_APP_CLIENT_ID作为.env),模板名称将采用不同的格式
1-4.作用域(access_as_user),模板名称将采用不同的格式
- 「公开API」 → 添加范围
- 输入:
- 作用域名称: access_as_user - 谁可以同意: Admins and users - 显示名称/描述:输入适当的说明
- “已启用” 中选择所需的墙类型
- 范围名称
access_as_user(稍后)ENTRA_REQUIRED_SCOPES作为.env),模板名称将采用不同的格式
1-5.应用程序角色(access_as_application),模板名称将采用不同的格式
- 对象应用程序的 “应用程序角色” 的双曲正切值
- “创建应用程序角色” 来修改标记元素的显示属性
- 输入:
- 表示名: access_as_application - 允许的成员类型: 应用程序 - 値: access_as_application - 说明:输入适当的说明
- 有効化 保存为
- 角色值
access_as_application(稍后)ENTRA_REQUIRED_ROLES作为.env),模板名称将采用不同的格式
💡 补足:此角色是在客户端凭据流等中获取的令牌的 roles 包含在索赔中。1-6.创建客户端密码(用于OBO流)
- “证书和密码” → 新客户端密码
- 设置说明和到期日期
- 秘密的 値 复制并记录(稍后)
ENTRA_APP_CLIENT_SECRET作为.env),模板名称将采用不同的格式
⚠️ 重要:仅在创建时显示密码值。你一定要记下来。
1-7.添加API访问权限
在OBO流中访问Azure或Graph API:
- 允许API访问 → 添加权限
- 添加:
- 微软图形: User.Read (授权访问) - Azure服务管理: user_impersonation (授权访问)
- “管理员同意” (需要管理员权限)
2.Microsoft Entra ID下的应用程序角色注册(可选)
如果要实现基于角色的访问控制(RBAC),请定义其他应用程序角色并将其分配给用户。另外,MCP服务器认证用角色 access_as_application 是按照前一章的步骤完成的假设。如果不需要RBAC功能,则可以跳过此步骤。
2-1.在Azure门户创建应用程序角色
- Azure门户→ “微软Entra ID” → “注册应用程序”
- 选择目标应用程序
- 从左侧菜单 “应用程序角色” 列表框中,此格式对应于条目“无”
- “创建应用程序角色” 来修改标记元素的显示属性
2-2.角色定义示例
创建以下三个角色:
字段:管理员 |----------|-------|---------|------| | 表示名 |管理员|审核员|用户| | 値 | Admin | Auditor | User | | 说明 |管理员权限。可访问所有信息=审计人员权限。可访问审计信息=一般用户权限。可访问基本信息 | 允许的成员类型 | ☑ 两者(用户/组+应用程序)☑ 两者☑ 两者 | 有効化 | ☑ 有効 | ☑ 有効 | ☑ 有効 |
注: 値 字段为访问标记的 roles 包含在索赔中。2-3.将角色分配给用户
- Azure门户→ “微软Entra ID” → 企业应用程序
- 搜索并选择目标应用程序
- 用户和组 → 添加用户或组
- 选择用户或组
- 选择角色 中描述的场景,使用下列步骤创建明细表,以便在概念设计中分析体量的周长
- 分配 来修改标记元素的显示属性
2-4.使用标记检查角色
如果角色被正确分配 roles 包括在索赔中:
{
"aud": "api://your-app-id",
"iss": "https://login.microsoftonline.com/tenant-id/v2.0",
"sub": "user-object-id",
"roles": ["Admin", "User"],
"scp": "access_as_user"
}令牌是 jwt.ms 啊 jwt.io 中所述修改相应参数的值。
⚠️ 注意事项: - 要分配角色,请执行以下操作: 租户管理员权限 时褪色为此颜色 - 角色分配后,用户 重新登录 中描述的场景,使用以下步骤创建明细表,以便在概念设计中分析体量的体积 - 现有标记不包含新角色信息
3.克隆存储库
git clone
cd entra-id-protected-mcp-server4.安装依赖包
这个项目 紫外线 中所述修改相应参数的值。
# uv がインストールされていない場合
pip install uv
# プロジェクト依存関係のインストール
uv sync注:uv是虚拟环境(.venv),模板名称将采用不同的格式。手动python -m venv而需要与环境混合的每条反射光线,进行环境采样。
5.设置环境变量
.env.example 的 .env 将条目添加到文档注册表。
# Windows (PowerShell)
Copy-Item .env.example .env
# Linux/macOS
cp .env.example .env.env 设置示例:
# Microsoft Entra ID 認証設定
ENTRA_TENANT_ID=your-tenant-id-here
ENTRA_APP_CLIENT_ID=your-client-or-api-id-here
ENTRA_REQUIRED_SCOPES=access_as_user
ENTRA_REQUIRED_ROLES=access_as_application
ENTRA_APP_CLIENT_SECRET=your-mcp-api-client-secret-here
# ログレベル設定(3 種類を個別制御可能)
# APP_LOG_LEVEL: アプリ・Azure SDK・Microsoft Graph SDK のログレベル
APP_LOG_LEVEL=INFO
# ENTRA_AUTH_LOG_LEVEL: Entra 認証・MSAL のログレベル(未指定なら APP_LOG_LEVEL と同じ)
ENTRA_AUTH_LOG_LEVEL=INFO
# MCP_SERVER_LOG_LEVEL: MCP サーバーのログレベル(未指定なら APP_LOG_LEVEL と同じ)
MCP_SERVER_LOG_LEVEL=INFO
# MCP サーバー設定
MCP_TRANSPORT=streamable-http
MCP_HOST=localhost
MCP_PORT=8000请设定在上述步骤1中取得的值。
実行方法
从VS Code启动(推荐)
VSCode的launch.json包含MCP服务器启动设置。
- 在VS代码中打开项目
.env创建文件并设置环境变量- 在运行和调试视图中 “运行MCP服务器” 列表框中,此格式对应于条目“无”
- 启动F5或开始调试
从命令行启动
# Windows (PowerShell)
$env:PYTHONPATH = "$PWD/src"
uv run python src/main.py
# Linux/macOS (Bash)
export PYTHONPATH="$PWD/src"
uv run python src/main.py当服务器启动时,将显示以下日志:
2026-02-15 04:16:19,695 INFO __main__: Logger Configuration: LoggerConfig(app=INFO, auth=INFO, mcp_server=INFO)
2026-02-15 04:16:19,702 INFO __main__: Entra Tenant ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
2026-02-15 04:16:19,702 INFO __main__: Entra Required Scopes: access_as_user
2026-02-15 04:16:19,702 INFO __main__: Entra Required Roles: access_as_application
2026-02-15 04:16:19,836 INFO auth.entra_auth_provider: JWKS fetched: keys=6
[02/15/26 04:16:21] INFO Starting MCP server 'entra-mcp-server' with
transport 'streamable-http' on http://localhost:8000/mcp在处理实际请求时,还将输出以下成功日志:
INFO auth.entra_auth_provider: Token validation succeeded via scopes: access_as_user认证流程概述
sequenceDiagram
participant Client as MCP クライアント
participant Server as MCP サーバー
participant Entra as Microsoft Entra ID
participant Azure as Azure/Graph API
Client->>Entra: 1. ユーザー認証
Entra-->>Client: 2. アクセストークン (JWT)
Client->>Server: 3. Bearer トークンで MCP ツール呼び出し
opt JWKSキャッシュなし/期限切れ
Server->>Entra: 3a. JWKS (公開鍵) 取得
Entra-->>Server: 3b. JWKS 返却
end
Server->>Server: 4. JWT 検証 (署名, aud, iss, scopes/roles)
Server->>Entra: 5. OBO フロー (必要な場合)
Entra-->>Server: 6. サービストークン
Server->>Azure: 7. Azure/Graph API 呼び出し
Azure-->>Server: 8. データ返却
Server-->>Client: 9. 結果を返却详细流程
- 客户端认证:MCP客户端(例如代理/编辑器扩展)从Microsoft Entra ID获取访问令牌
- 标记发送:
Authorization: Bearer以页眉发送到MCP服务器 - 标记验证:
EntraIDAuthProvider验证以下内容
- 签名验证(获取Entra的JWKS并在JOSE中验证) - audience 的 ENTRA_APP_CLIENT_ID 符合 - issuer 支持租户的URL - 所需作用域(ENTRA_REQUIRED_SCOPES)或必需角色(ENTRA_REQUIRED_ROLES)中的任一项 - 验证成功时,在INFO日志中记录匹配的scope/role
- 保存上下文:验证成功时,FastMCP的
AccessToken的明细栏样式中定义的设置 - 工具运行:MCP工具
get_access_token()通过访问索赔 - OBO流程 (如果需要):要访问Azure/Graph API,请将用户令牌更换为服务令牌
- 错误处理:如果标记无效、过期、必需范围/角色不足
AuthenticationError发生
交付工具
👤 get_user_info
从已认证用户的访问令牌中提取并返回代表性索赔。
返回字段示例:
{
"subject": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"client_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"tenant_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"user_principal_name": "user@contoso.com",
"email": "user@contoso.com",
"name": "山田 太郎",
"roles": ["Admin", "User"],
"scopes": ["access_as_user"],
"issued_at": 1707868800,
"expires_at": 1707872400
}☁️ list_azure_vms
获取指定预订中的“Azure Virtual Machines”列表。
引数:
subscription_id(string):Azure预订ID
动作:
- 在OBO流中将用户令牌更换为Azure资源管理器的令牌
azure-mgmt-compute在SDK中获取虚拟机列表- VMの基本情报(id,name,location,type,tags)を返却
返却例:
[
{
"id": "/subscriptions/.../resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm1",
"name": "vm1",
"location": "eastus",
"type": "Microsoft.Compute/virtualMachines",
"tags": {"environment": "production"}
}
]📊 get_graph_me
使用Microsoft Graph API获取已认证用户的完整配置文件信息。
动作:
- 在OBO流中更换为Graph API标记(作用域:
https://graph.microsoft.com/.default) msgraph-sdk的/v1.0/me调用端点- 返回用户的所有基本信息字段
返回字段示例:
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"displayName": "山田 太郎",
"mail": "yamada@contoso.com",
"userPrincipalName": "yamada@contoso.com",
"jobTitle": "Senior Engineer",
"department": "Engineering",
"officeLocation": "Tokyo Office"
}📊 get_graph_me_with_select_query
仅指定所需字段以获取用户简档信息(优化版)。
引数:
select(string):逗号分隔的字段列表
- 默认值: "displayName,mail,id,officeLocation,jobTitle"
优点:
- 减少网络传输量
- 缩短响应时间
- 仅高效获取所需信息
使用例:
# 名前とメールのみ取得
result = await get_graph_me_with_select_query(select="displayName,mail")
# ID、役職、部署のみ取得
result = await get_graph_me_with_select_query(select="id,jobTitle,department")🎭 get_company_info
根据角色逐步返回企业信息(RBAC实施示例)。
访问级别:
角色|可访问信息| |--------|-----------------| | 无角色 基本公开信息(公司名称、成立年份、联系方式等) | 用户 |详细な公开情报(従业员数范围、株式情报、认证情报など)| | 审计员 审核信息(实际员工数、年销售额、审核报告等) | 管理员 机密信息(未公开项目、详细财务、战略计划、董事报酬等)
返还示例(管理员角色):
{
"access_level": "admin",
"user_roles": ["Admin", "User"],
"company_name": "Contoso Corporation",
"public_info": { ... },
"audit_info": {
"employee_count": 2847,
"annual_revenue_usd": 450000000
},
"confidential_info": {
"unreleased_projects": [...],
"financial_details": {...},
"strategic_plans": {...}
}
}🔒 get_sensitive_data
获取只有具有管理员角色的用户才能访问的敏感数据。
所需角色: Admin
错误处理:
try:
data = await get_sensitive_data()
except AuthenticationError as e:
# insufficient_role: 'Admin' role required, but user has ['User']
print(f"アクセス拒否: {e}")📋 list_available_resources
列出当前用户角色可访问的资源和工具。
返却例:
{
"user_info": {
"name": "山田 太郎",
"user_id": "xxx-xxx-xxx",
"roles": ["Admin", "User"]
},
"accessible_resources": [
{
"resource": "公開会社情報",
"description": "会社の基本的な公開情報",
"access_level": "public",
"tools": ["get_company_info"]
},
{
"resource": "機密情報",
"description": "未公開プロジェクト、詳細財務情報",
"access_level": "admin",
"tools": ["get_company_info", "get_sensitive_data"]
}
]
}调试和测试
在VS代码中执行调试
此存储库包含用于VSCode的调试配置(.vscode/launch.json),模板名称将采用不同的格式。
事前准备
.env创建并设置所需的值uv sync安装依赖关系- 安装VS代码的Python扩展
选择Python解释器
- 打开命令选项板(Ctrl+Shift+P/Cmd+Shift+P)
- “Python:选择解释器” 输入/选择
.venv中选择Python
- 例: Python 3.x.x ('.venv': venv) ./.venv/Scripts/python
.venv对话框,您可以在此定义自定义格式settings.json添加: ``json { "python.venvPath": ".", "python.venvFolders": [".venv"] }``
调试启动
- 在VS代码中打开项目
- 在运行和调试视图中 “运行MCP服务器” 列表框中,此格式对应于条目“无”
- F5或 启动调试 启动
您可以设置断点来执行标记验证和工具执行步骤。
在MCP检验器上测试
您可以使用MCP检查器交互式测试工具。
前提条件
- Node.js (推奨: v22.7.5 以降)
- MCP服务器正在启动(
localhost:8000)
1.获取访问令牌
在测试MCP检查器之前,使用Azure CLI获取访问令牌。
# アプリケーション ID URI を指定
$RESOURCE = "api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# スコープを指定してログイン
az login --scope "$RESOURCE/access_as_user"
# アクセストークンを取得
$token = az account get-access-token --resource $RESOURCE --query accessToken -o tsv
# トークンの内容を確認 (オプション)
Write-Host "Token: $token"💡 提示之一:要登录来宾用户,请在az login命令中添加--tenant选项,并指定要访问的租户的租户ID
💡 提示2:获取的标记为 jwt.ms 啊 jwt.io 中描述的场景,使用以下步骤创建明细表,以便在概念设计中分析体量的体积。roles、scp等索赔是否正确包含。
2.MCP检查器的启动和设置
- 在VSCode的执行和调试视图中 “运行MCP检查器” 列表框中,此格式对应于条目“无”
- F5或 启动调试 启动
- 在浏览器中打开MCP检查器
- 设置MCP服务器连接:
- 传输: HTTP / streamable-http - 统一资源定位符: http://localhost:8000/mcp - 认证: Authorization: Bearer - `` 粘贴通过上述步骤获取的标记
3.测试工具
您可以在检查器上交互式测试以下工具:
get_user_info:确认令牌的索赔信息list_azure_vms:获取Azure VM列表(需要预订标识)get_graph_me:从Microsoft Graph获取用户简档get_company_info:根据角色获取企业信息list_available_resources:确认可访问的资源
调整日志级别
可以使用环境变量详细控制日志级别:
# 3 種類のログを個別制御
APP_LOG_LEVEL=DEBUG # アプリ・Azure SDK・Microsoft Graph SDK のログレベル
ENTRA_AUTH_LOG_LEVEL=DEBUG # Entra 認証・MSAL のログレベル
MCP_SERVER_LOG_LEVEL=INFO # MCP サーバーのログレベル记录级别: DEBUG | INFO | WARNING | ERROR | CRITICAL
了解更多信息 LOGGING_GUIDE.md 来修改标记元素的显示属性。
开发指南
添加新的MCP工具
新的工具 tools/ 只要在属下添加模块就会自动注册。
最小配置示例
tools/hello.py:
from fastmcp import FastMCP
def register_tools(mcp: FastMCP) -> None:
"""Hello 系ツールを登録する。"""
@mcp.tool()
async def say_hello(name: str = "world") -> str:
"""挨拶メッセージを返すサンプルツール。
引数:
name: 挨拶する相手の名前
"""
return f"Hello, {name}!"重新启动服务器时 say_hello 工具将自动可用。
访问认证的用户信息
from auth.claims_helpers import get_user_context, has_role
@mcp.tool()
async def my_tool():
"""認証済みユーザー情報を使用するツール。"""
# ユーザーコンテキストを取得(ヘルパー関数を使用)
roles, user_id, client_id, scopes, claims = get_user_context()
# ロールチェック
is_admin = has_role(roles, "Admin")
return {
"user_id": user_id,
"client_id": client_id,
"roles": roles,
"scopes": scopes,
"is_admin": is_admin
}使用OBO流
访问Azure或Graph API:
from auth.claims_helpers import get_access_token_and_context
from auth.entra_auth_provider import build_obo_credential
@mcp.tool()
async def my_azure_tool():
"""Azure リソースにアクセスするツール。"""
# アクセストークンとユーザーコンテキストを取得
access_token, roles, user_id, client_id, scopes, claims = (
get_access_token_and_context()
)
# OBO credential を作成
credential = build_obo_credential(
access_token.token,
"https://management.azure.com/.default"
)
# Azure SDK で使用
# from azure.mgmt.compute import ComputeManagementClient
# client = ComputeManagementClient(credential, subscription_id)错误处理
from starlette.authentication import AuthenticationError
import logging
logger = logging.getLogger(__name__)
@mcp.tool()
async def my_tool():
"""エラーハンドリングの例。"""
try:
# 処理
pass
except AuthenticationError:
logger.error("認証エラー")
raise
except Exception as e:
logger.error(f"予期しないエラー: {e}")
raise RuntimeError(f"tool_error: {str(e)}") from e范围/角色设置
ENTRA_REQUIRED_SCOPES 和 ENTRA_REQUIRED_ROLES 可以用逗号分隔:
ENTRA_REQUIRED_SCOPES=access_as_user, User.Read, files.read
ENTRA_REQUIRED_ROLES=access_as_application, Admin如果同时设置,则标记验证 满足所需范围 或 满足所需角色 中选择所需的墙类型。
utils.parse_scopes 将规格化为:
- 前后空格删除
- 小文字化
- 删除空元素
- 重复削除
- 排序
结果:
ENTRA_REQUIRED_SCOPES→["access_as_user", "files.read", "user.read"]ENTRA_REQUIRED_ROLES→["access_as_application", "admin"]
错误和日志
主要错误代码:
|错误代码|说明|发生时间| |------------|------|--------------| | jwks_fetch_failed |JWKS获取失败|服务器启动时| | access_token_expired 标记过期|标记验证时| | invalid_access_token |非法令牌|令牌验证时| | invalid_issuer |发行者不一致|令牌验证时| | invalid_audience |收件人不匹配|令牌验证时| | missing_required_permissions |必需作用域/角色不足|令牌验证时| | insufficient_role |角色不足|调用RBAC工具时| | obo_token_acquisition_failed 在访问OBO流失败时
部署到Azure App Service
也可以将此服务器部署到Azure App Service中,在云环境中运行,作为远程MCP服务器使用。
1.在Azure Portal上创建App Service
1-1.新建应用程序服务
- 登录Azure Portal“应用服务” 查找并选择
- 「+ 作成」 → 「Web App」 来修改标记元素的显示属性
- 设置以下项目:
- 预订:选择要使用的预订 - 资源组:选择现有或新建 - 名前:输入应用程序的唯一名称(例如: entra-mcp-server) - 公开: 代码 列表框中,此格式对应于条目“无” - 运行时栈: 「Python 3.12」 列表框中,此格式对应于条目“无” - 操作系统: 「Linux」 列表框中,此格式对应于条目“无” - 地域:选择任意区域(例如,Japan East)
- 应用服务计划 (例如,基本B1)
- 确认和创建 → 「作成」 来修改标记元素的显示属性
1-2.设置环境变量
创建应用程序服务后,设置环境变量。
- 转到已创建的应用程序服务页面
- 从左侧菜单 「设定」> \[环境变数\] 列表框中,此格式对应于条目“无”
- 应用程序设置 在工作空间的边缘 「+追加」 来修改标记元素的显示属性
- 添加以下环境变量:
| 名前 | 値 | 说明 |
|---|---|---|
ENTRA_TENANT_ID | your-tenant-id |Microsoft Entra ID租户ID| | |
ENTRA_APP_CLIENT_ID | api://your-client-id 应用程序(客户端)ID或API的URI | |
ENTRA_REQUIRED_SCOPES | access_as_user 必需的作用域(逗号分隔) | |
ENTRA_REQUIRED_ROLES | access_as_application 必须的应用程序角色(逗号分隔) | |
ENTRA_APP_CLIENT_SECRET | your-client-secret 客户机密(用于OBO流) | |
APP_LOG_LEVEL | INFO 应用程序日志级别 | |
ENTRA_AUTH_LOG_LEVEL | INFO |认证日志级别| | |
MCP_SERVER_LOG_LEVEL | INFO |MCP服务器日志级别| | |
MCP_TRANSPORT | streamable-http |MCP传输方式| | |
MCP_HOST | 0.0.0.0 | 重要:在App Service中 0.0.0.0 设置为 |
MCP_PORT | 8000 |MCP服务器端口| |
⚠️ 重要:MCP_HOST在App Service中必须0.0.0.0中所述修改相应参数的值。localhost中所述修改相应参数的值。
- 「保存」 单击保存设置
1-3.设置启动命令
在App Service中指定启动Python应用程序的命令。
- 「构成」 在工作空间的边缘 「全般设定」 选择选项卡
- 启动命令 在字段中输入:
python main.py注:在后述的ZIP部署中src/文件夹的内容/home/site/wwwroot中所述修改相应参数的值。因此main.py啊/home/site/wwwroot/main.py将条目添加到文档注册表。
- 「保存」 来修改标记元素的显示属性
2.使用VSCode的Azure Tools扩展进行ZIP部署
2-1.在VS代码中安装Azure App Service扩展
- 打开VS代码
- 打开扩展视图(Ctrl+Shift+X/Cmd+Shift+X)
- 「Azure应用服务」 搜索并安装
- 「Azure资源」 扩展功能也会自动安装
2-2.登录到Azure
- 在VS代码左侧的活动栏中 “空气”图标 来修改标记元素的显示属性
- “登录Azure…” 来修改标记元素的显示属性
- 因为浏览器打开,所以用Azure账户登录
2-3.准备部署
在部署之前requirements.txt 创建 src/ 放在下面。
💡 提示:src/仅将文件夹上传到App Service,因此依赖文件也src/中所述修改相应参数的值。
- 在项目根目录中运行以下命令:
# requirements.txt を生成
uv export --format requirements-txt --output-file requirements.txt --no-hashes
# Windows (PowerShell)
Move-Item requirements.txt src/requirements.txt -Force
# Linux/macOS (Bash)
mv requirements.txt src/requirements.txt- 确认:
- src/ 应用程序代码位于目录中 - src/requirements.txt 存在 - .env 文件是 不包括(环境变量已在App Service的配置中设置)
2-4.执行ZIP部署
- 在VS代码中打开项目
- 在左侧的活动栏中 “空气”图标 来修改标记元素的显示属性
- “资源” 展开节
- 展开预订- “应用服务” 展开
- 创建的应用程序服务(例如:
entra-mcp-server),模板名称将采用不同的格式 - “部署到Web应用程序…” 列表框中,此格式对应于条目“无”
- 选择要部署的文件夹-
src选择文件夹 - 单击功能区上 “部署” 来修改标记元素的显示属性
部署完成后,日志将显示在VS代码输出面板中:
Deploying to "entra-mcp-server"...
Creating zip package...
Uploading package...
Deployment successful.2-5.部署后确认
- 在Azure Portal上转到App Service页面
- 「概要」 在工作空间的边缘 统一资源定位符 点击进入应用程序
- 单击功能区上的日志流 的双曲正切值
如果已成功启动,则会显示以下日志:
2026-02-15 04:16:19,695 INFO __main__: Logger Configuration: LoggerConfig(app=INFO, auth=INFO, mcp_server=INFO)
2026-02-15 04:16:19,702 INFO __main__: Entra Tenant ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
2026-02-15 04:16:19,702 INFO __main__: Entra Required Scopes: access_as_user
2026-02-15 04:16:19,702 INFO __main__: Entra Required Roles: access_as_application
2026-02-15 04:16:19,836 INFO auth.entra_auth_provider: JWKS fetched: keys=6
[02/15/26 04:16:21] INFO Starting MCP server 'entra-mcp-server' with
transport 'streamable-http' on http://0.0.0.0:8000/mcp2-6.连接到MCP服务器
要连接到部署的MCP服务器,请使用以下URL:
https://{App Service ドメイン名}/mcp例:App Service名称为 entra-mcp-server 的情况下
https://entra-mcp-server.azurewebsites.net/mcp💡 提示:App Service的域名是Azure Portal的 「概要」 中所述修改相应参数的值。
______________________________________________________________________
