Slack MCP Server
Current Config
Entry in ~/.claude.json (HTTP type with static Bearer token):
"slack": {
"type": "http",
"url": "https://mcp.slack.com/mcp",
"headers": {
"Authorization": "Bearer xoxp-2333731943-2334562442-10676586932945-06c5f078171263519ccc1ba0e6fb7f76"
}
}
Workspace: Grain & Mortar
App Name: Claude MCP (App ID: A0AKE2U68LD)
Token type: User token (xoxp-) — allows acting as Eric
User Token Scopes
| Scope | Purpose |
|---|---|
search:read.public |
Search public channels |
search:read.private |
Search private channels |
search:read.files |
Search files |
canvases:read |
Read Slack canvases |
canvases:write |
Write Slack canvases |
channels:history |
Read public channel history |
chat:write |
Send messages |
groups:history |
Read private channel history |
im:history |
Read DM history |
mpim:history |
Read group DM history |
users:read |
Read user info |
users:read.email |
Read user email addresses |
Why This Setup Is Unusual
Most HTTP MCPs use OAuth with mcp-remote as the transport (e.g., Google services). Slack does not support this pattern. Here's why:
mcp-remoterequires the auth server to support dynamic client registration (RFC 7591)- Slack's OAuth server only supports
client_secret_posttoken exchange - You can confirm this:
curl https://slack.com/.well-known/oauth-authorization-server | jq .token_endpoint_auth_methods_supported - Result:
["client_secret_post"]— PKCE-only dynamic registration is not supported
Therefore: Slack requires a static Bearer token in the HTTP headers. There is no refresh — if the token expires or is revoked, you have to regenerate it.
If the Token Stops Working
- Go to api.slack.com/apps/A0AKE2U68LD
- Navigate to OAuth & Permissions
- Under OAuth Tokens for Your Workspace, click Reinstall to Grain & Mortar
- Complete the OAuth flow
- Copy the new
xoxp-token - Update
~/.claude.json:
# Remove and re-add with new token
claude mcp remove slack -s user
claude mcp add-json slack '{"type":"http","url":"https://mcp.slack.com/mcp","headers":{"Authorization":"Bearer xoxp-NEW-TOKEN-HERE"}}' -s user
How to Create This From Scratch
If the app gets deleted or you need to set this up in a new workspace:
- Go to api.slack.com/apps → Create New App → From scratch
- Name it "Claude MCP", select the target workspace
- Go to OAuth & Permissions → scroll to User Token Scopes → add all scopes listed above
- Do NOT add Bot Token Scopes — user token scopes are what matters here
- Do NOT add
admin.users:read— it's Enterprise-only and blocks install - Click Install to Workspace
- Copy the
xoxp-token from the OAuth Tokens section - Register with Claude Code:
claude mcp add-json slack '{"type":"http","url":"https://mcp.slack.com/mcp","headers":{"Authorization":"Bearer xoxp-TOKEN"}}' -s user
Lessons Learned (the hard way)
Don't try mcp-remote first. The error Incompatible auth server: does not support dynamic client registration is definitive — Slack will never support this. When you see that error, go straight to static Bearer token.
Check /.well-known/oauth-authorization-server before picking an auth strategy. If token_endpoint_auth_methods_supported includes only client_secret_post (not none), mcp-remote won't work. Go Bearer token.
app.slack.com/app-settings/ won't load directly. If you need Chrome MCP to interact with Slack app settings, navigate from within an already-authenticated workspace tab (app.slack.com/client/...), not by opening app-settings directly.
ReactVirtualized dropdowns need mouse events. Slack's scope dropdown uses a virtual list. Standard click events don't work — use Input.dispatchMouseEvent targeting [role="option"] elements by text content.
Enterprise-only scopes block install. admin.users:read silently breaks the install flow. If "Allow" fails, check for orange warning icons on any scope and remove them.
OAuth form submit via CDP: If the Allow button is at the viewport edge and click doesn't register, use document.querySelector('form').submit() instead.