Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .sources/VERSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ motoko-core v2.4.0
cdk-rs ic-cdk v0.20.1 / ic-cdk-timers v1.0.0 / ic-cdk-executor v2.0.0 317f55c
candid 2025-12-18 # candid v0.10.20, didc v0.5.4 2e4a2cf
response-verification v3.1.0 18c5a37
internetidentity release-2026-07-06 37670ecf
internetidentity release-2026-07-17 8ffbe6f6
2 changes: 1 addition & 1 deletion .sources/internetidentity
Submodule internetidentity updated 90 files
+14 −102 demos/using-dev-build/package-lock.json
+252 −160 docs/mcp-server-guide.md
+89 −39 package-lock.json
+2 −1 package.json
+3 −12 src/canister_tests/src/api/internet_identity.rs
+45 −9 src/canister_tests/src/api/internet_identity/api_v2.rs
+15 −1 src/frontend/src/hooks.client.ts
+53 −0 src/frontend/src/lib/components/ui/AccessLevelSelector.svelte
+0 −72 src/frontend/src/lib/components/ui/AccessLevelToggle.svelte
+20 −9 src/frontend/src/lib/components/ui/HoldToConfirm.svelte
+1 −0 src/frontend/src/lib/constants/store.constants.ts
+189 −1 src/frontend/src/lib/flows/authFlow.svelte.test.ts
+86 −43 src/frontend/src/lib/flows/authFlow.svelte.ts
+26 −4 src/frontend/src/lib/generated/internet_identity_idl.js
+21 −23 src/frontend/src/lib/generated/internet_identity_types.d.ts
+1 −1 src/frontend/src/lib/globals.ts
+17 −0 src/frontend/src/lib/icons/multidex_logo.svg
+121 −8 src/frontend/src/lib/legacy/flows/dappsExplorer/dapps.json
+62 −0 src/frontend/src/lib/legacy/flows/dappsExplorer/dapps.test.ts
+1 −0 src/frontend/src/lib/legacy/flows/dappsExplorer/dapps.ts
+1 −0 src/frontend/src/lib/legacy/flows/verifiableCredentials/allowCredentials.ts
+1 −0 src/frontend/src/lib/legacy/flows/verifiableCredentials/index.ts
+13 −7 src/frontend/src/lib/state/featureFlags.ts
+58 −0 src/frontend/src/lib/stores/access-level.store.test.ts
+58 −0 src/frontend/src/lib/stores/access-level.store.ts
+1 −1 src/frontend/src/lib/stores/authentication.store.ts
+9 −6 src/frontend/src/lib/stores/channelHandlers/delegation.ts
+1 −0 src/frontend/src/lib/stores/session-delegation.store.test.ts
+1 −1 src/frontend/src/lib/stores/session-delegation.store.ts
+1 −1 src/frontend/src/lib/stores/session.store.ts
+1 −45 src/frontend/src/lib/utils/accessLevel.test.ts
+0 −24 src/frontend/src/lib/utils/accessLevel.ts
+98 −0 src/frontend/src/lib/utils/analytics/analytics.test.ts
+77 −19 src/frontend/src/lib/utils/analytics/analytics.ts
+178 −0 src/frontend/src/lib/utils/authCallbacks.test.ts
+165 −0 src/frontend/src/lib/utils/authCallbacks.ts
+1 −0 src/frontend/src/lib/utils/authentication/sessionDelegation.test.ts
+3 −1 src/frontend/src/lib/utils/discoverablePasskeyIdentity.ts
+13 −0 src/frontend/src/lib/utils/mcpConfig.ts
+121 −0 src/frontend/src/lib/utils/transport/legacy.test.ts
+9 −3 src/frontend/src/lib/utils/transport/legacy.ts
+86 −0 src/frontend/src/lib/utils/transport/utils.test.ts
+11 −1 src/frontend/src/lib/utils/transport/utils.ts
+40 −0 src/frontend/src/lib/utils/utils.test.ts
+23 −0 src/frontend/src/lib/utils/utils.ts
+8 −1 src/frontend/src/routes/(new-styling)/authorize/+page.svelte
+72 −31 src/frontend/src/routes/(new-styling)/authorize/views/ContinueView.svelte
+2 −1 src/frontend/src/routes/(new-styling)/cli/utils.ts
+40 −17 src/frontend/src/routes/(new-styling)/cli/views/CliAuthorizeView.svelte
+219 −0 src/frontend/src/routes/(new-styling)/manage/(authenticated)/settings/components/McpAddConnectorDialog.svelte
+90 −214 ...rontend/src/routes/(new-styling)/manage/(authenticated)/settings/components/McpTrustedServersSection.svelte
+112 −30 src/frontend/src/routes/(new-styling)/mcp/+page.svelte
+77 −69 src/frontend/src/routes/(new-styling)/mcp/+page.ts
+38 −7 src/frontend/src/routes/(new-styling)/mcp/load.test.ts
+183 −286 src/frontend/src/routes/(new-styling)/mcp/utils.test.ts
+123 −158 src/frontend/src/routes/(new-styling)/mcp/utils.ts
+87 −37 src/frontend/src/routes/(new-styling)/mcp/views/McpAuthorizeView.svelte
+13 −14 src/frontend/src/routes/(new-styling)/mcp/views/McpCloseWindowView.svelte
+4 −4 src/frontend/src/routes/(new-styling)/mcp/views/McpConnectingView.svelte
+1 −5 src/frontend/src/routes/+layout.svelte
+256 −103 src/frontend/tests/e2e-playwright/fixtures/mcp.ts
+5 −2 src/frontend/tests/e2e-playwright/routes/authorize/index.spec.ts
+130 −0 src/frontend/tests/e2e-playwright/routes/authorize/openid.spec.ts
+39 −0 src/frontend/tests/e2e-playwright/routes/authorize/sso.spec.ts
+4 −4 src/frontend/tests/e2e-playwright/routes/cli.spec.ts
+3 −0 src/frontend/tests/e2e-playwright/routes/index.spec.ts
+20 −2 src/frontend/tests/e2e-playwright/routes/manage/index.spec.ts
+245 −130 src/frontend/tests/e2e-playwright/routes/mcp.spec.ts
+7 −7 src/frontend/tests/e2e-playwright/utils.ts
+1 −1 src/frontend/tests/e2e-playwright/utils/dnssecTestSigner.ts
+1 −1 src/frontend/tests/e2e-playwright/utils/renderDnssecTestAnchor.mjs
+58 −26 src/internet_identity/internet_identity.did
+55 −32 src/internet_identity/src/main.rs
+36 −9 src/internet_identity/src/mcp.rs
+420 −0 src/internet_identity/src/mcp_registration.rs
+1 −1 src/internet_identity/src/openid.rs
+114 −31 src/internet_identity/src/openid/sso.rs
+81 −0 src/internet_identity/src/openid/verify.rs
+1 −1 src/internet_identity/src/state.rs
+96 −2 src/internet_identity/src/storage.rs
+1 −0 src/internet_identity/src/storage/storable.rs
+51 −8 src/internet_identity/src/storage/storable/mcp_config.rs
+7 −5 src/internet_identity/src/storage/storable/mcp_grant.rs
+97 −0 src/internet_identity/src/storage/storable/mcp_registration.rs
+31 −0 src/internet_identity/tests/integration/config/sso_discovery.rs
+11 −6 src/internet_identity/tests/integration/delegation_ingress.rs
+732 −138 src/internet_identity/tests/integration/mcp.rs
+118 −0 src/internet_identity/tests/integration/openid.rs
+30 −4 src/internet_identity_interface/src/internet_identity/types.rs
+1 −1 src/internet_identity_interface/src/internet_identity/types/attributes.rs
84 changes: 58 additions & 26 deletions public/references/internet-identity.did
Original file line number Diff line number Diff line change
Expand Up @@ -1124,11 +1124,23 @@ type McpConfig = record {
url : opt text;
};

