Skip to main content
Glama
tung2744
by tung2744

test-mcp

Authgear의 DCR(동적 클라이언트 등록) + resource-indicator 지원(docs/specs/dcr.md, docs/specs/access-token-audience-binding.md, authgear-server 리포지토리)을 수동으로 테스트하기 위한 최소 MCP 리소스 서버입니다.

이 서버 자체로는 특별한 기능이 없습니다. Authgear를 권한 부여 서버로 하여 그 뒤에 위치하는 것이 전부이며, 실제 MCP 클라이언트가 전체 흐름을 수행해보도록 하는 것입니다: discovery → DCR 자체 등록 → 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 클라이언트는 이를 자동으로 발견합니다. 즉, 클라이언트에 Authgear의 URL을 직접 설정할 필요가 없습니다.

Related MCP server: MCP Server OAuth Toy

전제 조건

  • DCR이 활성화되어 실행 중인 Authgear 인스턴스. 예를 들어 authgear.yaml에서:

    oauth:
      dynamic_client_registration:
        enabled: true
        initial_access_token_required: false # open registration, for easy testing
  • 아래 RESOURCE_URI와 일치하는 Resource를 해당 프로젝트에 등록하고, Resource 자체와 테스트 도구에 필요한 모든 Scope에 access_policy.allow_dynamic_third_party_client_access: true를 설정해야 합니다. 그렇지 않으면 DCR 클라이언트의 resource= 요청이 invalid_target/invalid_scope 오류를 받게 됩니다. Admin API GraphQL 플레이그라운드(또는 authgear-server 리포지토리 안에서 진행 중이라면 e2e 테스트의 admin_api_graphql)로 생성하세요:

    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와 byte-for-exact해 일치해야 하며, 그리고 이 서버의 실제 오리진(스킴 + 호스트 + 포트)이어야 합니다. 임의의 자리표시자가 아닙니다. 이는 두 가지 독립적인 제약 때문입니다.

  • Authgear는 모든 Resource URI가 https://이도록 요구합니다 (pkg/lib/resourcescope/formats.go).

  • RFC 9728 보호 리소스 메타데이터의 resource 필드는 클라이언트가 실제로 연결한 URL(또는 오리진)과 일치할 것으로 기대되며, 엄격한 클라이언트는 이를 강제합니다. RESOURCE_URI를 서버의 실제 주소 대신 연결 관련 식별자를 지정하면 MCP Inspector는 Protected resource ... does not match expected ... (or origin) 같은 오류로 연결을 거부합니다.

이 바로 그 조합 때문에 이 서버는 일반 HTTP가 아니라 HTTPS(자체 서명)를 기본으로 서빙합니다. https://localhost:<PORT>는 동시에 유효한 Authgear Resource URI이면서 이 서버의 진짜 오리진입니다. PORT을 변경하면 Resource의 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

Authgear 인스턴스의 기본 URL. make start 프로세스 서버를 직접 사용하면 http://localhost:3000, 또는 일반적인 https://http://localhost:3100`을 local dev nginx 프록시(docker compose up -d proxy)를 거치면 http://localhost:3100을 로컬하십시오. 어느 쪽이든 /.well-known/openid-configuration이 실제로 resolve되는 어디 안 되는 주소여야 합니다.

RESOURCE_URI

https://localhost:<PORT>

RFC 8707 리소스 식별자. 위에서 등록한 Resource와 일치해야 하며, 이 서버의 실제 오리진이어야 합니다(위 참고).

USE_HTTP

unset 가리키지 않음

1 값을 주면 HTTPS 대신 일반 HTTP를 제공합니다. 권장하지 않음: USE_HTTP=1이면 RESOURCE_URI가 더 이상 이 서버의 실제 오리진과 같을 수 없습니다(http://여야 하는데, Authgear는 그런 Resource URI를 거부합니다). 따라서 엄격한 MCP 클라이언트의 리소스 일치 검사가 실패합니다. 이 검사를 강제하지 않는 클라이언트에 대해서만 사용하세요.

실제 MCP 클라이언트로 테스트하기

MCP Inspector (첫 단계로 권장)

npx @modelcontextprotocol/inspector

출력된 로컬 URL을 열고 서버 URL을 https://localhost:8090/mcp로 설정한 뒤, 연결하세요. Inspector의 “Auth” 패널이 discovery, DCR, 인가/토큰 교환을 단계별로 진행하므로 각 응답에 무엇이 들어 있는지 정확히 확인할 수 있습니다.

인증서가 자체 서명이므로 Inspector의 자체 요청을 위해 Node에 신뢰를 알려줘야 할 수 있습니다:

NODE_EXTRA_CA_CERTS=$(pwd)/certs/localhost.crt npx @modelcontextprotocol/inspector

(로컬 테스트에서만 하세요. 실제 서버와 통신하는 어떤 것에서도 인증서 검증을 비활성화하면 안 됩니다.)

mcp-remote (Claude Desktop용 테스트)

npx mcp-remote https://localhost:8090/mcp

그런 다음 mcp-remote의 문서에 따라 Claude Desktop 설정이 생성된 로컬 stdio 브리지를 바라보게 하면 됩니다.

확인할 것들

  • resource= 요청 없음 (일반 OIDC 클라이언트 또는 resource를 보내지 않는 MCP 클라이언트): Authgear는 기본적으로 제3자/DCR 클라이언트에 불투명(opaque) 토큰을 발급합니다. 이 서버는 불투명 토큰을 전혀 검증할 수 없습니다(JWT가 아니므로), 그래서 모든 도구 호출은 401로 실패합니다. 이는 의도된 동작입니다 (docs/specs/dcr.md, access-token-audience-binding 참고): 바인딩되어 있지 않은 제3자 token은 Authgear 자체의 /oauth2/userinfo`에서만 사용할 수 있고 다른 곳에서는 사용할 수 없는 것입니다.

  • resource=<RESOURCE_URI> 요청됨: Authgear는 aud: [RESOURCE_URI]を持つ JWT를 발급합니다. 이로 부여된 스코프와 무관하게 whoami는 성공해야 합니다. list_widgets/run_widget은 동의 시 해당 스코프(read:tools/execute:tools)가 부여된 경우에만 성공합니다.

  • 다른 리소스에 바인딩된 리소스 바인딩된 토큰, 또는 Resource/Scope에 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-9728 엄격 클라이언트) — RESOURCE_URI가 이 서버의 실제 오리진이 다른 값으로 설정되어 있습니다. RESOURCE_URI(및 Authgear의 일치하는 Resource)를 임의의 자리표시자가 아닌 https://localhost:<PORT>로 수정하세요. 위 “전제 조건” 참고.

  • /oauth2/authorize 내지 /oauth2/token 솔에 invalid_target — Resource(및/또는 특정 Scopeaccess_policy.allow_dynamic_third_party_client_access: true가 없거나, 클라이언트가 보낸 resource=` 값이 등록된 값과 정확히 일치하지 않는 경우입니다.

  • 이 서버에서 401과 error_description: "fetch failed" — 이 서버가 discovery 메타데이터를 회수 위해 AUTHGEAR_ENDPOINT에 접근하지 못했습니다. 실제로 Authgear가 그 주소에서 실행 중인지 확인하세요.

  • JWT 검증 오류와 401 — 토큰은 실제하지만 만료되었거나, 다른 issuer가 서명했거나, RESOURCE_URI가 아닌 다른 aud에 바인딩되어 있을 수 있습니다.

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