[BUG] MCP OAuth refresh started during session shutdown is abandoned, and the server ends up logged out

Status Open
Reported on v2.1.289
Maintainer reply None cached
Activity 0 comments · opened Oct 5, 2026

Environment

  • Claude Code 2.1.289, macOS 26.6.2
  • Two user-scoped HTTP MCP servers on https://mcp.atlassian.com/v2/mcp (atlassian-a and atlassian-b), each with its own OAuth login
  • Several Claude Code sessions open and closed during the day
  • Debug logging enabled with DEBUG=1

What happens

Every 2 or 3 days both servers show up as needing authentication again, although nothing changed on the Atlassian side.

From the debug logs, I think the sequence is the following:

  1. The access tokens (8 hours) expire while no session is refreshing them.
  2. A session that has been idle is closed. During its shutdown it notices the expired tokens, takes the refresh lock and starts a refresh.
  3. The process exits about 150 ms later. No "Saving tokens" and no "Released refresh lock" line is logged.
  4. The next session tries to refresh with the stored refresh token, the authorization server rejects it, and Claude Code clears the stored credentials.

Atlassian rotates the refresh token on each use, so ISTM the refresh in step 2 reached the server and the new refresh token was lost when the process exited. This step is an inference: the log does not show the HTTP request or the response.

Logs

Session being closed (the shutdown starts at 23:27:06.510, the refresh starts after it):

2026-10-04T23:27:06.510Z [DEBUG] MCP server "other-stdio-server": Sending SIGINT to MCP server process
2026-10-04T23:27:06.551Z [DEBUG] MCP server "atlassian-a": Token expires in -730s, attempting proactive refresh
2026-10-04T23:27:06.551Z [DEBUG] MCP server "atlassian-b": Token expires in -729s, attempting proactive refresh
2026-10-04T23:27:06.553Z [DEBUG] MCP server "atlassian-a": Acquired refresh lock
2026-10-04T23:27:06.554Z [DEBUG] MCP server "atlassian-b": Acquired refresh lock
2026-10-04T23:27:06.601Z [DEBUG] MCP server "atlassian-a": Starting token refresh
2026-10-04T23:27:06.603Z [DEBUG] MCP server "atlassian-b": Starting token refresh
2026-10-04T23:27:06.981Z [DEBUG] MCP server "atlassian-a": Found client info
2026-10-04T23:27:06.987Z [DEBUG] MCP server "atlassian-b": Found client info
2026-10-04T23:27:07.130Z [DEBUG] [REPL:unmount] REPL unmounting

Next session, 31 minutes later:

2026-10-04T23:58:43.344Z [DEBUG] MCP server "atlassian-a": Token expires in -2626s, attempting proactive refresh
2026-10-04T23:58:43.344Z [DEBUG] MCP server "atlassian-b": Token expires in -2626s, attempting proactive refresh
2026-10-04T23:58:43.501Z [DEBUG] MCP server "atlassian-b": Starting token refresh
2026-10-04T23:58:43.506Z [DEBUG] MCP server "atlassian-a": Starting token refresh
2026-10-04T23:58:44.155Z [DEBUG] MCP server "atlassian-b": Token refresh failed: DCR client expired or invalid; clearing stored client registration
2026-10-04T23:58:44.171Z [DEBUG] MCP server "atlassian-a": Token refresh failed: DCR client expired or invalid; clearing stored client registration
2026-10-04T23:58:44.227Z [DEBUG] MCP server "atlassian-b": Invalidated credentials (scope: all)
2026-10-04T23:58:44.286Z [DEBUG] MCP server "atlassian-a": Invalidated credentials (scope: all)
2026-10-04T23:58:45.301Z [ERROR] MCP server "atlassian-a" McpClientRegistrationDeferredError: Authentication required; client registration is deferred until the user authenticates

The six refreshes logged before this one, including one where two sessions waited on the refresh lock, completed and saved their tokens.

Related

  • #95822 describes the same kind of abandoned refresh for the Claude account login in short-lived commands. This report is about MCP server logins, in an interactive session being closed.
  • #16957 (closed) was about an exit-time refresh not being persisted.
  • #93537 is about MCP OAuth entries being emptied with concurrent processes. Here a single process was involved in the lost refresh.

Steps to reproduce

I have not reproduced it on demand. I think these steps would do it:

  1. Log in to an HTTP MCP server whose authorization server rotates refresh tokens (e.g. https://mcp.atlassian.com/v2/mcp).
  2. Leave a session open and idle until the access token expires, with no other session running.
  3. Close that session.
  4. Start a new session and check the server status.

Expected

The login survives closing a session.

Suggestion

I would suggest either skipping the proactive refresh once shutdown has started, or waiting for a refresh already in flight to complete and save its tokens before exiting.

A side note: the message "DCR client expired or invalid" may be misleading here, since the stored client ID was https://claude.ai/oauth/claude-code-client-metadata and not a dynamically registered client.

View original on GitHub ↗