FastMCP + Cognito OAuth + 密钥认证
这是一个在AWS Lambda上运行FastMCP,并集成了Cognito托管登录和密码密钥认证的MCP服务器的示例项目。
概要
此项目是一个集以下技术于一体的端到端的示例:
- FastMCP用Python编写的高速MCP服务器框架
- FastMCP OIDC代理自动整合符合OIDC标准的OAuth 2.0认证的代理
- AWS Cognito(亚马逊网络服务身份验证与用户管理服务)全托管认证服务
- 管理登录托管于Cognito的认证用户界面(支持密码密钥)
- AWS Lambda无服务器执行环境(Python 3.12)
- 曼古姆用于在Lambda上运行ASGI应用程序的适配器
- AWS CDK(Amazon Web Services Cloud Development Kit,亚马逊网络服务云开发工具包)通过基础设施即代码自动部署资源
项目构成
.
├── sample-oauth-lambda-mcp.ts # CDKアプリケーションエントリーポイント
├── stack/
│ ├── main-stack.ts # MainStack(Cognito、Lambda、Function URL)
│ └── update-stack.ts # UpdateStack(Custom Resourceで設定更新)
├── lambda/
│ ├── main.py # FastMCPサーバー実装
│ ├── pyproject.toml # Python依存関係
│ └── .env.example # 環境変数テンプレート
├── package.json # Node.js依存関係
└── cdk.json # CDK設定CDK堆栈配置
该项目由两个堆栈组成:
- MainStack(可译为“主栈”或根据上下文具体含义翻译,但在此直接保留原英文形式以体现其技术或品牌名称的特性) (
SampleOauthLambdaMcpStack)
- Cognito User Pool(支持密码密钥认证) - Cognito 用户池域名(托管登录) - 用户池客户端(OAuth设置) - Lambda 函数(FastMCP 服务器) - 函数URL(HTTPS终端节点)
- 更新堆栈 (
SampleOauthLambdaMcpUpdateStack)
- 自定义资源:获取客户端密钥 - 自定义资源:更新回调URL - 自定义资源:更新Lambda环境变量 - 依赖MainStack顺序执行
主要功能
Cognito集成(使用CDK自动构建)
- 用户池在ESSENTIALS及以上套餐中支持Passkey认证
- 受管理的登录域可定制的认证用户界面
- 应用程序客户端启用ALLOW_USER_AUTH流程
- OAuth 2.0授权码模式(支持PKCE)
密码密钥认证
- 基于WebAuthn的无密码认证
- 支持生物识别(指纹、面部识别)或安全密钥
- 具有高钓鱼攻击抵抗力的安全认证方式
FastMCP OIDC代理
- 通过OIDC发现自动与Cognito集成
- OAuth认证流程的自动化处理
- JWT(ID令牌)验证与会话管理
- 与MCP客户端的透明集成
- 支持动态客户端注册(DCR)
快速启动
前提条件
- Node.js 18及以上版本
- Python 3.12
- AWS CLI已配置
- AWS CDK CLI(
npm install -g aws-cdk)
部署
# 依存関係のインストール
npm install
# Pythonの依存関係をインストール
cd lambda
uv sync
cd ..
# CDKブートストラップ(初回のみ)
npx cdk bootstrap
# CDKのビルド
npm run build
# 両方のスタックを順番にデプロイ
npx cdk deploy --all
# または個別にデプロイ(MainStackが先に完了してからUpdateStackが実行される)
npx cdk deploy SampleOauthLambdaMcpStack
npx cdk deploy SampleOauthLambdaMcpUpdateStack部署后的输出
部署完成后,将以以下JSON格式输出设置信息:
{
"mcpServerUrl": "https://xxxx.lambda-url.ap-northeast-1.on.aws/mcp",
"userPoolId": "ap-northeast-1_XXXXXXXXX",
"userPoolClientId": "xxxxxxxxxxxxxxxxxxxx",
"cognitoDomain": "mcp-oauth-xxx-xxx.auth.ap-northeast-1.amazoncognito.com",
"region": "ap-northeast-1",
"loginUrl": "https://mcp-oauth-xxx-xxx.auth.ap-northeast-1.amazoncognito.com/login?...",
"callbackUrl": "https://xxxx.lambda-url.ap-northeast-1.on.aws/oauth2/callback"
}将输出保存到文件:
cdk deploy --all --outputs-file outputs.json或者,部署后获取:
# MainStackから設定情報を取得
aws cloudformation describe-stacks \
--stack-name SampleOauthLambdaMcpStack \
--query 'Stacks[0].Outputs[?OutputKey==`Config`].OutputValue' \
--output text | jq .
# UpdateStackの状態を確認
aws cloudformation describe-stacks \
--stack-name SampleOauthLambdaMcpUpdateStack \
--query 'Stacks[0].Outputs'架构
┌─────────────┐
│ MCP Client │
└─────┬───────┘
│
▼
┌─────────────────────┐
│ Lambda Function URL │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ FastMCP Server │
│ (with OAuthProxy) │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Cognito User Pool │
│ (Managed Login + │
│ Passkey Auth) │
└─────────────────────┘认证流程
- MCP客户端向服务器发出请求
- 检测到FastMCP OIDCProxy未认证
- OIDCProxy自动处理客户端注册(DCR)
- 重定向到Cognito托管登录
- 用户通过密码密钥或密码进行认证
- 认证成功后,将重定向至回调URL
- OIDCProxy使用Cognito的JWKS来验证令牌
- 会话建立,允许访问MCP服务器
使用方法
用户创建
# デプロイ後の出力からuserPoolIdを取得
USER_POOL_ID=$(cat outputs.json | jq -r '.SampleOauthLambdaMcpStack.Config | fromjson | .userPoolId')
# ユーザーを作成
aws cognito-idp admin-create-user \
--user-pool-id $USER_POOL_ID \
--username testuser \
--user-attributes Name=email,Value=test@example.com \
--temporary-password TempPass123!密钥认证测试
# ログインURLを取得
LOGIN_URL=$(cat outputs.json | jq -r '.SampleOauthLambdaMcpStack.Config | fromjson | .loginUrl')
# ブラウザで開く
open $LOGIN_URL在Managed Login的用户界面注册密码密钥后,下次即可无需密码直接登录。
从MCP客户端连接
# MCPサーバーURLを取得
MCP_URL=$(cat outputs.json | jq -r '.SampleOauthLambdaMcpStack.Config | fromjson | .mcpServerUrl')
# MCPクライアント設定に追加
echo $MCP_URLFastMCP的OIDCProxy会自动处理认证流程。
限制事项
客户信息的持久化
在当前的实现中,MCP客户端的注册信息已传至Lambda/tmp已保存至目录:
限制:
- 在Lambda冷启动时
/tmp数据丢失 - 虽然成功率高,但在完全冷启动时可能会失败
- 令牌过期后重新认证时,如果数据已消失则需要重新注册
动作:
- 冷启动→MCP客户端
/register进行调用/tmp进行保存 - 热启动 →
/tmp数据保持正常 → 正常运行 - 完全冷启动(容器循环后)→ 数据丢失 → 需重新注册
建议的改进:
在生产环境中,建议将数据迁移到以下持久性存储:
- DynamoDB最推荐(低成本、高可用性)
# カスタムDynamoDBStorageクラスを実装
client_storage = DynamoDBStorage(table_name="oauth-mcp-clients")- S3简单实现(延迟稍高)
client_storage = S3Storage(bucket_name="oauth-mcp-clients")无论哪种情况JSONFileStorage只需替换它,无需更改其他代码。
故障排除
“未找到客户端ID”错误
若Lambda冷启动后出现认证错误:
{"error":"invalid_request","error_description":"Client ID 'xxx' not found"}原因: /tmp客户端注册信息丢失
解决方法:
- 在MCP客户端清除缓存
- 重新连接(自动重新注册)
未显示密码密钥认证
- 确认用户池的计划为ESSENTIALS及以上
- 在应用程序客户端中
ALLOW_USER_AUTH确认其有效性 - 确认浏览器支持WebAuthn
令牌验证错误
# CloudWatch Logsでエラーログを確認
aws logs tail /aws/lambda/SampleOauthLambdaMcpStack-McpServerFunction --follow- 确认环境变量已正确设置
- 确认令牌未过期
- OIDCProxy将使用Cognito的JWKS自动进行验证
部署错误
# 全スタック削除
cdk destroy --all
# 再デプロイ
cdk deploy --all若发生栈间依赖关系错误时:
# UpdateStackを先に削除
cdk destroy SampleOauthLambdaMcpUpdateStack
# MainStackを削除
cdk destroy SampleOauthLambdaMcpStack
# 再デプロイ
cdk deploy --all关于安全的注意事项
此样本为开发和验证用途。如需在生产环境中使用,请考虑以下事项:
- 秘密管理将客户端密钥保存到AWS Secrets Manager
- 资源政策将移除策略更改为保留
- 日志CloudWatch Logs的保留期设置
- 监测CloudWatch报警和X-Ray追踪
- WAF(Web Application Firewall,网络应用防火墙)通过API Gateway或CloudFront启用WAF
CDK命令
# TypeScriptをコンパイル
npm run build
# 変更を監視
npm run watch
# CloudFormationテンプレートを生成(全スタック)
npx cdk synth
# 特定のスタックをシンセサイズ
npx cdk synth SampleOauthLambdaMcpStack
# デプロイ前に差分を確認
npx cdk diff --all
# 全スタックをデプロイ
npx cdk deploy --all
# 個別にデプロイ
npx cdk deploy SampleOauthLambdaMcpStack
npx cdk deploy SampleOauthLambdaMcpUpdateStack
# 全スタックを削除(UpdateStackから先に削除される)
npx cdk destroy --all
# 個別に削除(逆順で削除する必要がある)
npx cdk destroy SampleOauthLambdaMcpUpdateStack
npx cdk destroy SampleOauthLambdaMcpStack参考资料
许可证
此项目为示例代码。请随意使用和修改。
