## Question
How should an MCP client refresh an expired token without replaying a completed write?
## Why this matters
Recurring public developer task for MCP.
## Environment / product
MCP
## What needs to be determined
Current researched guidance, applicability, limitations, and primary sources for this question.
Researched guidance is proposed, not an execution report.
Problem details
- Observed symptom
- How should an MCP client refresh an expired token without replaying a completed write?
- Context
- Recurring public developer task; researched guidance is proposed, not an execution report.
- Environment
- Unknown · not established
- Symptom signature
- Literal source
- Not supplied
- Expected behavior
- Not supplied
Known approaches
solution · Revision 1
Researched guidance: How should an MCP client refresh an expired token without replaying a completed write?
## Summary
Refresh credentials before retrying an MCP request only when the failure is a definite authentication rejection; do not blindly replay an MCP POST after an ambiguous disconnect or timeout.
## Candidate action
Use a single-flight OAuth refresh and a one-retry authentication path. For a definite MCP HTTP 401 with an invalid or expired bearer token, parse WWW-Authenticate, refresh at the authorization server (including MCP's required resource parameter), atomically replace the access token and any rotated refresh token, then retry the same logical JSON-RPC request at most once. Treat a connection loss, stream closure, or timeout after an MCP POST as an unknown write outcome: do not resend a non-idempotent operation unless the server documents idempotency/deduplication or the client can establish that the original was never applied. Reconcile through a server-supported status/query operation or ask for confirmation before retrying.
## Applicability
- MCP Streamable HTTP clients using OAuth bearer access tokens and JSON-RPC POST requests.
- Writes or other side-effecting tool calls where duplicate execution would be harmful.
- Servers that return a standards-compliant 401/WWW-Authenticate challenge and expose an authorization server or refresh-token flow.
## Procedure
- Before sending, refresh proactively when the client knows the access token is expired; serialize concurrent refreshes so callers use the same new token.
- On HTTP 401, parse WWW-Authenticate. Treat invalid_token/expired-token authentication failure as refreshable; do not treat 403 insufficient_scope as an expired-token case.
- Obtain the new access token from the authorization server with grant_type=refresh_token. MCP requires the resource parameter in token requests; never send the refresh token to the MCP resource server.
- If refresh succeeds, atomically publish the new access token and replace the stored refresh token when the authorization server rotates it. If refresh returns invalid_grant, stop and reauthorize instead of retrying repeatedly.
- Retry the original JSON-RPC request once with the new bearer token only when the response is a definite 401 authentication rejection. Keep the same logical operation identity; if the server supports an idempotency key, reuse that key.
- If the connection drops, an SSE stream closes, or a timeout occurs after the POST was sent, classify completion as unknown. Reconnect/resume the stream with Last-Event-ID when applicable, but do not resend the original POST merely because no response was observed.
- If completion is unknown, use an application/server status or result lookup, or obtain explicit confirmation before a new attempt. A server-specific idempotency or deduplication contract is the safe basis for an automatic retry.
## Key findings
- MCP servers must return 401 for invalid or expired access tokens, and clients must parse WWW-Authenticate; the authorization page does not define a dedicated refresh-after-401 algorithm. (S1)
- MCP sends every JSON-RPC message in a new HTTP POST; disconnect does not imply cancellation, and resumability uses GET plus Last-Event-ID rather than replaying the original POST. MCP does not define general request replay or write idempotence. (S2)
- Bearer-token guidance allows a client to request a new access token and retry the protected request for invalid_token, while RFC 9110 permits repeating a 401 request with a new Authorization header but warns against automatic retries of non-idempotent requests unless semantics are known or non-application is established. (S3, S5)
- OAuth refresh tokens are used at the authorization server, and a newly issued refresh token replaces the old one; the original protected-resource replay procedure is outside RFC 6749's scope. (S4)
- MCP requires the resource parameter in both authorization and token requests so the token is audience-bound to the target MCP server. (S1, S6)
## Known limitations
- MCP authorization specifies 401 handling and discovery but does not define a universal refresh-token implementation or a general retry budget for expired-token writes.
- MCP transport requires POST for JSON-RPC messages and does not declare JSON-RPC tool calls or writes idempotent; server method semantics remain application-specific.
- A 401 is defined as the request not being applied for lack of valid credentials, but implementations or intermediaries may still leave uncertainty in other failure classes; this rule must not be generalized to timeouts or disconnects.
- OAuth refresh-token issuance is optional, refresh tokens may rotate, and refresh failure can require a new authorization flow.
- No universal MCP idempotency-key or operation-status endpoint is defined by the cited sources.
## Obsolete approaches
- Blindly replaying every MCP POST after a timeout, connection reset, or stream disconnect.
- Refreshing on every authorization failure, including 403 insufficient_scope, or retrying indefinitely.
- Sending the OAuth refresh token in the MCP Authorization header or to the MCP resource endpoint.
- Treating SSE resumption with Last-Event-ID as permission to resend the original client POST.
## Negative results
- The MCP authorization page does not specify a separate client procedure for refreshing an access token after 401; it specifies 401 parsing/discovery and explicit retry guidance for insufficient-scope step-up.
- The MCP transport page does not define general request replay or write idempotence; its resumability guidance concerns server-to-client SSE messages after a disconnect.
- The cited standards do not provide a universal way to determine whether an MCP tool-side write completed after a transport failure.
## Evidence boundary
- This is researched proposed guidance from public MCP documentation and IETF RFCs, not an execution result.
- No MCP server call, write, PASS/FAIL outcome, or independent reproduction was performed.
- The safe distinction is definite authentication rejection versus ambiguous post-send transport failure; server-specific idempotency/status guarantees must remain explicit.
## What remains unknown
- Whether a particular MCP server authenticates before invoking a tool and whether it offers idempotency keys or operation-status lookup.
- Whether a particular proxy can generate or transform a 401 after application processing.
- The side effects and deduplication semantics of each server's JSON-RPC method.
- How a given authorization server handles refresh-token rotation, revocation, and concurrent refresh requests.
## Evidence
- basis: researched_guidance
- executed: false
- independent reproduction: false
## Sources
- [S1] Authorization - Model Context Protocol (2025-11-25) — https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization (official_documentation; accessed 2026-09-27)
- [S2] Transports - Model Context Protocol (2025-11-25) — https://modelcontextprotocol.io/specification/2025-11-25/basic/transports (official_documentation; accessed 2026-09-27)
- [S3] RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage — https://www.rfc-editor.org/rfc/rfc6750 (standard; accessed 2026-09-27)
- [S4] RFC 6749: The OAuth 2.0 Authorization Framework — https://www.rfc-editor.org/rfc/rfc6749 (standard; accessed 2026-09-27)
- [S5] RFC 9110: HTTP Semantics — https://www.rfc-editor.org/rfc/rfc9110 (standard; accessed 2026-09-27)
- [S6] RFC 8707: Resource Indicators for OAuth 2.0 — https://www.rfc-editor.org/rfc/rfc8707 (standard; accessed 2026-09-27)
- Problem id
- 790be7f9-02e7-4957-8813-4a2fe5397ac0
- Proposed action
- Use a single-flight OAuth refresh and a one-retry authentication path. For a definite MCP HTTP 401 with an invalid or expired bearer token, parse WWW-Authenticate, refresh at the authorization server (including MCP's required resource parameter), atomically replace the access token and any rotated refresh token, then retry the same logical JSON-RPC request at most once. Treat a connection loss, stream closure, or timeout after an MCP POST as an unknown write outcome: do not resend a non-idempotent operation unless the server documents idempotency/deduplication or the client can establish that the original was never applied. Reconcile through a server-supported status/query operation or ask for confirmation before retrying.
- Applicability
- State
- partial
- Text
- MCP Streamable HTTP clients using OAuth bearer access tokens and JSON-RPC POST requests. Writes or other side-effecting tool calls where duplicate execution would be harmful. Servers that return a standards-compliant 401/WWW-Authenticate challenge and expose an authorization server or refresh-token flow.
- Limitations
- State
- partial
- Text
- MCP authorization specifies 401 handling and discovery but does not define a universal refresh-token implementation or a general retry budget for expired-token writes. MCP transport requires POST for JSON-RPC messages and does not declare JSON-RPC tool calls or writes idempotent; server method semantics remain application-specific. A 401 is defined as the request not being applied for lack of valid credentials, but implementations or intermediaries may still leave uncertainty in other failure classes; this rule must not be generalized to timeouts or disconnects. OAuth refresh-token issuance is optional, refresh tokens may rotate, and refresh failure can require a new authorization flow. No universal MCP idempotency-key or operation-status endpoint is defined by the cited sources.
- Success criteria
- Not supplied
- Risk notes
- Not supplied
- Lifecycle
- active
- Pack
- Schema version
- 1
- Candidate action
- Use a single-flight OAuth refresh and a one-retry authentication path. For a definite MCP HTTP 401 with an invalid or expired bearer token, parse WWW-Authenticate, refresh at the authorization server (including MCP's required resource parameter), atomically replace the access token and any rotated refresh token, then retry the same logical JSON-RPC request at most once. Treat a connection loss, stream closure, or timeout after an MCP POST as an unknown write outcome: do not resend a non-idempotent operation unless the server documents idempotency/deduplication or the client can establish that the original was never applied. Reconcile through a server-supported status/query operation or ask for confirmation before retrying.
- Applicability
- MCP Streamable HTTP clients using OAuth bearer access tokens and JSON-RPC POST requests.
Writes or other side-effecting tool calls where duplicate execution would be harmful.
Servers that return a standards-compliant 401/WWW-Authenticate challenge and expose an authorization server or refresh-token flow. - Limitations
- MCP authorization specifies 401 handling and discovery but does not define a universal refresh-token implementation or a general retry budget for expired-token writes.
MCP transport requires POST for JSON-RPC messages and does not declare JSON-RPC tool calls or writes idempotent; server method semantics remain application-specific.
A 401 is defined as the request not being applied for lack of valid credentials, but implementations or intermediaries may still leave uncertainty in other failure classes; this rule must not be generalized to timeouts or disconnects.
OAuth refresh-token issuance is optional, refresh tokens may rotate, and refresh failure can require a new authorization flow.
No universal MCP idempotency-key or operation-status endpoint is defined by the cited sources. - Evidence boundary
- This is researched proposed guidance from public MCP documentation and IETF RFCs, not an execution result.
No MCP server call, write, PASS/FAIL outcome, or independent reproduction was performed.
The safe distinction is definite authentication rejection versus ambiguous post-send transport failure; server-specific idempotency/status guarantees must remain explicit. - What remains unknown
- Whether a particular MCP server authenticates before invoking a tool and whether it offers idempotency keys or operation-status lookup.
Whether a particular proxy can generate or transform a 401 after application processing.
The side effects and deduplication semantics of each server's JSON-RPC method.
How a given authorization server handles refresh-token rotation, revocation, and concurrent refresh requests. - Summary
- Refresh credentials before retrying an MCP request only when the failure is a definite authentication rejection; do not blindly replay an MCP POST after an ambiguous disconnect or timeout.
- Steps
- Before sending, refresh proactively when the client knows the access token is expired; serialize concurrent refreshes so callers use the same new token.
On HTTP 401, parse WWW-Authenticate. Treat invalid_token/expired-token authentication failure as refreshable; do not treat 403 insufficient_scope as an expired-token case.
Obtain the new access token from the authorization server with grant_type=refresh_token. MCP requires the resource parameter in token requests; never send the refresh token to the MCP resource server.
If refresh succeeds, atomically publish the new access token and replace the stored refresh token when the authorization server rotates it. If refresh returns invalid_grant, stop and reauthorize instead of retrying repeatedly.
Retry the original JSON-RPC request once with the new bearer token only when the response is a definite 401 authentication rejection. Keep the same logical operation identity; if the server supports an idempotency key, reuse that key.
If the connection drops, an SSE stream closes, or a timeout occurs after the POST was sent, classify completion as unknown. Reconnect/resume the stream with Last-Event-ID when applicable, but do not resend the original POST merely because no response was observed.
If completion is unknown, use an application/server status or result lookup, or obtain explicit confirmation before a new attempt. A server-specific idempotency or deduplication contract is the safe basis for an automatic retry. - Obsolete approaches
- Blindly replaying every MCP POST after a timeout, connection reset, or stream disconnect.
Refreshing on every authorization failure, including 403 insufficient_scope, or retrying indefinitely.
Sending the OAuth refresh token in the MCP Authorization header or to the MCP resource endpoint.
Treating SSE resumption with Last-Event-ID as permission to resend the original client POST. - Negative results
- The MCP authorization page does not specify a separate client procedure for refreshing an access token after 401; it specifies 401 parsing/discovery and explicit retry guidance for insufficient-scope step-up.
The MCP transport page does not define general request replay or write idempotence; its resumability guidance concerns server-to-client SSE messages after a disconnect.
The cited standards do not provide a universal way to determine whether an MCP tool-side write completed after a transport failure. - Key findings
- Text
- MCP servers must return 401 for invalid or expired access tokens, and clients must parse WWW-Authenticate; the authorization page does not define a dedicated refresh-after-401 algorithm.
- Source ids
- S1
- Text
- MCP sends every JSON-RPC message in a new HTTP POST; disconnect does not imply cancellation, and resumability uses GET plus Last-Event-ID rather than replaying the original POST. MCP does not define general request replay or write idempotence.
- Source ids
- S2
- Text
- Bearer-token guidance allows a client to request a new access token and retry the protected request for invalid_token, while RFC 9110 permits repeating a 401 request with a new Authorization header but warns against automatic retries of non-idempotent requests unless semantics are known or non-application is established.
- Source ids
- S3
S5
- Text
- OAuth refresh tokens are used at the authorization server, and a newly issued refresh token replaces the old one; the original protected-resource replay procedure is outside RFC 6749's scope.
- Source ids
- S4
- Text
- MCP requires the resource parameter in both authorization and token requests so the token is audience-bound to the target MCP server.
- Source ids
- S1
S6
- Research sources
- Id
- S1
- Title
- Authorization - Model Context Protocol (2025-11-25)
- Url
- https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization
- Source class
- official_documentation
- Accessed at
- 2026-09-27
- Id
- S2
- Title
- Transports - Model Context Protocol (2025-11-25)
- Url
- https://modelcontextprotocol.io/specification/2025-11-25/basic/transports
- Source class
- official_documentation
- Accessed at
- 2026-09-27
- Id
- S3
- Title
- RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage
- Url
- https://www.rfc-editor.org/rfc/rfc6750
- Source class
- standard
- Accessed at
- 2026-09-27
- Id
- S4
- Title
- RFC 6749: The OAuth 2.0 Authorization Framework
- Url
- https://www.rfc-editor.org/rfc/rfc6749
- Source class
- standard
- Accessed at
- 2026-09-27
- Id
- S5
- Title
- RFC 9110: HTTP Semantics
- Url
- https://www.rfc-editor.org/rfc/rfc9110
- Source class
- standard
- Accessed at
- 2026-09-27
- Id
- S6
- Title
- RFC 8707: Resource Indicators for OAuth 2.0
- Url
- https://www.rfc-editor.org/rfc/rfc8707
- Source class
- standard
- Accessed at
- 2026-09-27
Page 1 · 1 children total
Sources and related records
No source relations recorded.