OAuth认证演示服务器

一个集成了OAuth认证与MCP功能的演示服务器,使用静态预注册的客户端凭证,适用于开发和调试场景。

  • by TsengX
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 TsengX/mcp-oauth-sample

使用说明

MCP OAuth示例

一个演示服务器,使用静态预注册的客户端凭据将OAuth身份验证与MCP功能集成在一起,非常适合开发和调试目的。

特性

  • ✅ 单端口部署:OAuth和MCP功能在同一端口上运行
  • ✅ 静态客户端注册:使用预先配置的 client_id 和 client_secret
  • ✅ 无动态注册:适用于单客户端使用场景
  • ✅ 易于使用:从以下内容开始 uv 在一个命令中
  • ✅ 生产准备就绪:支持自定义凭据和配置文件

快速开始

先决条件

安装uv

# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Or using Homebrew (macOS)
brew install uv

# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

克隆存储库

git clone https://github.com/TsengX/mcp-oauth-sample.git
cd mcp-oauth-sample

启动服务器

方法1:使用默认设置

# Use default port 9003 and default credentials
uv run python mcp_simple_auth/statically_registered_client_server.py

# Or using uv script command
uv run mcp-static-auth

方法2:自定义端口和凭据

uv run python mcp_simple_auth/statically_registered_client_server.py \
    --port 9003 \
    --client-id "my-client-001" \
    --client-secret "my-secure-secret-12345"

方法3:使用环境变量

export MCP_STATIC_CLIENT_ID="my-client-001"
export MCP_STATIC_CLIENT_SECRET="my-secure-secret"
export MCP_STATIC_PORT=9003

uv run python mcp_simple_auth/statically_registered_client_server.py

服务器端点

启动后,服务器提供以下端点:

  • MCP端点: http://localhost:9003/mcp
  • OAuth授权: http://localhost:9003/authorize
  • OAuth令牌: http://localhost:9003/token
  • 登录页面: http://localhost:9003/login
  • 代币反思: http://localhost:9003/introspect

配置

环境变量

支持的环境变量(含 MCP_STATIC_ 前缀):

  • MCP_STATIC_CLIENT_ID:预先注册的客户ID
  • MCP_STATIC_CLIENT_SECRET:预先注册的客户机密
  • MCP_STATIC_PORT:服务器侦听端口
  • MCP_STATIC_HOST:服务器主机地址

命令行参数

python mcp_simple_auth/statically_registered_client_server.py --help

可用参数:

  • --port:侦听端口(默认值:9003)
  • --client-id:客户端ID(默认值:static-mcp-Client-001)
  • --client-secret:客户端密钥(默认:您的密钥在生产中更改此密钥)

客户端集成

Java客户端示例

public class McpClient {
    // Use the same credentials as server configuration
    private static final String CLIENT_ID = "static-mcp-client-001";
    private static final String CLIENT_SECRET = "your-secret-key-change-this-in-production";
    private static final String SERVER_URL = "http://localhost:9003";
    
    // OAuth endpoints
    private static final String AUTHORIZE_ENDPOINT = SERVER_URL + "/authorize";
    private static final String TOKEN_ENDPOINT = SERVER_URL + "/token";
    private static final String MCP_ENDPOINT = SERVER_URL + "/mcp";
    
    // ... implement OAuth flow
}

使用预先注册的凭据

无需动态注册,直接使用预注册 client_id 和 client_secret:

  1. 请求授权URL: GET /authorize
  2. 用户通过浏览器登录
  3. 获取授权码
  4. 交换令牌: POST /token (使用预先注册的凭据)

OAuth流

流程图

Client                          Server (9003)
  │                                │
  ├── GET /authorize ────────────►│
  │                                │
  │←── Login page URL ────────────┤
  │                                │
  └──► Open browser to login ───►│
  │                                │
  │←── Callback with auth code ───┤
  │    /callback?code=xxx          │
  │                                │
  ├── POST /token ────────────────►│
  │    (using pre-registered creds)│
  │                                │
  │←── access_token ───────────────┤
  │                                │
  ├── Use token to access MCP ───►│
  │    Authorization: Bearer token  │
  │                                │
  │←── MCP Response ───────────────┤

