slack-mcp & slack-cli: Give Your AI Assistant Read Access to Slack
← Back to blog

slack-mcp & slack-cli: Give Your AI Assistant Read Access to Slack

Published on
5 mins read
--- views
slack-mcp — an AI assistant searching Slack messages, threads, and users

So much of the context an AI assistant needs lives in Slack — the conversation behind a ticket, the back-and-forth that explains a bug, the thread where a decision actually got made. The model can't see any of it. So I built a pair of tools that fix that: slack-mcp, a Model Context Protocol server, and slack-cli, the Go command-line tool that powers it.

Together they give your AI assistant read access to Slack — search messages, unroll threads, and resolve who said what — and pull that real context straight into its working memory.

Two Repos, One Tool

These ship as two binaries on purpose:

  • slack-cli is the engine. It authenticates to Slack, encrypts and stores credentials, and does the actual API calls — usable on its own from a terminal or a script.
  • slack-mcp is a thin MCP layer on top. It exposes the same capabilities as MCP tools over stdio so any MCP-aware agent (Claude, Cursor, etc.) can call them.

Splitting it this way means the auth-and-Slack logic lives in one well-tested place, and the MCP server stays small. You can drive Slack from a shell script and from your AI assistant with the same credentials.

MCP Tools

The server exposes nine read-and-auth tools. load_slack_context is the headline:

ToolParametersDescription
search_messagesworkspace, query, count?, start_from?Search messages across all channels — returns channel, author, snippet, timestamp, permalink
load_slack_contextworkspace, channel_id, thread_ts, permalink?, channel_name?, search_query?, start_from?Primary tool — load a thread with every user resolved, formatted as markdown
load_threadworkspace, channel_id, thread_ts, start_from?Load every message in a thread (raw user IDs; paginates up to ~2000)
get_user_infoworkspace, user_idResolve a user ID to a display name
list_workspacesList workspaces with saved credentials
get_credentialsworkspaceCheck whether credentials exist (never exposes tokens)
auth_startworkspace?Open Slack + return token-extraction instructions
auth_completeworkspace, token, cookieValidate and save credentials
delete_credentialsworkspaceRemove stored credentials

load_slack_context is the one I designed everything around: give it a channel and a thread, and it returns the full conversation with every user resolved to a display name, formatted as markdown — exactly what an LLM wants to read. No raw U01ABCD IDs, no JSON soup.

📅 start_from accepts a YYYY-MM-DD date — only messages on or after it are returned. Works on search_messages, load_thread, and load_slack_context.

CLI Commands

Everything the server does, slack-cli exposes directly — handy for auth and for scripting:

CommandParametersDescription
auth[workspace]Interactive auth — opens browser, prompts for token + cookie
auth-start[workspace]Print DevTools extraction instructions without saving
auth-complete<workspace> --token --cookieSave credentials non-interactively
list-workspacesList all saved workspace names
get-credentials<workspace>Show whether token + cookie are present
test-creds[workspace]Validate stored credentials against Slack auth.test
remove-creds[workspace]Delete stored credentials for a workspace
show-credsPrint the path to the credentials file

Authentication Without a Slack App

This is the part that makes it actually usable. slack-cli authenticates with a browser-session token (xoxc-…) plus cookie (xoxd-…) — no Slack app to register, no admin approval, no OAuth scopes to beg for. You sign into the workspace you already use, extract the pair once, and you're done.

slack-cli auth acme            # interactive — opens the browser, prompts for token + cookie
# or, non-interactively:
export SLACK_MCP_PASSPHRASE=your-passphrase-here
slack-cli auth-complete acme --token xoxc-... --cookie xoxd-...

Credentials are encrypted at rest with a passphrase read from SLACK_MCP_PASSPHRASE (or an interactive prompt). The passphrase that saved them must match the one that reads them — the MCP server uses the same env var, so the agent decrypts and never sees the raw tokens in a transcript.

Setup

Prerequisites

  • Go 1.26+ — to build or go install
  • slack-cli on your PATH (or point to it with SLACK_CLI_PATH=/abs/path/to/slack-cli) — it's the companion binary that stores credentials and calls Slack

Install

# the CLI engine
go install github.com/artschekoff/slack-cli/cmd/slack-cli@latest

# the MCP server
go install github.com/artschekoff/slack-mcp/cmd/slack-mcp@latest

Both also build from source with git clone … && make install.

Wire it into your MCP client

Add a stdio server entry — the passphrase goes in env so credentials decrypt at runtime:

{
  "mcpServers": {
    "slack": {
      "type": "stdio",
      "command": "slack-mcp",
      "env": {
        "SLACK_MCP_PASSPHRASE": "your-passphrase"
      }
    }
  }
}

Or with the Claude Code CLI:

claude mcp add slack --env SLACK_MCP_PASSPHRASE=your-passphrase -- slack-mcp

Why Read-Only, and Why Split the Binary

I deliberately scoped this to reading. An agent that can post to Slack on your behalf is a different, scarier risk profile; an agent that can pull the context behind a ticket is just useful. Keeping it read-only means you can hand it to your assistant without worrying it'll message a channel.

Splitting the CLI from the MCP server follows the same principle behind my other MCP tools — put the real work in a mature, testable binary, then wrap exactly the operations an agent needs in a thin MCP layer. Credentials stay encrypted, tokens never hit the transcript, and the same engine serves both your shell and your AI assistant.

Both projects are open on GitHub — slack-mcp and slack-cli — pure Go, running over stdio. Issues and pull requests welcome.

Open for contract collaboration

I am available for contract-based collaboration. If you have an interesting project idea, schedule a call via Calendly.

Schedule a 30-min call