Skip to main content
Glama
tung2744
by tung2744

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

Переменные окружения (все не обязательны):

Переменная

Значение по умолчанию

Описание

PORT

8090

Порт, который прослушивает этот сервер.

AUTHGEAR_ENDPOINT

http://localhost:4000

Базовый URL вашего экземпляра Authgear. Используйте http://localhost:3000, если вы идёте напрямую к процессу make start, или http://localhost:3100, если используете традиционный локальный dev-прокси nginx (docker compose up -d proxy) — в любом случае это должен быть адрес, где реально отвечает /.well-known/openid-configuration.

RESOURCE_URI

https://localhost:<PORT>

Идентификатор ресурса по RFC 8707. Он должен совпадать с созданным выше ресурсом и быть реальным origin данного сервера (см. выше).

USE_HTTP

не задано

Установите в 1, чтобы работать по простому HTTP вместо HTTPS. Не рекомендуется: при USE_HTTP=1 RESOURCE_URI больше не может равняться реальному origin сервера (пришлось бы использовать http://..., который Authgear не принимает как Resource URI), поэтому у строгого MCP-клиента проверка соответствия ресурса не пройдёт. Используйте только способом, при котором вы точно знаете, что клиент такую проверку не делает.

Тестирование с реальным 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.

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    A proof-of-concept MCP server implementing OAuth 2.1 authorization with CIMD client registration and PKCE, demonstrating protected resource access and step-up authentication.
  • -
    license
    Not graded
    quality
    F
    maintenance
    A 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.
  • A
    license
    Not graded
    quality
    C
    maintenance
    A demo MCP server protected by OAuth (DCR), enabling hands-on exploration of OAuth flow for local MCP servers.
    MIT

View all related MCP servers

Related MCP Connectors

  • MCP server for verifying EUDI/Talao wallet data via OIDC4VP (pull) for AI agents.

  • Self-hosted federated MCP gateway: one OAuth 2.1 MCP server in front of N apps, user-level scopes.

  • The official MCP Server from Mia-Platform to interact with Mia-Platform Console

View all MCP Connectors

Latest Blog Posts

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/tung2744/test-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server