Skip to content

Serve the II app-metadata document at the origin root - #169

Merged
sea-snake merged 1 commit into
mainfrom
feat/ii-app-metadata
Aug 28, 2026
Merged

Serve the II app-metadata document at the origin root#169
sea-snake merged 1 commit into
mainfrom
feat/ii-app-metadata

Conversation

@sea-snake

Copy link
Copy Markdown
Collaborator

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 name half 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() in src/lib.rs, next to auth_callbacks_router and 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.
  • The document is three hardcoded constants — name: "ICP MCP", and the product's own pages at https://internetcomputer.org/icp-mcp/privacy-policy and .../terms. Written absolute rather than derived from public_url: II requires https and a local build's public_url is http://localhost:8000. It never fetches these documents (it renders links the user opens), so they may live on any origin.
  • The router is deliberately left out of the crate's usage example: the document names this deployment, and an embedder serving imcp2 on its own origin should publish its own metadata rather than DFINITY's. Noted on the function.
  • tests/routers.rs merges it into the composed app and asserts the document meets II's requirements — name non-blank and within the 40-code-point cap, both URLs https and 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.
  • README: one line in the endpoint list.

Testing

  • cargo build --locked --all-targets
  • cargo test --locked --all-targets — 245 pass, including the new router test (which caught its own wiring: the harness app() had to merge the router, exactly as main.rs does)
  • cargo clippy --all-targets — no new warnings; the 6 pre-existing ones in imcp2-core are untouched
  • cargo fmt --allnot 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 unchanged

Checklist

  • I have read the Contributing guidelines.
  • Docs (README / comments) updated for any user-visible change.
  • No secrets, credentials, or internal-only information are included.

🤖 Generated with Claude Code

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>
@sea-snake
sea-snake requested review from a team and a balanced review from Copilot August 28, 2026 14:58

Copilot AI 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.

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.

Comment thread tests/routers.rs
Comment thread README.md
@sea-snake
sea-snake merged commit 3473724 into main Aug 28, 2026
13 checks passed
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
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.

3 participants