Skip to main content
Glama
antonkazlouski-orca

Slack MCP Server

README.md
# Slack MCP Server

A comprehensive Model Context Protocol (MCP) server providing complete Slack Web API integration with 9 tools for reading messages, managing channels, searching content, and interacting with Slack workspaces.

## Features

**Channel Operations (5 tools)**
- List all channels you're a member of
- Get message history from channels
- Get detailed channel information
- Search messages across all channels
- Post messages to channels and threads

**User Operations (4 tools)**
- Get user profile information
- List all workspace users
- Get thread replies
- Get messages where you were mentioned

## Prerequisites

- Python 3.12 or higher
- Slack workspace with user token access
- Slack User OAuth Token with appropriate scopes

## Installation

1. Install dependencies using uv:
```bash
cd /Users/dimay/mcp/slack_mcp
uv sync
```

## Configuration

### Getting a Slack User Token

You have two options:

#### Option 1: Create a Slack App (Recommended)

1. Go to https://api.slack.com/apps and create a new app
2. Under **OAuth & Permissions**, add these **User Token Scopes**:
   - `channels:history` - View messages in public channels
   - `channels:read` - View basic public channel info
   - `groups:history` - View messages in private channels
   - `groups:read` - View basic private channel info
   - `im:history` - View direct messages
   - `mpim:history` - View group direct messages
   - `users:read` - View users in workspace
   - `search:read` - Search workspace content
   - `chat:write` - Send messages (optional, for posting)

3. Install the app to your workspace and authorize it
4. Copy the **User OAuth Token** (starts with `xoxp-`)

#### Option 2: Extract Token from Browser (Quick but Less Secure)

