Token导航 LogoToken导航

MCP Server · AI代理

Sts Entraid Single A2a Adkagent MCP Poc

一个安全的多层AI代理系统,用户身份从前端认证传播到代理层再到资源API,通过三层独立访问控制实现深度防御。

stdio官方级别未说明来源级核验工具 7
AI代理访问控制Claude

快速开始

作者 / 组织
sanjay-sts
提供方
sanjay-sts

工具数量

7

来源目录标注

资源数量

0

来源目录标注

提示词数量

0

来源目录标注

GitHub Star

0

仓库热度

收录来源

1 个

MCP World

选型结论

Sts Entraid Single A2a Adkagent MCP Poc 属于AI代理类 MCP Server,公开资料标注 7 个工具,通过stdio 本地进程接入,适配 Claude,有可以直接复制的安装命令;接入前要先准备 OAuth 授权。

分类

AI代理

传输方式

stdio

认证方式

OAuth 授权

部署方式

公开资料未说明

安装与配置

安装命令

pip install -r requirements.txt

公开命令不是通用的启动方式,拼不出可靠配置示例;请在客户端 MCP 配置里按官方文档填写 command 和 args。

上手步骤

  1. 1

    准备运行环境

    stdio 服务在本地起进程,需要先装好 对应的运行时,再按安装命令拉取依赖。

  2. 2

    安装服务

    复制下面的安装命令执行;命令里带占位符的位置换成自己的密钥或路径。

  3. 3

    写入客户端配置

    在客户端的 MCP 配置里填启动命令和参数,保存后完全退出客户端再打开,让新配置生效。

  4. 4

    验证是否可用

    连接成功后客户端会列出 7 个工具,随便调一个只读工具确认能返回结果。

接入前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

详细介绍

身份感知人工智能代理系统

一个安全的多层人工智能代理系统,用户身份从前端身份验证通过代理层传播到资源API。该架构在三个独立的级别上实施访问控制,提供深度防御。

目录

______________________________________________________________________

系统设计

概述

该系统使用 OAuth 2.0与OpenID连接(OIDC) 对于身份验证和授权,支持多个身份提供商(Microsoft Entra ID和AWS Cognito):

  • 协议:使用PKCE(代码交换证明密钥)的OAuth 2.0授权代码流
  • 令牌格式:由IdP签名的JWT访问令牌,通过JWKS(JSON Web密钥集)验证
  • 前端:使用MSAL.js 3.6(Entra)+AWS Amplify 6(Cognito)进行反应——统一的身份验证提供者
  • 网关:A2A用于代理发现和请求路由的协议服务器
  • 代理:谷歌ADK与克劳德·海库4.5通过LiteLLM(AWS基岩)
  • 工具:提供身份识别软件工具的FastMCP服务器(Graph API+S3)

技术栈

组件技术端口目的
前端React 18+MSAL.js 3.6+AWS Amplify 610003用户身份验证、令牌获取
网关A2A协议(FastAPI+A2A-sdk)10000代理发现、代理级ACL、流媒体
代理谷歌ADK+LiteLLM+Claude Haiku 4.5(基岩)10001LLM编排、工具调用
工具FastMCP(无状态HTTP)10002工具执行、令牌传播
身份Entra ID+AWS Cognito-OAuth 2.0+OIDC,多IdP JWT验证
资源Microsoft Graph API、AWS S3-用户数据、文件、电子邮件、云存储

三层安全模型

级别位置机制强制执行拒绝访问
1.代理人A2A服务器组成员资格,阻止列表auth_middleware用户被阻止或不在允许的组中
2.工具FastMCP基于角色的权限(RBAC)内置身份验证(JWT验证)+ auth=require_role() 装饰师+ UserContextMiddleware令牌无效、未担任角色或角色缺乏工具权限
3.资源Graph APIOAuth作用域Microsoft Graph缺少所需作用域的令牌

______________________________________________________________________

当前状态

工作特点

功能状态注释
入境者身份验证✅ 工作中MSAL.js弹出/静默令牌获取
AWS Cognito身份验证✅ 工作增强托管UI重定向流
自定义API范围✅ 工作api://{client-id}/access_as_user
多IdP令牌验证✅ 工作中Entra v1.0/v2.0+Cognito JWTs
A2A协议✅ 工作代理卡发现、消息/发送
ADK+克劳德·海库4.5✅ 工作通过LiteLLM在AWS基岩上
MCP工具(无状态)✅ 正在工作通过header_provider传递的令牌
多回合对话✅ 工作会话状态保留在ADK中
RBAC执行✅ 工作三层访问控制
海外建筑运营管理局代币交换✅ 工作通过On-Behalf-Of流绘制API图形
S3工具✅ 工作服务器端AWS凭据
X—承担角色✅ 工作端到端角色传播

