feat(fe): legal links from the app metadata on the MCP connect screen - #4302
Merged
Conversation
The `/.well-known/ii-app-metadata` document gains two optional fields, `privacyPolicyUrl` and `termsOfServiceUrl`, and the MCP connect screen links them above "Allow access" in place of its revoke note. Unlike the logo, the documents are only ever linked to, never fetched, so they may live on any origin, as a policy on a separate domain commonly does. They must be `https` (or on the origin that served the document, so an app served over plain `http` in local development still works), which is what rules out `javascript:`, `data:` and the other schemes a link must never carry. A field that is present and invalid rejects the whole document, like every other field. The connect screen consumed no app metadata before this, so it now also resolves the server's name from the same document to say whose documents these are, next to the host it has verified and displays above. Each link appears only for the field the server publishes; a server publishing neither gets no fine print. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
✅ No security or compliance issues detected. Reviewed everything up to 372f3fd. Security Overview
Detected Code Changes
|
Contributor
There was a problem hiding this comment.
Pull request overview
Adds support for MCP servers to publish and display Privacy Policy / Terms of Service links on the MCP connect (“Allow access”) screen by extending the existing permissionless /.well-known/ii-app-metadata document and consuming it from the connect UI.
Changes:
- Extend app metadata validation to support optional
privacyPolicyUrlandtermsOfServiceUrlwith scheme restrictions and relative resolution. - Render server-provided legal links (with translatable variants) in a sticky fine-print area on the MCP connect screen.
- Add/adjust unit + Playwright E2E coverage and update the public spec/schema docs.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/frontend/tests/e2e-playwright/routes/mcp.spec.ts | Adds E2E coverage for rendering legal links (and removes now-obsolete “revoke in settings” assertions). |
| src/frontend/tests/e2e-playwright/fixtures/mcp.ts | Adds fixture helper to serve /.well-known/ii-app-metadata for MCP-origin in tests. |
| src/frontend/src/routes/(new-styling)/mcp/views/McpAuthorizeView.svelte | Fetches app metadata for the MCP server origin and conditionally renders legal links above the CTA. |
| src/frontend/src/routes/(new-styling)/mcp/+page.svelte | Wires mcpServerOrigin into McpAuthorizeView. |
| src/frontend/src/lib/utils/appMetadata.ts | Adds metadata fields + validation logic for policy URLs. |
| src/frontend/src/lib/utils/appMetadata.test.ts | Adds unit tests for policy URL validation/resolution and scheme constraints. |
| src/frontend/src/lib/stores/app-metadata.store.ts | Updates store documentation to reflect the new metadata fields/consumer. |
| docs/ii-spec.mdx | Documents new fields, scheme rules (incl. local-dev exception), and updates the JSON Schema. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The plain-`http` carve-out for the document's own origin served nobody. The only screen rendering these links takes its origin from `parseMcpServerUrl`, which is https-only, and II's production CSP (`connect-src 'self' https:`) means an `http` origin's metadata document is never read there at all. A local app publishes neither field. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both from the Copilot review. A value with nothing but whitespace in it resolved to the origin's root, since the URL parser ignores what surrounds a URL; it is now refused, matching the text fields' "must read as something" rule. Userinfo grants an app no destination it couldn't write plainly, as any https origin is allowed by design, but it is the one way a value could read as one host and resolve to another, and the link text the user sees is II's own generic "Privacy Policy". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The connect screen asks the server's origin for its app-metadata document as soon as it mounts, so the 12 specs that reach `/mcp` without installing the server stand-in were left making a real request to mcp.id.ai. The fixture now answers that path 404 by default, the way an origin publishing nothing does; `serveAppMetadata` and the connect interceptor register later and take precedence. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
MRmarioruci
reviewed
Aug 28, 2026
MRmarioruci
approved these changes
Aug 28, 2026
8 tasks
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.
Motivation
The MCP connect screen ("Connect mcp.example.com") asks the user to hand an AI agent a standing delegation to their identity. What it says about the server it is connecting is the origin in its heading and nothing else: the server has no way to point the user at its privacy policy or its terms of service on the screen where the decision is actually made.
Apps already publish their own presentation permissionlessly, in the
/.well-known/ii-app-metadatadocument introduced by #4221. This extends that document with the two legal links and renders them on the connect screen, which until now consumed no app metadata at all.Changes
privacyPolicyUrlandtermsOfServiceUrl, validated in$lib/utils/appMetadata.tslike the rest of the document: absent is fine, present-and-invalid rejects the whole document with a console warning naming the field, and a document carrying nothing but a policy URL is still usable.https, which rules outjavascript:,data:and anything else a link must never carry, along with plainhttp— II's production CSP (connect-src 'self' https:) means it would never have read the document overhttpto begin with, and the only screen rendering these links takes its origin fromparseMcpServerUrl, which is https-only. An app served overhttpin local development publishes neither field.Review <name>'s Privacy Policy and Terms of Service., in three translatable variants so a server publishing one link reads correctly. A server that publishes neither gets no fine print, and the spacing goes with it. Both links open in a new tab, so the connect request in this one isn't lost.docs/ii-spec.mdxdocuments the fields, the scheme rule and its local-development exception, and extends the published JSON Schema. The schema preamble now names two requirements it cannot express (isolate balance, and the policy-URL scheme) rather than one.Tests
appMetadata.test.tsfor any-origin acceptance (with nothing fetched for it), relative resolution against the origin that served the document, a policy-URL-only document, and the scheme rejections:httpboth cross-origin and on the app's own origin,javascript:,data:,mailto:, unparseable, and empty.serveAppMetadata, andmcp.spec.tscovers the links rendering with the published hrefs and staying pinned above the CTA when the panel scrolls, plus a server publishing nothing showing no fine print. The "keeps the consent in view" spec no longer asserts on the revoke link this removes; that sticky-footer coverage moved to the new spec.🤖 Generated with Claude Code