Skip to content

feat: support Client ID Metadata Documents (CIMD) alongside DCR - #62

Draft
nonchan7720 wants to merge 3 commits into
mainfrom
claude/mcp-major-update-bmrdy6
Draft

feat: support Client ID Metadata Documents (CIMD) alongside DCR#62
nonchan7720 wants to merge 3 commits into
mainfrom
claude/mcp-major-update-bmrdy6

Conversation

@nonchan7720

@nonchan7720 nonchan7720 commented Jul 31, 2026

Copy link
Copy Markdown
Owner

What does this PR do?

MCP 2025-11-25 仕様アップデートの CIMD (Client ID Metadata Documents, SEP-991) に、既存の Dynamic Client Registration (RFC 7591) を維持したまま双方向で対応します。

内蔵認可サーバー側(MCP クライアント → Manifold)

  • client_id として HTTPS URL を受け付け、その URL から CIMD ドキュメントを取得・検証(client_id と取得元 URL の一致、redirect_uris の検証、パブリッククライアントのみ許可)。検証済みドキュメントは store に 5 分間キャッシュ
  • ドキュメント取得は SSRF 対策済みの SafeHTTPClient(プライベート IP 拒否)+ Content-Type 検証 + 1MB サイズ上限
  • AS メタデータに client_id_metadata_document_supported: true を追加
  • 事前登録を持たない CIMD クライアント向けに、RFC 8707 の resource パラメータ(https://host/mcp/{name})から対象 MCP サーバーを解決するフォールバックを追加
  • 従来の DCR エンドポイント(/auth/clients, /register)は変更なし

MCP クライアント側(Manifold → 上流 MCP サーバー)

  • GET /{server}/auth/client-metadata.json で Manifold 自身の CIMD ドキュメントを配信
  • OAuth 自動発見時、上流認可サーバーが client_id_metadata_document_supported を広告し、かつゲートウェイが HTTPS で公開されている場合は CIMD を優先し、それ以外は従来どおり DCR にフォールバック

その他

  • LoginEndpoint のクライアント解決/サーバー解決を resolveLoginClient / resolveLoginServer に抽出(gocyclo 閾値対応)
  • README (EN/JA) にエンドポイントと動作説明を追記

Related issues

なし

Checklist

  • make test passes locally(CI=true go test ./pkg/... 全パッケージ成功。pkg/internal/client の一部テストは CI 環境変数なしでは main でも失敗する既存事象)
  • make lint passes locally(ローカルの golangci-lint バイナリが Go 1.26 非対応のため実行不可。gocyclo は手動確認済み)
  • Tests added/updated for behavior changes (if applicable)
  • Documentation updated (README / examples, if applicable)

🤖 Generated with Claude Code

https://claude.ai/code/session_019mm3HwL3YGD2uoGYUhkKft


Generated by Claude Code

Summary by CodeRabbit

  • 新機能

    • OAuth 2.1 サーバーが CIMD(Client ID Metadata Documents)に対応しました。
    • HTTPS URL形式の client_id からクライアント情報を取得・検証できるようになりました。
    • CIMDドキュメント配信用エンドポイントと関連するエイリアスを追加しました。
    • 対応状況に応じてCIMDを優先し、非対応時は動的クライアント登録へフォールバックします。
  • ドキュメント

    • CIMD、エンドポイント、フォールバック動作の説明を追加しました。

Implements CIMD (SEP-991) from the MCP 2025-11-25 spec update in both
directions while keeping existing Dynamic Client Registration (RFC 7591):

Authorization server side:
- Accept HTTPS URLs as client_id: fetch, validate (client_id match,
  redirect_uris, public client only) and cache the metadata document
- Advertise client_id_metadata_document_supported in AS metadata
- Resolve the target MCP server from the RFC 8707 resource parameter
  for CIMD clients that have no pre-registration

Client side (upstream MCP servers):
- Serve manifold's own CIMD document at
  GET /{server}/auth/client-metadata.json
- Prefer CIMD during OAuth discovery when the upstream AS advertises
  support and the gateway is served over HTTPS; fall back to DCR

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mm3HwL3YGD2uoGYUhkKft
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 287be461-0605-487b-8b8b-2699ea92c9c5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

CIMD requires fetching the client-supplied client_id URL by design.
SSRF is mitigated by enforcing the https scheme, blocking private IPs
via SafeHTTPClient, and applying size/content-type limits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mm3HwL3YGD2uoGYUhkKft

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
pkg/interfaces/http/cimd.go (1)

184-190: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

CIMD ドキュメント URL の生成を 1 か所に集約してください。

clientMetadataDocumentURL(189 行)と ClientMetadataDocument(206 行)が同じ書式を重複して組み立てています。ベース URL に末尾スラッシュが付く場合、両方が二重スラッシュを生成します。url.JoinPath を使うヘルパーへ統一すると、client_id の不一致を防げます。

Also applies to: 205-207

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/interfaces/http/cimd.go` around lines 184 - 190, Consolidate CIMD URL
construction in clientMetadataDocumentURL and ClientMetadataDocument by
introducing or reusing one helper based on url.JoinPath. Preserve the existing
HTTPS validation and ensure gatewayBaseURL values with or without a trailing
slash produce the same URL and client_id.
pkg/interfaces/http/cimd_test.go (1)

191-213: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

サイズ上限のテストを追加してください。

fetchCIMDDocumentcimdMaxBodySize を超えるレスポンスを拒否します。この境界は現在テストされていません。1 MB を超えるボディを返すハンドラでエラーを確認するテストを追加してください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/interfaces/http/cimd_test.go` around lines 191 - 213, Add a test
alongside TestFetchClientIDMetadata_WrongContentType and
TestFetchClientIDMetadata_NotFound that makes the test server return a response
body larger than 1 MB, invokes fetchClientIDMetadata, and asserts an error is
returned, covering the cimdMaxBodySize enforcement in fetchCIMDDocument.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/interfaces/http/auth_handler.go`:
- Around line 554-560: Before resolving the server in the resource lookup block,
validate that the resource URL’s host matches the gateway base URL, rejecting
resources from arbitrary hosts such as evil.example.com. Update the flow around
serverNameFromResource so path-based server resolution and the existing
h.servers lookup occur only after this host validation.

In `@pkg/interfaces/http/cimd.go`:
- Around line 82-89: Update the httpClient fallback in the AuthHandler flow
around fetchCIMDDocument to use the project’s SSRF-protected client package
instead of http.DefaultClient, and configure a request timeout for CIMD
retrieval. Preserve the existing h.httpClient path while ensuring nil-client
construction remains protected against private IP access and unbounded waits.
- Around line 110-121: Update fetchCIMDDocument to prevent unsafe redirects:
configure the HTTP request/client flow to reject redirects, or validate every
redirect target before following it, ensuring each CIMD URL remains HTTPS and
meets the existing host restrictions. Preserve the current request and response
handling for valid non-redirected URLs.

---

Nitpick comments:
In `@pkg/interfaces/http/cimd_test.go`:
- Around line 191-213: Add a test alongside
TestFetchClientIDMetadata_WrongContentType and
TestFetchClientIDMetadata_NotFound that makes the test server return a response
body larger than 1 MB, invokes fetchClientIDMetadata, and asserts an error is
returned, covering the cimdMaxBodySize enforcement in fetchCIMDDocument.

In `@pkg/interfaces/http/cimd.go`:
- Around line 184-190: Consolidate CIMD URL construction in
clientMetadataDocumentURL and ClientMetadataDocument by introducing or reusing
one helper based on url.JoinPath. Preserve the existing HTTPS validation and
ensure gatewayBaseURL values with or without a trailing slash produce the same
URL and client_id.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: eb53cd21-081f-4a0f-9429-b111fd202672

📥 Commits

Reviewing files that changed from the base of the PR and between 67ea4cc and d49a6e1.

📒 Files selected for processing (5)
  • README.ja.md
  • README.md
  • pkg/interfaces/http/auth_handler.go
  • pkg/interfaces/http/cimd.go
  • pkg/interfaces/http/cimd_test.go

Comment thread pkg/interfaces/http/auth_handler.go
Comment thread pkg/interfaces/http/cimd.go
Comment thread pkg/interfaces/http/cimd.go
Address review findings:
- Fall back to SafeHTTPClient instead of http.DefaultClient so the
  SSRF protection holds on every construction path, and bound the
  CIMD fetch with a 10s timeout
- Stop following redirects when fetching CIMD documents so the
  https-only validation cannot be bypassed via a redirect hop
- Require the RFC 8707 resource host to match the gateway host before
  resolving an MCP server from it
- Consolidate CIMD document URL construction into a single helper
- Add tests for the body size limit and redirect rejection

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mm3HwL3YGD2uoGYUhkKft
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants