mcp-oauth-test
FastMCP OIDC Server
Это MCP-сервер, защищённый входом через OIDC, написанный с использованием FastMCP. Он использует OIDCProxy из FastMCP: MCP-клиент проходит аутентификацию через метаданные OAuth, предоставляемые сервером, а фактический вход и обмен токенами пересылаются в QA OIDC-провайдер.
В настоящее время подключён QA MGT OpenAPI, сгенерированы MCP-инструменты, связанные с трейни, заказами, товарами, клиентами, кампусным наймом и международным наймом.
Адрес обнаружения OIDC по умолчанию настроен как:
https://auth-qa.drillinsight.com/.well-known/openid-configurationПодготовка к аутентификации
Сначала зарегистрируйте OAuth-приложение в auth-qa.drillinsight.com и добавьте следующий адрес обратного вызова в белый список:
http://localhost:8000/auth/callbackПри развёртывании по другому адресу замените http://localhost:8000 на значение BASE_URL. Адрес обратного вызова должен точно совпадать с BASE_URL в FastMCP.
Локальный запуск
cp .env.example .env
# 编辑 .env,至少填写 OIDC_CLIENT_ID 和 OIDC_CLIENT_SECRET
uv sync
uv run mcp-oidc-serverТакже можно запустить модуль напрямую:
uv run python -m oidc_mcp_server.serverСервис по умолчанию прослушивает http://127.0.0.1:8000. Если MCP-клиент работает на другой машине или в контейнере, установите BASE_URL, доступный клиенту, и подходящий HOST (например, 0.0.0.0).
Плагин Claude Code
Репозиторий содержит приватный marketplace Claude Code и MCP-плагин:
.claude-plugin/marketplace.json
└── plugins/mcp-oauth-test/
├── .claude-plugin/plugin.json
├── .mcp.json
└── README.mdПлагин только подключает Claude Code к уже развёрнутому удалённому MCP-сервису и не запускает локально Python-сервис. Для разработки и тестирования можно загрузить его напрямую:
claude --plugin-dir ./plugins/mcp-oauth-testПлагин жёстко подключён к MCP-серверу среды разработки:
https://api-mcp-oauth-dev.beaconfireinc.com/mcpТакже можно установить из приватного marketplace:
/plugin marketplace add /path/to/mcp-oauth-test
/plugin install mcp-oauth-test@authsome-internalТекущий корень marketplace — это корень репозитория. Пожалуйста, храните этот marketplace в приватном GitHub-репозитории компании и не публикуйте его в публичный marketplace. Для общей среды используйте HTTPS-адрес и ограничьте доступ пользователей компании на стороне корпоративного IdP и MCP-сервера.
Почему используется OIDCProxy
Верхнеуровневый auth-qa.drillinsight.com не требует поддержки DCR или CIMD. OIDCProxy предназначен именно для такого сценария:
ChatGPT ── MCP OAuth / CIMD ──> FastMCP OIDCProxy
│
└── 固定 client_id/client_secret ──> auth-qa.drillinsight.comЗаранее на верхнем уровне нужно зарегистрировать только OAuth-приложение FastMCP и настроить ${BASE_URL}/auth/callback. CIMD, используемый ChatGPT, обрабатывается прокси-слоем FastMCP и не пересылается верхнему OAuth-серверу.
Конфигурация ChatGPT CIMD
При создании пользовательского MCP в ChatGPT в расширенных настройках OAuth выберите «Регистрация клиента»:
客户端标识元数据文档(CIMD)Текущая информация, генерируемая коннектором ChatGPT:
CIMD Client ID / 客户端元数据 URL:
https://chatgpt.com/oauth/0Buhw3sHVv1-/client.json
ChatGPT Callback URL:
https://chatgpt.com/connector/oauth/0Buhw3sHVv1-Сам URL CIMD — это client_id, который ChatGPT использует при обращении к OAuth-прокси FastMCP. Его не нужно и не следует регистрировать в верхнем auth-qa.drillinsight.com.
В этом проекте существуют два разных уровня OAuth Client ID:
Цепочка OAuth |
| Место настройки |
ChatGPT → FastMCP OIDCProxy |
| Предоставляется автоматически ChatGPT, после выбора CIMD заполнять вручную не нужно |
FastMCP OIDCProxy → |
|
|
Соответствующий поток данных:
ChatGPT
│ client_id=https://chatgpt.com/oauth/0Buhw3sHVv1-/client.json
▼
FastMCP OIDCProxy
│ client_id=app_74a4b555-5b87-4212-9dda-d584fa78caf8
▼
auth-qa.drillinsight.comКонфигурация переменных окружения MCP-сервера:
OIDC_CLIENT_ID=app_74a4b555-5b87-4212-9dda-d584fa78caf8
OIDC_CLIENT_SECRET=<上游 OAuth Server 颁发的客户端密钥>Верхнему OAuth-серверу достаточно настроить адрес обратного вызова FastMCP для приложения app_...:
https://heroic-verbally-crawdad.ngrok-free.app/auth/callbackНе настраивайте адрес обратного вызова ChatGPT https://chatgpt.com/connector/oauth/... на верхнем OAuth-сервере; этот адрес используется прокси-слоем FastMCP после завершения аутентификации.
В начале аутентификации в обычных журналах сначала должен появиться CIMD Client ID ChatGPT:
CIMD document fetched and validated
GET /authorize?client_id=https://chatgpt.com/oauth/.../client.json ... 302Затем FastMCP использует app_74a4b555-... для перехода на верхний OAuth-сервер.
Конфигурация MCP-клиента
Настройте адрес MCP как:
http://localhost:8000/mcpFastMCP предоставит следующие адреса обнаружения аутентификации:
http://localhost:8000/.well-known/oauth-authorization-server
http://localhost:8000/.well-known/oauth-protected-resource/mcpКлиент должен автоматически считывать эти конечные точки обнаружения MCP/OAuth. После успешного входа можно вызвать два защищённых инструмента:
ping: проверка работоспособности.who_am_i: возвращаетclient_id, scope и claims, извлечённые FastMCP из текущего токена аутентификации.
Параметры конфигурации
Переменная окружения | Обязательна | Значение по умолчанию | Описание |
| Да | - | Идентификатор клиента верхнего OIDC |
| Одно из двух | - | Секрет конфиденциального клиента |
| Одно из двух | - | Ключ подписи токенов FastMCP для public PKCE-клиента или производственной среды |
| Нет | URL обнаружения QA | Адрес обнаружения OIDC |
| Нет |
| Публичный адрес MCP-сервера |
| Нет |
| Scope для запроса авторизации OAuth/рекламы по умолчанию; не используется для проверки scope токена доступа |
| Нет | Issuer из обнаружения OIDC | Значение для проверки |
| Нет |
| Адрес JWKS для пользовательского issuer токена |
| Нет | - | Необязательное значение для проверки |
| Нет |
| Адрес прослушивания |
| Нет |
| Порт прослушивания |
| Нет | Адрес QA MGT | Базовый URL фактического вызова MGT API |
| Нет |
| Путь к локальной спецификации OpenAPI |
В производственной среде явно задайте случайный JWT_SIGNING_KEY и используйте BASE_URL с HTTPS. Не коммитьте .env или любые секреты клиента в Git.
Пользовательский Issuer токена
Если iss токена — не issuer, возвращаемый обнаружением OIDC, а переписан auth middleware в адрес арендатора, например:
实际 token iss:
https://api-authsome-qa.drillinsight.com/auth-middleware/t_adecdb63-afab-4346-a1aa-b50bbbae7aee/Установите:
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 по-прежнему используется для обнаружения конечных точек входа и авторизации OAuth; OIDC_TOKEN_ISSUER используется только для проверки iss JWT-токена доступа. Они могут различаться. OIDC_TOKEN_ISSUER должен точно совпадать с iss в токене, включая завершающий /.
Текущий проект не проверяет scope или scp claim токена доступа, поскольку исторические токены MGT используют нестандартный формат scope. OIDC_REQUIRED_SCOPES по-прежнему используется для запроса авторизации OAuth, но не блокирует действительные токены без стандартного scope claim. Проверка подписи, issuer, audience, срока действия и JWKS сохраняется.
Интеграция QA MGT OpenAPI
Спецификация QA OpenAPI сохранена в:
specs/mgt-qa-openapi.jsonMCP не обращается к онлайн-/api-docs во время выполнения, поэтому в будущем в производственной среде отсутствие открытой документации API не повлияет на работу. Достаточно переключить фактический адрес API через MGT_API_BASE_URL. Docker-образ копирует specs/mgt-qa-openapi.json в /app/specs/mgt-qa-openapi.json и автоматически устанавливает MGT_OPENAPI_SPEC_PATH.
Область API, предоставляемая в первой версии:
/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)Интерфейс ссылки на оплату заказа подключён по текущим требованиям:
/api/v1/order/queryPayLink
/api/v1/order/reGenaratePayLinkПо-прежнему исключены интерфейсы возврата, обратного вызова оплаты и экспорта данных клиентов:
/mall/v1/order/refund
/alipay/**
/stripe/**
/weixin/refund/**
/api/v1/customers/export
/api/v1/campus-recruitment/export
/api/v1/recruitment-info/exportПри каждом вызове MGT OpenAPI-клиент получает из текущего запроса FastMCP пользовательский OAuth-токен доступа верхнего уровня и отправляет:
Authorization: Bearer <user access token>
X-Application-Id: <token.app_id>Здесь X-Application-Id не требует дополнительной настройки — он считывается напрямую из claim app_id проверенного JWT. Токены без app_id отклоняются, чтобы не отправлять в MGT неполные запросы.
Поэтому MGT должен доверять пользовательским токенам, выпущенным auth-qa.drillinsight.com, и выполнять контроль прав на основе личности пользователя.
Диагностика таймаута ChatGPT CIMD
Если журнал содержит:
CIMD fetch failed for https://chatgpt.com/.../client.json: Timeout fetching
Unregistered client_id=https://chatgpt.com/.../client.jsonэто означает, что FastMCP не может напрямую получить доступ к размещённым ChatGPT метаданным клиента. Если текущая машина должна выходить в интернет через доверенный исходящий прокси, настройте:
FASTMCP_SSRF_TRUST_PROXY=true
HTTPS_PROXY=http://127.0.0.1:7897Затем полностью остановите и перезапустите сервис. Программа автоматически загружает .env из корня проекта перед импортом FastMCP; FastMCP по умолчанию выполняет проверку DNS и фиксацию IP для запросов CIMD/JWKS, поэтому обычные переменные окружения прокси не используются автоматически. После включения этой опции ответственность за защиту от SSRF передаётся указанному прокси, а NO_PROXY игнорируется. Включайте её только для доверенного прокси.
Первый POST /mcp 401 в журнале — это попытка клиента проверить защищённый ресурс до аутентификации; 404 на несколько адресов /.well-known/... — это проверка совместимости ChatGPT. Пока /.well-known/oauth-authorization-server возвращает 200, они не являются причиной сбоя.
Если в журнале отображается Unregistered client_id=app_... или другой не-URL client ID, это означает, что ChatGPT кэшировал старую регистрацию DCR, которая была потеряна из хранилища сервера. Зафиксируйте JWT_SIGNING_KEY, перезапустите сервис, затем удалите и заново создайте этот пользовательский MCP в ChatGPT, чтобы он снова вызвал /register. Простой повтор входа не восстановит старый client ID, неизвестный серверу.
Тестирование
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