mcp-oauth-test
Servidor FastMCP OIDC
Este es un servidor MCP protegido por inicio de sesión OIDC, escrito con FastMCP. Utiliza el OIDCProxy de FastMCP: el cliente MCP completa la autenticación a través de los metadatos OAuth expuestos por el servidor, y el inicio de sesión real y el intercambio de tokens se reenvían al proveedor OIDC de QA.
Actualmente está integrado con la API abierta MGT de QA, generando herramientas MCP relacionadas con trainees, pedidos, productos, clientes, reclutamiento en campus y reclutamiento internacional.
La dirección de descubrimiento OIDC ya está configurada por defecto como:
https://auth-qa.drillinsight.com/.well-known/openid-configurationPreparación de autenticación
Primero registra una aplicación OAuth en auth-qa.drillinsight.com y añade la siguiente dirección de callback a la lista blanca:
http://localhost:8000/auth/callbackAl desplegar en otra dirección, reemplaza http://localhost:8000 por el valor de BASE_URL. La dirección de callback debe coincidir exactamente con el BASE_URL de FastMCP.
Ejecución local
cp .env.example .env
# 编辑 .env,至少填写 OIDC_CLIENT_ID 和 OIDC_CLIENT_SECRET
uv sync
uv run mcp-oidc-serverTambién puedes ejecutar el módulo directamente:
uv run python -m oidc_mcp_server.serverEl servicio escucha por defecto en http://127.0.0.1:8000. Si el cliente MCP se ejecuta en otra máquina o en un contenedor, configura un BASE_URL accesible para el cliente y un HOST adecuado (por ejemplo, 0.0.0.0).
Plugin para Claude Code
El repositorio incluye un marketplace privado de Claude Code y un plugin MCP:
.claude-plugin/marketplace.json
└── plugins/mcp-oauth-test/
├── .claude-plugin/plugin.json
├── .mcp.json
└── README.mdEl plugin solo se encarga de conectar Claude Code al servicio MCP remoto ya desplegado; no inicia el servicio Python localmente. Para pruebas de desarrollo, puedes cargarlo directamente:
claude --plugin-dir ./plugins/mcp-oauth-testEl plugin está fijado para conectarse al servidor MCP del entorno de desarrollo:
https://api-mcp-oauth-dev.beaconfireinc.com/mcpTambién puedes instalarlo desde el marketplace privado:
/plugin marketplace add /path/to/mcp-oauth-test
/plugin install mcp-oauth-test@authsome-internalLa raíz del marketplace actual es la raíz del repositorio. Mantén este marketplace en un repositorio privado de GitHub de la empresa; no lo envíes a un marketplace público. Los entornos compartidos deben usar direcciones HTTPS y restringir el acceso a usuarios de la empresa tanto en el IdP corporativo como en el lado del servidor MCP.
Por qué usar OIDCProxy
El upstream auth-qa.drillinsight.com no necesita soportar DCR ni CIMD. OIDCProxy está diseñado precisamente para este escenario:
ChatGPT ── MCP OAuth / CIMD ──> FastMCP OIDCProxy
│
└── 固定 client_id/client_secret ──> auth-qa.drillinsight.comLo único que hay que registrar previamente en el upstream es la aplicación OAuth de FastMCP, y configurar ${BASE_URL}/auth/callback. El CIMD utilizado por ChatGPT lo gestiona la capa de proxy de FastMCP y no se reenvía al servidor OAuth upstream.
Configuración CIMD para ChatGPT
Al crear un MCP personalizado en ChatGPT, en la configuración avanzada de OAuth, en "Registro de clientes", selecciona:
客户端标识元数据文档(CIMD)La información que genera el conector de ChatGPT actualmente es:
CIMD Client ID / 客户端元数据 URL:
https://chatgpt.com/oauth/0Buhw3sHVv1-/client.json
ChatGPT Callback URL:
https://chatgpt.com/connector/oauth/0Buhw3sHVv1-La URL CIMD es en sí misma el client_id que ChatGPT utiliza al acceder al proxy OAuth de FastMCP. No necesita, ni debe, registrarse en el upstream auth-qa.drillinsight.com.
Este proyecto tiene dos niveles diferentes de ID de cliente OAuth:
Cadena OAuth |
| Ubicación de configuración |
ChatGPT → FastMCP OIDCProxy |
| Lo proporciona ChatGPT automáticamente; no es necesario rellenarlo manualmente al seleccionar CIMD |
FastMCP OIDCProxy → |
|
|
El flujo de datos correspondiente es:
ChatGPT
│ client_id=https://chatgpt.com/oauth/0Buhw3sHVv1-/client.json
▼
FastMCP OIDCProxy
│ client_id=app_74a4b555-5b87-4212-9dda-d584fa78caf8
▼
auth-qa.drillinsight.comConfiguración de variables de entorno del servidor MCP:
OIDC_CLIENT_ID=app_74a4b555-5b87-4212-9dda-d584fa78caf8
OIDC_CLIENT_SECRET=<上游 OAuth Server 颁发的客户端密钥>El servidor OAuth upstream solo necesita configurar la dirección de callback de FastMCP para la aplicación app_...:
https://heroic-verbally-crawdad.ngrok-free.app/auth/callbackNo configures la dirección de callback de ChatGPT https://chatgpt.com/connector/oauth/... en el servidor OAuth upstream; esa dirección la utiliza la capa de proxy de FastMCP después de completar la autenticación.
Al iniciar la autenticación, en los registros normales debería aparecer primero el ID de cliente CIMD de ChatGPT:
CIMD document fetched and validated
GET /authorize?client_id=https://chatgpt.com/oauth/.../client.json ... 302Después, FastMCP usará app_74a4b555-... para redirigir al servidor OAuth upstream.
Configuración del cliente MCP
Configura la dirección MCP como:
http://localhost:8000/mcpFastMCP proporcionará las siguientes direcciones de descubrimiento de autenticación:
http://localhost:8000/.well-known/oauth-authorization-server
http://localhost:8000/.well-known/oauth-protected-resource/mcpEl cliente debería leer automáticamente estos endpoints de descubrimiento MCP/OAuth. Tras iniciar sesión correctamente, se pueden invocar dos herramientas protegidas:
ping: comprobación de estado.who_am_i: devuelve elclient_id, los scopes y los claims que FastMCP extrae del token de autenticación actual.
Opciones de configuración
Variable de entorno | Requerida | Valor por defecto | Descripción |
| Sí | - | ID de cliente OIDC upstream |
| Una de las dos | - | Secreto de cliente confidencial |
| Una de las dos | - | Cliente PKCE público o clave de firma de tokens FastMCP en producción |
| No | URL de descubrimiento de QA | Dirección de descubrimiento OIDC |
| No |
| Dirección pública del servidor MCP |
| No |
| Scope para la solicitud de autorización OAuth/anuncio por defecto; no se usa para la validación de scopes del token de acceso |
| No | Issuer del descubrimiento OIDC | Valor de validación de |
| No |
| Dirección JWKS para emisores de tokens personalizados |
| No | - | Valor de validación opcional de |
| No |
| Dirección de escucha |
| No |
| Puerto de escucha |
| No | Dirección MGT de QA | URL base real de llamada a la API MGT |
| No |
| Ruta local del spec OpenAPI |
En producción, configura explícitamente un JWT_SIGNING_KEY aleatorio y usa un BASE_URL con HTTPS. No envíes .env ni ningún secreto de cliente a Git.
Emisor de tokens personalizado
Si el iss del token no es el issuer devuelto por el descubrimiento OIDC, sino que el middleware de autenticación lo reescribe a una dirección de tenant, por ejemplo:
实际 token iss:
https://api-authsome-qa.drillinsight.com/auth-middleware/t_adecdb63-afab-4346-a1aa-b50bbbae7aee/Configura:
OIDC_TOKEN_ISSUER=https://api-authsome-qa.drillinsight.com/auth-middleware/t_adecdb63-afab-4346-a1aa-b50bbbae7aee/
OIDC_JWKS_URI=https://auth-qa.drillinsight.com/oauth/jwksOIDC_CONFIG_URL se sigue usando para el descubrimiento de los endpoints de inicio de sesión y autorización OAuth; OIDC_TOKEN_ISSUER se usa únicamente para la validación de iss del token de acceso JWT. Ambos pueden ser diferentes. OIDC_TOKEN_ISSUER debe coincidir exactamente con el iss del token, incluida la / final.
El proyecto actual no valida el claim scope ni scp del token de acceso, porque los tokens históricos de MGT usan un formato de scope no estándar. OIDC_REQUIRED_SCOPES se sigue usando para la solicitud de autorización OAuth, pero no bloquea tokens válidos que carezcan del claim de scope estándar. La validación de firma, issuer, audiencia, tiempo de expiración y JWKS se mantiene.
Integración con la API abierta MGT de QA
El spec OpenAPI de QA se ha guardado fijado en:
specs/mgt-qa-openapi.jsonMCP no accede a /api-docs en línea durante la ejecución, por lo que en el futuro, si el entorno de producción no expone la documentación de la API, no afectará al funcionamiento. Basta con cambiar la dirección real de la API mediante MGT_API_BASE_URL. La imagen Docker copia specs/mgt-qa-openapi.json a /app/specs/mgt-qa-openapi.json y configura automáticamente MGT_OPENAPI_SPEC_PATH.
El alcance de la API expuesta en la primera versión:
/api/v1/user/current
/course/list
/batch/list
/batch/trainee/list
/equity/userequity/give
/api/v1/order/**
/api/v1/item/**
/api/v1/open/getSku*
/api/v1/customers
/api/v1/campus-recruitment/**(排除 export)
/api/v1/recruitment-info/**(排除 export)La interfaz de enlace de pago de pedidos se integra según los requisitos actuales:
/api/v1/order/queryPayLink
/api/v1/order/reGenaratePayLinkSe siguen excluyendo las interfaces de reembolso, callback de pago y exportación de datos de clientes:
/mall/v1/order/refund
/alipay/**
/stripe/**
/weixin/refund/**
/api/v1/customers/export
/api/v1/campus-recruitment/export
/api/v1/recruitment-info/exportEn cada llamada a MGT, el cliente OpenAPI obtiene el token de acceso OAuth upstream del usuario de la solicitud FastMCP actual y envía:
Authorization: Bearer <user access token>
X-Application-Id: <token.app_id>Donde X-Application-Id no requiere configuración adicional; se lee directamente del claim app_id del JWT ya validado. Los tokens sin app_id se rechazan para evitar enviar solicitudes incompletas a MGT.
Por lo tanto, MGT debe confiar en los tokens de usuario emitidos por auth-qa.drillinsight.com y aplicar el control de permisos según la identidad del usuario.
Diagnóstico de timeout CIMD en ChatGPT
Si los registros contienen:
CIMD fetch failed for https://chatgpt.com/.../client.json: Timeout fetching
Unregistered client_id=https://chatgpt.com/.../client.jsonSignifica que FastMCP no puede acceder directamente a los metadatos del cliente alojados por ChatGPT. Si la máquina actual debe acceder a Internet a través de un proxy de salida de confianza, configura:
FASTMCP_SSRF_TRUST_PROXY=true
HTTPS_PROXY=http://127.0.0.1:7897Luego detén y reinicia el servicio por completo. El programa carga automáticamente el .env de la raíz del proyecto antes de importar FastMCP; FastMCP realiza por defecto validación DNS y fijación de IP para las solicitudes CIMD/JWKS, por lo que no usa automáticamente las variables de entorno de proxy normales. Al activar esta opción, la responsabilidad de protección SSRF se delega al proxy especificado y se ignora NO_PROXY. Solo se puede activar con un proxy de confianza.
El primer POST /mcp 401 en los registros es el cliente sondeando el recurso protegido antes de la autenticación; los 404 para varias direcciones /.well-known/... también son sondeos de compatibilidad de ChatGPT. Mientras /.well-known/oauth-authorization-server devuelva 200, no son la causa de este fallo.
Si los registros muestran Unregistered client_id=app_... u otro ID de cliente que no sea una URL, significa que ChatGPT ha almacenado en caché un registro DCR antiguo que ya se ha perdido del almacenamiento del servidor. Fija JWT_SIGNING_KEY, reinicia el servicio y luego elimina y vuelve a crear el MCP personalizado en ChatGPT para que vuelva a llamar a /register. Solo reintentar el inicio de sesión no recuperará un ID de cliente antiguo desconocido para el servidor.
Pruebas
uv run pytestThis server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for AI access to Swagger by SmartBear.
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
MCP Server for agents to onboard, pay, and provision services autonomously with InFlow
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/beaconfire-projects/mcp-oauth-test'
If you have feedback or need assistance with the MCP directory API, please join our Discord server