已知限制

限制影响
前端使用缓冲 /chat 不 /chat/stream一次显示所有响应
内存中的会话服务重新启动时丢失
JWKS缓存永远不会时间失效(A2A)可能会出现过期密钥(未命中时自动清除)
未处理组超龄Entra>记录了150个组,但未提取

______________________________________________________________________

架构图

系统架构

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                    USER BROWSER                                       │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│  │                         React Frontend (Port 10003)                              │ │
│  │  ┌──────────────┐    ┌──────────────┐    ┌──────────────────────────────────┐   │ │
│  │  │   MSAL.js    │───▶│ Auth State   │───▶│  Chat Interface                  │   │ │
│  │  │  (Login)     │    │ (Token)      │    │  - Send messages                 │   │ │
│  │  └──────────────┘    └──────────────┘    │  - Display responses             │   │ │
│  │         │                   │            │  - Scope selection               │   │ │
│  │         ▼                   ▼            └──────────────────────────────────┘   │ │
│  │  ┌─────────────────────────────────────────────────────────────────────────┐    │ │
│  │  │              Microsoft Entra ID (OAuth 2.0 + OIDC)                      │    │ │
│  │  │  - Token issuance (custom API scope + Graph scopes)                     │    │ │
│  │  │  - Group claims in token                                                │    │ │
│  │  └─────────────────────────────────────────────────────────────────────────┘    │ │
│  └─────────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                          │
                                          │ HTTP POST + Bearer Token
                                          ▼
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              A2A Gateway (Port 10000)                                │
│  ┌──────────────────────────────────────────────────────────────────────────────┐   │
│  │                         auth_middleware                                       │   │
│  │  1. Validate JWT signature (JWKS from Entra ID)                              │   │
│  │  2. Check blocklist (BLOCKED_USERS)                                          │   │
│  │  3. Verify group membership (ALLOWED_GROUPS)                                 │   │
│  │  4. Set ContextVar: current_user_claims, current_access_token                │   │
│  └──────────────────────────────────────────────────────────────────────────────┘   │
│                                          │                                           │
│                                          ▼                                           │
│  ┌──────────────────────────────────────────────────────────────────────────────┐   │
│  │                    IdentityAwareAgentExecutor                                 │   │
│  │  1. Extract user claims from ContextVar                                       │   │
│  │  2. Ensure ADK session exists for user                                        │   │
│  │  3. Forward request to ADK Agent                                              │   │
│  │  4. Emit TaskStatusUpdateEvent with response                                  │   │
│  └──────────────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                          │
                                          │ HTTP POST + Bearer Token
                                          ▼
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              ADK Agent (Port 10001)                                  │
│  ┌──────────────────────────────────────────────────────────────────────────────┐   │
│  │                         Session Management                                    │   │
│  │  - InMemorySessionService                                                     │   │
│  │  - Session state: user:access_token, user:email, user:role, user:groups      │   │
│  └──────────────────────────────────────────────────────────────────────────────┘   │
│                                          │                                           │
│                                          ▼                                           │
│  ┌──────────────────────────────────────────────────────────────────────────────┐   │
│  │                    LlmAgent (Claude Haiku 4.5 via LiteLLM)                     │   │
│  │  - Processes user message                                                     │   │
│  │  - Decides which tools to call                                               │   │
│  │  - Formats final response                                                     │   │
│  └──────────────────────────────────────────────────────────────────────────────┘   │
│                                          │                                           │
│                                          ▼                                           │
│  ┌────────────────────────┐    ┌────────────────────────────────────────────────┐   │
│  │    Local Tools         │    │              McpToolset                         │   │
│  │  - get_identity_info   │    │  - header_provider injects Bearer token        │   │
│  │  - check_my_permissions│    │  - Calls FastMCP server                        │   │
│  └────────────────────────┘    └────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                          │
                                          │ HTTP POST + Bearer Token (from header_provider)
                                          ▼
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              FastMCP Server (Port 10002)                             │
│  ┌──────────────────────────────────────────────────────────────────────────────┐   │
│  │                      FastMCP Built-in Auth (MultiAuth)                        │   │
│  │  1. AzureJWTVerifier (v2.0) — auto-configured from Azure app registration  │   │
│  │  2. JWTVerifier (v1.0 fallback) — for sts.windows.net issuer tokens         │   │
│  │  3. Validates JWT signature, issuer, audience, expiry via JWKS              │   │
│  └──────────────────────────────────────────────────────────────────────────────┘   │
│                                          │                                           │
│                                          ▼                                           │
│  ┌──────────────────────────────────────────────────────────────────────────────┐   │
│  │                      UserContextMiddleware                                    │   │
│  │  1. Detect IdP provider from iss claim (entra/cognito/auth0)                │   │
│  │  2. Extract email, groups from validated token claims                        │   │
│  │  3. Resolve available roles via TomlPolicyEvaluator (permissions.toml)      │   │
│  │  4. Validate X-Assume-Role header against available roles                   │   │
│  │  5. Set ContextVars: current_user_token, current_user_role, current_user_email│  │
│  └──────────────────────────────────────────────────────────────────────────────┘   │
│                                          │                                           │
│                                          ▼                                           │
│  ┌──────────────────────────────────────────────────────────────────────────────┐   │
│  │                      Per-Tool Auth Decorators                                │   │
│  │  1. auth=require_role() checks user role via ContextVar                      │   │
│  │  2. Raises ToolError with [TOOL_DENIAL] prefix on denial                    │   │
│  └──────────────────────────────────────────────────────────────────────────────┘   │
│                                          │                                           │
│                                          ▼                                           │
│  ┌──────────────────────────────────────────────────────────────────────────────┐   │
│  │                              MCP Tools                                        │   │
│  │  - get_user_profile      (all roles)                                         │   │
│  │  - list_files            (admin, developer)                                  │   │
│  │  - send_email            (admin only)                                        │   │
│  │  - delete_resource       (admin only)                                        │   │
│  │  - get_current_time      (admin only)                                        │   │
│  │  - convert_timezone      (admin only)                                        │   │
│  │  - get_time_difference   (admin only)                                        │   │
│  └──────────────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                          │
                                          │ (Optional) Graph API calls with user token
                                          ▼
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              Microsoft Graph API                                     │
│  - /me (User.Read scope)                                                            │
│  - /me/drive/root/children (Files.Read scope)                                       │
│  - /me/sendMail (Mail.Send scope)                                                   │
└─────────────────────────────────────────────────────────────────────────────────────┘