// Result of mcp_register: the expiration (ns since epoch) of the MCP session
// grant just registered. Every server-facing mcp_* call returns Unauthorized
// once it passes; the server reconnects through a new consent flow.
type McpRegistration = record {
// Result of prepare_mcp_registration_delegation: the canister-signature public
// key the registration delegation is rooted at (P_reg), and the (short)
// expiration of that delegation. The frontend fetches the signed delegation via
// get_mcp_registration_delegation and delivers the chain to the trusted MCP
// server, which redeems it with mcp_register_v2.
type PrepareMcpRegistrationDelegation = record {
user_key : UserKey;
expiration : Timestamp;
};

// Result of mcp_register_v2: the expiration (ns since epoch) of the MCP session
// grant, plus the access level the user chose at connect (queries = read-only,
// all = full). The server reads permissions to learn the read-only state up
// front (the v2 flow has no completion POST carrying it).
type McpRegistrationV2 = record {
expiration : Timestamp;
permissions : Permissions;
};

type GetAccountsError = variant {
Expand Down Expand Up @@ -1819,28 +1831,6 @@ service : (opt InternetIdentityInit) -> {
permissions : opt Permissions
) -> (variant { Ok : SignedDelegation; Err : AccountDelegationError }) query;

// Register the trusted MCP server's session key for the anchor: grant the
// key's self-authenticating principal access to the server-facing mcp_*
// methods until the grant expires (grant_ttl_ns clamped to [10 min, 30
// days]). Called by the /mcp connect flow after user consent, with a key
// the frontend fetched from the *trusted* server's callback — never taken
// from the unauthenticated connect link. No account is chosen here
// (accounts are per-origin and the connector isn't an app) — the app
// account is selected per call on mcp_prepare_delegation.
//
// At most one session per identity: registering replaces any previous
// grant. Requires the identity's MCP config to be enabled with a trusted
// server set, so every session stays revocable via mcp_set_config.
mcp_register : (
anchor_number : UserNumber,
session_key : SessionKey,
grant_ttl_ns : nat64,
// `opt (queries)` makes every per-app delegation this session later
// mints queries-only (read-only, chosen once for the whole session).
// Omitted (`null`) or `opt (all)` means full, update-capable access.
permissions : opt Permissions
) -> (variant { Ok : McpRegistration; Err : text });

// Read the identity's synced trusted-MCP-server config (master toggle + the
// trusted server URL). Persisted on-chain, so it follows the identity across
// devices. Read by the Settings UI and the /mcp connect flow (which verifies
Expand Down Expand Up @@ -1905,6 +1895,48 @@ service : (opt InternetIdentityInit) -> {
expiration : Timestamp
) -> (variant { Ok : SignedDelegation; Err : SessionDelegationError }) query;

// Mint a short-lived MCP registration delegation (P_reg -> registration_key).
// Authenticated as the identity (only the consenting user can create one).
// registration_key is an ephemeral key the II frontend generates for this
// connect (browser-held — the canister never delegates to a key taken from
// the connect link; the frontend extends the chain to the server's key
// browser-side). P_reg is derived from a fresh random nonce, and the whole
// consent — the anchor, permissions (read-only choice), max_ttl (session-
// grant lifetime), and the identity's current trusted-server URL — is
// recorded on an index entry keyed by P_reg, so mcp_register_v2 recovers it
// server-side and the server cannot alter any of it.
prepare_mcp_registration_delegation : (
anchor_number : UserNumber,
registration_key : SessionKey,
permissions : opt Permissions,
max_ttl : opt nat64
) -> (variant { Ok : PrepareMcpRegistrationDelegation; Err : text });

// Fetch the signed registration delegation prepared above, to deliver to the
// trusted MCP server. Authenticated as the identity, like the prepare call.
// user_key is the value the prepare call returned; the seed is recovered
// from it, so no consent parameters need re-passing.
get_mcp_registration_delegation : (
anchor_number : UserNumber,
registration_key : SessionKey,
user_key : PublicKey,
expiration : Timestamp
) -> (variant { Ok : SignedDelegation; Err : text }) query;

// Called by the trusted MCP server, authenticated by the registration
// delegation chain: bind the server's long-lived session_key to the
// consenting anchor. The entire consent — anchor, read-only choice, grant
// lifetime — is recovered from the entry keyed by caller() (the registration
// principal), so the server passes only session_key: it cannot name a
// different anchor, upgrade the access level or stretch the grant, and never
// learns the anchor number. A trusted-server switch or disable since consent
// invalidates the delegation. Usable until the registration delegation
// expires (~5 min); re-registration within that window replaces the anchor's
// single MCP session.
mcp_register_v2 : (
session_key : SessionKey
) -> (variant { Ok : McpRegistrationV2; Err : text });

get_default_account : (
anchor_number : UserNumber,
origin : FrontendHostname,
Expand Down
Loading