MCP OAuth refresh silently killed my Claude Desktop session
Spent Friday afternoon debugging why Claude Desktop kept dropping my custom MCP server mid-session.
Turns out the OAuth refresh token expired after ~55 minutes, the client just stopped calling tools with zero error toast. Logs said transport closed once. Restart fixed it until the next hour.
Anyone shipping MCP with short-lived tokens — are you baking a refresh loop into the server itself, or telling users to bounce the app? Feels like half the demos ignore this.
5 comments
Join the discussion
Log in to comment.
ugh that tracks. we hit the same thing on a tutoring MCP — google oauth, 1h access tokens.
i ended up refreshing inside the server before each tool call if expiry was under 5 min. clunky but students dont notice. did your client ever surface a reconnect UI or just die quietly?
Same failure mode in a tutoring MCP last semester. Access token ~50 min, Claude Desktop just went quiet — no reconnect dialog, just tools stop working mid-lesson.
We put refresh in the server (check expiry before every tool call). Still wish the client would surface "auth expired, reconnect" instead of
transport closedonce in the logs. Did you try bumping the refresh window or only restart?If "restart Claude" is in your runbook, congratulations, you built a demo.
We put refresh on the server too, plus a health tool that returns token_expires_in so the agent can panic early. Still broke once in CI when the secret vault rotated mid-job.
the vault rotate mid-job bit is the part that gets me. we had the same in GH Actions — secret rotated on a schedule, agent mid-run, refresh starts failing with 401 and zero useful toast.
now the health tool returns
token_expires_inANDvault_version. if either flips we fail the job early instead of shipping a half-written PR. still feels like duct tape.measured it once: mean time from expiry to first failed tool call was ~11s, but the ui stayed green the whole time. only clue was one
transport closedline.server-side refresh + expose
expires_inon a tiny ping tool. if the agent can't see the clock, it will happily keep calling a dead transport. restart-as-runbook is just admitting the loop is broken.