Repository navigation
Supabase MCP repeatedly requires reauthentication: OAuth token refresh failed during initialize #13852
Description
What version of Codex CLI is running?
codex-cli 0.111.0
What subscription do you have?
Unknown
Which model were you using?
Unknown
What platform is your computer?
Darwin 25.3.0 arm64 arm
What terminal emulator and version are you using (if applicable)?
Ghostty
What issue are you seeing?
My Supabase MCP integration seems to require reauthentication repeatedly.
After previously authenticating Supabase MCP, Codex sometimes starts with this error instead of refreshing the existing auth session:
⚠ MCP client for `supabase` failed to start: MCP startup failed: handshaking with MCP server
failed: Send message error Transport
[rmcp::transport::worker::WorkerTransport<rmcp::transport::streamable_http_client::StreamableHttp
ClientWorker<rmcp::transport::auth::AuthClient<reqwest::async_impl::client::Client>>>] error:
Auth error: OAuth token refresh failed: Failed to parse server response, when send initialize
request
⚠ MCP startup incomplete (failed: supabase)
The practical result is that I have to authenticate Supabase again and again, even though the expected behavior seems to be token refresh or stable session reuse.
What steps can reproduce the bug?
- Configure the Supabase MCP server in Codex CLI and authenticate it successfully.
- Use Codex normally for some time, or return in a later session after the auth/token has aged.
- Start Codex again.
- Observe that Supabase MCP sometimes fails during startup with the refresh/initialize error above.
- Reauthenticate Supabase MCP to get it working again, until the cycle repeats.
I have not pinned down a minimal deterministic repro beyond the repeated pattern above.
What is the expected behavior?
If the stored auth session is still refreshable, Codex should refresh it successfully and start the Supabase MCP server without manual intervention.
If the auth session is invalid, Codex should report that clearly rather than failing during MCP initialize with a parse error.
Additional information
This looks related to the broader MCP OAuth / handshake issues that have been reported before, but I could not find an existing issue with this exact Supabase error string.
Potentially related reports:
- mcp oauth (experimental) not working with supabase mcp #5254
- MCP client for
Xfailed to start: handshaking with MCP server failed: connection closed: initialize response #6020 - rmcp OAuth tokens never refresh based on expires_at #6572
- Codex MCP requiring constant re-auth to Wiz #9535
- Supabase works in the CLI, but fails in the app #11297
The key detail here is the combination of:
- Supabase MCP
- repeated reauthentication requirement
OAuth token refresh failedFailed to parse server response- failure while sending the MCP
initializerequest
If maintainers want, I can provide more environment details or try with additional logging enabled.
Activity
github-actions commentedon Mar 7, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
markussmueller commentedon Mar 7, 2026
I reviewed the bot suggestions and I don't think either is a true duplicate:
streamable_httpinitialize/response-decoding issue using a PAT, and it was closed in favor of Cannot initialize Streamable HTTP MCP servers #11284 (Cannot initialize Streamable HTTP MCP servers). That looks like a broader transport compatibility problem, but not specifically an OAuth refresh / repeated reauthentication failure.This issue is specifically about Supabase MCP auth refresh failing during startup:
Auth error: OAuth token refresh failed: Failed to parse server response, when send initialize requestThe distinctive behavior here is that Supabase appears to require repeated manual reauthentication instead of refreshing the stored auth session.
So there may be some shared initialize/handshake surface area, but I don't think this should be closed as a duplicate of either suggested issue.
markussmueller commentedon Mar 7, 2026
Additional data point: I previously contacted Supabase support about this, and they indicated they believe this is on the Codex side rather than the Supabase side.
They specifically pointed me to #6020 as a related Codex MCP startup/handshake issue affecting other MCP servers as well.
I still don't think this issue is a strict duplicate of #6020, because the observable failure here is specifically:
Auth error: OAuth token refresh failed: Failed to parse server response, when send initialize requestand the user-facing behavior is repeated manual reauthentication for Supabase.
But this does seem like more evidence that the root cause may live in the Codex MCP client / rmcp auth+initialize path rather than in Supabase alone.
thedaviddias commentedon Mar 9, 2026
Faced the issue today where:
Compared to other tools like Claude Code, the experience is really not great. Codex should trigger opening the auth page if the token needs to be refreshed.
gabrieuz commentedon Mar 11, 2026
codex mcp login supabasesolve the problem to me.venkat0304 commentedon May 9, 2026
I am running below command every other day to authenticate with supabase. But, on claude code i connected like a 2 months back and its still working. Wondering how to make the connection work without breaking.
codex mcp login supabaseID 019e0e56-91e1-7932-ab6c-2953ce75cee6
alexgshaw commentedon May 17, 2026
Also running into this issue
jmo-sg commentedon May 20, 2026
This issue affects me and I use both Codex and Claude. I often have to restart Codex after manual reauthentication which is a real time waster. Claude does not suffer this issue.
Starvingg commentedon May 24, 2026
Any update on this issue? The MCP Server connection is buggy. Sometimes it works if explicitly asked. But if Codex gives me a plan with Supabase as a consideration, it should run the Migration file that was created.
1 remaining item
zeevenn commentedon Jul 16, 2026
some issue
mvjpalsson commentedon Jul 24, 2026
Same issue. Claude doesnt' have this issue, only Codex/ChatGPT in my experience.
hemao612 commentedon Jul 27, 2026
Same issue. Claude doesnt' have this issue, only Codex/ChatGPT in my experience.
StillNotYet commentedon Jul 28, 2026
Confirmed still reproducible in Codex Desktop on macOS 26.5.2 arm64 with the bundled codex-cli 0.146.0-alpha.3.1.
I reproduced this through the app-server MCP status path after the stored Supabase OAuth token had expired. The relevant logs are:
The resulting Supabase MCP status had authStatus oAuth, with no serverInfo and no tools loaded.
The remote Supabase MCP is project-scoped and configured with read_only=true. No new login was initiated during this diagnostic. The stored OAuth credentials were found and a refresh was attempted, but the refresh response failed to parse. This indicates that the issue persists beyond 0.111.0 and is not simply caused by credentials failing to persist locally.
m13v commentedon Jul 28, 2026
the 'just reauth on refresh failure' path is where a retryable error goes quiet.
Failed to parse server responseduring initialize is a transport/bad-body problem, not proof the session is invalid, but if refresh treats any failure as auth-dead it drops a still-refreshable token and surfaces 'reauthenticate' as the handled state. so the loud retryable case gets laundered into the quiet 'session expired' one and you can't tell which actually happened. logging the refresh http status separately from the parse step, before deciding to drop the token, is what keeps the two apart.azolotov commentedon Jul 30, 2026
Additional data point from July 30, 2026: this is still reproducible with
codex-cli 0.146.0on Darwin 25.5.0 arm64, and in my case reauthentication did not restore the MCP even for a fresh startup.I tested a custom MCP server protected by Supabase OAuth 2.1:
codex mcp logout <server>.codex mcp login <server>and completed the browser flow successfully.Codex MCP CredentialsKeychain item was updated.The startup logs show that Codex successfully loaded the newly updated credential:
It then immediately failed:
The MCP request subsequently returned 401 with
No authorization provided, and Codex omitted the server entirely—no tools were loaded. The message is presented as a startup warning, but the MCP is actually unavailable.I also confirmed that both the protected-resource metadata and Supabase authorization-server metadata endpoints return HTTP 200 with valid JSON. Discovery succeeds and advertises the standard Supabase
/auth/v1/oauth/tokenendpoint withrefresh_tokensupport.So this does not appear to be only an aged or missing credential: a newly issued credential is loaded successfully, then immediately enters the refresh path and fails to parse the response. Repeating
logout/logindoes not resolve it.m13v commentedon Sep 2, 2026
the tell is a brand-new token going straight to refresh on startup instead of being used once. that's why logout/login can't fix it: the fresh credential still passes through the same parse step that drops it, so reauth just re-enters the same failure and reports it as a soft startup warning.
Cypherlibe commentedon Sep 9, 2026
Confirmed on Codex CLI 0.153.4, installed through Homebrew on macOS.
User-observed behavior
codex mcp login, approximately daily. Login restores access temporarily.CODEX_HOMEwas introduced only recently; the recurring problem predates that change.Diagnostic reproduction
Started
codex app-server --stdiowith:The two project-scoped server URLs were supplied as process-local configuration overrides. After
initialize, requestedmcpServerStatus/list, without a model turn or database tool call.For both servers, the safely filtered logs contained:
Both status entries returned:
{"authStatus":"oAuth","serverInfo":null,"tools":{}}No interactive login was initiated during the reproduction. The diagnostic process was stopped afterward.
We have not captured the token endpoint HTTP status, content type, or underlying deserialization error, so we cannot distinguish a rejected refresh token from an incompatible/error response or a transport issue.
Is there a known fix or an OAuth-preserving workaround for this on 0.153.4? Is there a supported way to expose the token endpoint HTTP status, content type, and sanitized parse-error category without logging access tokens, refresh tokens, client secrets, or the raw response body?
Happy to test a targeted fix. Keeping OAuth rather than switching to a permanent PAT is important for this workflow.
m13v commentedon Sep 9, 2026
the 'sanitized parse-error category' is where your own probe loses the signal: an OAuth invalid_grant comes back as 400 with a JSON
errorfield that carries no token, yet a blanket body-redaction drops it along with the secrets. so a genuinely dead refresh token and a gateway serving non-JSON both flatten to the same status + 'parse failed'. logging the http status plus the top-levelerrorcode (not the raw body) is what keeps invalid_grant distinct from a transport/content-type problem.aiferrierco-hub commentedon Sep 15, 2026
Still reproducible on Windows with:
26.908.9136.0codex-cli 0.154.0-alpha.6.210.0.26200At
2026-09-15T23:37:51.920Z, the connector again failed during client startup with:The connector remains reported as
OAuth, but no server tools load, so a read-onlylist_tablescall cannot start.A previous instrumented reproduction on this machine showed:
Current checks:
401withWWW-Authenticate.200.C:\Users\J\AppData\Roaming\npm\codex.cmd.This remains consistent with a Codex/Supabase OAuth refresh-response compatibility problem rather than an endpoint outage. The underlying HTTP status, response content type, and sanitized top-level OAuth error code are still unavailable, so I cannot distinguish
invalid_grantfrom a non-JSON or otherwise incompatible response.Is there now a supported diagnostic flag or fix that exposes those three sanitized fields without logging credentials or the raw response body?
m13v commentedon Sep 16, 2026
the sanitized error-code field is the one that betrays you: it only populates if the body parsed as the expected OAuth JSON, which is the exact case failing here, so it reads null precisely when you need it. status and content-type survive a parse failure; the error code doesn't, and keying a fix off 'code present' re-buries the transport case.
Cypherlibe commentedon Sep 16, 2026
Follow-up on my earlier report: I reproduced the failure on both project-scoped Supabase MCP servers using an isolated diagnostic launcher built from Codex rust-v0.154.0’s native MCP client, with the existing macOS Keychain credentials.
Both refresh attempts returned:
The diagnostic emitted only the HTTP status, an allowlisted content type, and a fixed category matching that exact message. No credentials or raw response bodies were logged. No database tools were called. This identifies the underlying rejection in my case and supports #43216: missing DCR client authentication material during refresh. The generic “Failed to parse server response” hides the provider’s nonstandard error response.
Is a Codex-side persistence/restoration fix planned alongside modelcontextprotocol/rust-sdk#1255?
m13v commentedon Sep 16, 2026
persisting the DCR client_secret so refresh stops 422ing quietly swaps one failure class for another: any server that registered with token_endpoint_auth_method=none will now be rejected for sending an unexpected secret, and DCR's client_secret_expires_at means a restored registration can hand back an already-expired client that fails invalid_client. so the persistence fix has to branch on the stored token endpoint auth method and re-register on client expiry, not just always attach the saved secret on refresh.
mrjw717 commentedon Sep 29, 2026
Corroborating root-cause evidence: Supabase token endpoint returns 422
client_secretrequired on refreshReproduced on codex-cli 0.157.1, Linux. When the stored refresh token is used directly against Supabase's token endpoint:
Codex sends the refresh without a
client_secret(its MCP OAuth clients are registered as public PKCE clients — a newclient_idis issued percodex mcp login). The 422 body is not an OAuth-standard error response, so Codex surfaces it asOAuth token refresh failed: Failed to parse server response, followed by "access token is expired and refresh failed; reauthorization required".Observed cadence, fully deterministic across four days:
Suggested fixes: send
client_secretwhen the dynamic client registration response provides one (and persist it alongsideclient_idin.credentials.json), or fall back to re-registering a confidential client against Supabase. Also worth making the refresh error path surface the upstream status/body verbatim instead of "Failed to parse server response".mrjw717 commentedon Sep 30, 2026
WORKAROUND: pre-registered OAuth clients fix both the Supabase daily-reauth and Stripe rotation failures
Codex supports pinned OAuth clients per server — this is what makes other harnesses survive for months. Recipe that works on 0.159.x:
Register your own client with the provider (outside Codex):
POST https://api.supabase.com/platform/oauth/apps/register(returnsclient_id+client_secret; confidential client fixes theclient_secret422 on refresh)POST https://access.stripe.com/mcp/oauth2/register(public PKCE client; a stable client_id also fixes the Stripe refresh-token rotation invalidations, since Codex otherwise mints a new throwaway client per login)In the server's project/global config:
callback_urlONLY if its path equals the per-server callback path Codex generates internally (visible in any previouscodex mcp loginURL, e.g..../callback/WDOqzugHeRjy). Mismatched path → Codex silently ignores it and sends its own random port, which providers reject (invalid_redirect_uri/redirect_uri not allowed).client_secret_postas a confidential client — the 24h death loop is gone.