• AgentArmor teamTeam3d agoNeeds helpSolved

    Codex MCP OAuth access token not refreshed after expiry despite stored refresh_token

    Codex (CLI up to 0.137.0 and Desktop builds through June 2026, on macOS and Windows) stores an MCP OAuth refresh_token in ~/.codex/.credentials.json or the macOS Keychain, but after the access token expires, MCP tool calls fail with invalid_grant, invalid_token, or Auth required instead of automatically refreshing. Running codex mcp login, restarting the MCP server, or starting a new chat restores access temporarily. Is this a known limitation and is there a supported workaround?

    Originally asked on GitHub: https://github.com/openai/codex/issues/17265

    5 answers

    • Best answerAgentArmor teamTeam3d ago

      Status: open. As of the latest reports in the thread, Codex does not automatically refresh an expired MCP OAuth access token, either before MCP initialization or after receiving a 401 invalid_token signal, and no maintainer fix is recorded here.

      Multiple reporters verified the provider side is healthy: the stored refresh_token is valid, a direct POST to the token endpoint with grant_type=refresh_token returns HTTP 200 with a fresh access token, and using that fresh token immediately makes MCP initialize succeed. The failure is in Codex's MCP runtime, which keeps using the stale cached access token. One controlled test showed that manually writing the refreshed token response into the existing macOS Keychain item 'Codex MCP Credentials' made the next codex exec succeed, proving Codex can read stored credentials but does not refresh them itself. Other reports indicate the Codex Desktop app may reuse a ChatGPT-client token for the same MCP server, and that multiple sessions can rotate refresh tokens while older sessions keep stale generations.

      Workarounds reported in the thread:

      • Re-run codex mcp login to restore access temporarily.
      • In Codex Desktop, go to Settings -> MCP Servers, toggle the affected server off and on, then click Restart; this works until the next expiry.
      • Start a new chat, which forces a fresh MCP session initialize and picks up a refreshed token.

      General advice: the credential store contains live OAuth tokens, so keep it readable only by your user account.

      Did this work for you?
    • AgentArmor teamTeam3d ago

      What @drkvj tried on GitHub (Worked)

      After a direct refresh with the stored refresh_token returned a fresh access token, manually wrote that fresh token response into the existing 'Codex MCP Credentials' Keychain item. A fresh codex exec then succeeded in exposing and calling the MCP tool.

      Source: https://github.com/openai/codex/issues/17265#issuecomment-4639128590 (opens external site)

      Did this work for you?
    • AgentArmor teamTeam3d ago

      What @Cyanoth tried on GitHub (Partly worked)

      In Codex Desktop, toggled the affected MCP server off and on in Settings and clicked Restart, which restored tool calls in the current chat temporarily until the access token expired again. Starting a new chat also made the MCP server work again.

      Source: https://github.com/openai/codex/issues/17265#issuecomment-4311947145 (opens external site)

      Did this work for you?
    • AgentArmor teamTeam3d ago

      What @w00ing tried on GitHub (Partly worked)

      On codex-cli 0.130.0 with the Mixpanel MCP server, re-ran codex mcp login mixpanel after the stored access token was rejected; this restored the Keychain credential and MCP access temporarily.

      Source: https://github.com/openai/codex/issues/17265#issuecomment-4428199017 (opens external site)

      Did this work for you?
    • AgentArmor teamTeam3d ago

      What @infoseekAI tried on GitHub (Didn't work)

      Confirmed that codex mcp login succeeds, valid tokens are stored, direct refresh works, and direct authenticated MCP calls work, but built-in MCP tool calls still return 401 oauth_required after the token expires.

      Source: https://github.com/openai/codex/issues/17265#issuecomment-4227175386 (opens external site)

      Did this work for you?

    Add your answer or comment