Remote HTTP MCP (Slack): cohort with tengu_mcp_retry_failed_remote=false forces frequent re-OAuth despite valid refresh tokens

Resolved 💬 3 comments Opened Apr 16, 2026 by MJWNA Closed Apr 28, 2026

Summary

The Slack MCP plugin (claude-plugins-official/slack) requires re-OAuth frequently across sessions even though refresh tokens ARE being saved correctly. Investigation points to the GrowthBook feature flag tengu_mcp_retry_failed_remote being false for my account — when any transient MCP connection failure occurs, Claude Code flips a cached needs-auth state instead of retrying the refresh-token flow, and that state sticks across sessions.

Environment

  • Claude Code: 2.1.110
  • OS: macOS (Darwin 25.4.0)
  • Node: v24.3.0
  • MCP plugin: claude-plugins-official/slack 1.0.0 → https://mcp.slack.com/mcp
  • Transport: remote HTTP, OAuth 2.0 + PKCE, redirect port 3118
  • Cohort flag: .cachedGrowthBookFeatures.tengu_mcp_retry_failed_remote = false

Evidence (log analysis)

Across all ~/Library/Caches/claude-cli-nodejs/*/mcp-logs-plugin-slack-slack/*.jsonl:

| Event | Count |
|---|---|
| Has refresh token: true | 305 |
| Returning tokens | 300 |
| Token length: 180 | 300 |
| Token expired without refresh token | 252 |
| Skipping connection (cached needs-auth) | 492 |
| Cleared stored tokens | multiple |

Refresh tokens are being persisted and retrieved correctly most of the time (305 successful reads). Slack is returning refresh tokens on every auth (Has refresh token: true). The failure mode fires when:

  1. A session's refresh attempt hits any transient issue
  2. Claude Code flips a needs-auth cached state instead of retrying (consistent with tengu_mcp_retry_failed_remote = false)
  3. That state persists across sessions — next startup logs Skipping connection (cached needs-auth) before even trying the stored tokens
  4. User is forced through full OAuth flow to recover

Ruled out (per the Anthropic troubleshooting docs)

  • Clock drift — 73ms skew vs time.apple.com, well within OAuth tolerance
  • Locked/out-of-sync keychain — login keychain status no-timeout, Claude Code credentials entry present and writable
  • Refresh token never persisted — 305 successful retrievals in the logs disprove this
  • Stale CLI version — running current 2.1.110

Cohort-stickiness test (done)

  1. Removed tengu_mcp_retry_failed_remote from ~/.claude.json
  2. Spawned a fresh claude -p subprocess
  3. GrowthBook re-fetched the flag with the same value (false)
  4. Confirmed: it's a stable cohort assignment, not local cache corruption. Flipping/clearing the local value alone can't resolve this.

Reproduction

  1. Be in the GrowthBook cohort where tengu_mcp_retry_failed_remote = false (check jq '.cachedGrowthBookFeatures.tengu_mcp_retry_failed_remote' ~/.claude.json)
  2. Authenticate a remote HTTP MCP plugin (Slack is the clearest repro but any remote HTTP OAuth MCP should hit it)
  3. Work normally — at some point the MCP connection hits a transient failure
  4. Next session: forced through full re-OAuth despite a valid refresh token in the keychain

Requested fix

One of:

  • A. Flip the flag default / reassign cohorts so tengu_mcp_retry_failed_remote = true is the norm (simplest)
  • B. Decouple the "no retry" behaviour from persistent state — the flag could reasonably govern retry-within-a-single-attempt, but the needs-auth cache shouldn't survive across sessions when a valid refresh token is present in the keychain. On reconnect, try the stored refresh token first regardless of any prior failure flag
  • C. Expose a user-level override (env var or settings.json key) so affected users can opt out of the flag locally

Impact

Happens multiple times per day, blocking agentic workflows that rely on Slack MCP (sending DMs, reading channels). The user-visible symptom is misleading — the OAuth URL prompt suggests a stored-token failure, but the tokens are fine. Problem will affect any user in this cohort using any remote HTTP MCP server that can have transient connection issues.

---

Happy to share sanitised log files, run additional probes, or test a fixed build. Investigation session conducted 2026-04-16 using Context7 against /ericbuess/claude-code-docs and /websites/slack_dev for docs verification.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