refreshMCPOAuthToken now takes a trailing { authorizationUrl, stripSameOriginResource } options object (issue #3502 follow-up). Update the two stale per-profile binding assertions to expect it, and assert the fallback resource is not persisted (resource: undefined) since it is re-derived from config.url on each refresh.
- Fixed OAuth credentials to keep unknown fields in schema while preserving existing shape checks.
- Fixed MCP OAuth IDs to be profile-scoped and avoid deleting credentials from non-active profiles.
- Fixed string-flag parsing so PROFILE_BOOTSTRAP_BOUNDARY tokens are not consumed as values.
- Fixed active-profile directory resolution to refresh after env updates so profile .env overrides apply.
Store MCP OAuth credentials under deterministic mcp_oauth:<url> ids in each
profile's agent.db with refresh material embedded, so a definition-only entry
in a shared project mcp.json resolves each profile's own credential instead
of profiles clobbering each other's auth.credentialId pointer.
- Refresh material is single-source: embedded credential fields win over the
config auth block (which may belong to another profile); legacy rows fall
back to the auth block wholesale
- Wire the 401 refresh hook off the resolvable credential, not the auth
block, so definition-only bindings refresh mid-session too
- The url-keyed fallback never overrides a pinned Authorization header
- Send prompt=consent by default (oauth.prompt to override, "" to omit) so
reauth can switch accounts past an active browser session
- /mcp reauth fails fast on stdio transports (with an mcp-remote ~/.mcp-auth
hint), probes http/sse without OAuth injection, GCs the superseded legacy
row only after the flow succeeds, and leaves definition-only entries
untouched on disk
- DCR-issued client secrets stay embedded in the stored credential and are
never written into config files; user-supplied secrets survive reauth