请求流程图

┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐
│  User    │     │ Frontend │     │   A2A    │     │   ADK    │     │   MCP    │
│ Browser  │     │  React   │     │ Gateway  │     │  Agent   │     │  Server  │
└────┬─────┘     └────┬─────┘     └────┬─────┘     └────┬─────┘     └────┬─────┘
     │                │                │                │                │
     │  1. Login      │                │                │                │
     │───────────────▶│                │                │                │
     │                │ 2. MSAL        │                │                │
     │                │ acquireToken   │                │                │
     │                │───────────────▶│ Entra ID      │                │
     │                │◀───────────────│ (Token)       │                │
     │                │                │                │                │
     │  3. Send msg   │                │                │                │
     │───────────────▶│                │                │                │
     │                │ 4. POST /      │                │                │
     │                │ + Bearer token │                │                │
     │                │───────────────▶│                │                │
     │                │                │ 5. Validate    │                │
     │                │                │    JWT         │                │
     │                │                │ 6. Check       │                │
     │                │                │    groups      │                │
     │                │                │                │                │
     │                │                │ 7. POST /chat  │                │
     │                │                │ + Bearer token │                │
     │                │                │───────────────▶│                │
     │                │                │                │ 8. Store token │
     │                │                │                │    in session  │
     │                │                │                │                │
     │                │                │                │ 9. LLM decides │
     │                │                │                │    tool call   │
     │                │                │                │                │
     │                │                │                │ 10. MCP call   │
     │                │                │                │ + Bearer token │
     │                │                │                │───────────────▶│
     │                │                │                │                │ 11. Validate
     │                │                │                │                │     JWT
     │                │                │                │                │ 12. Check
     │                │                │                │                │     role
     │                │                │                │                │ 13. Execute
     │                │                │                │                │     tool
     │                │                │                │◀───────────────│
     │                │                │                │ 14. Tool result│
     │                │                │                │                │
     │                │                │                │ 15. LLM formats│
     │                │                │                │     response   │
     │                │                │◀───────────────│                │
     │                │                │ 16. Response   │                │
     │                │◀───────────────│                │                │
     │                │ 17. A2A result │                │                │
     │◀───────────────│                │                │                │
     │ 18. Display    │                │                │                │
     │                │                │                │                │

