feat(be): backend /mcp account-delegation methods — #4034 rebased on latest main#4052
Draft
aterga wants to merge 9 commits into
Draft
feat(be): backend /mcp account-delegation methods — #4034 rebased on latest main#4052aterga wants to merge 9 commits into
aterga wants to merge 9 commits into
Conversation
Adds the canister side of the backend-direct MCP delegation model: a single, deploy-configured MCP server can fetch per-app account delegations for an anchor without a per-app browser flow. - `mcp_server_origin` deploy arg (InternetIdentityInit + PersistentState, persisted via StorablePersistentState like `backend_origin`). When unset, the path is disabled. - New reverse index `lookup_anchor_with_mcp_principal` (StableBTreeMap<Principal, AnchorNumber>, MemoryId 25): maps the principal II derives for an anchor's default account at `mcp_server_origin` to the anchor. - `mcp_set_access(anchor_number, enabled)` / `mcp_access_enabled(anchor_number)`: opt-in toggle (authorized as the anchor) that binds/unbinds that principal in the index. This is the opt-in the connect flow sets. - `mcp_prepare_account_delegation(target_origin, session_key, max_ttl)` and `mcp_get_account_delegation(target_origin, session_key, expiration)`: called by the MCP server as the anchor's mcp-origin principal. The anchor is recovered from `caller()` via the index (no `anchor_number` param — being the right caller is the authorization); the delegation is for the anchor's default account at `target_origin`, capped at 5 minutes, reusing the existing account-delegation machinery. Candid updated for all of the above. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The /mcp route now grants the whole-session MCP connection rather than a per-app authorization: - On "Allow access", call `mcp_set_access(anchor, true)` before issuing the standing delegation, so II records the anchor's principal at `mcp_server_origin` and authorizes the MCP server's later on-demand per-app delegation calls (it recovers the anchor from the caller). Idempotent. - Reframe the authorize view copy: "Connect <mcp server>" / "act as you across your apps for this session (~1h, then reconnect)", instead of the per-app "act as your <app> account". - Regenerate II candid bindings (didc) for the new `mcp_*` methods and the `mcp_server_origin` init field. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Handle `mcp_set_access`'s `{ Ok; Err: text }` result directly (its string Err
isn't a record, so `throwCanisterError` can't type it).
- Add the new `mcp_server_origin` init field to the two `InternetIdentityInit`
test/mock fixtures (iiConnection.test.ts, vc-flow +page) so `tsc` passes.
- Rework McpHero into a single MCP-server node + hostname badge, mirroring the
generic (non-app) /cli screen — the connection is whole-session, not per app,
so there's no app tile. Drops the unused `app`/dapp lookup; views/+page pass
only `mcpServer`.
`tsc --noEmit` + `svelte-check`: 0 errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The connection is to the MCP server itself, whose origin II already holds in its `mcp_server_origin` config (FE: callback/CSP check; BE: caller-principal derivation). So `app` was redundant — a leftover from the per-app authorize model. `/mcp` now derives the delegation's account origin from the configured MCP server origin instead of requiring an `app` fragment param (which also removed an easy way to land on the invalid screen). - `mcpAuthorize` takes `mcpServerOrigin` (the configured origin) instead of `app`. - `+page.ts` no longer parses/requires `app` (parseApp removed). - `+page.svelte` passes `mcpServer.origin`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The new lookup_anchor_with_mcp_principal_memory_wrapper field was never read, which clippy (-D warnings) rejects. Report its size alongside the other managed-memory wrappers, matching every other lookup index. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cipal test The connect-flow pivot broke the #4026 per-app mcp e2e: - `mcpAuthorize` now calls `mcp_set_access` on the backend, which reads the BE `mcp_server_origin` — but the e2e only set it on the frontend canister. Add it to the backend install args in canister-tests.yml so the connect (and its delegation post) succeeds. - Remove "MCP acts as the same principal /authorize gives for that app": the browser flow no longer derives per-app — it issues the standing credential for the configured MCP-server origin, and per-app delegations are minted server-side by mcp_prepare/get_account_delegation (parity test belongs there). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…+ config Holistic split: the per-app principal check (removed from the e2e suite) is canister logic, so it lives here as an integration test, alongside the rest of the backend behaviour. The browser e2e keeps only the connect-flow UX. - tests/integration/mcp.rs: caller-authorized minting (anchor recovered from the index, no anchor_number arg), 5-min TTL cap, principal-derivation parity with the regular account-delegation API, opt-in/revoke, and path-disabled-without- mcp_server_origin. - tests/integration/config/mcp_server_origin.rs: init/update/retain round-trip, mirroring the other config fields. - api_v2 bindings for mcp_set_access / mcp_access_enabled / mcp_prepare_account_delegation / mcp_get_account_delegation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Brings the MCP backend-delegation branch up to date with the latest main (data-only OpenID providers + on-demand SSO discovery/JWKS caches, the form_post OpenID callback, session delegations, refreshed sign-in dialogs, etc.). Conflict resolved in the generated frontend candid binding src/frontend/src/lib/generated/internet_identity_types.d.ts: regenerated with the pinned didc from the merged .did so the file is main's binding plus the mcp_* methods and the mcp_server_origin config field.
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.
What this is
This branch is #4034 (
sea-snake:feat/mcp-backend-delegation) brought up to date with the latestmain, with the merge conflict resolved. #4034's head lives on an external fork that this environment can't push to, so the merged result is published here on adfinity/internet-identitybranch instead. It carries the full #4034 diff plus a merge of currentmain.What was done
main(66bd7bc) into the feat(be): backend /mcp account-delegation methods (MCP server acts as anchor) #4034 head (e3a9a9b) — GitHub "Update branch" semantics (merge base → head), preserving the original commits and authorship.src/frontend/src/lib/generated/internet_identity_types.d.ts:lookup_device_key: feat(be): backend /mcp account-delegation methods (MCP server acts as anchor) #4034 added themcp_*methods;mainadded a doc comment for theopenid_*methods..didusing the repo's pinneddidc(2025-12-18, sha256-verified). The result is byte-for-byte main's binding plus themcp_*methods and themcp_server_originconfig field — nothing else. This also dropped two stale doc comments that feat(be): backend /mcp account-delegation methods (MCP server acts as anchor) #4034 still carried from an oldermain.internet_identity_idl.js(auto-merged) was confirmed identical to the freshly generated output.internet_identity_frontend_*) were kept identical tomain(feat(be): backend /mcp account-delegation methods (MCP server acts as anchor) #4034 never touched that.did).Verification
cargo check -p internet_identity— clean.cargo test -p internet_identity --test integration --no-run— clean (includes feat(be): backend /mcp account-delegation methods (MCP server acts as anchor) #4034's newmcp.rs/config/mcp_server_origin.rs).didc.tsc/npm cicould not run in this environment (requires node ≥24/npm ≥11; node 22/npm 10 present) — this is unrelated to the merge:package.json/package-lock.jsonare byte-identical tomain.See #4034 for the feature description.
🤖 Generated with Claude Code
https://claude.ai/code/session_01CGvgPmEVcgyUP2mAnwnDcj
Generated by Claude Code