Skip to main content
Glama

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.counts endpoint, 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.py

Options:

Flag

Description

--logs-channel DXXXXXXXXX

Slack channel ID for server logs (optional; logs go to stderr if omitted)

--workspace https://myco.slack.com

Specific Slack workspace to open

--refresh-tokens

Re-extract tokens when they expire (skips all other steps)

--skip-verify

Skip the post-setup smoke test

When tokens expire, just run:

python3 slack-mcp/scripts/setup-slack-mcp.py --refresh-tokens

Desktop 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 --validate

This 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

--validate

Verify tokens against Slack's API after extraction

--env

Print tokens as env vars to stdout (for piping into other tools)

--output FILE

Write tokens to a custom path (default: ~/.local/share/slack-mcp/tokens.env)

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.


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

  1. Create a Slack App at api.slack.com/apps

  2. 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:write

  3. Install to your workspace and copy the Bot User OAuth Token (xoxb-...)

  4. 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_ONLY to a truthy value (1, true, yes, or on, case-insensitive).

  • CLI: pass --read-only when 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-mcp

Run 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.py

Then 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-mcp

Or, with tokens.env already in place, no env needed:

claude mcp add slack -- slack-mcp

Running 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=C7000000

In 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 tools
add_reactionB

Add a reaction to a message.

Inputs: reaction (required), channel_id (required), message_ts (required). Returns: result

clear_usergroupA
Destructive

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_channelA
Destructive

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_historyA
Read-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_nameA
Read-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_reactionsB
Read-only

Get reactions to a message.

Inputs: channel_id (required), message_ts (required), full. Returns: result

get_threadA
Read-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_channelA
Destructive

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_channelsA
Read-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_commandC
Destructive

Post a command to a channel.

Inputs: text (required), command (required), channel_id (required), skip_log. Returns: result

post_messageA
Destructive

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_channelA
Destructive

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_idA
Read-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_messagesA
Read-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_messagesB
Read-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_dmA
Destructive

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_dmB
Destructive

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_membersA
Destructive

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

whoamiA
Read-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

    B3.4/5.0

    Scored across 22 tools

    Disambiguation4/5

    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.

    Naming Consistency4/5

    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.

    Tool Count3/5

    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.

    Completeness3/5

    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

    ActivityMaintained
    ResponsivenessMostly unanswered

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      Enables AI assistants to interact with Slack workspaces through comprehensive channel management, messaging, direct messages, search functionality, and user management capabilities.
      30
      3 npm
      3
      MIT
    • F
      license
      Not graded
      quality
      D
      maintenance
      Enables AI assistants to interact with Slack workspaces through natural language, supporting channel management, message operations, user profiles, reactions, and threaded conversations.
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI assistants to read messages, threads, channel info, user profiles, search conversations, and generate permalinks in Slack workspaces.
      21 PyPI
      1
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      Enables AI assistants to interact with Slack workspaces, including listing channels, posting messages, replying to threads, adding reactions, and retrieving user information.
      10
      24 npm
      MIT