MCP Hub
Back to servers

slack-mcp-server

A production-grade MCP server for Slack that enables AI assistants to post messages, read channel history, and list channels across multiple workspaces using secure OAuth 2.0 and token rotation.

Tools
3
Updated
Jan 7, 2026
Validated
Jan 9, 2026

Slack MCP Server

A production-ready Model Context Protocol (MCP) server for Slack integration. This server enables AI assistants to interact with Slack workspaces through a secure, multi-tenant OAuth flow.

Features

  • 🔐 Secure OAuth 2.0 Flow - Full Slack OAuth v2 implementation with state validation
  • 🏢 Multi-Tenant Support - Handle multiple Slack workspaces simultaneously
  • 🔄 Token Rotation - Automatic token refresh for long-lived installations
  • 🛡️ Production Security - CORS, API key protection, Helmet.js, request timeouts
  • 📊 Structured Logging - Pino logger with configurable log levels
  • 🐳 Docker Ready - Multi-stage Dockerfile with non-root user
  • MCP Tools - Post messages, read channel history, list channels

Architecture

This server uses the Streamable HTTP transport for MCP, making it suitable for web-based AI assistants. It manages:

  • OAuth Flow: /slack/install and /slack/oauth/callback endpoints
  • MCP Endpoint: /mcp for all MCP protocol communication
  • Session Management: Automatic session pruning with configurable TTL
  • Installation Storage: Pluggable storage interface (in-memory by default)

Prerequisites

  1. Slack App - Create a Slack app at api.slack.com/apps
  2. Node.js - Version 18+ required
  3. pnpm - Package manager (or npm/yarn)

Quick Start

1. Install Dependencies

pnpm install

2. Configure Environment

Copy the example environment file and fill in your values:

cp .env.example .env

