[Slack MCP] Hardcoded OAuth callback port 3118 prevents authentication when multiple Claude Code sessions run in parallel

Resolved 💬 3 comments Opened Apr 20, 2026 by yusukefukuju Closed Apr 24, 2026

Summary

The Slack MCP plugin's OAuth config hardcodes callbackPort: 3118. Because the OAuth callback server binds to this single fixed port, only one Claude Code session on the machine can complete Slack OAuth at a time. Users running multiple parallel sessions (per-project, cmux-managed, detached terminals) hit unrecoverable auth failures whenever another session is already listening on 3118.

Reproduction

  1. Start a Claude Code session (A) that has loaded the Slack plugin. It binds localhost:3118 at some point during Slack MCP lifecycle.
  2. In another terminal, start session B.
  3. In session B, run /mcp and select Slack → Authenticate.
  4. Auth fails with:
Error: OAuth callback port 3118 is already in use — another process may be holding it.
Run `lsof -ti:3118 -sTCP:LISTEN` to find it.
  1. lsof reveals the port is held by another Claude Code process — a sibling session, not malware — with no way to proceed without killing that session.

Config

~/.claude/plugins/cache/claude-plugins-official/slack/1.0.0/.mcp.json:

{
  "mcpServers": {
    "slack": {
      "type": "http",
      "url": "https://mcp.slack.com/mcp",
      "oauth": {
        "clientId": "1601185624273.8899143856786",
        "callbackPort": 3118
      }
    }
  }
}

Root Cause

OAuth 2.0 requires redirect_uri to match a pre-registered value in the Slack OAuth app configuration. The Slack app (client_id: 1601185624273.8899143856786) has http://localhost:3118/callback registered as the only loopback redirect URI, so the MCP client cannot fall back to a different port.

Proposed Solutions (in order of preference)

1. RFC 8252 loopback redirect with wildcard port (recommended)

Per RFC 8252 §7.3, loopback redirect URIs SHOULD allow any port. Register http://127.0.0.1/callback (no port) in the Slack OAuth app and have the MCP client bind to an OS-assigned ephemeral port. This is the idiomatic modern approach and eliminates port collision entirely.

2. Port range fallback (GitHub CLI pattern)

Register a range (e.g., 3118-3127) in the Slack OAuth app, and have the client try each sequentially until one is free. This is what gh, gcloud, heroku, flyctl and many other dev-CLIs do.

3. Device Authorization Grant (RFC 8628)

No callback server needed. User copies a short code from terminal into browser. More user-friction but entirely port-independent. Good fallback if ①/② are blocked by Slack app policy.

4. Short-term UX improvement

The current error message points to lsof -ti:3118 -sTCP:LISTEN but doesn't tell the user that the port is almost always held by a sibling Claude Code session. Adding this context — and ideally offering to SIGTERM the blocking Claude process after confirmation — would reduce frustration significantly while ①/②/③ are being evaluated.

Environment

  • Claude Code: 2.1.114
  • Plugin: claude-plugins-official/slack@1.0.0
  • OS: macOS (Darwin 25.3.0)
  • Usage pattern: 5-10 parallel Claude Code sessions per day (cmux-managed + ad-hoc terminals). Common among heavy users.

Workaround

# Find the blocking Claude session
lsof -i:3118 -sTCP:LISTEN -n -P
# Kill it (destructive to that session)
lsof -ti:3118 -sTCP:LISTEN | xargs kill
# Then retry OAuth in the current session

This works but is destructive to the other session and counterintuitive — nothing in the error message hints that you're being blocked by your own previous Claude process.

Related Issues

  • #37714 — Slack MCP plugin OAuth fails: redirect_uri not registered (different root cause, resolved by Slack OSS team)
  • #37747 — MCP OAuth regression: client metadata document redirect_uris missing port
  • #48993 — Remote HTTP MCP (Slack): forces frequent re-OAuth despite valid refresh tokens

Impact

This affects any user who runs multiple Claude Code sessions simultaneously — a workflow that Anthropic actively supports (project-scoped sessions, cmux, background agents). Without a fix, users must serialize all Slack MCP auth attempts, which contradicts the parallel-session design of the product.

View original on GitHub ↗

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