Slack MCP (mcp.slack.com) OAuth stores empty accessToken after completing flow; complete_authentication also broken
Summary
The Slack MCP (https://mcp.slack.com/mcp) cannot be authenticated. The OAuth flow appears to complete successfully (success page shown in browser), but the stored accessToken is always empty. The manual fallback via mcp__slack__complete_authentication also fails. This worked previously (confirmed working on May 13, 2026 via debug logs).
Environment
- Claude Code version: 2.1.139 (also reproduced after updating)
- OS: macOS 24.6.0 (Darwin)
- MCP server:
https://mcp.slack.com/mcp
Bug 1: Empty accessToken after OAuth flow
After completing the Slack OAuth flow (clicking Allow, browser shows success page), the token stored in the macOS keychain has an empty accessToken:
security find-generic-password -s "Claude Code-credentials" -w | \
python3 -c "import sys,json; d=json.loads(sys.stdin.read()); print(d['mcpOAuth'])"
Output:
{'slack|38801a7d845718b3': {'serverName': 'slack', 'serverUrl': 'https://mcp.slack.com/mcp', 'accessToken': '', 'discoveryState': {...}}}
Root cause hypothesis: Slack's oauth/v2_user/authorize endpoint returns the user token nested under authed_user.access_token in the token exchange response, not at the top-level access_token field. If Claude Code's OAuth client reads the top-level field, it stores an empty string.
Debug logs from a working session (May 13) show Token length: 82 and successful connection. After the token expired/was revoked, re-authentication consistently produces accessToken: "".
Bug 2: complete_authentication loses session state between calls
The manual fallback (mcp__slack__complete_authentication) reports "No OAuth flow is in progress for slack" even when called immediately after mcp__slack__authenticate in the same conversation with a matching state parameter.
The state from mcp__slack__authenticate and the captured callback URL match:
- Generated state:
CAz80-nwEtCH5Cq9fpDO2iZ3eFzsOmvxG2VnsR74Fqg - Callback URL state:
CAz80-nwEtCH5Cq9fpDO2iZ3eFzsOmvxG2VnsR74Fqg
Yet complete_authentication still fails. The session state appears to be lost between the two tool calls, likely because each tool call opens a fresh connection to mcp.slack.com and session state is connection-scoped.
Steps to Reproduce
- Add Slack MCP (
https://mcp.slack.com/mcp) in Claude Code settings - Attempt to authenticate via the MCP settings dialog or
mcp__slack__authenticate - Complete the Slack OAuth flow in browser
- Observe success page in browser
- Check keychain:
accessTokenis"" - Slack MCP shows as unauthenticated; repeating auth has same result
Expected Behavior
- OAuth flow completes and a valid
accessTokenis stored - OR
mcp__slack__complete_authenticationworks as a fallback for cases wherelocalhost:8085is not reachable
Additional Context
mcp-needs-auth-cache.jsoncorrectly records Slack as needing auth, but noidfield is ever written (unlike other successfully-authenticated MCPs likeclaude.ai Gmailwhich get anidfield)- The automatic localhost:8085 callback handler appears to run (browser redirects away from localhost), but token exchange result is stored incorrectly
- Other MCPs (Gmail, Google Calendar) authenticate successfully, suggesting the issue is specific to Slack's OAuth token response format
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