You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have searched existing issues and this hasn't been reported yet
This is a single bug report (please file separate reports for different bugs)
I am using the latest version of Claude Code
What's Wrong?
Custom HTTP MCP server (Azure Function App) using Entra OAuth 2.0 + PKCE shows "Connection expired" daily in Claude.ai web and Claude Desktop, despite the refresh token being valid and the user's Entra session being within its 180-day sign-in frequency window.
When the user clicks Connect, Claude exchanges the stored refresh token at Entra's /token endpoint silently and reconnects in ~200ms — proving the refresh path itself works correctly. Claude just doesn't call it automatically when the access token expires; it falls through to the "needs reconnect" UI immediately.
This matches the diagnosis in closed issue #43789 by @nwoonet:
The encrypted token cache is populated and persisted across sessions, so refresh tokens are being stored. The client just isn't exercising the refresh endpoint when the access token expires — it falls straight through to the bootstrap auth tools.
Evidence from Entra sign-in logs when user clicks Connect after seeing "Connection expired":
additionalDetails: "MFA requirement satisfied by claim in the token" — Entra's signature of a successful silent refresh-token exchange
status.errorCode: 0
conditionalAccessStatus: success
appliedConditionalAccessPolicies: [] (no challenge required)
This proves the refresh exchange itself succeeds instantly when invoked — Claude is just not invoking it without a manual user trigger.
Impact: every OAuth-based MCP connector in our org sidebar (custom MCPs + Anthropic-first-party Atlassian, Microsoft 365, Google Drive) shows "Connection expired" daily. Multi-step automations stall when access tokens expire mid-workflow. The only workaround is the community mcp-stdio local bridge, which requires per-laptop install.
Cross-platform — not Windows-specific. Confirmed by multiple colleagues at our org on both Windows 11 and macOS. Matches @nwoonet's observation in #43789: "Confirming this on macOS 26 / Claude Code 2.1.122. The issue is not Windows-specific."
What Should Happen?
When the access token expires (or returns 401 from the MCP server), Claude should:
Detect the expiry
POST to the IdP's /token endpoint with the cached refresh token
Receive a new access token (no user interaction required)
Retry the original MCP call transparently
Surface no UI to the user
Only fall back to the "Connection expired / reconnect" UI when the refresh attempt itself fails (e.g. refresh token is also expired or revoked).
This is standard OAuth 2.0 client behavior (RFC 6749 §6) — auto-refresh is what makes long-running OAuth sessions usable. Most OAuth-aware HTTP clients (Microsoft.Identity.Web, MSAL, Google's auth libs, etc.) handle this automatically.
Error Messages/Logs
UI banner shown daily:
"Connection has expired. You can reconnect to re-authenticate."
No actual error logs are produced by Claude — the failure is silent (Claude flips state to expired without logging a 401 from a refresh attempt).
Entra sign-in log entry observed when user clicks Connect to recover (proves refresh works when invoked):
createdDateTime: 2026-06-01T13:18:50Z
status.errorCode: 0
status.additionalDetails: "MFA requirement satisfied by claim in the token"
conditionalAccessStatus: success
appliedConditionalAccessPolicies: []
The "MFA satisfied by claim in token" detail is Entra's signature of a silent refresh-token exchange. This succeeded in ~200ms with no user prompt. The same exchange should happen automatically on access token expiry, before showing the "Connection expired" UI.
Steps to Reproduce
Set up a custom HTTP MCP server that requires OAuth (Authorization Code + PKCE)
against any IdP that follows standard OAuth 2.0. We used Microsoft Entra,
but the issue is IdP-agnostic per other reports in MCP OAuth tokens expire frequently, requiring manual /mcp reconnect #43789 (which mentions
Sentry, Atlassian, Superhuman Mail, Vercel, etc.)
Add the MCP server as a custom connector in Claude.ai (web) and/or
Claude Desktop. Provide OAuth Client ID + Secret.
Click "Connect". OAuth flow completes successfully. Connector shows
as "Connected". Claude.ai stores: access_token (~1h lifetime) +
refresh_token (typically days to months).
Use the MCP server normally, invoke its tools from a chat. Works fine.
Wait for the access_token to expire (~1 hour after step 3).
Open Claude.ai / Claude Desktop. Observed: the connector shows
"Connection issue / Connection has expired. You can reconnect to
re-authenticate." Expected: silent background refresh; user sees
nothing.
Click "Connect". Claude silently exchanges the cached refresh_token
at the IdP's /token endpoint and reconnects in ~200ms — no Microsoft
login window, no MFA prompt, no UI interaction.
This step proves the refresh_token is valid and the refresh exchange
works perfectly when manually triggered. The bug is that step 6
should not require step 7 — Claude should perform step 7 automatically
when the access_token expires.
Use any MCP tool works again until the next ~1-hour expiry.
Next morning, GOTO step 6.
Minimal repro setup is in the linked closed issues #43789, #55055, etc.
We can provide our specific Azure Function App OAuth metadata if helpful
for reproduction with an Entra-backed test app.
Claude Model
None
Is this a regression?
No, this never worked
Last Working Version
No response
Claude Code Version
2.1.144 (Claude Code)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
Workaround in use today
Daily 1-click reconnect. We extended our Entra Conditional Access "Sign-in frequency" policy to 180 days specifically scoped to the MCP app, which makes the reconnect silent (no Microsoft login window, no MFA prompt) — but the "Connection expired" UI in Claude still appears daily because it's not driven by actual token state.
Community workaround
mcp-stdio (https://github.com/shigechika/mcp-stdio) — a local stdio bridge that holds the refresh token client-side and refreshes transparently on 401. Confirms the behavior is fixable from the client side; the gap is in Claude itself.
OAuth refresh is the foundation of every modern long-lived API integration. Without it, every OAuth-based MCP feels broken to users and looks "in beta" forever. Fixing this single client-side bug probably resolves a large portion of the connector pain reported across #28262, #5706, #12447, #43789, #47219, #53803, #54742, #55055.
Preflight Checklist
What's Wrong?
Custom HTTP MCP server (Azure Function App) using Entra OAuth 2.0 + PKCE shows "Connection expired" daily in Claude.ai web and Claude Desktop, despite the refresh token being valid and the user's Entra session being within its 180-day sign-in frequency window.
When the user clicks Connect, Claude exchanges the stored refresh token at Entra's
/tokenendpoint silently and reconnects in ~200ms — proving the refresh path itself works correctly. Claude just doesn't call it automatically when the access token expires; it falls through to the "needs reconnect" UI immediately.This matches the diagnosis in closed issue #43789 by @nwoonet:
Related closed/duplicate issues: #43789, #28262, #5706, #12447, #55055, #53803, #54742, #47219.
Evidence from Entra sign-in logs when user clicks Connect after seeing "Connection expired":
additionalDetails:"MFA requirement satisfied by claim in the token"— Entra's signature of a successful silent refresh-token exchangestatus.errorCode:0conditionalAccessStatus:successappliedConditionalAccessPolicies:[](no challenge required)This proves the refresh exchange itself succeeds instantly when invoked — Claude is just not invoking it without a manual user trigger.
Impact: every OAuth-based MCP connector in our org sidebar (custom MCPs + Anthropic-first-party Atlassian, Microsoft 365, Google Drive) shows "Connection expired" daily. Multi-step automations stall when access tokens expire mid-workflow. The only workaround is the community
mcp-stdiolocal bridge, which requires per-laptop install.Cross-platform — not Windows-specific. Confirmed by multiple colleagues at our org on both Windows 11 and macOS. Matches @nwoonet's observation in #43789: "Confirming this on macOS 26 / Claude Code 2.1.122. The issue is not Windows-specific."
What Should Happen?
When the access token expires (or returns 401 from the MCP server), Claude should:
/tokenendpoint with the cached refresh tokenOnly fall back to the "Connection expired / reconnect" UI when the refresh attempt itself fails (e.g. refresh token is also expired or revoked).
This is standard OAuth 2.0 client behavior (RFC 6749 §6) — auto-refresh is what makes long-running OAuth sessions usable. Most OAuth-aware HTTP clients (Microsoft.Identity.Web, MSAL, Google's auth libs, etc.) handle this automatically.
Error Messages/Logs
Steps to Reproduce
Set up a custom HTTP MCP server that requires OAuth (Authorization Code + PKCE)
against any IdP that follows standard OAuth 2.0. We used Microsoft Entra,
but the issue is IdP-agnostic per other reports in MCP OAuth tokens expire frequently, requiring manual /mcp reconnect #43789 (which mentions
Sentry, Atlassian, Superhuman Mail, Vercel, etc.)
Add the MCP server as a custom connector in Claude.ai (web) and/or
Claude Desktop. Provide OAuth Client ID + Secret.
Click "Connect". OAuth flow completes successfully. Connector shows
as "Connected". Claude.ai stores: access_token (~1h lifetime) +
refresh_token (typically days to months).
Use the MCP server normally, invoke its tools from a chat. Works fine.
Wait for the access_token to expire (~1 hour after step 3).
Open Claude.ai / Claude Desktop. Observed: the connector shows
"Connection issue / Connection has expired. You can reconnect to
re-authenticate." Expected: silent background refresh; user sees
nothing.
Click "Connect". Claude silently exchanges the cached refresh_token
at the IdP's /token endpoint and reconnects in ~200ms — no Microsoft
login window, no MFA prompt, no UI interaction.
This step proves the refresh_token is valid and the refresh exchange
works perfectly when manually triggered. The bug is that step 6
should not require step 7 — Claude should perform step 7 automatically
when the access_token expires.
Use any MCP tool works again until the next ~1-hour expiry.
Next morning, GOTO step 6.
Minimal repro setup is in the linked closed issues #43789, #55055, etc.
We can provide our specific Azure Function App OAuth metadata if helpful
for reproduction with an Entra-backed test app.
Claude Model
None
Is this a regression?
No, this never worked
Last Working Version
No response
Claude Code Version
2.1.144 (Claude Code)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
Workaround in use today
Daily 1-click reconnect. We extended our Entra Conditional Access "Sign-in frequency" policy to 180 days specifically scoped to the MCP app, which makes the reconnect silent (no Microsoft login window, no MFA prompt) — but the "Connection expired" UI in Claude still appears daily because it's not driven by actual token state.
Community workaround
mcp-stdio(https://github.com/shigechika/mcp-stdio) — a local stdio bridge that holds the refresh token client-side and refreshes transparently on 401. Confirms the behavior is fixable from the client side; the gap is in Claude itself.OAuth refresh is the foundation of every modern long-lived API integration. Without it, every OAuth-based MCP feels broken to users and looks "in beta" forever. Fixing this single client-side bug probably resolves a large portion of the connector pain reported across #28262, #5706, #12447, #43789, #47219, #53803, #54742, #55055.