Skip to main content
Glama
software-engineer-mj

Slack MCP Server

README.md
# Slack MCP Server

An MCP (Model Context Protocol) server that exposes the Slack API, enabling AI agents (Claude, Cursor, etc.) to interact with Slack directly.

Provides **20 tools** and **2 resources** with focused Slack API coverage.

## Features

- **20 MCP Tools** — channels, messages, users, files, and reactions
- **2 MCP Resources** — `slack://channels` and `slack://users` for workspace discovery
- **Rate Limit Handling** — automatic retry with `Retry-After` backoff via slack_sdk built-in handlers
- **Safety Controls** — channel whitelist for message-sending restrictions, write tools disabled by default
- **Conditional Tool Registration** — search tools auto-disabled when User Token is not provided
- **Block Kit Support** — all message tools accept Block Kit JSON
- **Multiple Transports** — stdio (default), SSE, and streamable-http
- **Docker Support** — production-ready Dockerfile included

## Requirements

- Python >= 3.10
- [uv](https://docs.astral.sh/uv/) (recommended) or pip
- Slack Bot Token (`xoxb-...`) — required
- Slack User Token (`xoxp-...`) — optional, enables search features

## Installation

```bash
git clone https://github.com/software-engineer-mj/slack-mcp.git
cd slack-mcp
uv sync
```

## Configuration

```bash
cp .env.example .env
```

Edit the `.env` file and fill in your tokens:

| Variable | Required | Description |
|----------|----------|-------------|
| `SLACK_BOT_TOKEN` | Yes | Bot token (`xoxb-...`) |
| `SLACK_USER_TOKEN` | No | User token (`xoxp-...`) for search features |
| `SLACK_MCP_LOG_LEVEL` | No | Log level: `DEBUG`, `INFO` (default), `WARNING`, `ERROR` |
| `SLACK_MCP_ALLOWED_CHANNELS` | No | Comma-separated channel IDs to restrict message sending (e.g., `C123,C456`). Default: all channels allowed |

### Safety Controls

**Channel Whitelist:** When `SLACK_MCP_ALLOWED_CHANNELS` is set, message-sending tools (`send_message`, `reply_to_thread`, `update_message`) are restricted to the listed channels only.

### Slack App Permissions (Bot Token Scopes)

The Bot Token requires the following OAuth scopes:

| Scope | Purpose |
|-------|---------|
| `channels:read` | List and view channel info |
| `channels:history` | Read channel message history |
| `groups:read` | View private channels |
| `groups:history` | Read private channel history |
| `chat:write` | Send and update messages |
| `im:read` | View direct messages |
| `im:history` | Read DM history |
| `im:write` | Open DMs |
| `mpim:read` | View group DMs |
| `mpim:history` | Read group DM history |
| `users:read` | View user info |
| `users:read.email` | Look up users by email |
| `users.profile:read` | View user profiles |
| `reactions:read` | View reactions |
| `reactions:write` | Add reactions |
| `files:read` | View files |
| `files:write` | Upload files |

Additional scope required for User Token:

| Scope | Purpose |
|-------|---------|
| `search:read` | Search messages and files |

## Usage

### stdio (default)

```bash
uv run python -m slack_mcp
```

### SSE transport

```bash
uv run python -m slack_mcp --transport=sse
```

### Streamable HTTP transport

```bash
uv run python -m slack_mcp --transport=streamable-http
```

### Docker

```bash
docker build -t slack-mcp .

docker run -e SLACK_BOT_TOKEN=xoxb-your-token \
           -e SLACK_USER_TOKEN=xoxp-your-token \
           slack-mcp
```

To restrict channels:

```bash
docker run -e SLACK_BOT_TOKEN=xoxb-your-token \
           -e SLACK_MCP_ALLOWED_CHANNELS=C123,C456 \
           slack-mcp
```

## MCP Client Configuration

### Claude Desktop

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "slack": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/slack-mcp", "python", "-m", "slack_mcp"],
      "env": {
        "SLACK_BOT_TOKEN": "xoxb-your-token",
        "SLACK_USER_TOKEN": "xoxp-your-token"
      }
    }
  }
}
```

### Claude Code

Add to `.mcp.json`:

```json
{
  "mcpServers": {
    "slack": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/slack-mcp", "python", "-m", "slack_mcp"],
      "env": {
        "SLACK_BOT_TOKEN": "xoxb-your-token",
        "SLACK_USER_TOKEN": "xoxp-your-token"
      }
    }
  }
}
```

## Development

```bash
# Install with dev dependencies
uv sync --dev

# Run tests
uv run pytest tests/ -v

# Lint
uv run ruff check src/ tests/

# Format
uv run ruff format src/ tests/
```

## Available Tools (20)

### Channels (6)

| Tool | Description |
|------|-------------|
| `list_channels` | List channels (with cursor pagination support) |
| `get_channel_info` | Get channel details |
| `get_channel_history` | Read channel message history |
| `get_channel_members` | List channel members (with cursor pagination support) |
| `get_channel_summary` | Summarize recent activity (resolved names + threads) |
| `open_conversation` | Open a DM conversation |

### Messages (5)

| Tool | Description |
|------|-------------|
| `send_message` | Send a message (supports Block Kit) |
| `reply_to_thread` | Reply to a thread (supports Block Kit) |
| `get_thread_replies` | Get thread replies |
| `update_message` | Update a message (supports Block Kit) |
| `search_messages` | Search messages (requires User Token) |

### Users (4)

| Tool | Description |
|------|-------------|
| `list_users` | List users (with cursor pagination support) |
| `get_user_info` | Get user details (cached) |
| `get_user_profile` | Get user profile |
| `lookup_user_by_email` | Look up a user by email |

### Files (3)

| Tool | Description |
|------|-------------|
| `list_files` | List files (with page-based pagination) |
| `upload_file` | Upload a file |
| `search_files` | Search files (requires User Token) |

### Reactions (2)

| Tool | Description |
|------|-------------|
| `add_reaction` | Add an emoji reaction |
| `list_reactions` | Get all reactions on a message |

## MCP Resources

| URI | Description |
|-----|-------------|
| `slack://channels` | CSV list of all channels (id, name, is_private, num_members) |
| `slack://users` | CSV list of all users (id, name, real_name, is_bot, deleted) |

## Project Structure

```
src/slack_mcp/
├── __init__.py          # FastMCP server instance
├── __main__.py          # Entry point with auto-discovery
├── client.py            # SlackClient singleton (API calls, error handling, pagination)
├── exceptions.py        # Custom exception hierarchy
├── lifespan.py          # Server lifecycle (conditional tool registration, safety controls)
├── resources.py         # MCP resources (channels, users)
└── tools/
    ├── __init__.py
    ├── channels.py      # Channels
    ├── files.py         # Files
    ├── messages.py      # Messages (Block Kit support)
    ├── reactions.py     # Reactions
    └── users.py         # Users
tests/
├── conftest.py          # Shared fixtures (mock Slack clients)
├── test_client.py       # SlackClient tests (error handling, pagination, safety)
├── test_exceptions.py   # Exception hierarchy tests
├── test_pagination.py   # Pagination utility tests
├── test_resources.py    # MCP resource tests
└── tools/
    ├── test_channels.py
    ├── test_files.py
    ├── test_messages.py
    ├── test_reactions.py
    └── test_users.py
```

## License

MIT - see [LICENSE](LICENSE) for details.