Skip to main content
Glama
tung2744
by tung2744

test-mcp

Authgear の Dynamic Client Registration (DCR) と resource-indicator サポート(authgear-server リポジトリ内の docs/specs/dcr.md、docs/specs/access-token-audience-binding.md)を手動でテストするための最小限の MCP リソースサーバーです。

それ自体は何も面白いことはしません。唯一の役割は、Authgear を認可サーバーとして背後に置き、実際の MCP クライアントが全体のフロー(ディスカバリ → 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 に一致するリソースがそのプロジェクトに登録されており、そのリソース自体と、テストツールが必要とするすべてのスコープに 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 とバイト単位で一致し、かつこのサーバー自身の実際のオリジン(スキーム + ホスト + ポート)でなければなりません。任意のプレースホルダーではありません。これを固定する独立した 2 つの制約があります:

    • Authgear はすべてのリソース URI が https:// であることを要求します(pkg/lib/resourcescope/formats.go)。

    • RFC 9728 の保護リソースメタデータの resource フィールドは、クライアントが実際に接続した URL(またはオリジン)と一致することが期待され、厳格なクライアントはこれを強制します。MCP Inspector は、RESOURCE_URI をサーバーの実際のアドレスではなく無関係な識別子に設定すると、Protected resource ... does not match expected ... (or origin) のようなエラーで接続を拒否します。

    その組み合わせこそが、このサーバーがデフォルトで平文 HTTP ではなく HTTPS(自己署名)を提供する理由です。https://localhost:<PORT> は、Authgear の有効なリソース URI であると同時に、このサーバーの真のオリジンでもあります。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

Authgear インスタンスのベース URL。make start プロセスに直接接続する場合は http://localhost:3000、通常のローカル開発用 nginx プロキシ(docker compose up -d proxy)経由の場合は http://localhost:3100 を使用します。いずれにしても、/.well-known/openid-configuration が実際に解決される場所でなければなりません。

RESOURCE_URI

https://localhost:<PORT>

RFC 8707 のリソース識別子。上記で作成したリソースと一致し、かつこのサーバーの実際のオリジンでなければなりません(上記参照)。

USE_HTTP

未設定

1 に設定すると、HTTPS の代わりに平文 HTTP で提供します。推奨しません。USE_HTTP=1 の場合、RESOURCE_URI はこのサーバーの実際のオリジンと等しくできなくなり(http://... にする必要がありますが、Authgear はリソース URI として拒否します)、厳格な MCP クライアントのリソース一致チェックが失敗します。このチェックを強制しないクライアントに対してのみ使用してください。

実際の MCP クライアントでのテスト

MCP Inspector(最初のステップとして推奨)

npx @modelcontextprotocol/inspector

表示されたローカル URL を開き、サーバー URL を https://localhost:8090/mcp に設定して接続します。Inspector の「Auth」パネルで、ディスカバリ、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 はデフォルトでサードパーティ/DCR クライアントに不透明トークンを発行します。このサーバーは不透明トークンを検証できません(JWT ではないため)、すべてのツール呼び出しは 401 で失敗します。これは意図された動作です(docs/specs/dcr.md、access-token-audience-binding.md): バインドされていないサードパーティトークンは、Authgear 自身の /oauth2/userinfo でのみ使用でき、他の場所では使用できません。

  • resource=<RESOURCE_URI> が要求された場合: Authgear は aud: [RESOURCE_URI] を持つ JWT を発行します。whoami は付与されたスコープに関係なく成功するはずです。list_widgets/run_widget は、対応するスコープ(read:tools/execute:tools)が同意時に付与された場合にのみ成功します。

  • 別のリソースにバインドされたリソースバインドトークン、またはリソース/スコープに 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 内の対応するリソース)を https://localhost:<PORT> に修正してください。任意のプレースホルダーではなく、上記の「前提条件」を参照してください。

  • /oauth2/authorize または /oauth2/token で invalid_target — リソース(および/または特定のスコープ)に access_policy.allow_dynamic_third_party_client_access: true がないか、クライアントが送信した resource= の値が登録されているものと完全に一致していません。

  • このサーバーから error_description: "fetch failed" 付きの 401 — このサーバーが AUTHGEAR_ENDPOINT に到達してディスカバリメタデータを取得できませんでした。Authgear が実際にそこで実行されているか確認してください。

  • JWT 検証エラー付きの 401 — トークンは本物ですが、期限切れか、別の発行者によって署名されているか、RESOURCE_URI とは異なる aud にバインドされています。

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    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