mcpField
S
Slack

Slack

Local
github.com/mindstoneCommunication13Updated today

About Slack

Slack is an MCP server for workspace operations through the Slack Web API, intended for users working with one or more Slack workspaces. The host application handles OAuth, while the server reads tokens from locally stored per-workspace credential files.

Key features

  1. 01Search, post, edit, and schedule messages
  2. 02Manage channels, history, and threads
  3. 03Find users, view profiles, and open DMs
  4. 04Reactions, pins, and bookmarks
  5. 05Upload and download files

Use cases

  1. 01Find a user's recent channel message and react to it
  2. 02Review channel history or thread replies
  3. 03Post or schedule a channel message
  4. 04Find a user and open a direct message

MCP support

It provides an MCP server exposing Slack workspace tools to clients. OAuth is initiated by the host application, and the server reads host-managed credential files for each workspace.

Configuration

Local server config is the same for every client. Copy it into your client’s MCP config file.

mcp.json · Universal config
{
"mcpServers": {
"mindstone-mcp-server-slack": {
"command": "npx",
"args": [
"-y",
"@mindstone/mcp-server-slack"
],
"env": {
"SLACK_CONFIG_PATH": "<SLACK_CONFIG_PATH>",
"SLACK_TEAM_ID": "<SLACK_TEAM_ID>",
"SLACK_CLIENT_ID": "<SLACK_CLIENT_ID>",
"SLACK_CLIENT_SECRET": "<SLACK_CLIENT_SECRET>",
"SLACK_DISABLE_REFRESH": "<SLACK_DISABLE_REFRESH>",
"SLACK_REQUEST_TIMEOUT_MS": "<SLACK_REQUEST_TIMEOUT_MS>",
"SLACK_MAX_RETRIES": "<SLACK_MAX_RETRIES>",
"MCP_WORKSPACE_PATH": "<MCP_WORKSPACE_PATH>"
}
}
}
}
Run commandnpx -y @mindstone/mcp-server-slack
Environment variables to set
SLACK_CONFIG_PATHPath to the host-managed Slack config directory
SLACK_TEAM_IDSlack workspace team ID (one process per workspace)
SLACK_CLIENT_IDSlack OAuth Connected App client ID. Only required to refresh a rotating token; saved non-rotating tokens authorize the Slack API without it.
SLACK_CLIENT_SECRETSecretSlack OAuth Connected App client secret. Only required to refresh a rotating token; saved non-rotating tokens authorize the Slack API without it.
SLACK_DISABLE_REFRESHSet to 1 to disable token refresh on this surface (cloud surface)
SLACK_REQUEST_TIMEOUT_MSOverride the upstream timeout (max 300000ms = 5 min)
SLACK_MAX_RETRIESWebClient retries on transient failures (0-20). Lower this on cloud to avoid stacking long retry budgets into multi-minute hangs.
MCP_WORKSPACE_PATHWorkspace directory upload_slack_file reads are constrained to (defaults to the system temp dir when unset)

Local servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.

Packages
npm@mindstone/mcp-server-slack0.3.1

Tools

39

Saved tool list · updated today

This tool takes no parameters.

Details

From the project README

@mindstone/mcp-server-slack

npm version License: FSL-1.1-MIT

Slack workspace MCP server — channels, messages, threads, reactions, users, files, bookmarks, and scheduled messages via the Slack Web API.

Multi-workspace Slack MCP. Host-driven OAuth, per-workspace credentials files on disk, and a security review on every release.

Status

Why this exists

When we started building this connector, Slack had not yet released an official MCP server — that came later (announced February 2026, generally available April 2026). The community Slack MCPs available at the time each got parts of the job right, but none of them combined fast user-name lookups for small and medium workspaces, the correct mention format for modern Slack (most still used the deprecated link_names=true), support for more than one Slack workspace from the same user account, and tokens that stay on the user's own machine. Slack's official server now exists and is a fine choice for many use cases. We continue to maintain this one because the host application handles the login flow, each workspace has its own credentials file on disk under the user's control, and the connector goes through our own security review before each release.

Example interaction

"Find the most recent message from Alice in #q3-planning and react with :eyes:."

Tools the host calls:

  1. lookup_user_by_email — resolves Alice's email to her Slack user ID.
  2. search_slack_messages — searches #q3-planning for her most recent message, returning the channel + timestamp.
  3. add_slack_reaction — adds the eyes reaction to that message.

Response (trimmed):

{
  "match": {
    "channel": "C08X...",
    "ts": "1715953812.004200",
    "user": "U07Z...",
    "text": "Pushed the updated forecast to the doc, ready for review."
  },
  "reaction": {
    "ok": true,
    "name": "eyes"
  }
}

Requirements

  • Node.js 20+
  • npm
  • A host application that performs the Slack OAuth flow and writes per-workspace token files to ${SLACK_CONFIG_PATH}/workspaces/{teamId}.json. This server reads those files; it does not initiate OAuth itself.

One-click install

Add to Cursor Add to VS Code Add to VS Code Insiders

After clicking the button, your host will prompt you to fill: SLACK_CONFIG_PATH, SLACK_TEAM_ID, SLACK_CLIENT_SECRET, SLACK_REQUEST_TIMEOUT_MS, SLACK_MAX_RETRIES.

Manual config for Claude Desktop / Claude Code / Goose / Continue.dev (Slack)
{
  "mcpServers": {
    "Slack": {
      "command": "npx",
      "args": [
        "-y",
        "@mindstone/mcp-server-slack"
      ],
      "env": {
        "SLACK_CONFIG_PATH": "",
        "SLACK_TEAM_ID": "",
        "SLACK_CLIENT_SECRET": "",
        "SLACK_REQUEST_TIMEOUT_MS": "60000",
        "SLACK_MAX_RETRIES": "10"
      }
    }
  }
}

Quick Start

Install & build
cd <path-to-repo>/connectors/slack
npm install
npm run build
npx (once published)
npx -y @mindstone/mcp-server-slack
Local
node dist/index.js

Configuration

This server is designed to run alongside a host application that performs the Slack OAuth flow on its own. The host writes credentials to disk; this server reads them.

Required environment variables
  • SLACK_CONFIG_PATH — Path to the Slack config directory (host-managed). Contains config.json (workspace metadata) and workspaces/{teamId}.json (per-workspace tokens, mode 0600).
  • SLACK_TEAM_ID — Workspace team ID (per-workspace instance).
Optional environment variables
  • SLACK_CLIENT_ID — OAuth Connected App client ID. Only needed to refresh a rotating token. Saved non-rotating tokens authorize the Slack API directly without it. When a refresh is required but this is absent, the server fails loud with REFRESH_NO_CLIENT_CREDENTIALS and directs the host to re-authenticate.
  • SLACK_CLIENT_SECRET — OAuth Connected App client secret. Same conditions as SLACK_CLIENT_ID.
  • SLACK_DISABLE_REFRESH — Set to 1 to disable token refresh on this surface. The server will fail-closed with a structured auth_required response on token expiry instead of attempting an oauth.v2.access refresh. Use this on the cloud surface so desktop remains the sole refresh authority and avoids racing for single-use refresh tokens.
  • SLACK_REQUEST_TIMEOUT_MS — Override the default 60s upstream timeout. Must be a positive integer ≤ 300000 (5 minutes).
  • MCP_WORKSPACE_PATH — Directory that upload_slack_file reads are constrained to. Paths outside it (including symlinks pointing outside) are refused. Defaults to the system temp dir when unset.
Authentication flow

The host calls the authenticate_slack_workspace tool. The OSS server returns a structured auth_required response of the form:

{
  "status": "auth_required",
  "user_action": {
    "id": "slack.connect_workspace",
    "label": "Connect Slack",
    "instruction": "Click \"Connect Slack\" in the side panel to authorise the workspace."
  },
  "agent_action": {
    "instruction": "Tell the user to click the Connect Slack button in the connector settings to authorise. Then call list_slack_workspaces to verify."
  },
  "setupToolName": "authenticate_slack_workspace"
}

The host's MCP service recognises this shape and dispatches to its registered Slack OAuth orchestrator (the desktop browser flow). Once the user signs in, the host writes tokens to ${SLACK_CONFIG_PATH}/workspaces/{teamId}.json and the server picks them up on the next call.

The OSS server never initiates OAuth itself.

Host configuration examples

This server is designed for host-orchestrated OAuth: the host writes per-workspace token files to disk and the server reads them. The examples below show the env shape — your host application is responsible for populating ${SLACK_CONFIG_PATH}/workspaces/{teamId}.json before tool calls succeed.

Claude Desktop / Cursor
{
  "mcpServers": {
    "Slack": {
      "command": "npx",
      "args": ["-y", "@mindstone/mcp-server-slack"],
      "env": {
        "SLACK_CONFIG_PATH": "/absolute/path/to/slack-config",
        "SLACK_TEAM_ID": "T0123ABCD",
        "SLACK_CLIENT_ID": "your-slack-app-client-id",
        "SLACK_CLIENT_SECRET": "your-slack-app-client-secret"
      }
    }
  }
}

Until the host has written ${SLACK_CONFIG_PATH}/workspaces/T0123ABCD.json for that team, every tool call returns a structured auth_required response (see the Authentication flow above).

Local development (no npm publish needed)
{
  "mcpServers": {
    "Slack": {
      "command": "node",
      "args": ["<path-to-repo>/connectors/slack/dist/index.js"],
      "env": {
        "SLACK_CONFIG_PATH": "/absolute/path/to/slack-config",
        "SLACK_TEAM_ID": "T0123ABCD",
        "SLACK_CLIENT_ID": "your-slack-app-client-id",
        "SLACK_CLIENT_SECRET": "your-slack-app-client-secret"
      }
    }
  }
}

Tools (39)

Authentication
  • authenticate_slack_workspace — Returns structured auth_required response; the host drives OAuth.
  • list_slack_workspaces — Check Slack connection status (connected, token health, near-expiry).
Messages
  • search_slack_messages — Search across all channels (Slack search modifiers supported). query may be left out when to_me, after or before is given; a call with none of them is refused. Uses Slack's Real-Time Search API (assistant.search.context) when the connected app holds the granular search:read.* scopes; otherwise falls back to legacy search.messages, whose results are equally complete. The response records which backend ran in search_backend; that field is diagnostic only and the fallback is not narrated to the user, because enabling the Real-Time Search path is an app-configuration change rather than anything the person asking can do. The fallback is cached per workspace only for installation-scoped refusals (missing_scope, not_allowed_token_type, feature_not_enabled, endpoint-deprecation codes) — a resource-specific access_denied surfaces as an ordinary error and RTS is retried on the next call.
  • get_slack_saved_messages — Get messages saved for later (uses is:saved). Same search-backend reporting as search_slack_messages.
  • get_slack_message_by_link — Retrieve a message from its permalink URL.
  • compose_slack_message — Open an inline editable compose form before sending; the form posts via post_slack_message when the user clicks Send.
  • post_slack_message — Post a message; DM recipient verification baked in. Self-DMs are blocked and redirected to send_myself_a_note (a user-token self-DM never notifies).
  • reply_to_slack_thread — Reply to an existing thread.
  • schedule_slack_message — Schedule a message for the future. Self-DMs are blocked (scheduled self-notes are not supported yet).
  • list_scheduled_slack_messages — List pending scheduled messages (optionally per channel), with the IDs needed to cancel them.
  • delete_scheduled_slack_message — Cancel a scheduled message before it posts.
  • update_slack_message — Edit a message you posted.
  • delete_slack_message — Permanently delete a message you posted.
  • send_myself_a_note — Send yourself a note that actually notifies you (posts a DM from the bot to the authenticated user). Use this for "jot something down" / reminders instead of a user-token self-DM.
Channels
  • list_slack_channels — List channels (filterable, paginated).
  • get_slack_channel_history — Get recent messages from a channel.
  • create_slack_channel — Create a new channel (public or private).
  • mark_slack_channel_as_read — Mark messages read up to a timestamp.
  • get_slack_unread_messages — Get unread messages based on your read position.
  • invite_user_to_channel — Add users to a channel (bulk).
Threads
  • get_slack_thread_replies — Get all replies in a thread.
Reactions
  • add_slack_reaction — Add an emoji reaction to a message.
  • remove_slack_reaction — Remove your own reaction from a message.
  • list_slack_emoji — List the workspace's custom emoji (name → URL/alias, both wrapped in <untrusted-content> envelopes). Entries that violate Slack's emoji name/value constraints are dropped and reported (omitted_invalid_entries), never forwarded.
Pins
  • list_slack_pins — List messages pinned in a channel.
  • pin_slack_message — Pin a message to a channel.
  • unpin_slack_message — Remove a message from a channel's pinned items (the message itself is not deleted).
Users
  • list_slack_users — List active users (auto-paginates name filter).
  • get_slack_user_profile — Get detailed profile for a user.
  • lookup_user_by_email — Find a user by exact email (preferred resolution method).
  • open_slack_dm — Open a DM with a user (returns DM channel + verified recipient identity).
Files
  • download_slack_file — Download a file attachment by ID or URL.
  • upload_slack_file — Upload a local file (workspace-constrained, race-free reads; max 50MB) and optionally share it to a channel or thread. Uses the 3-step external upload flow.
Workspace
  • add_slack_bookmark — Add a bookmark to a channel.
  • list_slack_bookmarks — List a channel's bookmarks.
  • add_slack_reminder — [EXPERIMENTAL] Create a reminder (Slack API partially deprecated; prefer schedule_slack_message).
  • list_slack_reminders — [EXPERIMENTAL] List your reminders.
  • complete_slack_reminder — [EXPERIMENTAL] Mark a reminder complete.
  • delete_slack_reminder — [EXPERIMENTAL] Permanently delete a reminder.

Security notes

  • Slack-owned download URL guard — download_slack_file validates that the Slack-supplied url_private_download is HTTPS and on slack.com / *.slack.com before attaching the workspace bearer token. The download helper also sets redirect: 'manual' and re-validates every redirect hop, so a 302 from a compromised Slack edge to an attacker-controlled host can never replay the bearer token (added in 0.1.3 to close finding slack-010).
  • Untrusted-content envelopes — every tool that returns external text wraps it in <untrusted-content source="…">…</untrusted-content> envelopes per AGENTS.md invariant #6, with close-tag breakout escaping. This applies to message text, channel topics/purposes, search results, thread replies, unread messages, and downloaded file content/names. Hosts must keep the envelopes intact when surfacing tool output to the model (added in 0.1.3 to close findings slack-001..007).
  • Atomic, durable token persistence — token files are written via temp-file + fsync + rename, then chmod 0600, so a crash mid-write cannot lose Slack's single-use refresh token.
  • Refresh-failure differentiation — transient network errors, HTTP 429 rate-limits, Slack auth rejections (invalid_grant), and malformed responses produce distinct error codes so hosts can react correctly without retrying unrecoverable failures.
  • No host-internal vocabulary — host-side bridge identifiers and bundled HTTP paths are explicitly absent from the published artefact (enforced by scripts/check-no-bridge-strings.sh during prepublishOnly, and by scripts/check-internal-refs.mjs — also run as npm run security:internal-refs — which additionally rejects internal issue-tracker references in src/ and dist/).
  • Race-free upload source reads — upload_slack_file validates the source path inside the workspace, then opens it once (no-follow, non-blocking), enforces regular-file-only and the 50MB cap via fstat on the opened descriptor, re-verifies the descriptor's dev+inode against a fresh confined path resolution (defeats post-validation replacement, including swapped ancestor directories), and reads the bytes through the descriptor with the cap enforced on what is actually read.
  • Envelope parity on add-paths — add_slack_bookmark and add_slack_reminder envelope the Slack-returned title/text exactly like the list paths, with close-tag breakout escaping.

Full implementation-level notes (request-timeout composition, MSW request manifest, token-file error states, server-version drift checks, etc.) live in docs/connectors/slack-cohort-hygiene.md.

Live probe

A live probe gate is committed at test/live-probe.ts. It is not auto-run; trigger it manually:

LIVE_PROBE_BOT_TOKEN=xoxb-... \
LIVE_PROBE_USER_TOKEN=xoxp-... \
LIVE_PROBE_TEAM_ID=T... \
npm run probe:live

The probe runs against the packed tarball (not the workspace source), exercising initialize + tools/list + 5 read-only + 2 write tool calls, and logs search.messages P95 latency to validate the 60s timeout default.

By default the probe is read-only: write probes (post_slack_message, add_slack_reaction) only run when LIVE_PROBE_TEST_CHANNEL_ID is set, otherwise they are skipped and the probe still exits OK.

Publish-gate mode

For pre-publish certification, run:

LIVE_PROBE_BOT_TOKEN=xoxb-... \
LIVE_PROBE_USER_TOKEN=xoxp-... \
LIVE_PROBE_TEAM_ID=T... \
LIVE_PROBE_TEST_CHANNEL_ID=C... \
npm run probe:live:gate

probe:live:gate sets LIVE_PROBE_REQUIRE_WRITES=1, which causes the probe to fail rather than skip if LIVE_PROBE_TEST_CHANNEL_ID is missing or any write probe doesn't complete cleanly. Use this before cutting a release.

Licence

FSL-1.1-MIT — Functional Source License, Version 1.1, with MIT future licence. The software converts to MIT licence on 2030-04-08.

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.