Skip to content

mcp: re-mint expired managed proxy tokens on demand instead of failing or misrouting to OAuth - #15538

Draft
Legoben wants to merge 1 commit into
bens/mcp_broaden_reconnect_retry_add_per-server_backoff_keep_tools_visible_during_reconnectfrom
bens/mcp_re-mint_expired_managed_proxy_tokens_on_demand_instead_of_failing_or_misrouting_to_oauth
Draft

mcp: re-mint expired managed proxy tokens on demand instead of failing or misrouting to OAuth#15538
Legoben wants to merge 1 commit into
bens/mcp_broaden_reconnect_retry_add_per-server_backoff_keep_tools_visible_during_reconnectfrom
bens/mcp_re-mint_expired_managed_proxy_tokens_on_demand_instead_of_failing_or_misrouting_to_oauth

Conversation

@Legoben

@Legoben Legoben commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Problem

Managed (backend-proxied) MCP servers authenticate with a short-lived proxy session token minted once per run via createManagedMcpClientConfig. Six of the mutation's eight response fields were dead code; nothing retained the managed uid. When the token expired (external sessions: 3h), every tool call failed for the rest of the run — the explicit v1 deferral in specs/managed-mcp-cli-resolution/TECH.md. Worse, an expired token at spawn time routed into the interactive OAuth flow with a misleading "Please authenticate this server in the Warp desktop app" message.

Changes

  • Resolution now records each managed installation's uid (ResolvedMcpSpecs.managed_uids).
  • Managed ephemerals spawn via spawn_managed_ephemeral_server carrying an InstallationRefresher: a closure that re-mints the client config (bounded retry — it sits on the tool-call latency path), re-parses it, and rebuilds the installation preserving the installation UUID (random for local runs, keys all manager state) and template UUID (keys the log file), then re-applies secrets.
  • reconnect_server invokes the refresher before respawning a managed server, so the end-to-end reactive path is: mid-run 401 proxy_token_expired → classified recoverable (prev PR) → retry via reconnect → re-mint → respawn with the fresh header → tool call succeeds, nothing surfaced to the user. Overlap-safe: proxy sessions are stateless JWTs server-side; the old token stays valid until its expiry.
  • Startup-401 misroute fix: the preflight now captures WWW-Authenticate, and a proxy re-mint reason returns a typed AuthRequired { reason: Some(..) } instead of entering the OAuth flow (no credential deletion either, per the guard in the classification PR).

Flag-gated by McpSelfHeal. Not covered (by design): third-party harnesses receive rendered JSON config and own their MCP connections; and an initial spawn hitting AuthRequired does not auto-re-mint — resolution happens seconds before spawn, so a token expired at that point indicates clock skew rather than age.

Tests

MockManagedMcpClient tests: refresher preserves identities and swaps only the Authorization value (asserted via rendered config), errors cleanly when the server disappears from the re-minted config, resolution records uids for both UUID and well-known specs; axum test asserts the preflight returns AuthRequired{Some(ProxyTokenExpired)} instead of the OAuth path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant