Manage Slack conversations, channels, users, and search workflows through MCP tools.
A Model Context Protocol (MCP) server that exposes Slack's API for messaging, channel operations, workspace discovery, and user-scoped automation.
Overview
The CL Slack MCP Server provides stateless, token-based Slack API access:
- Core messaging and thread workflows
- Channel and workspace discovery tools
- User and file search capabilities
Perfect for:
- AI-assisted Slack operations
- Workflow automation across channels and users
- Building Slack copilots with MCP-compatible clients
Returns a lightweight readiness response to confirm the MCP server is running.
Inputs:
Output:
{
"status": "ok",
"server": "CL Slack MCP Server"
}
usage Example:
POST /mcp/cl-slack-mcp/health_check
{}
Posts text and optional Block Kit content to a Slack conversation.
Inputs:
oauth_token (string, required) - Slack OAuth token (xoxb-... or xoxp-...)
channel (string, required) - Channel ID or name
text (string, optional) - Message text
blocks (array, optional) - Block Kit JSON
thread_ts (string, optional) - Parent timestamp for threaded reply
reply_broadcast (boolean, optional) - Broadcast threaded reply to channel
Output:
Reads recent message history with optional time window filtering.
Inputs:
oauth_token (string, required) - Slack OAuth token
channel (string, required) - Channel ID or name
limit (integer, optional) - Number of messages (1-100)
oldest (string, optional) - Lower timestamp bound
latest (string, optional) - Upper timestamp bound
Output:
{
"ok": true,
"messages": []
Updates message text or blocks for a specific channel timestamp.
Inputs:
oauth_token (string, required) - Slack OAuth token
channel (string, required) - Channel ID
ts (string, required) - Message timestamp
text (string, optional) - Updated text
blocks (array, optional) - Updated Block Kit payload
Output:
{
"ok": true,
"ts": "1712000000.123456"
Deletes a Slack message by channel and timestamp.
Inputs:
oauth_token (string, required) - Slack OAuth token
channel (string, required) - Channel ID
ts (string, required) - Message timestamp
Output:
{
"ok": true,
"channel": "C123ABC456",
"ts": "1712000000.123456"
}
usage Example:
Searches Slack messages by query with score/timestamp sorting controls.
Inputs:
oauth_token (string, required) - Slack OAuth token
query (string, required) - Search query
sort (string, optional) - score or timestamp
sort_dir (string, optional) - asc or desc
count (integer, optional) - Number of results
Output:
Adds a thread reply and optionally broadcasts it to the parent channel.
Inputs:
oauth_token (string, required) - Slack OAuth token
channel (string, required) - Channel ID
thread_ts (string, required) - Parent message timestamp
text (string, optional) - Reply text
blocks (array, optional) - Block Kit JSON
broadcast (boolean, optional) - Broadcast to channel
Output:
Lists channels with pagination, type filtering, and archived controls.
Inputs:
oauth_token (string, required) - Slack OAuth token
exclude_archived (boolean, optional) - Exclude archived channels
limit (integer, optional) - Page size (1-100)
cursor (string, optional) - Pagination cursor
types (string, optional) - Comma-separated channel types
team_id (string, optional) - Team ID for org-wide apps
Output:
Creates a public or private channel, with optional description.
Inputs:
oauth_token (string, required) - Slack OAuth token
name (string, required) - Channel name
is_private (boolean, optional) - Create private channel
description (string, optional) - Channel description
Output:
{
"ok": true,
"channel": {
"id": "C123ABC456",
"name"
Archives channel when archive=true; unarchives when archive=false.
Inputs:
oauth_token (string, required) - Slack OAuth token
channel (string, required) - Channel ID
archive (boolean, optional) - Archive toggle
Output:
usage Example:
Returns channel details including membership counts where available.
Inputs:
oauth_token (string, required) - Slack OAuth token
channel (string, required) - Channel ID
Output:
{
"ok": true,
"channel": {
"id": "C123ABC456"
}
}
usage Example:
Invites one or more user IDs to the target channel.
Inputs:
oauth_token (string, required) - Slack OAuth token
channel (string, required) - Channel ID
users (array[string], required) - User IDs to invite
Output:
{
"ok": true,
"channel": {
"id": "C123ABC456"
}
}
usage Example:
Searches Slack files by query, type, and sorting options.
Inputs:
oauth_token (string, required) - Slack OAuth token
query (string, optional) - Search query
sort (string, optional) - score or timestamp
sort_dir (string, optional) - asc or desc
count (integer, optional) - Number of results
types (string, optional) - File type filter
Paginates through channel listings and returns a combined map.
Inputs:
oauth_token (string, required) - Slack OAuth token
include_archived (boolean, optional) - Include archived channels
Output:
{
"ok": true,
"channels": [],
"total": 0
}
usage Example:
Performs direct ID lookup and fallback member filtering.
Inputs:
oauth_token (string, required) - Slack OAuth token
query (string, required) - Name, email, or user ID
Output:
{
"ok": true,
"matches": [],
"total": 0
}
usage Example:
Collects root messages that represent thread starters and returns summary fields.
Inputs:
oauth_token (string, required) - Slack OAuth token
channel (string, required) - Channel ID
limit (integer, optional) - Number of messages scanned
Output:
{
"ok": true,
"threads": [],
"note": "For full async summarization, implement polling with job ID"
}
usage Example:
Lists users with pagination controls.
Inputs:
oauth_token (string, required) - Slack OAuth token
limit (integer, optional) - Users per page (1-100)
cursor (string, optional) - Pagination cursor
Output:
{
"ok": true,
"members": []
}
usage Example:
Returns workspace details from Slack team.info.
Inputs:
oauth_token (string, required) - Slack OAuth token
Output:
{
"ok": true,
"team": {
"id": "T123ABC456",
"name": "Workspace Name"
}
}
usage Example:
Fetches active/away style presence for a given user ID.
Inputs:
oauth_token (string, required) - Slack OAuth token
user (string, required) - Slack user ID
Output:
{
"ok": true,
"presence": "active"
}
usage Example:
POST /mcp/cl-slack-mcp/get_user_presence
API Parameters Reference
oauth_token - Slack access token used for API authentication.
channel - Slack channel ID (for example, C123ABC456) or channel name where supported.
ts - Slack message timestamp identifier.
thread_ts - Parent message timestamp for thread operations.
limit - Page size/count for list and history operations.
cursor - Pagination cursor from response_metadata.next_cursor.
Channel Resource:
channel ID format: C########
Example: C123ABC456
user Resource:
user ID format: U######## or W########
Example: U123ABC456
message Resource:
message timestamp format: 1712000000.123456
Example:
Authentication Guide
All tools require a valid Slack OAuth token. This server supports user tokens (xoxp-...) and bot tokens (xoxb-...).
Step 1: Create Slack App
- Go to Slack App Management
- Create a new app from scratch
- Select your workspace
- Open OAuth & Permissions in your app settings
- Copy Client ID and Client Secret
- Add redirect URL (HTTPS required), for example:
https://your-tunnel-host/slack/oauth/callback
Step 3: Generate Token with Included Script
Use get_slack_oauth_token.py from this repository.
Example user token flow:
Troubleshooting
Missing or Invalid Token
- Cause:
oauth_token is missing, malformed, expired, or revoked
- Solution:
- Generate a fresh token with
get_slack_oauth_token.py
- Confirm token prefix (
xoxp- or xoxb-)
- Verify token has required scopes
Missing Scope Errors
- Cause: Token does not include scope required by the Slack endpoint
- Solution:
- Add needed scope in Slack app dashboard
- Reinstall/reauthorize app
- Generate a new token
bad_redirect_uri During OAuth
- Cause: Redirect URI mismatch between authorize and token-exchange steps
- Solution:
- Ensure exact same redirect URI is used in both steps
- Confirm redirect URL is added in Slack app settings
- Use HTTPS tunnel (zrok/ngrok) and keep it running
App Requests Bot Install Unexpectedly
Resources
{
"ok": true,
"channel": "C123ABC456",
"ts": "1712000000.123456"
}
POST /mcp/cl-slack-mcp/send_message
{
"oauth_token": "xoxp-...",
"channel": "C123ABC456",
"text": "Hello from MCP"
}
}
POST /mcp/cl-slack-mcp/read_messages
{
"oauth_token": "xoxp-...",
"channel": "C123ABC456",
"limit": 20
}
}
POST /mcp/cl-slack-mcp/update_message
{
"oauth_token": "xoxp-...",
"channel": "C123ABC456",
"ts": "1712000000.123456",
"text": "Updated message"
}
POST /mcp/cl-slack-mcp/delete_message
{
"oauth_token": "xoxp-...",
"channel": "C123ABC456",
"ts": "1712000000.123456"
}
{
"ok": true,
"messages": {
"matches": []
}
}
POST /mcp/cl-slack-mcp/search_messages
{
"oauth_token": "xoxp-...",
"query": "incident postmortem",
"count": 10
}
,
"thread_ts": "1712000000.123456"
}
POST /mcp/cl-slack-mcp/reply_thread
{
"oauth_token": "xoxp-...",
"channel": "C123ABC456",
"thread_ts": "1712000000.123456",
"text": "Follow-up update"
}
true
,
"channels": [],
"response_metadata": {
"next_cursor": ""
}
}
POST /mcp/cl-slack-mcp/list_channels
{
"oauth_token": "xoxp-...",
"limit": 50,
"types": "public_channel,private_channel"
}
:
"team-updates"
}
}
POST /mcp/cl-slack-mcp/create_channel
{
"oauth_token": "xoxp-...",
"name": "team-updates",
"is_private": false
}
POST /mcp/cl-slack-mcp/archive_channel
{
"oauth_token": "xoxp-...",
"channel": "C123ABC456",
"archive": true
}
POST /mcp/cl-slack-mcp/get_channel_info
{
"oauth_token": "xoxp-...",
"channel": "C123ABC456"
}
POST /mcp/cl-slack-mcp/invite_users_to_channel
{
"oauth_token": "xoxp-...",
"channel": "C123ABC456",
"users": ["U111", "U222"]
}
{
"ok": true,
"files": {
"matches": []
}
}
POST /mcp/cl-slack-mcp/search_files
{
"oauth_token": "xoxp-...",
"query": "roadmap pdf",
"count": 10
}
POST /mcp/cl-slack-mcp/map_channels
{
"oauth_token": "xoxp-...",
"include_archived": false
}
POST /mcp/cl-slack-mcp/find_user
{
"oauth_token": "xoxp-...",
"query": "alice@example.com"
}
POST /mcp/cl-slack-mcp/extract_threads
{
"oauth_token": "xoxp-...",
"channel": "C123ABC456",
"limit": 20
}
POST /mcp/cl-slack-mcp/list_users
{
"oauth_token": "xoxp-...",
"limit": 50
}
POST /mcp/cl-slack-mcp/get_workspace_info
{
"oauth_token": "xoxp-..."
}
{
"oauth_token": "xoxp-...",
"user": "U123ABC456"
}
1712000000.123456
python3 get_slack_oauth_token.py \
--type user \
--oauth-flow standard \
--scopes search:read,channels:read,chat:write
standard flow: /oauth/v2/authorize + oauth.v2.access
user-centric flow: /oauth/v2_user/authorize + oauth.v2.user.access
Step 4: Required Scopes
Ensure the token includes scopes required by the tools you will call.
chat:write - Send, update, delete, and reply to messages
channels:read - List and inspect public channels
channels:history - Read message history in public channels
search:read - Search workspace messages/files
users:read - List users and resolve identity metadata
If you use private channels, DMs, MPIMs, and usergroups, add corresponding groups:*, im:*, mpim:*, and usergroups:* scopes.
- Cause: Bot scopes/features are configured in Slack app while attempting user-only flow
- Solution:
- Remove unneeded bot scopes/capabilities from app config
- Use user-only scopes and rerun with
--type user
- Reinstall/reauthorize after configuration changes
MCP Server Not Reachable
- Cause: Server transport/host/port mismatch
- Solution:
- Start server with expected transport
- Confirm host/port arguments
- Check client points to
/mcp path for HTTP transport