slack-mcp
slack-mcp lets MCP clients read, search, and manage Slack workspaces through a broad set of Slack tools.
Read channel history with date filtering and optional thread replies.
Read full message threads and fetch reactions.
Search workspace messages or search within a specific channel.
Resolve channel names to IDs and list joined channels.
Resolve user IDs from names, handles, or emails and check authentication identity.
Post messages, threaded replies, Slack commands, DMs, and group DMs.
Add emoji reactions.
Join, create, and rename channels, and invite users to channels.
Clear or replace usergroup membership.
Refresh channel and user caches.
Run in read-only mode to allow browsing/searching while blocking mutating actions like posting, reacting, joining, or running commands.
Allows interaction with Slack workspaces, including reading messages, posting content, managing channels, adding reactions, sending DMs, and executing Slack commands.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@slack-mcp summarize today's messages in #general"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
slack-mcp
A Model Context Protocol (MCP) server that enables AI assistants to interact with Slack workspaces. This server provides a bridge between AI tools and Slack, allowing you to read messages, post content, and manage Slack channels programmatically through MCP-compatible clients.
Disclaimer: This is not an official Red Hat tool.
What is this and why should I use it?
This MCP server transforms your Slack workspace into an AI-accessible environment. It provides 21+ tools for comprehensive Slack interaction:
Message & Thread Operations
Read channel history with date filtering and thread support
List unread direct messages with read markers (browser-session auth only; uses Slack's
client.countsendpoint, which is not part of the public Web API)Post messages and replies to threads
Search messages across workspace or within specific channels
Execute Slack commands
Channel Management
List, join, create, and rename channels
Look up channel IDs by name
Invite users to channels
Reactions & Users
Add and view emoji reactions
Send direct messages and group DMs
Manage usergroups (clear members)
Utility
Check authentication status
Cache management for performance
Key Benefits
Seamless Integration: Connect your AI assistant directly to Slack without manual copy-pasting
Automated Workflows: Build AI-powered Slack bots that can read, analyze, and respond to messages
Enhanced Productivity: Let AI help manage notifications, summarize conversations, or automate routine Slack tasks
Real-time Collaboration: Enable AI assistants to participate in team discussions and provide instant insights
Use Cases
Team Assistant: Have an AI that can read team updates and provide summaries
Notification Manager: Automatically categorize and respond to incoming messages
Knowledge Base: AI that can search through channel history and provide context
Meeting Scheduler: AI that can read meeting requests and help coordinate schedules
Related MCP server: Slack MCP Server
Setting Up with Claude Code
This repo ships as a Claude Code plugin with a guided setup skill. Claude will walk you through the entire process — no manual config editing required.
Run the setup script. It handles everything — venv, Playwright, token extraction, wrapper script, and Claude Code registration. The only interaction required is logging in to Slack when the browser opens, and entering an optional channel ID for server logs, if desired.
python3 <(curl -fsSL https://raw.githubusercontent.com/redhat-community-ai-tools/slack-mcp/main/scripts/setup-slack-mcp.py)Or clone the repo first and run it locally:
git clone https://github.com/redhat-community-ai-tools/slack-mcp
python3 slack-mcp/scripts/setup-slack-mcp.pyOptions:
Flag | Description |
| Slack channel ID for server logs (optional; logs go to stderr if omitted) |
| Specific Slack workspace to open |
| Re-extract tokens when they expire (skips all other steps) |
| Skip the post-setup smoke test |
When tokens expire, just run:
python3 slack-mcp/scripts/setup-slack-mcp.py --refresh-tokensDesktop App Token Refresh (Linux)
If you have the Slack desktop app installed, you can refresh tokens without opening a browser:
slack-mcp/scripts/slack-refresh-tokens --validateThis reads tokens directly from the desktop app's local storage on disk — no DevTools, no Playwright, no manual steps. Requires the Slack app to be signed in.
Flag | Description |
| Verify tokens against Slack's API after extraction |
| Print tokens as env vars to stdout (for piping into other tools) |
| Write tokens to a custom path (default: |
Requirements: python3, python3-cryptography, secret-tool (libsecret/gnome-keyring), curl, jq
This is useful for CI hooks or session startup scripts that need to silently refresh tokens before launching the MCP server.
Bot token authentication (recommended)
For better security, use a Slack App bot token (xoxb-) instead of browser session tokens. Bot tokens provide:
Scoped access — only the OAuth permissions you grant, not full user access
Distinct identity — actions appear as the bot, not as your user account
Central management — IT can audit and revoke via the Slack admin panel
No browser DevTools — tokens are generated once in the Slack App settings
Setup
Create a Slack App at api.slack.com/apps
Add OAuth scopes:
channels:read,channels:history,channels:manage,groups:read,groups:history,groups:write,chat:write,reactions:read,reactions:write,search:read,users:read,commands,mpim:writeInstall to your workspace and copy the Bot User OAuth Token (
xoxb-...)Invite the bot to channels it needs access to
Running with a bot token
Set SLACK_BOT_TOKEN instead of SLACK_XOXC_TOKEN/SLACK_XOXD_TOKEN:
{
"mcpServers": {
"slack": {
"command": "podman",
"args": [
"run", "-i", "--rm",
"-e", "SLACK_BOT_TOKEN",
"-e", "LOGS_CHANNEL_ID",
"quay.io/redhat-ai-tools/slack-mcp"
],
"env": {
"SLACK_BOT_TOKEN": "xoxb-...",
"LOGS_CHANNEL_ID": "C7000000"
}
}
}
}LOGS_CHANNEL_ID is optional. When omitted, tool activity is written to stderr instead of posted to Slack.
If both SLACK_BOT_TOKEN and SLACK_XOXC_TOKEN/SLACK_XOXD_TOKEN are set, the bot token takes precedence.
Read-only mode
For agents or automation that should browse and search Slack without posting, reacting, running commands, or joining channels, enable read-only mode.
Environment variable: set
SLACK_MCP_READ_ONLYto a truthy value (1,true,yes, oron, case-insensitive).CLI: pass
--read-onlywhen starting the server (e.g.slack-mcp --read-only, equivalent to setting the variable).
In read-only mode, tools that mutate Slack state (post_message, send_dm, post_command, add_reaction, join_channel) raise a clear error. Read tools (history, search, threads, whoami, channel listing, cache refresh helpers, and so on) behave as usual. Tool activity that would normally be mirrored to LOGS_CHANNEL_ID is written to stderr instead.
On startup, the server logs a line to stderr when read-only mode is active.
For Podman or Docker, add -e SLACK_MCP_READ_ONLY=true (and the matching key in env) when you want the container to run read-only.
Running as a uv tool (local, no container)
Prefer not to run a container? Install slack-mcp as a uv tool. This puts a slack-mcp command on your PATH that runs the server directly.
Requires uv and Python ≥ 3.10.
# from a clone of this repo
uv tool install .
# or straight from git
uv tool install git+https://github.com/redhat-community-ai-tools/slack-mcpRun slack-mcp --help for a summary of flags and environment variables.
Tokens from tokens.env (recommended)
slack-mcp reads Slack session tokens from ~/.local/share/slack-mcp/tokens.env when they are not already set in the environment — the same file the token tooling writes:
scripts/slack-refresh-tokens # or: python3 scripts/setup-slack-mcp.pyThen the MCP client config needs no env block — just the command:
{
"mcpServers": {
"slack": {
"command": "slack-mcp"
}
}
}The file uses SLACK_MCP_XOXC_TOKEN / SLACK_MCP_XOXD_TOKEN; the server maps those onto the SLACK_XOXC_TOKEN / SLACK_XOXD_TOKEN it uses. Override the path with SLACK_MCP_TOKENS_FILE. Real environment variables always take precedence over the file, so you can still override per-client.
Tokens from the client config (alternative)
To keep tokens in the MCP config instead of a file, pass them in env:
{
"mcpServers": {
"slack": {
"command": "slack-mcp",
"env": {
"SLACK_XOXC_TOKEN": "xoxc-...",
"SLACK_XOXD_TOKEN": "xoxd-...",
"LOGS_CHANNEL_ID": "C7000000"
}
}
}
}A bot token works the same way — set SLACK_BOT_TOKEN in env instead of the xoxc/xoxd pair. If the client does not inherit your PATH, use the absolute path (~/.local/bin/slack-mcp after uv tool install), or launch via uv run --directory /path/to/slack-mcp slack-mcp.
The user cache and the default tokens.env live under ~/.local/share/slack-mcp/ (override with SLACK_MCP_DATA).
Claude Code (bot token):
claude mcp add slack -e SLACK_BOT_TOKEN=xoxb-... -- slack-mcpOr, with tokens.env already in place, no env needed:
claude mcp add slack -- slack-mcpRunning with Podman or Docker
You can run the slack-mcp server in a container using Podman or Docker:
Example configuration for running with Podman:
{
"mcpServers": {
"slack": {
"command": "podman",
"args": [
"run",
"-i",
"--rm",
"-e", "SLACK_XOXC_TOKEN",
"-e", "SLACK_XOXD_TOKEN",
"-e", "MCP_TRANSPORT",
"-e", "LOGS_CHANNEL_ID",
"quay.io/redhat-ai-tools/slack-mcp"
],
"env": {
"SLACK_XOXC_TOKEN": "xoxc-...",
"SLACK_XOXD_TOKEN": "xoxd-...",
"MCP_TRANSPORT": "stdio",
"LOGS_CHANNEL_ID": "C7000000"
}
}
}
}LOGS_CHANNEL_ID is optional. When omitted, tool activity is written to stderr instead of posted to Slack.
Activity logging
By default, tool activity is written to stderr (visible in your terminal or process logs). To mirror activity to a Slack channel instead, set LOGS_CHANNEL_ID to any channel the bot or session user has access to — a self-DM or a DM with Slackbot works well for personal use.
LOGS_CHANNEL_ID=C7000000In read-only mode, LOGS_CHANNEL_ID is ignored and all activity is always written to stderr.
Running with non-stdio transport
To run the server with a non-stdio transport (such as SSE), set the MCP_TRANSPORT environment variable to a value other than stdio (e.g., sse).
Example configuration to connect to a non-stdio MCP server:
{
"mcpServers": {
"slack": {
"url": "https://slack-mcp.example.com/sse",
"headers": {
"X-Slack-Web-Token": "xoxc-...",
"X-Slack-Cookie-Token": "xoxd-..."
}
}
}
}Extract your Slack XOXC and XOXD tokens easily using browser extensions or Selenium automation: https://github.com/maorfr/slack-token-extractor.
Available Tools
22 toolsadd_reactionB
Add a reaction to a message.
Inputs: reaction (required), channel_id (required), message_ts (required). Returns: result
clear_usergroupADestructive
Clear all users from a Slack usergroup.
Since Slack API doesn't support empty usergroups, this uses a workaround by setting the usergroup to contain only a randomly selected deleted user. This effectively clears the usergroup.
Args: usergroup_id: The usergroup ID (S...) to clear
Returns: True if usergroup was cleared successfully, False otherwise
Inputs: usergroup_id (required). Returns: result
create_channelADestructive
Create a new Slack channel.
Args: name: Channel name (will be sanitized: lowercase, hyphens, no spaces) is_private: Create as private channel (default: False for public)
Returns: Channel ID on success, None on failure
Inputs: name (required), is_private. Returns: result
get_channel_historyARead-only
Get the history of a channel with pagination support. Limit parameter controls max messages to fetch (default 1000).
Optional date filtering (accepts ISO 8601 dates or Unix timestamps):
oldest: Only messages after this date (e.g., "2024-01-15" or "2024-01-15T10:30:00")
latest: Only messages before this date (e.g., "2024-01-20" or "2024-01-20T18:00:00")
include_threads: If True, also fetch all replies in threads (default False)
Note: For date-only formats, 'oldest' defaults to start of day (00:00:00) and 'latest' to end of day (23:59:59).
Inputs: channel_id (required), limit, latest, oldest, +1 more. Returns: result
get_channel_id_by_nameARead-only
Get the channel ID by channel name. The channel name can be with or without the # prefix.
Inputs: channel_name (required). Returns: result
get_reactionsBRead-only
Get reactions to a message.
Inputs: channel_id (required), message_ts (required), full. Returns: result
get_threadARead-only
Get all messages in a thread given a channel ID and the parent message timestamp.
Use this to read a full conversation thread before replying to it. The thread_ts is the timestamp of the parent message that started the thread.
Inputs: thread_ts (required), channel_id (required), limit. Returns: result
invite_users_to_channelADestructive
Invite multiple users to a channel.
Args: channel_id: Target channel ID (C...) user_ids: List of user IDs to invite (U...)
Returns: True if all invitations succeeded, False otherwise
Inputs: user_ids (required), channel_id (required). Returns: result
join_channelC
Join a channel.
Inputs: channel_id (required), skip_log. Returns: result
list_joined_channelsARead-only
List channels the authenticated user is a member of.
Uses Slack's users.conversations API. By default returns public and private channels only. To include DMs and group DMs, set types to e.g. "public_channel,private_channel,im,mpim".
Inputs: limit, types, exclude_archived. Returns: result
post_commandCDestructive
Post a command to a channel.
Inputs: text (required), command (required), channel_id (required), skip_log. Returns: result
post_messageADestructive
Post a message to a channel. Optionally pass Block Kit blocks as a JSON string for rich formatting (e.g. nested lists via rich_text blocks). When blocks is provided, message is used as the plaintext fallback.
Inputs: message (required), channel_id (required), blocks, skip_log, +3 more. Returns: result
refresh_channel_cacheA
Refresh the channel cache. Use this when new channels are created or if channel lookups are failing.
Inputs: no named parameters. Returns: result
refresh_user_cacheA
Clear the user cache. Use this when user handles are outdated or if user lookups are failing. Returns the number of cached entries cleared.
Inputs: no named parameters. Returns: result
rename_channelADestructive
Rename a Slack channel.
Args: channel_id: Target channel ID (C...) new_name: New channel name (will be sanitized: lowercase, hyphens, no spaces)
Returns: True if rename succeeded, False otherwise
Inputs: new_name (required), channel_id (required). Returns: result
resolve_user_idARead-only
Resolve a Slack user ID from a name, @handle, or email address.
Searches the full workspace member list (cached for 24h). Returns up to 5 matches sorted by relevance: exact handle > exact email > case-insensitive name > partial substring match. Each result contains id, handle, real_name, display_name, and email.
Inputs: query (required). Returns: result
search_channel_messagesARead-only
Search for messages within a specific channel.
Uses Slack's search API with an 'in:' filter.
Args: channel_id: The channel ID to search within. query: The search query text. sort: Sort results by "timestamp" (newest first) or "score" (relevance). limit: Max number of results to return (default 100).
Inputs: query (required), channel_id (required), sort, limit. Returns: result
search_messagesBRead-only
Search for messages in the workspace with pagination support. Limit parameter controls max results to fetch (default 1000).
Inputs: query (required), sort, limit. Returns: result
send_dmADestructive
Send a direct message to a user. Optionally pass Block Kit blocks as a JSON string for rich formatting (e.g. nested lists via rich_text blocks). When blocks is provided, message is used as the plaintext fallback.
Inputs: message (required), user_id (required), blocks, unfurl_links, +1 more. Returns: result
send_group_dmBDestructive
Send a message to a group DM (multi-party direct message).
Args: user_ids: List of 2+ user IDs to include in group DM message: Message text to send
Returns: True if message sent successfully, False otherwise
Inputs: message (required), user_ids (required), blocks, unfurl_links, +1 more. Returns: result
update_usergroup_membersADestructive
Set the members of a Slack usergroup, replacing the current membership entirely.
Args: usergroup_id: The usergroup ID (S...) to update user_ids: List of user IDs (U...) that should be the members. Must contain at least one user — use clear_usergroup to remove all members.
Returns: True if the membership was updated successfully, False otherwise
Inputs: user_ids (required), usergroup_id (required). Returns: result
whoamiARead-only
Checks authentication & identity.
Inputs: no named parameters. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 22 tools
Most tools target distinct resources and actions, but get_thread overlaps with get_channel_history's include_threads option, and clear_usergroup is essentially a special case of update_usergroup_members. Otherwise, the boundaries are clear.
Tool names mostly follow a consistent verb_noun snake_case pattern (post_message, create_channel, search_messages). Minor deviations like whoami and the somewhat vague post_command keep it from being perfectly uniform.
With 22 tools, the set is at the heavy end for an MCP server, though Slack's broad domain justifies many of them. The inclusion of cache-refresh utilities and several overlapping search/message tools makes the surface feel slightly larger than necessary.
The server covers core messaging, channel management, reactions, search, and some usergroup operations. However, there are notable gaps such as message edit/delete, channel archive/delete/leave, and usergroup create/list/get, leaving some lifecycle workflows incomplete.
Maintenance
Related MCP Connectors
Enable interaction with Slack workspaces. Supports subscribing to Slack events through Resources.
Chat with your AI agents from Slack: each gets a thread in your DM, and your replies there wake it.
One place to build, share, and govern the skills and tools your AI agents use at work.
AI coworker for service businesses. Read a Slack workspace's context and hand Patricia work.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to interact with Slack workspaces through comprehensive channel management, messaging, direct messages, search functionality, and user management capabilities.303 npm3MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Slack workspaces through natural language, supporting channel management, message operations, user profiles, reactions, and threaded conversations.-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to read messages, threads, channel info, user profiles, search conversations, and generate permalinks in Slack workspaces.21 PyPI1MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to interact with Slack workspaces, including listing channels, posting messages, replying to threads, adding reactions, and retrieving user information.1024 npmMIT