默认凭据

开发环境默认凭据:

  • 客户端ID: static-mcp-client-001
  • 客户端密钥: your-secret-key-change-this-in-production

⚠️ 重要:确保在生产环境中更改这些凭据!

生产部署

生成安全密钥

# Using OpenSSL
openssl rand -hex 32

# Using Python
python3 -c "import secrets; print(secrets.token_hex(32))"

# Using /dev/urandom
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1

启动生产服务器

# Generate random key
CLIENT_SECRET=$(openssl rand -hex 32)

# Start server
uv run python mcp_simple_auth/statically_registered_client_server.py \
    --port 9003 \
    --client-id "prod-mcp-client-001" \
    --client-secret "$CLIENT_SECRET"

安全最佳实践

  1. ✅ 不要在代码中硬编码秘密
  2. ✅ 使用环境变量或秘密管理服务 (例如,AWS Secrets Manager、HashiCorp Vault)
  3. ✅ 旋转 client_secret 定期
  4. ✅ 使用强随机密钥 (至少32个字符)
  5. ✅ 禁用生产中的调试模式

可用工具

服务器提供以下MCP工具:

1. get_time

获取当前服务器时间。

退货:

{
  "current_time": "2024-01-01T12:00:00",
  "timezone": "UTC",
  "timestamp": 1704110400.0,
  "formatted": "2024-01-01 12:00:00"
}

2. echo

回一条消息。

参数: message (字符串) 退货:

{
  "echo": "Hello, World!",
  "length": 13
}

测试

测试OAuth端点

# 1. View authorization server metadata
curl http://localhost:9003/.well-known/oauth-authorization-server

# 2. Try dynamic registration (should fail with 403)
curl -X POST http://localhost:9003/register \
  -H "Content-Type: application/json" \
  -d '{"client_name": "test"}'

# 3. Access login page
open http://localhost:9003/login?state=test123&client_id=static-mcp-client-001

测试MCP功能

# Connect to server using MCP client
# Example using Python SDK
python -c "
from mcp import Client
client = Client('http://localhost:9003/mcp')
# Requires valid OAuth token
"

发展

项目结构

mcp-oauth-sample/
├── mcp_simple_auth/
│   ├── statically_registered_client_server.py  # Main server file
│   ├── simple_auth_provider.py                # OAuth provider
│   └── token_verifier.py                      # Token verifier
├── pyproject.toml                              # Project configuration
└── README.md                                   # This document

添加自定义工具

编辑 mcp_simple_auth/statically_registered_client_server.py:

def create_combined_mcp_server(settings: StaticallyRegisteredSettings) -> FastMCP:
    # ... existing code ...
    
    @app.tool()
    async def my_custom_tool(param: str) -> dict[str, Any]:
        """
        Your custom tool description.
        
        Args:
            param: Description of parameter
        
        Returns:
            Tool result
        """
        return {"result": f"Processed: {param}"}
    
    return app

地方发展

# Install dependencies
uv sync

# Run development server
uv run python mcp_simple_auth/statically_registered_client_server.py --port 9003

# Run tests
uv run pytest

常见问题解答

Q: 为什么要使用静态客户端注册?

**A.**静态注册适用于单客户端生产场景,更简单、更可控,避免了动态注册的复杂性。

Q: 如何支持多个客户?

A.:如果需要支持多个客户端,请考虑使用动态客户端注册,或为每个客户端运行具有不同凭据的多个服务器实例。

Q: 此服务器支持OAuth刷新令牌吗?

A.:当前的实现简化了刷新令牌功能。建议在生产中实现完整的刷新令牌流。

Q: 如何部署到生产环境?

A.:推荐的部署方法:

  1. 使用环境变量进行秘密管理
  2. 配置反向代理(例如Nginx)
  3. 启用HTTPS
  4. 配置防火墙规则
  5. 使用流程管理器(例如systemd、supervisord)

Q: 如何处理令牌过期?

A.:在当前实现中,访问令牌的有效期为3600秒(1小时)。您可以通过修改来调整有效期 expires_at 代码中的参数。

许可证

MIT许可证

贡献

欢迎问题和拉取请求!

致谢

建立在 模型上下文协议(MCP) Python SDK。