______________________________________________________________________

身份验证流程

系统使用 使用PKCE的OAuth 2.0授权代码流 通过Microsoft Entra ID。MSAL.js 3.6处理前端流——不使用隐式授权。令牌是包含OAuth 2.0/OIDC声明的标准JWT(iss, aud, exp, scp, groups, preferred_username等等),并在每一层使用提供商的JWKS公钥进行验证。

初始身份验证

1. User clicks "Sign In with Microsoft"
2. MSAL.js opens popup to Entra ID login (Authorization Code + PKCE)
3. User authenticates with credentials/MFA
4. Entra ID returns an authorization code to the SPA
5. MSAL.js exchanges the code for tokens (PKCE-secured, no client secret):
   - ID Token (OIDC — user identity claims)
   - Access Token (OAuth 2.0 — with custom API scope + Graph scopes)
6. MSAL.js caches tokens in browser storage
7. Frontend shows authenticated state

请求令牌获取

// Frontend: authConfig.js
const API_SCOPE = `api://${clientId}/access_as_user`;

export const graphScopes = {
  basic: [API_SCOPE, 'User.Read'],
  files: [API_SCOPE, 'User.Read', 'Files.Read'],
  email: [API_SCOPE, 'User.Read', 'Mail.Send'],
  full: [API_SCOPE, 'User.Read', 'Files.Read', 'Mail.Send'],
  destructive: [API_SCOPE, 'User.Read', 'Files.Read', 'Files.ReadWrite.All', 'Mail.Send'],
};

// Token acquisition (cached, no re-prompt unless expired)
const token = await instance.acquireTokenSilent({ scopes, account });

令牌格式和验证

访问令牌是 JWT(JSON Web令牌) 由Entra ID使用RS256签名。每个后端层通过从Microsoft的JWKS端点获取公钥并验证签名、颁发者、受众和到期时间来独立验证Bearer令牌。Entra ID可以发行v1.0代币(发行人: sts.windows.net/{tenant}/)或v2.0令牌(发行者: login.microsoftonline.com/{tenant}/v2.0)--两者都支持。

A2A服务器 --手动JWT验证:

# a2a_server/server.py — manual JWKS fetching, supports v1.0 and v2.0 tokens
JWKS_URIS = [
    f"https://login.microsoftonline.com/{TENANT_ID}/discovery/v2.0/keys",
    f"https://login.microsoftonline.com/{TENANT_ID}/discovery/keys",
    "https://login.microsoftonline.com/common/discovery/keys",
]
VALID_ISSUERS = [
    f"https://login.microsoftonline.com/{TENANT_ID}/v2.0",
    f"https://sts.windows.net/{TENANT_ID}/",
]

MCP 服务器 --FastMCP 3.1内置身份验证 MultiAuth:

# mcp_server/server.py — uses FastMCP's built-in auth providers
# v2.0 verifier (primary)
AzureJWTVerifier(client_id=CLIENT_ID, tenant_id=TENANT_ID, required_scopes=["access_as_user"])

# v1.0 verifier (fallback for sts.windows.net issuer tokens)
JWTVerifier(
    jwks_uri=f"https://login.microsoftonline.com/{TENANT_ID}/discovery/keys",
    issuer=f"https://sts.windows.net/{TENANT_ID}/",
    audience=[CLIENT_ID, f"api://{CLIENT_ID}"],
    required_scopes=["access_as_user"],
)
# Composed via MultiAuth — tries v2.0 first, falls back to v1.0

______________________________________________________________________

多回合对话流程

根据请求重新验证令牌

层动作频率缓存?
前端acquireTokenSilent()每个请求是(SWITCHache)
A2A服务器JWT签名验证每个请求JWKS缓存
A2A服务器组成员资格检查每个请求否
ADK代理在会话中存储令牌每个请求会话状态
MCP 服务器JWT签名验证每次工具调用JWKS缓存
MCP 服务器角色权限检查每次工具调用否

ADK中的会话状态

# Session state stored with user: prefix for persistence
session.state = {
    "user:access_token": "",      # Updated each request
    "user:email": "user@domain.com",
    "user:name": "User Name",
    "user:groups": ["group-id-1", "group-id-2"],
    "user:role": "admin"                      # Derived from groups
}

