Okta MCP适配器
MCP(模型上下文协议)客户端的非官方原型适配器,具有OAuth 2.1身份验证、多代理支持和跨应用令牌交换。仅用于评估和测试目的。
概述
状态: ✅ 完成(113项测试通过)
Okta MCP适配器提供:
- ✅ 基于路径路由的多后端MCP代理
- ✅ Okta OAuth 2.1 JWT验证与JWKS缓存
- ✅ 符合RFC标准的ID-JAG令牌交换,用于后端访问
- ✅ 多代理支持(每个客户端授权和凭据)
- ✅ 3种身份验证方法:Okta跨应用、预共享密钥、服务帐户
- ✅ 带TTL和自动过期处理的令牌缓存
- ✅ 全面的审计日志和SQLite持久性
- ✅ 受保护资源元数据发现(RFC9728)
快速开始
# Setup
cp env.template .env
# Edit .env with Okta credentials
# Install & test
pip install -r requirements.txt
pytest tests/ # 113 tests, all passing
# Start agent adapter
python -m okta_agent_proxy.main http
# or: ./scripts/run_gateway.sh配置
.env(环境变量)
OKTA_DOMAIN=dev-12345.okta.com
GATEWAY_BASE_URL=http://localhost:8000
GATEWAY_PORT=8000
LOG_LEVEL=INFO
# When true (default), tools/list without auth returns 401 to trigger OAuth. When false, allows unauthenticated tools/list (e.g. for AgentCore gateway target registration).
# PROTECTED_DISCOVERY=true备注:代理凭据(client_id、private_key)在中配置 config/config.yaml,不在 .env
config/config.yaml(后端和代理)
backends:
employees:
url: http://localhost:9001
paths: [/employees, /hr]
auth_method: okta-cross-app
auth_config:
id_jag_mode: static
target_authorization_server: https://target-okta.okta.com
target_token_endpoint: https://target-okta.okta.com/oauth2/v1/token
target_client_id: 0oa_target_app
target_client_secret: secret
partners:
url: http://localhost:9002
paths: [/partners]
auth_method: pre-shared-key
auth_config:
key: partner_api_key_123
agents:
cursor:
client_id: 0oa_cursor_app
private_key: |
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCA...
-----END PRIVATE KEY-----
scopes: [mcp:read, mcp:write]
backend_access: [employees, finance]
claude-code:
client_id: 0oa_claude_code
private_key: ...
scopes: [mcp:read]
backend_access: [partners]建筑
请求流
MCP Client (X-Agent-ID: cursor + Bearer Token)
↓
MCP Adapter
├─ 1. Validate Okta JWT
├─ 2. Extract Agent ID
├─ 3. Load Agent Config (backend_access)
├─ 4. Route to Backend
├─ 5. Authorize (backend in agent.backend_access?)
├─ 6. Exchange Token (ID-JAG)
├─ 7. Add Auth Headers
└─ 8. Forward Request
↓
Target MCP Backend → Response关键组件
- 代理处理程序 -请求处理管道
- 后端路由器 -基于路径的路由
- OktaTokenValidator -JWT验证
- 代理提取器 -多代理支持
- InMemory后端存储 -SQLite+YAML持久化
- ID-JAG发卡机构/交易所 -两步式代币交换
- 后端身份验证处理程序 -3种身份验证方法
代币交易所(ID-JAG)
Step 1: Client sends Okta token
Step 2: Gateway issues ID-JAG JWT (using agent credentials)
Step 3: Exchange ID-JAG JWT for backend token (at target auth server)
Step 4: Cache backend token with TTL
Step 5: Use cached token until expiration
Step 6: On 401: Invalidate cache, retry exchange实施状态
| 阶段 | 功能 | 状态 | 测试 |
|---|---|---|---|
| 1 | 基本代理 | ✅ | 17 |
| 1B | SQLite存储+YAML | ✅ | 20 |
| 2 | Okta JWT验证 | ✅ | 41 |
| 2+ | 多代理支持 | ✅ | 53 |
| 3 | 代币交换和代理 | ✅ | 集成 |
| 总计 | ✅ 完成 | 113 |
项目结构
okta_agent_proxy/
├── main.py # FastMCP entry point
├── config.py # Configuration management
├── auth/
│ ├── okta_validator.py # JWT validation
│ ├── agent_authz.py # Multi-agent authorization
│ ├── backend_auth.py # 3 auth methods
│ ├── id_jag_issuer.py # ID-JAG JWT issuing
│ └── id_jag_exchanger.py # Token exchange
├── middleware/
│ ├── auth.py # Auth utilities
│ └── agent_extractor.py # Agent extraction
├── backends/
│ └── router.py # Path-based routing
├── proxy/
│ └── handler.py # Request proxying
├── storage/
│ ├── base.py # Abstract interface
│ ├── models.py # SQLAlchemy ORM
│ └── in_memory.py # SQLite implementation
└── cache/ # Token caching
tests/
├── test_basic_gateway.py # 17 tests
├── test_okta_auth.py # 41 tests
├── test_in_memory_store.py # 20 tests
├── test_agent_support.py # 26 tests
└── test_agent_authz.py # 27 tests使用示例
测试
# All tests (113 tests, 0.29s)
pytest tests/ -v
# Specific test file
pytest tests/test_agent_authz.py -v
# With coverage
pytest tests/ --cov=okta_agent_proxy客户端请求(与代理)
curl -H "Authorization: Bearer " \
-H "X-Agent-ID: cursor" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":"1","method":"tools/list","params":{}}' \
http://localhost:8000/employees响应(成功)
{
"jsonrpc": "2.0",
"id": "1",
"result": { "tools": [...] }
}响应(授权错误)
{
"error": "authorization_denied",
"message": "Not authorized to access backend 'finance'",
"agent_id": "cursor"
}多代理授权
每个代理人都有:
- 客户端id:OAuth应用程序ID(适用于ID-JAG)
- private_key:PKCS8密钥(用于令牌交换)
- 范围:所需权限(默认值:mcp:read)
- 后端访问:代理可以访问的后端列表
示例流程:
Client (Cursor agent)
+ X-Agent-ID: cursor
+ Authorization: Bearer
↓
Gateway checks:
✓ Agent 'cursor' exists and enabled
✓ User has 'mcp:read' scope
✓ Backend 'employees' in agent.backend_access
✓ Exchange token for backend
↓
Allow → Forward to backend故障排除
端口已在使用中:更改 GATEWAY_PORT=8001 在 .env
导入错误: pip install -r requirements.txt --force-reinstall
Okta令牌验证失败:验证 OKTA_DOMAIN 在 .env
未找到代理:将代理添加到 config/config.yaml 并确保 X-Agent-ID 标题匹配
后端授权被拒绝:检查代理人的 backend_access 配置中的列表
启用调试日志: LOG_LEVEL=DEBUG python -m okta_agent_proxy.main http
图表和可视化文档
可视化架构和序列图可在 /docs/ 文件夹:
- 建筑设计_DIAGRAM.md -使用Mermaid图的系统架构
- 完整的组件可视化 - 7层代理架构 - 通过每一层的数据流 - 安全边界 - 多代理配置 - 代币交换流程
- 序列_图表.md -请求流序列
- 完整流程:Claude Code代理→ 员工MCP通过代理 - 5个阶段:认证→ 发现→ 请求→ TokenEx→ 刷新 - 6种错误情况及其处理 - 4个用例 - 组件交互
查看图表:
- 美人鱼现场 -复制架构图
- sequencediagram.org -复制序列图
- GitHub-自动渲染美人鱼图
- VS代码+美人鱼扩展
参考文献
状态
⚠️ 非官方原型仅供评估 -这是一个用于评估和测试目的的非官方原型。它不应该在生产环境中使用。使用风险自负。
许可证:Apache 2.0
