Serve the II app-metadata document at the origin root - #169
Merged
Conversation
Internet Identity's connect screen names the server a user is about to hand a standing delegation to, and can link that server's own privacy policy and terms of service beside the "Allow access" button — for any origin that publishes them at /.well-known/ii-app-metadata, with no involvement from the II team. This origin now serves that document: the name "ICP MCP", and the product's policy pages on internetcomputer.org. Like the auth-callback allow-list the path is origin-global (well-known URIs are origin-scoped), so one document covers every instance and the router merges at the application root, CORS-open because II's frontend fetches it cross-origin. The document names THIS deployment, so the crate's embedder-facing usage example leaves the router out; an embedder on its own origin publishes its own metadata. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds origin-level Internet Identity metadata so ICP MCP displays its name and legal links during connection authorization.
Changes:
- Adds and mounts the CORS-enabled metadata router.
- Tests metadata constraints.
- Documents the new endpoint.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/lib.rs |
Defines the metadata document and router. |
src/main.rs |
Mounts the router at the application root. |
tests/routers.rs |
Tests the metadata response and fields. |
README.md |
Lists the new well-known endpoint. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
aterga
approved these changes
Aug 28, 2026
aterga
pushed a commit
that referenced
this pull request
Aug 28, 2026
…oval One conflict, the main.rs import block: keep this branch's axum line (response::Html went away with the served pages) and main's imcp2 line (ii_app_metadata_router joins the imports). The two changes are complementary — #169 already points Internet Identity's legal links at the pages' one home on internetcomputer.org/icp-mcp/, the same destination this branch's redirects serve, and its router merges at the application root untouched by the redirect routes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
aterga
pushed a commit
that referenced
this pull request
Aug 31, 2026
…tions The base branch was rebased onto main (picking up #164, #169 and #170), so this branch's base commit no longer existed and the PR went un-mergeable. Merged the new base head rather than rewriting this branch's history. Five conflicts in tools.rs, resolved deliberately: - `discover_app_canisters`'s description: kept this branch's, which documents the empty-result behaviour for a domain with no Internet-Computer evidence. - SERVER_INSTRUCTIONS and its doc comment: kept this branch's rewrite, and adopted the base branch's corrected financial paragraph into it. That paragraph no longer says canister_update_call "refuses" financial transactions as a class — the guard is a safeguard, not a complete filter, so the policy rather than the absence of a refusal is stated as the limit. - The financial-policy test: took the base branch's corrected comment and its new assertion pinning "a safeguard, not a complete filter", so the hedge cannot be dropped by a later rewrite of this text. - The model-readable-metadata policy test block: kept this branch's; the base branch has none. Both submission documents merged cleanly: the base branch adopted the wording already reviewed here, so the two no longer diverge on the paragraph that described these instructions. Workspace green (52 + 10 + 10 + 149 + 21 + 1), clippy at the 10-warning baseline. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
7 tasks
This was referenced Sep 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Internet Identity's connect screen names the server a user is about to hand a standing delegation to. It can also link that server's own privacy policy and terms of service beside the "Allow access" button — for any origin that publishes them at
/.well-known/ii-app-metadata, permissionlessly, with no involvement from the II team.This origin now serves that document, so the connect screen reads "Connect mcp.internetcomputer.org … Review ICP MCP's Privacy Policy and Terms of Service." instead of naming the host and nothing else.
Related issues
The policy links half of the document is dfinity/internet-identity#4302 (the
namehalf already ships). Serving the document early is harmless: II ignores fields it doesn't know, so the name applies today and the links light up when that PR lands.Changes
ii_app_metadata_router()insrc/lib.rs, next toauth_callbacks_routerand built the same way: origin-global (well-known URIs are origin-scoped, so one document covers every instance), merged at the application root, CORS-open because II's frontend fetches it cross-origin.name: "ICP MCP", and the product's own pages athttps://internetcomputer.org/icp-mcp/privacy-policyand.../terms. Written absolute rather than derived frompublic_url: II requireshttpsand a local build'spublic_urlishttp://localhost:8000. It never fetches these documents (it renders links the user opens), so they may live on any origin.tests/routers.rsmerges it into the composed app and asserts the document meets II's requirements — name non-blank and within the 40-code-point cap, both URLshttpsand free of userinfo. Validation on II's side is all-or-nothing, so one bad field discards the document whole, silently, on a screen this server never sees; that is what the test guards.Testing
cargo build --locked --all-targetscargo test --locked --all-targets— 245 pass, including the new router test (which caught its own wiring: the harnessapp()had to merge the router, exactly asmain.rsdoes)cargo clippy --all-targets— no new warnings; the 6 pre-existing ones inimcp2-coreare untouchedcargo fmt --all— not run: my local rustfmt reformats ~15 files across the tree that this PR doesn't touch, so running it would bury the change. Added lines are hand-kept within the surrounding width.npm test --prefix monitoring/mcp-status— dashboard unchangedChecklist
🤖 Generated with Claude Code