# Slack MCP Server Permissions & Controls, Explained

How the official Slack MCP server's admin approval flow, OAuth scopes, IP allowlists, and per-call audit events actually work — and why nothing native can hold a message before it's sent.

# The Slack MCP server control model, explained

The official Slack MCP server is first-party, Salesforce-hosted (`https://mcp.slack.com/mcp`), and [generally available since February 17, 2026](https://docs.slack.dev/changelog/2026/02/17/slack-mcp/) — reachable today as a Claude Code plugin, a Claude Desktop connector, and through partner clients including Perplexity and Cursor. It closes a messy lineage: Anthropic's early reference Slack server was [archived in May 2025](https://github.com/modelcontextprotocol/servers-archived), the same month [Slack's API terms changed](https://www.computerworld.com/article/4005509/salesforce-changes-slack-api-terms-to-block-bulk-data-access-for-llms.html) to prohibit bulk export and LLM training on API data, and the gap was filled by community servers — the most popular of which runs on unofficial token modes lifted from a logged-in browser session, a path Slack's terms don't sanction and this page doesn't cover. The first-party server is the sanctioned answer, and this page is the reference for it: what ships, how each mechanism behaves, and where the model ends. Primary source: the [official server docs](https://docs.slack.dev/ai/slack-mcp-server/).

*This page covers the server's own controls. For the cross-server picture, see [the MCP server controls comparison](/mcp-controls); for what a control layer adds on top, [the coverage matrix](/coverage).*

One disambiguation before anything else, because Slack shipped both directions in 2026 and their control stories differ: this page is about **Slack as an MCP server** — outside agents reaching into your workspace through `mcp.slack.com`. Slackbot's **MCP client** — Slack reaching out to other vendors' servers — is a separate product with its own admin controls, and claims you'll read about "per-action confirmation on writes" belong to that client, not to this server. Nothing on the server side confirms a write per action.

## What's at stake on this surface

Two things, and they're different in kind from every other server in this series.

**Sends are social and instant.** The tool surface includes sending messages as the authenticated user. A merged PR can be reverted; a sent Slack message is read by humans within seconds, and deleting it doesn't unsend what was seen. The blast radius of a bad write here isn't state — it's what colleagues, customers in shared channels, and executives now believe you said. No other surface in [our comparison](/mcp-controls) is this irreversible this fast.

**Reads are candid internal speech.** History and search tools reach channel archives, private channels, group DMs, and DMs — wherever the connecting user's memberships reach. That's not documentation or ticket metadata; it's the unguarded way people actually talk to each other. An agent with search scopes across a workspace is reading the organization's least considered writing.

## Auth, admin approval, and permission mirroring

Authentication is [confidential OAuth 2.0 with user tokens](https://docs.slack.dev/ai/slack-mcp-server/) (PKCE for desktop clients) — the agent acts as the user who connected, not as a bot. The floor under everything is permission mirroring: actions run on behalf of the authenticated user, so the agent reads what that user can read and posts where that user can post. Same vendor-enforced floor as [GitHub's token scope](/mcp-controls/github) — and the same corollary: for most users, that floor is most of the workspace.

Above the floor sits a real admin plane, and it's connection-shaped. Every MCP client must be backed by a registered Slack app with a fixed app ID, and per the docs, workspace admins approve and manage all MCP client integrations through the standard app approval process. In a workspace with app approval required, no MCP client reaches any user until an admin says yes, and admins can remove the app later. This is [Atlassian's](/mcp-controls/atlassian) admin-plane story in messaging form — the vendor's controls answer "which apps may connect," decided by someone who isn't the agent.

## Scopes: what gates the write tools

Tools are gated by the user scopes granted to the backing app, [per capability](https://docs.slack.dev/ai/slack-mcp-server/):

- **Search** splits by surface: `search:read.public`, `search:read.private`, `search:read.im`, `search:read.mpim`, plus `search:read.files` and `search:read.users` — the one place the grain acknowledges that DMs are different from public channels.
- **Reading** history: `channels:history`, `groups:history`, `im:history`, `mpim:history`; file contents via `files:read`.
- **Sending**: `chat:write`. One scope, all destinations.
- **Creating conversations**: `channels:write` (public), `groups:write` (private), `im:write`, `mpim:write`.
- **The rest**: `reactions:write`, `canvases:read` / `canvases:write`, `users:read`, `users:read.email`.

The grain is the capability class, granted once at the app. What scopes cannot express: *where*. `chat:write` is one bit — an app holding it can post to every channel and DM the user can. There is no scope for "this channel set only," no read-only variant of a connection below withholding the write scopes app-wide.

## IP allowlists and eligibility

Two more vendor-side lines. If the backing app has allowed IP ranges configured, MCP requests face the identical restriction — calls from non-allowlisted IPs are rejected, same mechanism as the Web API. And eligibility is itself a control: [only Marketplace-published apps or internal apps may use MCP](https://docs.slack.dev/ai/slack-mcp-server/); unlisted apps are rejected outright. Combined with the May 2025 terms (no bulk export, no training on API data), the posture is deliberate: Slack data reaches agents through one reviewed, revocable, identity-carrying door. Rate limits ride along too — the same per-tool Web API tiers — but they're anti-abuse grain, not policy: nothing about them distinguishes a legitimate send from a regrettable one.

## Audit: per-call, named, Enterprise-gated

Be precise here, because Slack earns credit most servers don't. The [Audit Logs API actions reference](https://docs.slack.dev/reference/audit-logs-api/methods-actions-reference/) has a dedicated Slack MCP Server section: eleven actions, every one a per-invocation event — `mcp_slack_send_message_tool_called`, `mcp_slack_read_channel_tool_called`, `mcp_slack_read_thread_tool_called`, `mcp_slack_search_public_and_private_tool_called`, canvas create/read/update, user-profile reads, and the rest — each described as an AI app acting "on behalf of a user in your organization." That puts Slack among the three servers in this series — with [Atlassian](/mcp-controls/atlassian) and [Zapier](/mcp-controls/zapier) — that keep a per-call, admin-queryable record.

Its limits are the familiar shape of [the audit gap](/blog/mcp-audit-gap): the Audit Logs API is an Enterprise Grid feature, so most workspaces never see these events; the entries name the action and acting user, not the message text or arguments — `mcp_slack_send_message_tool_called` tells you a send happened, not what it said or to whom; and it's a record, not a rule — written after the call, consulted by nothing before one. On this surface that last limit bites hardest, because by the time the log line exists, so do the readers.

## What's missing

- **No approvals, no drafts.** Nothing native holds a send for a human. The admin approved the *connection*; from then on, every message the agent sends is exactly as unguarded as the user typing it — on the one surface in this series where the write is socially unrecallable.
- **No per-agent channel allowlist.** `chat:write` is workspace-wide within the user's reach. "This agent may post only in #agent-output" is not expressible.
- **No velocity control.** Rate tiers are abuse limits, not policy. Twenty messages a minute to twenty channels is within bounds.
- **No per-call policy.** Every control above decides which app connects with which capability classes. An approved app, in scope, on an allowed IP, can make any call those grants cover — and on Enterprise Grid, the log will faithfully record that it did.

## Where the native model ends

The seam, stated plainly: Slack built strong walls around the connection — approval, eligibility, scopes, IP, revocation — and a genuine per-call record behind it, and left nothing standing between an approved agent's decision to send and a human reading the result. Ten seconds of "wait" is the whole difference between an incident and a non-event on this surface, and no native mechanism can buy it.

The practical posture: keep app approval required and deliberate; grant write scopes only to apps whose agents genuinely must post, and keep search-scoped and send-scoped apps separate; turn on IP allowlists for headless clients; if you're on Enterprise Grid, watch the `mcp_slack_*_tool_called` events. Then put what no vendor ships — a hold on the send, a channel boundary per agent, a velocity ceiling, policy that sees the call before the channel does — in [a layer the agent can't edit](/what-is-an-agentic-control-plane).

Across the fifteen first-party MCP servers in this series: one native per-call approval mechanism — [AWS's fail-closed consent prompt](/mcp-controls/aws), deprecated by its own vendor's managed successor; three per-call audit trails (Atlassian's, this one, and [Zapier's](/mcp-controls/zapier) — all vendor consoles, none consulted before a call); and every other strong control either vendor-side credential scoping or an admin plane over connections. The vendors have built good walls. Nobody is standing at the gate per call — that seat is [still empty](/blog/what-survives-yolo-mode), and it's where the control layer goes.