多转弯示例

Turn 1: "What's my email?"
  ├─ Token validated at A2A (cached JWKS)
  ├─ Session created in ADK
  ├─ Local tool: get_identity_info
  └─ Response: "Your email is user@domain.com"

Turn 2: "What time is it in Tokyo?"
  ├─ Token validated at A2A (same JWKS)
  ├─ Session retrieved (same session_id)
  ├─ Token updated in session state
  ├─ MCP tool: get_current_time
  │   ├─ Token validated at MCP (cached JWKS)
  │   └─ Role check: admin required ✓
  └─ Response: "The time in Tokyo is..."

Turn 3: "List my files"
  ├─ Token validated at A2A
  ├─ Session retrieved
  ├─ MCP tool: list_files
  │   ├─ Token validated at MCP
  │   └─ Role check: admin/developer required ✓
  └─ Response: "Your files are..."

______________________________________________________________________

上下文和身份传递

A2A服务器→ ADK代理

# A2A Server uses ContextVar to pass auth data
current_user_claims: ContextVar[dict] = ContextVar("current_user_claims", default={})
current_access_token: ContextVar[str] = ContextVar("current_access_token", default="")

# Set in auth_middleware
current_user_claims.set(claims)
current_access_token.set(token)

# Read in IdentityAwareAgentExecutor
user_claims = current_user_claims.get()
access_token = current_access_token.get()

# Forward to ADK Agent via HTTP
POST /chat
{
    "message": "user message",
    "user_id": "sub-claim-value",
    "session_id": "session-uuid"
}
Headers: Authorization: Bearer 

ADK代理→ MCP 服务器

# McpToolset uses header_provider for dynamic auth
def mcp_header_provider(readonly_context: ReadonlyContext) -> Dict[str, str]:
    if readonly_context and readonly_context.state:
        access_token = readonly_context.state.get("user:access_token", "")
        if access_token:
            return {"Authorization": f"Bearer {access_token}"}
    return {}

# McpToolset configuration
self.mcp_toolset = McpToolset(
    connection_params=StreamableHTTPConnectionParams(url=MCP_SERVER_URL),
    header_provider=mcp_header_provider,  # Injects token per-request
)

MCP服务器上下文变量

# MCP Server stores validated claims in ContextVar (stateless mode — no ctx.get_state())
current_user_token: ContextVar[str] = ContextVar("current_user_token", default="")
current_user_role: ContextVar[str] = ContextVar("current_user_role", default="none")
current_user_email: ContextVar[str] = ContextVar("current_user_email", default="")

# Set by UserContextMiddleware, read by tools and auth= callables
@mcp.tool(auth=require_role("admin"))
async def get_current_time(timezone: str = "UTC") -> dict:
    user_role = current_user_role.get()
    user_email = current_user_email.get()
    # ... tool logic

______________________________________________________________________

RBAC(基于角色的访问控制)

角色继承

admin      → Full access to all tools
developer  → Access to profile and file tools
viewer     → Access to profile tools only
none       → No tool access (agent-level denied)

组到角色映射(permissions.toml)

角色定义见 permissions.toml (代理人所有,未经授权)。复制自 permissions.example.toml:

# permissions.toml — Agent-owned role assignments
# Group-to-role mapping is the PRIMARY mechanism.
# User-level overrides are optional for exceptions.

[group_rules.entra]
"" = "admin"
"" = "developer"
"" = "viewer"

[group_rules.cognito]
# "platform-admins" = "admin"  # Future: Cognito groups

[group_rules.auth0]
# "admin" = "admin"  # Future: Auth0 roles

[users]
# Optional direct user overrides (case-insensitive email lookup)
# "user@company.com" = { role = "admin" }

[defaults]
unknown_users = "none"

这 TomlPolicyEvaluator (mcp_server/policy.py)通过文件更改时的热重新加载,从组声明和用户覆盖中解析可用角色。角色优先级:管理员>开发人员>查看器。

角色选择:用户必须设置 X-Assume-Role MCP工具调用的标题。 UserContextMiddleware 根据可用角色验证假定的角色。对于工具列表,将自动使用优先级最高的角色。

备注:A2A服务器仍在使用 GROUP_TO_ROLE 来自env变量(ADMIN_GROUP_ID等等)用于代理级访问控制。MCP服务器使用 permissions.toml 用于工具级RBAC。

工具权限矩阵

