The Codex Changelog
All Episodes
Why MCP Tools Vanish: OAuth Refresh Bugs and Workspace Regressions

Why MCP Tools Vanish: OAuth Refresh Bugs and Workspace Regressions

0:00|0:00

This episode digs into a silent OAuth refresh failure that leaves MCP tools disappearing without warning, plus the debugging steps needed to force re-authentication when expired tokens get stuck in cache. It also covers a nasty workspace-root regression that can balloon environment paths across turns, along with a Responses Lite bug that breaks tools through custom gateways and Azure APIM.


Chapter 1

The MCP OAuth Refresh Trap and Silent Tool Loss

Ethan Park

Huge thanks to Jellypod for powering today's episode. So Maya, I spent two hours yesterday staring at Codex CLI version zero point one forty seven point zero, trying to figure out why all my Model Context Protocol tools just vanished into thin air. No error message, no re-authentication prompt, just zero point zero tools available.

Maya

Oh yeah, that is the new silent OAuth refresh trap in zero point one forty seven point zero and the zero point one forty eight point zero alpha. It turns out when your MCP OAuth token expires, instead of telling you, it gets stuck in an infinite background retry loop.

Ethan Park

It is wild. The UI literally shows authStatus oAuth as if everything is completely fine, but then returns a totally empty tools object. So you are sitting there looking at a working UI with no button to re-authenticate.

Maya

I actually pulled up the codebase to see what on earth was happening. It is inside codex rs slash rmcp client slash src slash oauth dot rs. The function oauth tokens are usable has one job, right? Check if the token is valid. But it evaluates token validity purely on whether refresh token contains a non empty string in your system keychain or in home directory slash dot codex slash mcp oauth dot json.

Ethan Park

Wait, so it completely ignores whether the server actually accepts the token?

Maya

Exactly. RFC sixty seven forty nine explicitly defines the HTTP four hundred invalid grant error for when a refresh token is expired or revoked. But oauth tokens are usable never checks the server response. If there is a string in that file, it assumes you are good to go.

Ethan Park

That explains the stderr disconnect. In the background, stderr is constantly spamming codex rmcp client oauth refresh transaction error equals failed to refresh OAuth tokens. But the app RPC layer looks at that usable check, sees true, and tells the frontend authStatus is oAuth. So the UI hides the Re-authenticate button because it thinks you are logged in, while giving you zero tools because the API call fails.

Maya

And the persistence logic makes it even worse. In oauth dot rs, the function persist if needed only deletes your stored credentials if a refresh succeeds and explicitly returns an empty token. So when the server throws an HTTP four hundred invalid grant, persist if needed keeps that dead credential saved forever. Restarting the app does nothing because it just reads the dead token right back out of mcp oauth dot json on boot.

Chapter 2

Terminal Workarounds and Workspace Root Regressions

Maya

If anyone listening is hit by this right now, you do not have to wait for a patch. You can catch it by running RUST LOG equals debug codex doctor in your terminal. That will finally expose those hidden invalid grant warnings on stderr.

Ethan Park

And once you confirm it, how do you actually force the app to let you log back in?

Maya

You have to explicitly force the status back to missing. Either run codex mcp logout followed by your server name, or manually go into home directory slash dot codex slash mcp oauth dot json and delete the cached credentials. Once that file is clean, StoredOAuthTokenStatus goes back to missing, and the UI finally shows the re-authorization prompt again.

Ethan Park

Man, silent failures are the worst. But speaking of regressions in zero point one forty seven point zero, issue thirty seven six thirty two was an even crazier headache for me this week.

Maya

Is that the filesystem permission expansion bug?

Ethan Park

Yes! If you have a relative write rule like dot equals write under permissions profile filesystem colon workspace roots, something bizarre happens. Relative write rules under colon workspace roots recursively expand across turns until process spawning fails with E two BIG.

Maya

Wait, recursively expand across turns? How many paths are we talking about?

Ethan Park

I started with two workspace roots. By turn five, those two roots had expanded into over one hundred and two distinct derived paths in the spawned environment. Running a basic pwd command went from taking sixty milliseconds all the way up to five point eighty eight seconds. That is a ninety seven times slowdown before it finally hits process spawning failure with E two BIG, argument list too long.

Maya

A ninety seven times slowdown on pwd just from holding environment variables! That is impressive in a terrible way.

Ethan Park

Right? And there is actually a third gotcha in zero point one forty seven point zero that hit custom provider users, issue thirty seven three eighty.

Maya

Oh, the Responses Lite issue! Yes, the Responses Lite tool path started emitting an empty description string inside the default functions namespace. So if you are routing through Azure APIM or certain custom API gateways, the gateway sees description equals empty quote, freaks out, and either throws an HTTP four hundred or strips every single execution tool, giving you dynamic tool count equals zero.

Ethan Park

Luckily for that one, you can just set use responses lite equals false in your config dot toml as a quick override.

Maya

Definitely. The big lesson from this release is definitely to audit your permission profiles and credential stores whenever your CLI tools start dropping capabilities without throwing errors.

Ethan Park

Well said. Alright, that is our quick update for today, good chatting as always!