MCP授权演示

一个实现Model Context Protocol (MCP)授权流程的概念验证,包含MCP服务器和客户端,支持动态客户端注册(DCR)、OAuth授权/令牌端点以及基于SSE的MCP传输。

  • by florenm2
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 florenm2/mcp-auth-demo

使用说明

MCP认证演示

模型上下文协议(MCP)授权流的概念验证实现,其特征是:

  • MCP服务器 (server/)公开动态客户端注册(DCR)、OAuth授权/令牌端点以及由承载令牌保护的基于SSE的MCP传输。
  • MCP客户端 (client/)它通过DCR自动进行自我注册,执行OAuth流,缓存凭据/令牌,并连接到服务器以使用经过身份验证的工具。

先决条件

  • Node.js≥18
  • npm

框架和关键版本

库/工具 版本 角色/基本原理
快速 ^5.1.0 轻量级HTTP框架,用于快速连接OAuth端点和SSE传输。v5为我们提供了开箱即用的异步处理程序支持。
@模型上下文协议/sdk ^1.22.0 提供规范的MCP服务器+客户端实现和传输助手,这样我们就可以在不重建协议栈的情况下保持规范合规性。
萨德 ^3.25.76 DCR/OAuth有效载荷和工具模式的运行时验证;明确错误消息。
TypeScript ^5.9.3 确保跨服务器和客户端的严格键入,以提高身份验证流的安全性。
TSX ^4.20.6 用于本地开发脚本的零配置TS/ESM运行器(dev:server, dev:client).

安装

npm install

运行服务器

npm run dev:server

默认值:

  • 基本URL: http://localhost:3333
  • 自动注册两个工具:
    • whoami:返回调用者的MCP上下文。
    • read-secret:返回受保护的秘密,需要 secret.read 范围。

环境变量(可选):

变量 描述 默认值
PORT 服务器端口 3333
PUBLIC_BASE_URL 外部基础URL(用于元数据+OAuth响应) http://localhost:${PORT}
SERVER_SECRET 返回的值 read-secret demo-mcp-secret
DEMO_USER_ID / DEMO_USER_NAME 授权过程中使用的模拟用户身份 demo-user / Demo User

运行客户端

npm run dev:client

发生了什么:

  1. 支票 .mcp-auth/clients.json 对于每个基本URL的现有注册。如果缺失/无效,请通过以下方式注册新客户端 /dcr/register.
  2. 在中查找有效的缓存访问令牌 .mcp-auth/tokens.json。如果过期或丢失,则运行OAuth授权+令牌交换流(使用 prompt=auto 以及手动重定向处理,因此不需要浏览器交互)。
  3. 通过以下方式连接到MCP服务器 SSEClientTransport,列出工具、调用 whoami,然后呼叫 read-secret (如果范围可用)。

CLI会自动从过时的客户端注册中恢复(例如,如果服务器重新启动并忘记了以前的客户端ID)。

客户端环境变量:

变量 描述 默认值
SERVER_BASE_URL MCP服务器的基本URL http://localhost:3333
CLIENT_REDIRECT_URI 重定向OAuth期间使用的URI http://localhost:4321/callback
CLIENT_SCOPES DCR/OAuth期间请求的范围 mcp:invoke secret.read
CLIENT_STORAGE_DIR 缓存凭据的根目录 ${PWD}/.mcp-auth
CLIENT_STORAGE_PATH 覆盖缓存客户端注册的路径 ${CLIENT_STORAGE_DIR}/clients.json
TOKEN_STORAGE_PATH 覆盖缓存令牌的路径 ${CLIENT_STORAGE_DIR}/tokens.json
TOKEN_LEEWAY_MS 重用缓存令牌之前的过期余地 60000 (1分钟)

⚠️ .mcp-auth/ 被git忽略;删除它以强制进行新的注册和令牌。

通过curl/Postman进行手动测试

如果需要,您可以手动驱动每个步骤:

  1. 动态条件响应: POST /dcr/register 使用JSON有效载荷进行接收 client_id + client_secret.
  2. 授权: GET /oauth/authorize?client_id=...&response_type=code&prompt=auto... 并检查要捕获的重定向URL code.
  3. 代币交换: POST /oauth/token (表格编码)带有授权码。
  4. 主控程序:使用 access_token 在 Authorization: Bearer ... 要调用的标头 GET /mcp (成立苏格兰和南方能源公司)以及 POST /mcp/messages?sessionId=... 用于JSON-RPC请求。

测试指导

仅服务器检查

  1. 健康+元数据
    curl http://localhost:3333/healthz
    curl http://localhost:3333/.well-known/oauth-authorization-server
    
  2. DCR验证
    curl http://localhost:3333/dcr/register \
      -H "Content-Type: application/json" \
      -d '{"client_name":"curl-test","redirect_uris":["http://localhost:9999/callback"],"scope":"mcp:invoke"}'
    
  3. OAuth流(手动)
    • 击打 /oauth/authorize?client_id=...&response_type=code&prompt=auto...
    • 交换代码通过 /oauth/token.
  4. 受保护的MCP端点
    • GET /mcp 和 POST /mcp/messages 使用承载令牌确保授权中间件正常工作。

仅限客户检查

  1. 清除缓存: rm -rf .mcp-auth
  2. 跑 npm run dev:client
    • 验证它是否注册、授权和打印工具响应。
  3. 再次运行以确认缓存的客户端+令牌重用。
  4. (可选)删除 .mcp-auth/clients.json 仅用于确认重新注册处理。

完整的端到端测试

  1. npm run dev:server
  2. 在另一个终端中: npm run dev:client
  3. 确认日志显示工具列表, whoami,以及 read-secret 输出。
  4. (可选)使用已发布的命令通过curl/Postman驱动其他工具调用 access_token.

回购结构

server/
  auth.ts          # In-memory DCR + OAuth storage + bearer middleware
  index.ts         # Express app exposing OAuth + MCP endpoints/tools
client/
  app.ts           # CLI entry point
  config.ts        # Configuration & environment defaults
  dcr.ts           # Client registration logic
  oauth.ts         # Authorization-code flow
  tokenManager.ts  # Token caching & refresh heuristics
  mcp.ts           # SSE client transport & demo tool invocations
  storage.ts       # File-based persistence helpers
  utils/           # Logging + HTTP helpers

未来的增强功能

  • 用于任意工具调用的交互式CLI命令。
  • 基于浏览器的OAuth,带有PKCE和嵌入式环回回调服务器。
  • 持久刷新令牌/长期会话。
  • 涵盖整个DCR的自动化测试→ OAuth→ MCP往返。

您可以随意调整范围、添加新工具或将客户端指向远程托管的MCP服务器,以尝试企业风格的部署。