工具允许的角色描述
get_user_profile管理员、开发人员、查看器获取Microsoft Graph配置文件(或令牌声明回退)
list_files管理员、开发人员列出OneDrive文件
send_emailadmin通过Graph发送电子邮件
delete_resourceadmin删除资源
get_current_timeadmin获取时区时间
convert_timezoneadmin时区转换
get_time_differenceadmin比较时区偏移

权限执行代码

# MCP Server: Per-tool auth= decorators (require_role only — IdP scope checking removed)
@mcp.tool(auth=require_role("admin", "developer", "viewer"))
async def get_user_profile() -> dict: ...

@mcp.tool(auth=require_role("admin", "developer"))
async def list_files(folder_path: str = "/") -> dict: ...

@mcp.tool(auth=require_role("admin"))
async def send_email(to: str, subject: str, body: str) -> dict: ...

# Auth helper
def require_role(*allowed_roles):
    # Reads current_user_role ContextVar (set by UserContextMiddleware)
    # Raises: "[TOOL_DENIAL] Access denied: Role '...' cannot use this tool. Required roles: [...]"
    ...

拒绝访问示例

No X-Assume-Role header:
  → [ROLE_SELECTION] Role selection required. Set X-Assume-Role header to one of: ['admin']

Viewer tries to list files:
  → [TOOL_DENIAL] Access denied: Role 'viewer' cannot use this tool. Required roles: ['admin', 'developer']

Developer tries to send email:
  → [TOOL_DENIAL] Access denied: Role 'developer' cannot use this tool. Required roles: ['admin']

User tries to assume a role they don't have:
  → [TOOL_DENIAL] Cannot assume role 'admin'. Available roles: ['developer']

No-group user (not in permissions.toml):
  → [TOOL_DENIAL] No roles available for user@domain.com. Contact admin to assign group membership.

User without groups at A2A gateway:
  → 403 {"error": "access_denied", "denial_level": "agent", "denial_reason": "no_group_membership"}

Blocked user:
  → 403 {"error": "access_denied", "denial_level": "agent", "denial_reason": "blocked_user"}

______________________________________________________________________

API 参考

A2A服务器(端口10000)

代理卡发现
GET /.well-known/agent-card.json

答复:

{
  "name": "Identity-Aware AI Agent",
  "description": "An AI agent with Entra ID authentication...",
  "url": "http://localhost:10000/",
  "version": "1.0.0",
  "capabilities": {"streaming": true},
  "skills": [...]
}
发送消息(A2A协议)
POST /
Authorization: Bearer 
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "method": "message/send",
  "params": {
    "message": {
      "messageId": "msg-123",
      "role": "user",
      "parts": [{"type": "text", "text": "What time is it?"}]
    }
  },
  "id": "req-123"
}

答复:

{
  "id": "req-123",
  "jsonrpc": "2.0",
  "result": {
    "id": "task-uuid",
    "kind": "task",
    "status": {
      "state": "completed",
      "message": {
        "kind": "message",
        "role": "agent",
        "parts": [{"kind": "text", "text": "The current time is..."}]
      }
    }
  }
}
健康检查
GET /health
安全上下文
GET /me
Authorization: Bearer 

答复:

{
  "user": { "email": "user@domain.com", "name": "User Name", "oid": "..." },
  "security": {
    "role": "developer",
    "groups": ["group-id-1"],
    "group_names": { "group-id-1": "developer" },
    "token_scopes": ["User.Read", "Files.Read"],
    "token_expiry": 1741363200,
    "issuer": "https://login.microsoftonline.com/{tenant}/v2.0"
  },
  "permissions": {
    "get_user_profile": true, "list_files": true, "send_email": false,
    "delete_resource": false, "get_current_time": false,
    "convert_timezone": false, "get_time_difference": false
  },
  "tool_scopes": {
    "get_user_profile": ["User.Read"], "list_files": ["Files.Read"],
    "send_email": ["Mail.Send"], "delete_resource": ["Files.ReadWrite.All"],
    "get_current_time": [], "convert_timezone": [], "get_time_difference": []
  }
}

ADK代理(端口10001)

创建会话
POST /session
Authorization: Bearer 
Content-Type: application/json

{
  "user_id": "user-sub-claim",
  "user_info": {
    "email": "user@domain.com",
    "name": "User Name",
    "groups": ["group-id-1"]
  }
}

答复:

{"session_id": "session-uuid"}
聊天
POST /chat
Authorization: Bearer 
Content-Type: application/json

