Skip to content

MCP OAuth refresh races across concurrent expired requests #34074

Closed as not planned

Description

@mroffmix

Description

When several MCP tool calls run in parallel and the OAuth access token has expired, each request independently runs the refresh-token grant with the same stored refresh token. Because the authorization server rotates refresh tokens, one refresh succeeds and the others fail with invalid_grant. The SDK then invalidates the stored credentials, so the MCP server drops to needs_auth and a manual opencode mcp auth <server> is required.

Same race that #28234 fixed for the Codex OAuth provider, but in the MCP Streamable HTTP transport. Related symptom: #21702. Surfaced while fixing #34034 (configured scopes are needed for the AS to issue a refresh token in the first place).

Plugins

No response

OpenCode version

dev

Steps to reproduce

  1. Configure a remote OAuth MCP server (Streamable HTTP) whose scope includes offline_access so a refresh token is stored.
  2. Let the access token expire (~15 min).
  3. In one turn, trigger several MCP tool calls at once.
  4. Some calls return Unauthorized; mcp-auth.json loses its refreshToken; the server drops to needs_auth.

Expected: concurrent expired requests share a single refresh instead of each refreshing and racing the rotating token.

Screenshot and/or share link

No response

Operating System

macOS

Terminal

Ghostty

Activity

  1. github-actions commented on Aug 26, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions