Skip to main content
Glama
cnye36

Slack MCP Server

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

Variable

Required

Default

Description

PORT

No

8080

Server port

HOST

No

0.0.0.0

Server host

PUBLIC_BASE_URL

No

http://localhost:8080

Public URL for OAuth redirects

SLACK_CLIENT_ID

Yes

-

Slack app client ID

SLACK_CLIENT_SECRET

Yes

-

Slack app client secret

SLACK_REDIRECT_URI

Yes

-

OAuth callback URL

SLACK_SCOPES

Yes

-

Comma-separated bot scopes

AFFINITYBOTS_MCP_API_KEY

Recommended

-

API key for MCP endpoint

ALLOWED_ORIGINS

No

-

Comma-separated allowed origins for CORS

SESSION_TTL_MS

No

900000

MCP session timeout (15 min)

LOG_LEVEL

No

info

Log 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

  • 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

-
security - not tested
F
license - not found
-
quality - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cnye36/slack-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server