Plugin MCP OAuth fails for Slack (mcp.slack.com) + need shared credential deduplication

Resolved 💬 3 comments Opened Mar 4, 2026 by iam-thewalrus Closed Mar 8, 2026

Bug: Plugin Slack MCP OAuth never completes

Environment

  • Claude Code: 2.1.68
  • Platform: macOS (Darwin 25.3.0)
  • Shell: zsh

Description

OAuth authentication for the Slack MCP server (https://mcp.slack.com/mcp) fails silently across all plugins that declare it. The OAuth flow never completes — tokens are stored as empty strings with expiresAt: 0 in .credentials.json.

Meanwhile, the built-in first-party claude_ai_Slack integration works fine — it's authenticated and fully functional against the same Slack workspace.

Reproduction

  1. Enable any plugin from knowledge-work-plugins that declares a Slack MCP server (e.g., product-management, engineering, design)
  2. Open /mcp dialog — Slack server shows auth error
  3. Attempt to re-authenticate — flow does not complete successfully
  4. Check ~/.claude/.credentials.json — the mcpOAuth entry for the plugin's Slack server has accessToken: "" and expiresAt: 0

Observed credential state

9 separate Slack OAuth entries exist in .credentials.json, all pointing to the same https://mcp.slack.com/mcp endpoint, all with empty tokens:

plugin:marketing:slack           → accessToken: "", expiresAt: 0
plugin:legal:slack               → accessToken: "", expiresAt: 0
plugin:finance:slack             → accessToken: "", expiresAt: 0
plugin:engineering:slack         → accessToken: "", expiresAt: 0
plugin:design:slack              → accessToken: "", expiresAt: 0
plugin:operations:slack          → accessToken: "", expiresAt: 0
plugin:human-resources:slack     → accessToken: "", expiresAt: 0
plugin:slack-by-salesforce:slack → accessToken: "", expiresAt: 0
plugin:product-management:slack  → accessToken: "", expiresAt: 0

The discovery metadata is populated correctly (authorization endpoint, token endpoint, scopes, PKCE support), so the initial .well-known discovery succeeds — the failure is in the actual token exchange.

Two issues here

Issue 1: OAuth flow broken

The token exchange for mcp.slack.com never completes. Possible causes:

  • Client credential mismatch in the authorization code exchange
  • Callback URL issue
  • PKCE code_verifier not being sent correctly to the token endpoint
  • Slack's MCP OAuth server rejecting the request silently
Issue 2 (Feature Request): Shared MCP credential deduplication

Each plugin that declares https://mcp.slack.com/mcp gets its own namespaced OAuth credential, even though they all hit the exact same server with the same scopes. This means:

  • A user would need to authenticate 9 separate times for the same Slack workspace
  • Each authentication is a full OAuth redirect flow
  • The built-in claude_ai_Slack integration (which works) is yet another separate auth — it doesn't share credentials with plugin MCP servers

Proposed behavior: When multiple plugins (or a plugin + a first-party integration) declare MCP servers pointing to the same origin (https://mcp.slack.com), Claude Code should:

  1. Deduplicate at the credential layer — store one OAuth token per (server_url, user) pair, not per (plugin, server_url, user)
  2. Share the token across all plugins referencing that server
  3. Ideally, also share with the first-party integration if the scopes are compatible — e.g., if claude_ai_Slack is already authenticated with sufficient scopes, plugin Slack MCP servers should be able to reuse that credential

This would eliminate redundant auth prompts and reduce the credential sprawl in .credentials.json.

Workaround

Using the built-in claude_ai_Slack integration directly, which authenticates and works correctly. Plugin skills that try to use their own Slack MCP tools will fail, but most plugin skills are prompt-driven workflows that don't strictly require their own Slack connection.

🤖 Generated with Claude Code

View original on GitHub ↗

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