一个OAuth 2.1授权服务器,为模型上下文协议(MCP)服务提供透明的身份验证和授权。
使用GitHub容器注册表中的预构建Docker镜像:
# 使用内存存储(开发)
docker run -p 8080:8080 \
-v $(pwd)/config.yaml:/app/config.yaml \
-e GOOGLE_CLIENT_ID="your-google-client-id" \
-e GOOGLE_CLIENT_SECRET="your-google-client-secret" \
ghcr.io/akshay5995/mcp-oauth-gateway:latest
# 复制环境模板
cp .env.example .env
# 编辑.env文件,添加您的OAuth凭证
# 启动所有服务(网关 + Redis + 示例计算器)
docker-compose up -d
# 测试设置
curl http://localhost:8080/health
curl http://localhost:8080/calculator/mcp # 应返回401并带有OAuth信息
pip install -r requirements.txt
# 可选:对于现代库的Redis存储后端
pip install -r requirements-redis.txt
重要:每个网关实例只能配置一个OAuth提供商。
设置Google OAuth环境变量:
export GOOGLE_CLIENT_ID="your-google-client-id"
export GOOGLE_CLIENT_SECRET="your-google-client-secret"
📚 其他提供商:参见配置指南了解GitHub、Okta和自定义OAuth提供商的配置方法。
创建一个config.yaml文件:
# 网关设置
host: "localhost"
port: 8080
issuer: "http://localhost:8080"
session_secret: "your-dev-secret-change-in-production"
debug: true
# OAuth提供商
oauth_providers:
google:
client_id: "${GOOGLE_CLIENT_ID}"
client_secret: "${GOOGLE_CLIENT_SECRET}"
scopes: ["openid", "email", "profile"]
# 示例服务(替换为您自己的MCP服务)
mcp_services:
calculator:
name: "计算器服务"
url: "http://localhost:3001"
oauth_provider: "google"
auth_required: true
scopes: ["read", "calculate"]
python -m src.gateway --config config.yaml --debug
访问您的服务以验证其是否正常工作:
curl http://localhost:8080/calculator/mcp
# 应返回401并带有OAuth认证信息
在config.yaml中替换示例服务为您实际的MCP服务。所有服务必须使用相同的OAuth提供商。
📚 完整配置指南 - 详细的配置选项
MCP客户端首先访问服务端点:
GET /calculator/mcp HTTP/1.1
Host: localhost:8080
网关响应OAuth元数据:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="http://localhost:8080/.well-known/oauth-protected-resource"
客户端获取OAuth元数据:
curl http://localhost:8080/.well-known/oauth-authorization-server
curl http://localhost:8080/.well-known/oauth-protected-resource
客户端自动注册:
curl -X POST http://localhost:8080/oauth/register \
-d "client_name=我的MCP客户端" \
-d "redirect_uris=http://localhost:8080/callback"
客户端遵循标准的OAuth 2.1流程,包括PKCE:
host: "0.0.0.0"
port: 8080
issuer: "https://mcp-gateway.example.com"
session_secret: "production-secret-key"
debug: false
为Web客户端配置跨源资源共享(CORS):
cors:
allow_origins: ["*"] # 允许的来源(生产环境中使用具体域名)
allow_credentials: true # 在CORS请求中允许凭证
allow_methods: # 允许的HTTP方法
- "GET"
- "POST"
- "PUT"
- "DELETE"
- "OPTIONS"
allow_headers: ["*"] # 允许的头信息(生产环境中使用具体头信息)
对于生产部署,限制CORS设置:
cors:
allow_origins:
- "https://myapp.example.com"
- "https://dashboard.example.com"
allow_credentials: true
allow_methods: ["GET", "POST", "OPTIONS"]
allow_headers:
- "Authorization"
- "Content-Type"
- "MCP-Protocol-Version"
重要:由于OAuth 2.1资源参数的限制,每个网关实例只能配置一个OAuth提供商。
oauth_providers:
google:
client_id: "${GOOGLE_CLIENT_ID}"
client_secret: "${GOOGLE_CLIENT_SECRET}"
scopes: ["openid", "email", "profile"]
📚 替代提供商:参见配置指南了解GitHub、Okta和自定义OAuth提供商的配置示例。
mcp_services:
calculator:
name: "计算器服务"
url: "http://calculator:3001"
oauth_provider: "google" # 必须与配置的OAuth提供商匹配
auth_required: true
scopes: ["read", "calculate"]
timeout: 30000
# 所有认证服务必须使用相同的OAuth提供商
weather:
name: "天气服务"
url: "http://weather:3002"
oauth_provider: "google" # 与上面相同
auth_required: true
scopes: ["read"]
后端MCP服务接收带有用户上下文头的信息请求:
GET /mcp HTTP/1.1
Host: calculator:3001
x-user-id: google_user_123456
x-user-email: user@example.com
x-user-name: John Doe
x-user-provider: google
x-user-avatar: https://example.com/avatar.jpg
服务可以使用这些头信息进行:
# 本地构建镜像
docker build -t mcp-oauth-gateway .
# 使用自定义构建运行
docker run -p 8080:8080 \
-v $(pwd)/config.yaml:/app/config.yaml \
-e GOOGLE_CLIENT_ID="your-google-client-id" \
-e GOOGLE_CLIENT_SECRET="your-google-client-secret" \
mcp-oauth-gateway
# 启动Redis容器
docker run -d --name redis \
-p 6379:6379 \
redis:alpine redis-server --requirepass mypassword
# 更新config.yaml以使用Redis
cat >> config.yaml << EOF
storage:
type: "redis"
redis:
host: "host.docker.internal" # 或Redis容器IP
port: 6379
password: "\${REDIS_PASSWORD}"
EOF
# 使用Redis运行网关
docker run -p 8080:8080 \
-v $(pwd)/config.yaml:/app/config.yaml \
-e GOOGLE_CLIENT_ID="your-google-client-id" \
-e GOOGLE_CLIENT_SECRET="your-google-client-secret" \
-e REDIS_PASSWORD="mypassword" \
ghcr.io/akshay5995/mcp-oauth-gateway:latest
# 启动Vault容器(开发模式)
docker run -d --name vault \
-p 8200:8200 \
-e VAULT_DEV_ROOT_TOKEN_ID="myroot" \
vault:latest
# 更新config.yaml以使用Vault
cat >> config.yaml << EOF
storage:
type: "vault"
vault:
url: "http://host.docker.internal:8200"
token: "\${VAULT_TOKEN}"
mount_point: "secret"
path_prefix: "mcp-gateway"
EOF
# 使用Vault运行网关
docker run -p 8080:8080 \
-v $(pwd)/config.yaml:/app/config.yaml \
-e GOOGLE_CLIENT_ID="your-google-client-id" \
-e GOOGLE_CLIENT_SECRET="your-google-client-secret" \
-e VAULT_TOKEN="myroot" \
ghcr.io/akshay5995/mcp-oauth-gateway:latest
GET /.well-known/oauth-authorization-server - 服务器元数据GET /.well-known/oauth-protected-resource - 资源元数据GET /oauth/authorize - 授权端点POST /oauth/token - 令牌端点POST /oauth/register - 动态客户端注册GET /services - 列出可用服务GET /services/{service-id} - 获取服务信息ALL /{service-id}/mcp - MCP服务代理GET / - 网关信息GET /health - 健康检查# 安装测试依赖(已包含在requirements.txt中)
pip install pytest pytest-asyncio pytest-httpx
# 运行所有测试
pytest tests/
# 运行带覆盖率的测试
pytest tests/ --cov=src
# 运行特定测试文件
pytest tests/test_oauth_server.py -v
# 格式化和检查代码
ruff check src/ demo/ --fix
ruff format src/ demo/
MCP_CONFIG_PATH - 配置文件路径MCP_GATEWAY_HOST - 主机覆盖MCP_GATEWAY_PORT - 端口覆盖MCP_DEBUG - 调试模式GOOGLE_CLIENT_ID - Google OAuth客户端IDGOOGLE_CLIENT_SECRET - Google OAuth客户端密钥GITHUB_CLIENT_ID - GitHub OAuth客户端IDGITHUB_CLIENT_SECRET - GitHub OAuth客户端密钥OKTA_CLIENT_ID - Okta OAuth客户端IDOKTA_CLIENT_SECRET - Okta OAuth客户端密钥OKTA_DOMAIN - Okta域(例如,dev-123.okta.com)REDIS_HOST - Redis服务器主机REDIS_PORT - Redis服务器端口REDIS_PASSWORD - Redis认证密码REDIS_SSL - 启用Redis SSL(true/false)VAULT_URL - Vault服务器URLVAULT_TOKEN - Vault认证令牌VAULT_MOUNT_POINT - Vault KV挂载点VAULT_PATH_PREFIX - Vault秘密路径前缀选择适合您部署的适当存储后端:
storage:
type: "memory"
✅ 最佳适用:开发、测试、单实例演示
❌ 限制:重启时数据丢失,仅限单实例
storage:
type: "redis"
redis:
host: "${REDIS_HOST:-localhost}"
port: 6379
password: "${REDIS_PASSWORD}"
ssl: true
max_connections: 20
✅ 最佳适用:生产部署、水平扩展
✅ 特性:持久存储、多实例支持、连接池
✅ 兼容性:使用现代redis-py库以支持Python 3.11+
storage:
type: "vault"
vault:
url: "${VAULT_URL}"
token: "${VAULT_TOKEN}"
mount_point: "secret"
path_prefix: "mcp-gateway"
auth_method: "token" # 或"approle", "kubernetes"
✅ 最佳适用:企业环境、合规需求
✅ 特性:静态加密、审计日志、细粒度访问控制
网关实现了清晰的关注点分离:
📖 查看完整架构文档
遇到问题?查阅故障排除指南:
📚 故障排除指南 - 包括常见问题及其解决方案:
MIT许可 - 查看LICENSE文件以获取详情。