{
  "message": "What's my email?",
  "user_id": "user-sub-claim",
  "session_id": "session-uuid"
}

答复:

{
  "response": "Your email is user@domain.com",
  "session_id": "session-uuid"
}

MCP服务器(端口10002)

MCP端点
POST /mcp
Authorization: Bearer 
Content-Type: application/json

# Standard MCP protocol messages
可用工具
工具参数返回
get_user_profile(无)来自Graph或令牌声明的用户配置文件
list_filesfolder_path?: string文件名列表
send_emailto, subject, body发送状态
delete_resourceresource_id删除状态
get_current_timetimezone?: string带纪元的时间信息
convert_timezonetime_str, from_timezone, to_timezone转换时间
get_time_differencetimezone1, timezone2偏移差

______________________________________________________________________

安装指南

先决条件

  • Python 3.10+
  • Node.js 18+
  • Microsoft Entra ID租户
  • Anthropic API密钥(用于Claude)

1.微软Entra ID配置

  1. 在中创建应用程序注册 Entra管理中心
  2. 配置平台:单页应用

- 重定向URI: http://localhost:10003, http://localhost:10003/redirect

  1. 公开API:

- 添加范围: access_as_user - 应用程序ID URI: api://{client-id}

  1. API权限:

- openid, profile, User.Read, Files.Read, Mail.Send

  1. 令牌配置:

- 添加组声明(安全组)

  1. 创建安全组:

- 管理员组、开发人员组、查看器组

2.环境设置

# Backend (.env)
cp .env.example .env

# Required variables:
ENTRA_CLIENT_ID=
ENTRA_TENANT_ID=
ADMIN_GROUP_ID=
DEVELOPER_GROUP_ID=
VIEWER_GROUP_ID=
ANTHROPIC_API_KEY=

# Frontend (frontend/.env)
cd frontend && cp .env.example .env

REACT_APP_ENTRA_CLIENT_ID=
REACT_APP_ENTRA_TENANT_ID=

# MCP Permissions (group-to-role mapping)
cp permissions.example.toml permissions.toml
# Edit permissions.toml with your Entra ID security group GUIDs

3.安装依赖项

# Backend
pip install -r requirements.txt
# or with uv:
uv pip install -r requirements.txt

# Frontend
cd frontend && npm install

4.运行服务

# Terminal 1: MCP Server
uv run python mcp_server/server.py

# Terminal 2: ADK Agent
uv run python adk_agent/agent.py

# Terminal 3: A2A Gateway
uv run python a2a_server/server.py

# Terminal 4: Frontend
cd frontend && npm start

5.访问申请

  • 前端:http://localhost:10003
  • A2A网关:http://localhost:10000
  • 代理卡:http://localhost:10000/.well-已知/代理卡.json

______________________________________________________________________

安全测试仪表板

前端包括一个全面的安全测试仪表板,用于测试和可视化三层访问控制系统。

仪表板组件

组件位置目的
安全上下文面板左侧边栏显示角色、组、范围、令牌到期倒计时
令牌检查器左侧边栏(可折叠)解码JWT标头/有效载荷以供显示
RBAC测试矩阵左侧边栏一键式测试网格,带通过/失败跟踪
对话选项卡主区域多选项卡聊天,每个选项卡范围选择(最多4个)
审核日志主区域(底部)拒绝分类的请求历史记录
拒绝指示器内联徽章颜色编码的拒绝层:代理(红色)、工具(橙色)、资源(紫色)
帐户切换器标题支持多帐户以测试不同角色

拒绝分类

拒绝被自动分为四个等级:

层检测者示例
代理http401/403+ denial_level 在响应正文中用户不在任何组中
工具[TOOL_DENIAL] 响应文本中的标记查看器正在尝试 list_files
RESOURCE响应文本中的Graph API 403Graph权限不足

前端文件结构

frontend/src/
  App.js                      # Dashboard layout shell
  App.css                     # Dark theme styles
  authConfig.js               # MSAL config + scope presets (basic, files, email, full, destructive)
  index.js                    # MSAL provider setup
  components/
    AuthStatus.js             # Multi-account switcher dropdown
    LoginPrompt.js            # Sign-in prompt
    SecurityContextPanel.js   # Role, groups, scopes, expiry countdown
    TokenInspector.js         # JWT decoder display
    ConversationTabs.js       # Multi-tab chat with per-tab scope
    ChatInterface.js          # Chat with denial tagging and latency tracking
    RBACTestMatrix.js         # One-click test grid
    AuditLog.js               # Request history table
    DenialIndicator.js        # Color-coded denial badge
  utils/
    tokenDecoder.js           # JWT base64url decode helper
    denialClassifier.js       # HTTP status + response text → denial tier
    testScenarios.js          # Predefined test prompts with expected outcomes

