slack-mcp
Acts as the user in Slack via a user OAuth token, providing tools for channel and DM messaging, threads, message search, user and channel lookup, user groups, emoji reactions, scheduled messages, canvases, and Slack Lists.
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 post 'standup in 10 minutes' to #engineering"
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 lean MCP server that acts in Slack as you, through a user OAuth token (xoxp-…). One small Python process covers messaging, threads, search, users, channels, user groups and reactions, plus the APIs most Slack MCP servers skip: scheduled messages, canvases and Slack Lists.
Tools
Tool | What it does | Slack methods |
| Channel or DM messages as CSV; |
|
| A thread as CSV |
|
| Post as you; markdown is rendered by Slack ( |
|
| Delete a message you posted |
|
| Search with channel, user, date and thread filters, or fetch one message by URL |
|
| Find users by ID, handle, name or email, with their DM channel |
|
| All channels, filtered and sorted / channels you are in |
|
| User groups / the groups you belong to (read-only) |
|
| Emoji reactions |
|
| Scheduled messages |
|
| Canvases from and to markdown |
|
| Slack Lists (paid plans); |
|
Wherever a tool takes a channel, it accepts an ID, #channel-name, or @user for that user's DM. conversations_add_message and schedule_message also accept @a,@b for a group DM with those users (it needs the mpim:write scope; Slack returns the existing group DM when one exists). Only those two tools open a DM that does not exist yet; read tools fail instead. A user is matched by ID, handle, then display or real name, and an ambiguous name is refused. Paging cursors carry the original window and page size. Tool names and parameters match korotovsky/slack-mcp-server for the overlapping tools, so existing prompts and permission rules keep working.
Related MCP server: Slack MCP Server
Setup
Create a Slack app at https://api.slack.com/apps → From a manifest:
{ "display_information": { "name": "Slack MCP" }, "oauth_config": { "scopes": { "user": [ "channels:history", "channels:read", "groups:history", "groups:read", "im:history", "im:read", "im:write", "mpim:history", "mpim:read", "mpim:write", "users:read", "users:read.email", "chat:write", "search:read", "usergroups:read", "reactions:write", "canvases:read", "canvases:write", "files:read", "files:write", "lists:read", "lists:write" ] } }, "settings": { "org_deploy_enabled": false, "socket_mode_enabled": false, "token_rotation_enabled": false } }Drop the scopes for tools you will not use; a call that needs a missing scope fails with
missing_scope (token lacks scope: …).Install to Workspace and copy the User OAuth Token.
Register a launcher that reads the token from your secret manager at startup, so the token never lands in a config file or on a command line:
#!/usr/bin/env bash # slack-mcp-start.sh SLACK_USER_TOKEN="$(op read 'op://Private/Slack MCP/token')" || exit 1 # or any secret manager export SLACK_USER_TOKEN exec uvx --from git+https://github.com/asaphe/slack-mcp slack-mcpclaude mcp add slack --scope user -- /path/to/slack-mcp-start.shAvoid
claude mcp add … -e SLACK_USER_TOKEN="$(…)": the shell expands the secret before Claude Code runs, and it is stored in plain text in~/.claude.json.
Security
The token is read from
SLACK_USER_TOKENonly, sent only in theAuthorizationheader toslack.com/api/and, forcanvas_read, tofiles.slack.comover HTTPS (any other file URL is refused and redirects are not followed). It is never logged or included in errors.Posting tools act as you. Gate them in your MCP client (for Claude Code:
permissions.askonmcp__slack__conversations_add_message,schedule_message,canvas_create,canvas_edit,list_create,list_item_create,list_items_update,delete_scheduled_message,reactions_*).No telemetry, no disk cache; user and channel directories live in memory for the process lifetime.
Tools run in worker threads, so a slow Slack call or a rate-limit wait never blocks the MCP connection.
Development
uv sync --all-groups
uv run pytest
uv run ruff check . && uv run ruff format --check . && uv run mypy srcLicense
MIT
Available Tools
22 toolscanvas_createADestructive
Create a canvas from markdown. channel_id tabs it in that channel; omit for a standalone canvas.
Inputs: title, channel_id, markdown_content.
canvas_editADestructive
Apply one edit. operation: insert_at_start|insert_at_end|insert_before|insert_after|replace|delete|rename. insert_before/insert_after/delete need section_id (canvas_find_sections); replace without section_id replaces the whole canvas; rename uses markdown_content as the new title.
Inputs: canvas_id (required), operation (required), section_id, markdown_content.
canvas_find_sectionsBRead-only
Find section IDs in a canvas by text and/or type (h1, h2, h3, any_header, list, table, ...).
Inputs: canvas_id (required), contains_text, section_types.
canvas_readCRead-only
A canvas's title and text content.
Inputs: canvas_id (required).
channels_listBRead-only
Workspace channels as CSV. channel_types: comma-separated public_channel, private_channel, im, mpim. query: case-insensitive substring over query_targets (name, topic, purpose). sort: 'popularity' (member count).
Inputs: channel_types (required), sort, limit, query, +2 more. Returns: result
channels_meBRead-only
Conversations you are a member of, as CSV. channel_types as in channels_list.
Inputs: limit, cursor, channel_types. Returns: result
conversations_add_messageBDestructive
Post a message as you. content_type: 'text/markdown' (standard markdown, rendered by Slack) or 'text/plain'. blocks: a Block Kit array, which takes precedence; text then becomes the notification fallback. Link and media unfurling is off.
Inputs: channel_id (required), text, blocks, thread_ts, +1 more. Returns: result
conversations_historyARead-only
Messages in a channel or DM as CSV, newest first. limit: a count ('50') or a window ('1d', '2w', '3m', counted from local midnight); leave it empty when passing cursor. A non-empty Cursor column on the last row means more results: pass it back as cursor, which keeps the original window and page size.
Inputs: channel_id (required), limit, cursor, include_activity_messages. Returns: result
conversations_repliesBRead-only
A thread (parent plus replies) as CSV. thread_ts: the parent's ts, e.g. 1234567890.123456. limit and cursor work as in conversations_history.
Inputs: thread_ts (required), channel_id (required), limit, cursor, +1 more. Returns: result
conversations_search_messagesARead-only
Search messages as CSV. search_query may carry Slack modifiers (in:, from:, before:, …) or be a message URL, which returns that one message. Users: ID, @handle or name. Channels: ID or #name. Dates: YYYY-MM-DD, today, yesterday, 'N days ago', 'July 2026' (during: the whole month) or a month name (during only). limit: 1-100; a cursor replays the original query and page size; filters passed with it are ignored.
Inputs: limit, cursor, search_query, filter_date_on, +8 more. Returns: result
delete_scheduled_messageBDestructive
Cancel a scheduled message before it posts.
Inputs: channel (required), scheduled_message_id (required).
list_createCDestructive
Create a Slack List. schema: [{"key","name","type":"text|date|select|user|...","is_primary_column"?,"options"?}].
Inputs: name (required), schema, todo_mode.
list_item_createBDestructive
Add an item. initial_fields: [{"column_id", : value}]; text columns take "rich_text" blocks.
Inputs: list_id (required), initial_fields, parent_item_id.
list_itemsCRead-only
A List's items; include_list also returns its columns (column_id values for writes).
Inputs: list_id (required), limit, cursor, include_list.
list_items_updateCDestructive
Update up to 100 cells: [{"row_id","column_id", : value}].
Inputs: cells (required), list_id (required).
list_scheduled_messagesCRead-only
Your pending scheduled messages, optionally for one channel.
Inputs: cursor, channel.
reactions_addB
Add an emoji reaction (name without colons) to a message.
Inputs: emoji (required), timestamp (required), channel_id (required). Returns: result
reactions_removeBDestructive
Remove your emoji reaction from a message.
Inputs: emoji (required), timestamp (required), channel_id (required). Returns: result
schedule_messageBDestructive
Schedule a message up to 120 days ahead. post_at: Unix seconds or ISO-8601 with offset.
Inputs: text (required), channel (required), post_at (required), thread_ts.
usergroups_listBRead-only
User groups (@mention groups) as CSV: id, name, handle, description, user_count, users (if include_users).
Inputs: include_users, include_disabled. Returns: result
usergroups_meARead-only
User groups you belong to, as CSV.
Inputs: no named parameters. Returns: result
users_searchARead-only
Find users by ID, handle, display name, real name or email (case-insensitive substring) as CSV, with the DM channel ID when one exists.
Inputs: query (required), limit. 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 a clear resource+action (reactions_add/remove, canvas_create/edit/read, conversations_history/replies/search). The main confusion is the 'list_' prefix colliding between Slack Lists (list_create, list_items, list_item_create) and the verb 'list' (list_scheduled_messages, usergroups_list, channels_list), which can mislead at a glance. Descriptions largely resolve this, so ambiguity is minor.
The server mixes noun_verb (canvas_read, usergroups_list, reactions_add, schedule_message, list_create) with verb_noun (list_scheduled_messages, delete_scheduled_message, canvas_find_sections, users_search, channels_list). Individual names are readable but there's no single predictable pattern, and the overloaded 'list' token adds noise.
22 tools is on the heavy side but justified by covering several distinct Slack surfaces (canvas, lists, usergroups, reactions, scheduling, conversations, users, channels). Each tool maps to a real operation with little redundancy, so it stays reasonable for a product as broad as Slack.
Core read/write workflows are present (post, schedule, search, react, canvases, lists), but notable gaps exist: no edit/delete for posted messages, no channel management (create/join/leave), no file upload/download, and reactions only cover add/remove. These are workable-around but leave the surface incomplete for full Slack automation.
Related MCP Connectors
Chat with your AI agents from Slack: each gets a thread in your DM, and your replies there wake it.
Messaging tools for AI agents: send messages, manage chats, groups and channels.
Hosted Slack MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
Carbon Voice MCP serves as a bridge that connects AI assistants like ChatGPT, Claude, and Cursor to a user's Carbon Voice account, turning voice messages and conversations into a private, on-demand knowledge base. It provides 28 specialized tools for comprehensive voice messaging management, including creating and sending messages, accessing conversation history with instant transcription, running AI actions (summarization, TLDR generation, meeting notes), and managing workspace collaboration through folders, contacts, and team communications.
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.-
- AlicenseAqualityDmaintenanceIntegrates AI assistants with Slack workspaces using OAuth 2.0 authenticated user tokens for secure, multi-functional interaction. It enables comprehensive operations including channel management, message searching, file handling, and reaction management through natural language.20169 npmMIT
- AlicenseAqualityDmaintenanceEnables AI assistants to interact with Slack workspaces, including listing channels, posting messages, replying to threads, adding reactions, and retrieving user information.1024 npmMIT