1. Open Slack in your web browser (https://app.slack.com)
2. Open Developer Tools (F12)
3. Go to Console tab
4. Run: `TS.boot_data.api_token`
5. Copy the token (starts with `xoxc-`)

**Note:** Browser tokens may expire and are less secure. Use OAuth method for production.

### Set Environment Variables

The server supports two authentication methods:

#### Method 1: Browser Token + Cookie (Quick)

1. Open Slack in your browser (https://app.slack.com)
2. Open Developer Tools (F12) → Console
3. Run: `TS.boot_data.api_token` to get your token (starts with `xoxc-`)
4. Go to Application/Storage tab → Cookies → https://app.slack.com
5. Find cookie named `d` and copy its value (starts with `xoxd-`)
6. Add both to your shell profile (~/.zshrc):

```bash
export SLACK_USER_TOKEN="xoxc-your-token-here"
export SLACK_USER_COOKIE="xoxd-your-cookie-here"
```

Then run: `source ~/.zshrc`

**Note:** Browser tokens may expire with your browser session.

#### Method 2: OAuth Token (Recommended for Production)

```bash
export SLACK_USER_TOKEN="xoxp-your-oauth-token-here"
```

OAuth tokens (from creating a Slack App) don't require a cookie and are more reliable.

## Usage

### Running the MCP Server

```bash
cd /Users/dimay/mcp/slack_mcp
uv run slack_mcp_server.py
```

### Configuring with Claude Code

Add to your Claude Code MCP settings:

**For Browser Token (xoxc-):**
```json
{
  "mcpServers": {
    "slack": {
      "command": "uv",
      "args": ["run", "slack_mcp_server.py"],
      "cwd": "/Users/dimay/mcp/slack_mcp",
      "env": {
        "SLACK_USER_TOKEN": "xoxc-your-token-here",
        "SLACK_USER_COOKIE": "xoxd-your-cookie-here"
      }
    }
  }
}
```

**For OAuth Token (xoxp-):**
```json
{
  "mcpServers": {
    "slack": {
      "command": "uv",
      "args": ["run", "slack_mcp_server.py"],
      "cwd": "/Users/dimay/mcp/slack_mcp",
      "env": {
        "SLACK_USER_TOKEN": "xoxp-your-token-here"
      }
    }
  }
}
```

**Alternatively**, if you've set the environment variables in your shell profile, you can omit the `env` section entirely.

## Available Tools (9 Total)

### Channel Operations

#### slack_list_channels
List all channels you're a member of.

**Parameters:**
- `types` (optional): Comma-separated types (default: "public_channel,private_channel")
  - Options: `public_channel`, `private_channel`, `mpim`, `im`
- `exclude_archived` (optional): Exclude archived channels (default: true)
- `limit` (optional): Maximum channels to return (default: 1000)

**Returns:** List of channels with ID, name, member count, topic, and purpose

**Example:**
```json
{
  "types": "public_channel,private_channel",
  "exclude_archived": true
}
```

---

#### slack_get_channel_history
Get messages from a specific channel.

**Parameters:**
- `channel_id` (required): Channel ID (e.g., "C1234567890")
- `limit` (optional): Number of messages (max 1000, default: 100)
- `oldest` (optional): Unix timestamp - only messages after this time
- `latest` (optional): Unix timestamp - only messages before this time

**Returns:** List of messages with user, text, and timestamp

**Example:**
```json
{
  "channel_id": "C1234567890",
  "limit": 50
}
```

---

#### slack_get_channel_info
Get detailed information about a channel.

**Parameters:**
- `channel_id` (required): Channel ID

**Returns:** Channel details including name, topic, purpose, creator, member count

---

#### slack_search_messages
Search for messages across all channels.

**Parameters:**
- `query` (required): Search query (supports Slack search syntax)
- `count` (optional): Number of results (max 100, default: 20)
- `sort` (optional): Sort by "timestamp" or "score" (default: "timestamp")
- `sort_dir` (optional): "asc" or "desc" (default: "desc")

**Returns:** Matching messages with channel context and permalinks

**Search Examples:**
- `from:@username` - Messages from specific user
- `in:#channel-name` - Messages in specific channel
- `during:2024-01` - Messages during January 2024
- `has:link` - Messages containing links
- `"exact phrase"` - Exact phrase match

---

#### slack_post_message
Post a message to a channel.

**Parameters:**
- `channel_id` (required): Channel ID
- `text` (required): Message text (supports Slack markdown)
- `thread_ts` (optional): Thread timestamp to reply to

**Returns:** Posted message confirmation with timestamp

**Note:** Requires `chat:write` scope

---

### User Operations

#### slack_get_user_info
Get information about a specific user.

**Parameters:**
- `user_id` (required): User ID (e.g., "U1234567890")

**Returns:** User profile with name, email, title, status, and admin flags

---

#### slack_list_users
List all users in the workspace.

**Parameters:**
- `limit` (optional): Maximum users to return (default: 1000)

**Returns:** List of active users with profile information

---

#### slack_get_thread_replies
Get all replies in a thread.

**Parameters:**
- `channel_id` (required): Channel ID
- `thread_ts` (required): Thread timestamp (parent message ts)
- `limit` (optional): Maximum replies (default: 100)

**Returns:** All messages in the thread

---

#### slack_get_mentions
Get messages where you were mentioned.

**Parameters:**
- `hours` (optional): Look back this many hours (default: 24)
- `count` (optional): Number of results to return (max 100, default: 20)

**Returns:** Messages mentioning you with channel context and permalinks

**Example:**
```json
{
  "hours": 24,
  "count": 10
}
```

**Use Cases:**
- "What did I miss while I was away?"
- "Where was I mentioned today?"
- "Show me all mentions from the last week"

---

## Common Workflows

### Reading Channel Messages

```
1. List your channels:
   Tool: slack_list_channels

2. Find the channel you want (note the channel ID)

3. Get messages from that channel:
   Tool: slack_get_channel_history
   channel_id: "C1234567890"
   limit: 100
```

### Searching for Information

```
1. Search across all channels:
   Tool: slack_search_messages
   query: "bug report from:@john"
   count: 20

2. Get user details if needed:
   Tool: slack_get_user_info
   user_id: "U1234567890"
```

### Reading Thread Conversations

```
1. Get channel history to find a thread:
   Tool: slack_get_channel_history
   channel_id: "C1234567890"

2. Get all replies in a specific thread:
   Tool: slack_get_thread_replies
   channel_id: "C1234567890"
   thread_ts: "1234567890.123456"
```

### Posting Messages

```
1. List channels to find where to post:
   Tool: slack_list_channels

2. Post a message:
   Tool: slack_post_message
   channel_id: "C1234567890"
   text: "Hello from MCP!"

3. Reply to a thread:
   Tool: slack_post_message
   channel_id: "C1234567890"
   text: "Reply message"
   thread_ts: "1234567890.123456"
```

### Catching Up on Mentions

```
1. Check mentions from the last 24 hours:
   Tool: slack_get_mentions
   hours: 24
   count: 20

2. Check mentions from the last week:
   Tool: slack_get_mentions
   hours: 168
   count: 50
```

## Understanding Slack IDs

Slack uses unique IDs for different objects:

- **Channel IDs**: Start with `C` (e.g., `C1234567890`)
- **User IDs**: Start with `U` (e.g., `U1234567890`)
- **Direct Message IDs**: Start with `D` (e.g., `D1234567890`)
- **Group DM IDs**: Start with `G` (e.g., `G1234567890`)
- **Message Timestamps**: Unix timestamps (e.g., `1234567890.123456`)

## Slack Search Syntax

The `slack_search_messages` tool supports advanced search operators:

- `from:@username` - Messages from specific user
- `in:#channel` - Messages in specific channel
- `to:@username` - Direct messages to user
- `on:YYYY-MM-DD` - Messages on specific date
- `before:YYYY-MM-DD` - Messages before date
- `after:YYYY-MM-DD` - Messages after date
- `during:YYYY-MM` - Messages during month
- `has:link` - Messages with links
- `has:pin` - Pinned messages
- `has::emoji:` - Messages with specific reaction
- `"exact phrase"` - Exact phrase match
- `-word` - Exclude messages with word

## Troubleshooting

### Authentication Issues

**Error: "SLACK_USER_TOKEN environment variable not set"**
- Set the environment variable: `export SLACK_USER_TOKEN="xoxp-..."`
- Check your shell profile if it's not persisting

**Error: "invalid_auth"**
- Your token may be expired or invalid
- Create a new token using the OAuth method
- Ensure you copied the full token (they're quite long)

### Permission Errors

**Error: "missing_scope"**
- Your token doesn't have required permissions
- Add the necessary scopes to your Slack App
- Reinstall the app to your workspace to apply new scopes

**Error: "channel_not_found"**
- The channel ID is incorrect
- You're not a member of that channel
- Use `slack_list_channels` to find valid channel IDs

### Rate Limiting

Slack has rate limits:
- Tier 3 methods (reading): 50+ requests per minute
- Tier 2 methods (posting): 20+ requests per minute

If you hit rate limits, wait a minute before retrying.

## Development

### Project Structure

```
slack_mcp/
├── slack_mcp_server.py  # Main MCP server (8 tools)
├── pyproject.toml       # Project dependencies
├── .gitignore          # Git ignore rules
├── .python-version     # Python version specification
└── README.md           # This file
```

### Architecture

The server is organized into sections:
- **Shared Utilities**: Slack client, error handling, message formatting
- **Channel Operations**: Channel listing, history, search, posting
- **User Operations**: User info, workspace members, threads
- **MCP Handlers**: Tool registration and execution

### Error Handling

All tools provide consistent error responses with:
- Clear error messages from Slack API
- Detailed error information
- Helpful suggestions for resolution

## Security Best Practices

1. **Never commit tokens** - Use environment variables
2. **Use OAuth tokens** - More secure than browser tokens
3. **Minimum scopes** - Only request permissions you need
4. **Rotate tokens** - Regenerate tokens periodically
5. **Monitor usage** - Check Slack App dashboard for suspicious activity

## Version History

### v0.1.0 (Current)
- Initial release with 8 tools
- Channel operations (list, history, info, search, post)
- User operations (info, list, threads)
- Complete Slack Web API integration
- Support for public/private channels and DMs

## License

MIT

## Related Resources

- [Slack Web API Documentation](https://api.slack.com/web)
- [Slack Search Syntax](https://slack.com/help/articles/202528808-Search-in-Slack)
- [MCP Documentation](https://modelcontextprotocol.io)