test-mcp
test-mcp
Минимальный MCP-сервер ресурсов для ручного тестирования поддержки динамической регистрации клиентов (Dynamic Client Registration, DCR) и индикатора ресурса в Authgear (docs/specs/dcr.md, docs/specs/access-token-audience-binding.md из репозитория authgear-server).
Сам по себе он не делает ничего интересного — его единственная задача: разместиться позади Authgear как авторизационного сервера и дать реальному MCP-клиенту прогнать весь процесс: discovery → самостоятельная DCR-регистрация → authorize/consent через PKCE → обмен токена с привязкой к resource этого сервер → аутентифицированный вызов MCP-инструмента.
Как компоненты связаны между собой
MCP client --1. GET /mcp (no token)--> test-mcp
<--2. 401 + WWW-Authenticate: Bearer resource_metadata="..."--
MCP client --3. GET /.well-known/oauth-protected-resource--> test-mcp
<--4. { resource, authorization_servers: [Authgear] }--
MCP client --5. GET /.well-known/oauth-authorization-server--> Authgear
<--6. { registration_endpoint, authorization_endpoint, ... }--
MCP client --7. POST /oauth2/register--> Authgear (DCR)
MCP client --8. /oauth2/authorize + consent, resource=<RESOURCE_URI>--> Authgear
MCP client --9. POST /oauth2/token, resource=<RESOURCE_URI>--> Authgear
<--10. JWT access token, aud=[RESOURCE_URI]--
MCP client --11. POST /mcp, Authorization: Bearer <token>--> test-mcp
<--12. tool result (or 401 if scope/audience don't match)--Шаги 1–2 и 11–12 выполняются на этом сервере. Всё, что между ними, делает Authgear, который любой MCP-клиент, соответствующий спецификации, обнаруживает автоматически: вы не указываете клиенту URL Authgear напрямую.
Related MCP server: MCP Server OAuth Toy
Предварительные требования
Запущенный экземпляр Authgear с включённой DCR, например в
authgear.yaml:oauth: dynamic_client_registration: enabled: true initial_access_token_required: false # open registration, for easy testingРесурс (Resource) в этом проекте, соответствующий указанному ниже
RESOURCE_URI, сaccess_policy.allow_dynamic_third_party_client_access: trueна самом Ресурсе и на каждом Scope, который нужен тестовым инструментам, — иначе запрос DCR-клиента сresource=получитinvalid_target/invalid_scope. Создайте его через admin API GraphQL (или черезadmin_api_graphqlв e2e-тесте, если вы работаете из репозиторияauthgear-server):mutation { createResource(input: { resourceURI: "https://localhost:8090" name: "test-mcp" accessPolicy: { allowDynamicThirdPartyClientAccess: true } }) { resource { id } } } mutation { createScope(input: { resourceURI: "https://localhost:8090" scope: "read:tools" accessPolicy: { allowDynamicThirdPartyClientAccess: true } }) { scope { id } } } mutation { createScope(input: { resourceURI: "https://localhost:8090" scope: "execute:tools" accessPolicy: { allowDynamicThirdPartyClientAccess: true } }) { scope { id } } }https://localhost:8090должен байт-в-байт совпадать сRESOURCE_URIниже, и это должен быть реальный origin данного сервера (схема + хост + порт), а не какой-то произвольный плейсхолдер. Это фиксируют два независимых ограничения:Authgear требует, чтобы URI любого Ресурса был
https://(pkg/lib/resourcescope/formats.go).Согласно RFC 8707, поле
resourceв metadata защищённого ресурса должно соответствовать URL (или origin), к которому клиент фактически подключается, и строгие клиенты это проверяют — MCP Inspector откажется подключаться с ошибкой видаProtected resource ... does not match expected ... (or origin), если вы направитеRESOURCE_URIна какой-нибудь unrelated идентификатор вместо реального адреса сервера.
Именно поэтому этот сервер по умолчанию работает через HTTPS (самоподписанный сертификат), а не через обычный HTTP:
https://localhost:<PORT>одновременно является валидным URI ресурса Authgear и уже настоящим origin этого сервера. Если вы меняетеPORT, приведите URI Ресурса (иRESOURCE_URIниже) в соответствие.
Настройка
npm install
npm run setup # generates a self-signed TLS cert for localhost (see below)Запуск
npm startПеременные окружения (все не обязательны):
Переменная | Значение по умолчанию | Описание |
|
| Порт, который прослушивает этот сервер. |
|
| Базовый URL вашего экземпляра Authgear. Используйте |
|
| Идентификатор ресурса по RFC 8707. Он должен совпадать с созданным выше ресурсом и быть реальным origin данного сервера (см. выше). |
| не задано | Установите в |
Тестирование с реальным MCP-клиентом
MCP Inspector (рекомендуемый первый шаг)
npx @modelcontextprotocol/inspectorОткройте выводимый локальный URL, введите URL сервера https://localhost:8090/mcp и подключитесь — панель «Auth» в Inspector пошагово проводит через discovery, DCR и обмен authorize/token, так что вы можете увидеть содержимое каждого ответа.
Раз сертификат самоподписанный, возможно, потребуется указать Node, чтобы он доверял ему в исходящих запросах самого Inspector:
NODE_EXTRA_CA_CERTS=$(pwd)/certs/localhost.crt npx @modelcontextprotocol/inspector(Делайте это только для локального тестирования — никогда не отключайте валидацию сертификатов для того, что обращается к настоящему серверу.)
mcp-remote (для тестирования с Claude Desktop)
npx mcp-remote https://localhost:8090/mcpи настройте конфигурацию Claude Desktop на получившийся локальный stdio-мост в соответствии с документацией mcp-remote.
Что важно проверить
Запрос без
resource=(обычный OIDC-клиент или MCP-клиент, который не передаётresource: Authgear по умолчанию выдаст стороннему/DCR-клиенту opaque токен. Этот сервер не может проверить opaque-токен вообще (это не JWT), поэтому все вызовы инструментов будут оканчиваться 401 — это ожидаемое поведение (docs/specs/dcr.md,docs/specs/access-token-audience-binding.md): непривязанный сторонний токен можно использовать только в Authgear/oauth2/userinfoи нигде ещё.Запрошенный
resource=<RESOURCE_URI>: Authgear выдаёт JWT сaud: [RESOURCE_URI]. После этогоwhoamiдолжен успешно работать, независимо от выданных scope;list_widgets/run_widgetже работают, только если на этапе consent был выдан соответствующий scope (read:tools/execute:tools).Токен, привязанный к другому ресурсу, или токен, чей Scope/Resource не имеет
allow_dynamic_third_party_client_access: будет отклонён самим Authgear (invalid_target/invalid_scope) ещё до того, как попадёт на этот сервер.
Устранение неполадок
Failed to connect ...Protected resource <X> does not match expected <Y> (or origin)(MCP Inspector или другой клиент, строго следующий RFC 8728) — значит, вRESOURCE_URIуказано не то, что является реальным origin этого сервера. ПриведитеRESOURCE_URI(и соответствующий ресурс в Authgear) кhttps://localhost:<PORT>, а не к произвольному плейсхолдеру — см. «Предварительные ре-clerk».invalid_targetв/oauth2/authorizeили/oauth2/token— у Ресурса и/или конкретного Scope не заданaccess_policy.allow_dynamic_third_party_client_access: true, либо значениеresource=, которое передал клиент, не совпадает с зарегистрированным.401 с этого сервера и
error_description: "fetch failed"— сервер не смог связаться сAUTHGEAR_ENDPOINT, чтобы получить discovery-метаданные; проверьте, что Authgear там полностью поднят.401 с ошибкой проверки JWT — токен настоящий, но либо истёк, либо подписан другим решение об эмиттере, либо привязан к другому
aud, нежелиRESOURCE_URI.
This server cannot be deployed
Maintenance
Related MCP Connectors
Minimal streamable HTTP MCP server used for owned-account registry connectivity tests.
Experimental MCP server for current empirical verification of explicit public HTTPS endpoint claims.
- StytchOAuthdev.stytch.mcp
The Stytch MCP server is a reference implementation that demonstrates remote MCP server authentication and authorization using Stytch Connected Apps. It provides OAuth 2.1-compliant authorization (including PKCE), Dynamic Client Registration, and validates Stytch-issued access tokens to enable AI agents to securely interact with external services through permissioned access, supporting scopes like openid, email, profile, and manage:project_data.
MCP server for verifying EUDI/Talao wallet data via OIDC4VP (pull) for AI agents.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA proof-of-concept MCP server implementing OAuth 2.1 authorization with CIMD client registration and PKCE, demonstrating protected resource access and step-up authentication.-
- FlicenseNot gradedqualityDmaintenanceA simple MCP server with OAuth 2.0 authentication for testing OAuth support in mcp-cli.-
- -licenseNot gradedqualityFmaintenanceA minimal remote (Streamable HTTP) MCP server that is an OAuth 2.1 resource server, demonstrating the MCP authorization spec with token validation and audience checks.-
- AlicenseNot gradedqualityCmaintenanceA demo MCP server protected by OAuth (DCR), enabling hands-on exploration of OAuth flow for local MCP servers.MIT