______________________________________________________________________

测试

运行测试

# With services running
uv run pytest tests/test_access_control.py -v

手动测试

  1. 使用管理员组中的用户登录
  1. 测试:“我的电子邮件是什么?”→ 应该可以
  1. 测试:“东京现在几点了?”→ 应该工作(仅限管理员)
  1. 测试:“列出我的文件”→ 应该可以
  1. 使用查看器组中的用户登录
  1. 测试:“我的电子邮件是什么?”→ 应该可以
  1. 测试:“东京现在几点了?”→ 应该失败(仅限管理员)

检查日志

# All logs in logs/ directory
tail -f logs/a2a_server.log
tail -f logs/adk_agent.log
tail -f logs/mcp_server.log

______________________________________________________________________

文档链接

______________________________________________________________________

许可证

麻省理工学院

工具与能力

工具数量

7

资源数量

0

提示词数量

0

能力标签

AI代理本地部署身份认证访问控制OAuth2.0RBAC

支持客户端

Claude

数量来自来源目录的标注,具体工具清单以官方文档为准。

典型使用场景

多步任务编排

把拆解、检索、执行串成一条链,模型按步骤调用工具。

长期上下文

把会话、笔记和知识放到外部存储,换个会话还能接着做。

接自有流程

把内部系统和模型连起来,让助手调用已有的工作流。

选择建议

值得选的地方

  • 只提供 7 个工具,职责集中,接入后不容易误操作。
  • 有现成的安装命令,不用自己找入口,照着跑就能起服务。
  • 公开说明写得比较完整,接入前能看清能力边界。

先想清楚的地方

  • stdio 方式要求本地装好 运行环境,换机器要重新装一遍。
  • 需要自备OAuth 授权,没有凭据没法直接试。
  • 公开摘要偏短,具体能力和限制要回到仓库确认。

更适合

  • 需要在AI代理场景里让模型直接调用外部能力的人。
  • 已经在用 Claude 的用户,接入路径最短。
  • 想先快速试一下、能接受在本地跑服务的人。

不太适合

  • 完全不想在本地装环境的人。
  • 暂时拿不到OAuth 授权的人。
  • 需要厂商级 SLA 和技术支持的生产环境。

同类对比

5 个同类
MCP Server工具数传输方式安装命令收录来源最后核验
Sts Entraid Single A2a Adkagent MCP Poc

MCP World · 本页

7stdio有1 个2026-05-17
Everything Claude Code

MCP World

0stdio有1 个2026-05-17
Filesystem 560c4363

MCP World

13未说明未标注2 个2026-05-17
Time 7365cb6d

MCP.so

2SSE有2 个2026-05-17
Server Everything (everything)

MCP World

11stdio有1 个2026-05-17

按同分类和工具数量挑出最接近的几条,字段以各自详情页为准。

常见问题

5 条

Sts Entraid Single A2a Adkagent MCP Poc 怎么安装?

公开资料给出的安装命令是 pip install -r requirements.txt,运行环境为 未标注。装完后按客户端要求写进 MCP 配置,重启客户端生效。

Sts Entraid Single A2a Adkagent MCP Poc 怎么在 Claude Desktop、Cursor 里配置?

它是stdio 本地进程,客户端配置里要写启动命令和参数,运行环境是 未标注;保存后完全退出客户端再打开,配置才会生效。

Sts Entraid Single A2a Adkagent MCP Poc 收费吗?

本站只整理公开资料,不代收费用,也没有标注具体价格。是否收费取决于服务本身和背后的接口额度,正式使用前按官方说明确认。

Sts Entraid Single A2a Adkagent MCP Poc 需要 API Key 吗?

公开资料标注的认证方式是OAuth 授权,也就是要先拿到凭据才能连上;凭据只填在自己本地的配置里,不要写进公开仓库。

Sts Entraid Single A2a Adkagent MCP Poc 支持哪些客户端?

公开资料标注支持 Claude;其他客户端只要能配置 MCP Server,也能用同样的命令或地址接入。

来源信息

继续浏览同类 MCP