Required variables:

  • SLACK_CLIENT_ID - From your Slack app's OAuth settings
  • SLACK_CLIENT_SECRET - From your Slack app's OAuth settings
  • SLACK_REDIRECT_URI - Your callback URL (e.g., https://yourdomain.com/slack/oauth/callback)
  • SLACK_SCOPES - Comma-separated bot scopes (e.g., chat:write,channels:history,channels:read)
  • AFFINITYBOTS_MCP_API_KEY - Secret key to protect your MCP endpoint

3. Run Development Server

pnpm dev

The server will start on http://localhost:8080 by default.

4. Install Slack App

  1. Navigate to http://localhost:8080/slack/install
  2. Authorize the app for your workspace
  3. You'll be redirected back with a success message

5. Use MCP Tools

Connect your MCP client to http://localhost:8080/mcp with:

  • Authorization header: Bearer YOUR_AFFINITYBOTS_MCP_API_KEY
  • Origin header: Must match ALLOWED_ORIGINS if configured

Available MCP Tools

slack_post_message

Post a message to a Slack channel.

Parameters:

  • team_id (string) - Slack workspace/team ID (T...)
  • channel_id (string) - Channel/DM ID (C... or D...)
  • text (string) - Message text (1-4000 characters)
  • thread_ts (string, optional) - Thread timestamp to reply to

slack_get_channel_history

Read messages from a Slack channel.

Parameters:

  • team_id (string) - Slack workspace/team ID
  • channel_id (string) - Channel/DM ID
  • limit (number, optional) - Number of messages (1-200, default: 50)

slack_list_channels

List all channels in the workspace.

Parameters:

  • team_id (string) - Slack workspace/team ID
  • types (string, optional) - Channel types: public_channel,private_channel,mpim,im (default: public_channel)
  • limit (number, optional) - Number of channels (1-1000, default: 200)

Configuration

Environment Variables

VariableRequiredDefaultDescription
PORTNo8080Server port
HOSTNo0.0.0.0Server host
PUBLIC_BASE_URLNohttp://localhost:8080Public URL for OAuth redirects
SLACK_CLIENT_IDYes-Slack app client ID
SLACK_CLIENT_SECRETYes-Slack app client secret
SLACK_REDIRECT_URIYes-OAuth callback URL
SLACK_SCOPESYes-Comma-separated bot scopes
AFFINITYBOTS_MCP_API_KEYRecommended-API key for MCP endpoint
ALLOWED_ORIGINSNo-Comma-separated allowed origins for CORS
SESSION_TTL_MSNo900000MCP session timeout (15 min)
LOG_LEVELNoinfoLog level: trace, debug, info, warn, error, fatal

Required Slack Scopes

At minimum, your Slack app needs these bot token scopes:

  • chat:write - Post messages
  • channels:history - Read public channel messages
  • channels:read - List public channels

Additional recommended scopes:

  • groups:history - Read private channel messages
  • groups:read - List private channels
  • im:history - Read direct messages
  • im:read - List direct messages
  • mpim:history - Read group DM messages
  • mpim:read - List group DMs

Production Deployment

Using Docker

Build the image:

docker build -t slack-mcp-server .

Run the container:

docker run -d \
  -p 8080:8080 \
  -e SLACK_CLIENT_ID=your_client_id \
  -e SLACK_CLIENT_SECRET=your_client_secret \
  -e SLACK_REDIRECT_URI=https://yourdomain.com/slack/oauth/callback \
  -e SLACK_SCOPES=chat:write,channels:history,channels:read \
  -e AFFINITYBOTS_MCP_API_KEY=your_secret_key \
  -e ALLOWED_ORIGINS=https://yourdomain.com \
  slack-mcp-server

Production Checklist

  • Set AFFINITYBOTS_MCP_API_KEY to a strong random value
  • Configure ALLOWED_ORIGINS with your frontend domains
  • Use HTTPS for all endpoints (required by Slack)
  • Set PUBLIC_BASE_URL to your public HTTPS URL
  • Replace InMemoryInstallStore with persistent storage (Redis/PostgreSQL)
  • Set up monitoring and alerting
  • Configure log aggregation
  • Set appropriate SESSION_TTL_MS for your use case
  • Enable Slack token rotation in your app settings (recommended)
  • Set up rate limiting at the reverse proxy level
  • Configure health check monitoring on /health

Storage

The default InMemoryInstallStore is suitable for development but not for production. For production, implement the InstallStore interface with a persistent backend:

export interface InstallStore {
  upsert(install: SlackInstallation): Promise<void>;
  getByTeamId(teamId: string): Promise<SlackInstallation | null>;
}

Recommended storage options:

  • PostgreSQL - Best for relational data and complex queries
  • Redis - Fast, simple key-value storage
  • MongoDB - Document-based storage
  • DynamoDB - Serverless AWS option

Security Features

Implemented

  • ✅ CSRF protection via OAuth state parameter
  • ✅ API key authentication for MCP endpoint
  • ✅ CORS with origin allowlist
  • ✅ Helmet.js security headers
  • ✅ Request timeouts (30s)
  • ✅ Session expiration and pruning
  • ✅ Automatic token refresh
  • ✅ Secure error messages (no info leakage)
  • ✅ Non-root Docker user

Recommended Additional Security

  • Add rate limiting (e.g., express-rate-limit)
  • Use a reverse proxy (nginx, Caddy) with TLS
  • Implement request size limits
  • Add request ID tracking
  • Set up WAF rules
  • Enable Slack signing secret verification for webhooks (if added)

Monitoring

Health Check

curl http://localhost:8080/health

Returns ok if the server is running.

Logs

The server uses structured JSON logging via Pino. Key log events:

  • OAuth flow initiation and completion
  • MCP session creation and expiration
  • Token refresh operations
  • API errors and warnings
  • Security events (unauthorized access, invalid origins)

Set LOG_LEVEL=debug for detailed debugging.

Troubleshooting

OAuth Errors

"Invalid or expired state"

  • The OAuth state token expired (10 min TTL)
  • Try the installation flow again

"Slack OAuth failed: invalid_code"

  • The authorization code was already used or expired
  • Restart the installation flow

"Origin not allowed"

  • Your frontend origin is not in ALLOWED_ORIGINS
  • Add your origin to the environment variable

MCP Errors

"Unauthorized"

  • Missing or invalid Authorization header
  • Ensure you're sending Bearer YOUR_API_KEY

"Unknown or expired session"

  • MCP session expired (default 15 min)
  • Reinitialize the MCP connection

"No Slack installation found"

  • The workspace hasn't installed the app
  • Complete the OAuth flow first

Token Errors

"Token refresh failed"

  • The refresh token is invalid or revoked
  • User needs to reinstall the app
  • Check if token rotation is enabled in Slack app settings

Development

Project Structure

slack-mcp-server/
├── src/
│   ├── index.ts          # Main server and routing
│   ├── mcp.ts            # MCP tool definitions
│   ├── slackOauth.ts     # OAuth flow handlers
│   ├── slackClient.ts    # Slack API client with token refresh
│   ├── installStore.ts   # Installation storage interface
│   └── security.ts       # Security utilities
├── Dockerfile
├── package.json
├── tsconfig.json
└── README.md

Adding New Tools

Register new tools in src/mcp.ts:

server.tool(
  "tool_name",
  "Tool description",
  {
    team_id: z.string(),
    // ... other parameters
  },
  async ({ team_id, ...params }) => {
    const slack = await getSlackClientForTeam(store, team_id);
    // ... implement tool logic
    return { content: [{ type: "text", text: "result" }] };
  }
);

Testing

# Run development server with debug logging
LOG_LEVEL=debug pnpm dev

# Build for production
pnpm build

# Run production build
pnpm start

License

MIT

Support

For issues and questions:

  1. Check the IMPLEMENTATION.md guide
  2. Review Slack API documentation at api.slack.com
  3. Check MCP documentation at modelcontextprotocol.io

Contributing

Contributions welcome! Please:

  1. Follow the existing code style
  2. Add tests for new features
  3. Update documentation
  4. Ensure all lints pass

Reviews

No reviews yet

Sign in to write a review