Token导航 LogoToken导航TokenDH.com
self hosted oauth MCP logo
安全风控stdio官方级别未说明来源级核验

self hosted oauth MCP

MCP Server

一个自托管的MCP服务器,支持OAuth 2.0认证,使用Keycloak作为身份提供者,适用于需要自主控制基础设施的场景。

工具数

2

提示词数

0

GitHub Stars

0

资源数

0
自托管Python安全

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

OhadRubin

提供方

OhadRubin

最后核验

2026/5/17 20:21

运行时

Python

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

命令预览

uv run python client.py

详细介绍

自托管OAuth MCP服务器

一个自托管的MCP(模型上下文协议)服务器,使用Keycloak作为身份提供者进行OAuth 2.0身份验证。此设置允许您完全在自己的基础设施上运行受OAuth保护的MCP服务器,并支持动态URL(ngrok、反向代理等)。

特性

  • 使用PKCE的完整OAuth 2.0授权代码流
  • 动态客户端注册(DCR)支持
  • 适用于ngrok和其他反向代理
  • Keycloak作为身份提供者
  • FastMCP发行JWT代币
  • 预配置的测试用户和客户端

建筑

┌─────────────┐      ┌─────────────────┐      ┌──────────────────┐
│   Client    │─────▶│  nginx (:9000)  │─────▶│  mcp-server      │
│             │      │                 │      │  (:8007)         │
└─────────────┘      │  /mcp ──────────┼─────▶│  FastMCP + OAuth │
                     │                 │      └──────────────────┘
                     │  /realms/* ─────┼─────▶┌──────────────────┐
                     │  /authorize     │      │  Keycloak        │
                     │  /token         │      │  (:9090)         │
                     └─────────────────┘      └──────────────────┘
  • 引擎X:端口9000上的反向代理,路由MCP流量和OAuth端点
  • 钥匙斗篷:OAuth 2.0/OpenID连接身份提供者
  • mcp服务器:带有DynamicOIDCProxy的FastMCP服务器,用于URL感知身份验证

先决条件

  • Docker和Docker Compose
  • Python 3.11+(用于本地开发/测试)
  • 紫外线 (Python包管理器)

快速开始

  1. 启动服务:
   docker compose up -d
  1. 等待初始化 (大约需要30秒):
   docker compose logs -f keycloak-init

init服务会自动配置Keycloak并将凭据写入 .env.

  1. 使用预先生成的令牌进行测试:
   uv run python client.py
  1. 使用完整的OAuth流程进行测试:
   uv run python oauth_client.py http://localhost:9000

配置

默认凭据

设置
领域mcp
客户端IDmcp-server
测试用户user / password
管理控制台http://localhost:9090 (admin / admin)

环境变量

keycloak-init 服务创建了一个 .env 文件包含:

变量描述
KEYCLOAK_CLIENT_IDOAuth客户端ID
KEYCLOAK_CLIENT_SECRETOAuth客户端密钥(自动生成)
MCP_TOKEN预先生成的JWT访问令牌用于测试

服务器环境变量

变量默认值描述
KEYCLOAK_URLhttp://localhost:9090JWKS的内部密钥斗篷URL
KEYCLOAK_PUBLIC_URLhttp://nginx:80通过nginx创建密钥斗篷URL
KEYCLOAK_REALMmcpKeycloak领域名称
KEYCLOAK_CLIENT_IDmcp-serverOAuth客户端ID

用法

选项1:直接令牌身份验证

使用来自的预生成令牌 .env:

import asyncio
from fastmcp import Client
from dotenv import load_dotenv
import os

load_dotenv()

async def main():
    async with Client(
        "http://localhost:9000/mcp",
        auth=os.getenv("MCP_TOKEN"),
    ) as client:
        tools = await client.list_tools()
        print("Tools:", [t.name for t in tools])

        result = await client.call_tool("hello", {"name": "World"})
        print(result.content[0].text)

asyncio.run(main())

选项2:完整的OAuth流程

运行执行完整授权代码流的OAuth客户端:

uv run python oauth_client.py http://localhost:9000

这将:

  1. 发现OAuth端点
  2. 注册为动态客户端
  3. 打开浏览器进行用户登录(使用 user / password)
  4. 代币的交换授权码
  5. 使用访问令牌调用MCP工具

接触互联网(ngrok)

要与外部客户端一起使用或测试来自不同来源的OAuth流:

  1. 开始ngrok:
   ngrok http 9000
  1. 使用ngrok URL进行测试:
   uv run python oauth_client.py https://your-subdomain.ngrok-free.app

服务器自动检测来自的公共URL X-Forwarded-* 并相应地调整所有OAuth URL。

端点

端点描述
/mcpMCP服务器(可流式传输http)
/.well-known/oauth-authorization-serverOAuth服务器元数据
/.well-known/oauth-protected-resource/mcp受保护的资源元数据
/authorizeOAuth授权端点
/tokenOAuth令牌端点
/register动态客户端注册
/realms/mcp/...Keycloak OIDC端点(代理)
/debug显示请求标头的调试端点

MCP工具

服务器提供了两个示例工具:

  • 你好(姓名:str):返回问候语(hello, {name})
  • add(a:int,b:int):将两个数字相加

项目结构

.
├── docker-compose.yml    # Service orchestration
├── Dockerfile            # MCP server container
├── nginx.conf            # Reverse proxy configuration
├── server.py             # FastMCP server with DynamicOIDCProxy
├── client.py             # Simple test client (uses pre-generated token)
├── oauth_client.py       # Full OAuth flow test client
├── setup_keycloak.py     # Keycloak configuration script
├── realm-export.json     # Keycloak realm import config
├── pyproject.toml        # Python dependencies
└── .env                  # Generated credentials (gitignored)

发展

本地设置

# Install dependencies
uv sync

# Run server locally (requires Keycloak running in Docker)
uv run python server.py

重建MCP服务器

docker compose build mcp-server
docker compose up -d mcp-server

查看日志

# All services
docker compose logs -f

# Specific service
docker compose logs -f mcp-server
docker compose logs -f keycloak

重置所有内容

docker compose down -v
rm -f .env
docker compose up -d

运作原理

动态OIDC代理

服务器使用自定义 DynamicOIDCProxy 扩展FastMCP的类 OIDCProxy 要支持动态URL,请执行以下操作:

  1. 动态URL检测:从中提取公共URL X-Forwarded-ProtoX-Forwarded-Host 标头
  2. URL重写中间件:在响应中将内部URL(nginx、keycloak、localhost)重写为公共URL
  3. 动态代币交换:使用检测到的公共URL进行OAuth令牌交换redirect_uri
  4. 灵活的令牌验证:跳过发行者验证,以支持使用不同公共URL发行的令牌

OAuth流

  1. 客户端从以下位置发现OAuth端点 /.well-known/oauth-authorization-server
  2. 客户端通过以下方式动态注册 /register
  3. 客户端将用户重定向到 /authorize PKCE挑战
  4. 用户使用Keycloak进行身份验证
  5. Keycloak重定向回MCP服务器 /auth/callback
  6. MCP服务器与Keycloak交换代码并发出FastMCP JWT
  7. 客户端通过以下方式交换FastMCP令牌的授权码 /token
  8. 客户端使用访问令牌调用MCP工具

故障排除

“不记名代币被拒绝”

  • 检查Keycloak是否正常: docker compose ps
  • 查看令牌验证日志: docker compose logs mcp-server
  • 服务器跳过颁发者验证以获得动态URL支持

“无效的redirect_uri”

  • 确保realm-export.json具有 "redirectUris": ["*"]
  • 更改后重建: docker compose down -v && docker compose up -d

“连接被拒绝”

  • 等待所有服务启动: docker compose ps
  • 检查Keycloak健康状况: curl http://localhost:9090/health

与ngrok的代币交换失败

  • 确保nginx正在转发X-Forwarded标头
  • 检查调试终结点: curl https://your-ngrok-url/debug

安全说明

  • 默认配置使用开发设置(无SSL,简单密码)
  • 生产:

- 通过nginx启用HTTPS - 使用强凭据 - 考虑使用固定的公共URL启用颁发者验证 - 查看Keycloak安全设置

  • .env 文件包含机密,不应提交

许可证

麻省理工学院

目录标签

目录标签

自托管Python安全本地部署OAuth2.0身份认证KeycloakMCP协议

接入字段

传输方式(transport,传输协议)

stdio

鉴权方式(authType,认证方式)

oauth

运行时(runtime,运行环境)

Python

工具数量(toolCount,工具数)

2

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

stdiooauth部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

来源信息

继续浏览同类 MCP