slack-bot-mcp
Enables an AI agent to work in Slack as a bot: send DMs and channel messages, thread replies, edit or delete bot messages, search for users, list channels, read conversation history and threads, add/remove reactions, track pending questions, and wait for or check replies.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@slack-bot-mcpsend a DM to @sarah asking if she can review the Q3 report today"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
slack-bot-mcp
An MCP server that lets an AI agent work in Slack as a bot. The agent can send DMs and channel messages, find members by email or name, read history and threads, react to messages, and wait for replies.
It is built on Chat SDK (chat + @chat-adapter/slack). By default it receives events over Socket Mode, so it needs no public URL. Set SLACK_MODE=webhook to receive events through a Request URL instead.
Quick start
SLACK_BOT_TOKEN=xoxb-... SLACK_APP_TOKEN=xapp-... npx -y @liusdev/slack-bot-mcp@latest
# or
SLACK_BOT_TOKEN=xoxb-... SLACK_APP_TOKEN=xapp-... pnpm dlx @liusdev/slack-bot-mcp@latestCheck the installed version with npx -y @liusdev/slack-bot-mcp@latest -v (or --version); --help lists usage. The whoami tool also reports server_version.
Claude Code
claude mcp add slack-bot \
-e SLACK_BOT_TOKEN=xoxb-... \
-e SLACK_APP_TOKEN=xapp-... \
-- npx -y @liusdev/slack-bot-mcp@latestClaude Desktop, Cursor and other MCP clients
{
"mcpServers": {
"slack-bot": {
"command": "npx",
"args": ["-y", "@liusdev/slack-bot-mcp@latest"],
"env": {
"SLACK_BOT_TOKEN": "xoxb-...",
"SLACK_APP_TOKEN": "xapp-..."
}
}
}
}Related MCP server: Slack MCP Server
Create the Slack app
A Slack app manifest is a YAML file that describes an app's configuration. The manifest below sets up everything this server needs in one step:
a bot user that people can DM (the App Home Messages tab)
the bot token scopes the tools use
the
app_mentionandmessage.imevents, which feedget_inboxSocket Mode, so no public URL is needed
Go to api.slack.com/apps, click Create New App, choose From an app manifest, pick your workspace, and paste the manifest below.
Under Basic Information → App-Level Tokens, generate a token with the
connections:writescope. This isSLACK_APP_TOKEN(xapp-…).Under OAuth & Permissions, install the app to the workspace and copy the Bot User OAuth Token. This is
SLACK_BOT_TOKEN(xoxb-…).Invite the bot to any private channel it should read or post in:
/invite @AI Assistant.
display_information:
name: AI Assistant
features:
app_home:
messages_tab_enabled: true
messages_tab_read_only_enabled: false
bot_user:
display_name: AI Assistant
always_online: true
oauth_config:
scopes:
bot:
- app_mentions:read
- channels:history
- channels:read
- chat:write
- chat:write.public
- groups:history
- groups:read
- im:history
- im:read
- im:write
- mpim:history
- mpim:read
- reactions:read
- reactions:write
- users:read
- users:read.email
settings:
event_subscriptions:
bot_events:
- app_mention
- message.im
interactivity:
is_enabled: true
org_deploy_enabled: false
socket_mode_enabled: true
token_rotation_enabled: falseUse an existing app
To reuse an app you already created, open it at api.slack.com/apps and select App Manifest in the sidebar. Merge in the scopes, events, socket_mode_enabled and app_home settings above. Do not paste over the whole manifest: that replaces the app's current configuration and can drop scopes, events or Request URLs it already uses. Save, then click Reinstall to Workspace under OAuth & Permissions so new scopes take effect. If the app has no app-level token yet, create one as in step 2.
You can drop scopes you do not need. Tools that lack a scope return an error that names the missing scope. chat:write.public lets the bot post in public channels without being invited first.
Tools
Tool | What it does | Bot scopes |
| Bot identity, connection status, granted scopes, and the scopes each tool is missing | none |
| Find members by email, name, display name, @handle or job title |
|
| Profile of one user (ID, email or @handle) |
|
| List channels, filtered by type, name or membership |
|
| Post to a channel, a thread, or a user's DM: Markdown or plain text, an optional context line, or custom Block Kit. |
|
| Replace the content of a message the bot posted (same formatting options as |
|
| Delete a message the bot posted (bots cannot delete other people's messages) |
|
| Read recent messages in a channel or DM |
|
| Read a thread | same as above |
| Add or remove an emoji reaction |
|
| Wait briefly (default 45 s) for a reply; saves the question as pending on timeout | history scopes |
| Check all pending questions, or one conversation, once and return any answers | history scopes |
| DMs and @mentions the bot received while the server was running |
|
Wherever a tool takes a channel or user, you can pass:
a channel ID (
C…),#channel-name, or Slack markup (<#C…>)a user ID (
U…),@handle, email, or display name
For a user, the tool opens a DM with them. If a name matches several users, the tool returns the candidates so the agent can ask which one you mean.
Bot tokens cannot call Slack's search.messages API, so this server has no message search.
Message formatting
send_message has three levels of formatting:
textalone: standard Markdown (bold, lists, code, links, quotes), or plain text withformat: "plain".context: small grey details under a divider at the bottom of the message, such as the Jira ticket or comment a question refers to. Each item is{ label, value, url? }or a pre-formatted mrkdwn string:{ "target": "quy@example.com", "text": "Does `VECURA_CONTENT_BACKEND_URL` have a public staging address?", "context": [ { "label": "Jira", "value": "VEC-123", "url": "https://example.atlassian.net/browse/VEC-123" }, { "label": "Comment", "value": "#4521", "url": "https://example.atlassian.net/browse/VEC-123?focusedCommentId=4521" } ] }This renders as: the question, a divider, then Jira: VEC-123 · Comment: #4521 in small text.
blocks: any Block Kit layout (header, section fields, images and so on).textthen becomes the notification fallback, andcontextis still appended. Try layouts in the Block Kit Builder. Interactive elements such as buttons are not supported, because the server does not handle clicks. If Slack rejects the blocks, the error lists the invalid fields.
Errors
Every tool returns failures as an MCP tool error (isError: true). The text says what failed, why, and what to do. For example:
Permission denied: the Slack bot is missing the OAuth scope `reactions:write` needed to add the :eyes: reaction.
Scopes the bot currently has: chat:write,users:read.
A Slack workspace admin must add it under api.slack.com/apps → your app → OAuth & Permissions → Bot Token Scopes, then reinstall the app to the workspace.The server also explains common Slack errors: not_in_channel, channel_not_found, users_not_found, is_archived, invalid_auth, and rate limits with the retry delay. Without users:read.email, Slack silently leaves emails out of user lists. In that case, email lookups report the missing scope instead of "user not found".
Configuration
Variable | Required | Default | Description |
| yes | Bot token, | |
| socket mode | App-level token with | |
| no |
|
|
| webhook mode | Signing secret from Basic Information | |
| no |
| Port for incoming Slack events in webhook mode |
| no |
| Path for incoming Slack events in webhook mode |
| no | any | Comma-separated targets |
| no |
|
|
| no |
| Where pending questions are stored, one JSON file per workspace |
| no |
| Pending questions older than this are dropped |
Webhook mode
Set SLACK_MODE=webhook and SLACK_SIGNING_SECRET. The server then listens on SLACK_MCP_HTTP_PORT. In the app settings, turn off Socket Mode and set the Request URL under Event Subscriptions and Interactivity to https://<your-host>/slack/events.
Waiting for replies
People may answer in a minute or the next morning. Polling inside one agent turn is cheap for the server but not for the agent: every wait_for_reply call is a model turn that re-reads the whole conversation. So the server keeps waits short and remembers what it is waiting for:
The agent sends the question with
send_messageandexpect_reply: true. The server saves it as a pending question inSLACK_MCP_STATE_DIR, which outlives the MCP process and the agent session.If a quick answer is likely, the agent calls
wait_for_replyonce or twice. After two timeouts the tool tells the agent to stop and report back to the user.Later,
check_replieswith no arguments checks every pending question in one call, returns the answers, and removes answered questions from the list.
Something has to run the agent again for step 3; the server cannot wake an agent. Slack's official MCP server has no wait tool either, so agents using it re-read threads the same way. Options:
The user asks: "check Slack replies".
A loop in an open session, for example
/loop 30m check Slack replies and continuein Claude Code.A scheduled run, for example a cron job at 8:00 running
claude -p "check Slack replies and continue".
Each check is one short turn, instead of one turn every minute.
To let a single wait_for_reply call block longer, raise your client's tool timeout and pass a larger timeout_seconds (up to 300). In Claude Code, set MCP_TOOL_TIMEOUT in milliseconds, for example MCP_TOOL_TIMEOUT=320000.
Running several instances
Every tool except get_inbox calls the Slack Web API directly with the bot token. Those tools give the same results no matter how many agents run this server at once. Keep in mind:
Events are split. Slack delivers each event to only one of an app's open Socket Mode connections. Each instance's
get_inboxtherefore sees only part of the incoming messages.wait_for_replyandcheck_repliesread the Web API, so they are not affected.Connection limit. Slack allows at most 10 Socket Mode connections per app. Instances beyond that cannot open a socket, so their
get_inboxreports the connection error. Their other tools still work.Rate limits are shared. All instances spend the same token's Slack rate limits. A tool that hits a limit fails at once and says how long to wait.
Development
pnpm install
pnpm dev # rebuild on change
pnpm test
pnpm typecheck
pnpm build
npx @modelcontextprotocol/inspector node dist/index.js # try the tools interactivelyReleasing
Pushing a v* tag publishes to npm through GitHub Actions (.github/workflows/publish.yml). The workflow authenticates with npm Trusted Publishing, so the repository stores no npm token.
npm version patch # or minor / major: bumps package.json, commits, and tags
git push --follow-tags # the tag triggers the publish workflowThe workflow fails if the tag does not match the package.json version.
Available Tools
14 toolschannels_listList Slack channelsARead-only
List channels the bot can see, optionally filtered by name. Private channels and DMs appear only if the bot is a member. is_member: false means the bot must be invited before it can post there (unless it has chat:write.public).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of channels to return | |
| query | No | Case-insensitive filter on channel name, topic or purpose | |
| types | No | Conversation types to include | |
| member_only | No | Only channels the bot is a member of |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so safety is covered. The description adds genuinely useful behavioral context beyond that: membership-gated visibility and the chat:write.public exception for posting. It doesn't describe pagination or return shape, but with annotations present a 4 fits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, no waste, with the core scope front-loaded before the visibility caveats.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, but the description covers the key semantic an agent needs: which channels appear and what membership means. It could say more about returned fields or pagination, but it is adequate for a filtered list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema documents limit, query, types, and member_only. The description adds meaning around membership gating but references 'is_member', which is not a parameter name (the parameter is member_only) – this could confuse an agent mapping it to input. Baseline 3 for full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Uses a specific verb (List) and resource (channels) with an explicit scope: 'channels the bot can see'. The optional name filter is stated. It doesn't explicitly differentiate itself from siblings like conversations_history, but the resource is distinct enough to route correctly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context on visibility: private channels and DMs appear only if the bot is a member, and explains the is_member=false implication. It stops short of naming alternatives or stating exclusions ('use X instead'), which keeps it from a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_repliesCheck for Slack repliesA
Check once, without waiting, whether people answered the bot. With no arguments, checks every pending question (saved by send_message with expect_reply, or by wait_for_reply on timeout), including ones from earlier sessions; answered questions are removed from the pending list. With channel and since_ts, checks one conversation instead. Cheap to call, so use it for long waits: end your turn, then call it later from a scheduled or looped run.
| Name | Required | Description | Default |
|---|---|---|---|
| channel | No | Check only this conversation (ID, #name, or user). Requires since_ts. Omit to check all pending questions. | |
| dismiss | No | Pending question IDs to drop without an answer (e.g. no longer needed) | |
| since_ts | No | With channel: only messages after this ts | |
| thread_ts | No | With channel: thread to check; new top-level messages in the channel are checked too |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, it discloses that answered questions are removed from the pending list and that earlier-session pending questions are included. It does not describe authorization needs or rate limits, but the key mutation of pending state is explained.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core behavior, then covers mode selection and usage advice without filler. The parenthetical about pending-question sources earns its place by explaining the tool's state model.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
It covers behavior, modes, side effects, and long-wait workflow, which is strong for a tool with four optional parameters and full schema coverage. Because there is no output schema and the description does not explain the return shape, a minor completeness gap remains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents channel, since_ts, thread_ts, and dismiss. The description adds mode-level context for no-argument versus channel/since_ts usage, but it does not add parameter details beyond the schema, making 3 the appropriate baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: checking once, without waiting, whether people answered the bot. It also distinguishes the all-pending mode from the single-conversation mode, so an agent can identify the tool's role immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear usage context: no arguments checks all pending questions, channel plus since_ts checks one conversation, and it is cheap to call for long waits via scheduled or looped runs. It does not explicitly route the agent to wait_for_reply as the blocking alternative, so it falls short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
conversations_historyRead Slack channel historyARead-only
Read recent messages from a channel or DM, newest first. channel accepts a channel ID, #channel-name, or a user (ID, @handle, email) for the bot's DM with them. Use cursor from the previous response to page further back. Thread replies are not included; use conversations_replies for those.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Number of messages to return | |
| cursor | No | Pagination cursor from a previous call | |
| latest | No | Only messages before this time (same formats as oldest) | |
| oldest | No | Only messages after this time: Slack ts, ISO date, or relative (30m, 6h, 2d, 1w) | |
| channel | Yes | Channel ID, #channel-name, or user (ID, @handle, email) for a DM | |
| include_activity | No | Include join/leave/topic change messages |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so safety is covered; the description adds real behavioral context – result ordering (newest first), pagination direction, and the fact that thread replies are omitted. It stops short of mentioning rate limits or any auth scope quirks, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with what it returns and the ordering, then paging, then the exclusion. Every clause carries information an agent would otherwise have to guess.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering the read-only/open-world profile and the schema covering all six parameters, this description covers what remains: result scope, ordering, pagination mechanics, and thread exclusion. No output schema exists, so no return-shape explanation is owed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so every parameter including limit, latest, oldest, and include_activity is already documented. The description only reinforces `channel` (repeating the schema's own wording) and adds a bit on `cursor`; it does not explain the relative/ISO time formats that make oldest/latest non-obvious.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read recent messages from a channel or DM'), plus ordering ('newest first') and the DM/channel scope. It explicitly sets itself apart from conversations_replies, so an agent can distinguish it without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives both the paging procedure ('use `cursor` from the previous response to page further back') and the exclusion rule with a named alternative ('Thread replies are not included; use conversations_replies for those'). The condition that selects the sibling is explicit, not inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
conversations_repliesRead a Slack threadARead-only
Read the replies in a thread, oldest first, including the parent message. thread_ts is the ts of the parent message (or of any message in the thread).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Number of messages to return | |
| cursor | No | Pagination cursor from a previous call | |
| channel | Yes | Channel ID, #channel-name, or user (ID, @handle, email) for a DM | |
| thread_ts | Yes | Timestamp of the thread's parent message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so safety is covered; the description then adds real behavioral detail the annotations don't: results are ordered oldest first and the parent message is included in the result set. It stays silent on pagination behavior (limit default 50, max 200) and on whether you must page through large threads, which is the remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero waste, with the ordering-and-parent guarantee front-loaded before the parameter note. Nothing is repeated from the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter read tool with full schema coverage and covered safety annotations, this is close to complete: result ordering and parent inclusion are stated. The remaining omission is pagination guidance — with limit capped at 200 and a cursor parameter, an agent would benefit from knowing when to expect truncation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema does not: thread_ts accepts the ts of the parent message *or of any message in the thread*, which actually extends the schema's narrower 'parent message' wording. That resolves a real ambiguity in how to call it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Read') and resource ('replies in a thread') plus the ordering and the inclusion of the parent message, which is genuinely distinguishing information. It does not, however, contrast itself with the sibling check_replies or conversations_history, so an agent must infer which of the three thread-reading tools applies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the resource name — you call it when you want a thread's contents — but there is no explicit 'use this instead of X when Y' guidance despite check_replies and conversations_history being obvious overlaps. The thread_ts clarification hints at the calling context but doesn't set boundaries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_messageDelete a Slack messageADestructiveIdempotent
Delete a message the bot posted, identified by channel and ts (as returned by send_message). Slack only lets a bot delete its own messages. Deleting the parent of a thread leaves its replies in place. This cannot be undone, so confirm with the user unless they asked for it.
| Name | Required | Description | Default |
|---|---|---|---|
| ts | Yes | Timestamp of the bot's message to delete | |
| channel | Yes | Channel ID, #channel-name, or user (ID, @handle, email) for a DM |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the destructive/idempotent annotations by disclosing the permission constraint (bot can only delete its own messages), the thread consequence (deleting a parent leaves replies), and irreversibility. These are exactly the behaviors an agent needs before invoking a destructive call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, each carrying a distinct and necessary fact: identity, permission scope, thread side effect, irreversibility/confirmation. The destructive warning is placed at the end where it lands before invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter destructive tool with no output schema, the definition covers identity, preconditions, side effects, and safety. The only minor gap is what the agent should expect on success or failure (e.g., error when the message isn't the bot's own).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented; the description adds provenance for ts ('as returned by send_message'), which helps the agent source the value correctly. No additional format or validation detail beyond that.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (delete) and resource (a message the bot posted), plus the identifying keys (channel, ts). It also implicitly distinguishes itself from siblings like send_message and edit_message by scoping the operation to the bot's own messages.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Establishes clear preconditions: the message must be one the bot posted, and Slack enforces that constraint. It also gives a confirmation directive ('confirm with the user unless they asked for it'), though it never names an alternative sibling (e.g., edit_message to blank content) for cases where deletion isn't possible.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_messageEdit a Slack messageADestructiveIdempotent
Replace the content of a message the bot posted, identified by channel and ts (as returned by send_message). Slack only lets a bot edit its own messages. The new text, context and blocks fully replace the old content, so resend any context you want to keep.
| Name | Required | Description | Default |
|---|---|---|---|
| ts | Yes | Timestamp of the bot's message to edit | |
| text | Yes | New message content. When `blocks` is set, this is only the notification/fallback text | |
| blocks | No | Custom Slack Block Kit blocks (https://docs.slack.dev/reference/block-kit/blocks), e.g. header, section with fields, image, markdown, context, divider. Replaces the rendered `text`; `context` is still appended. Do not use interactive elements (buttons, menus): this server does not handle clicks. | |
| format | No | markdown: standard Markdown rendered by Slack. plain: sent as-is | markdown |
| channel | Yes | Channel ID, #channel-name, or user (ID, @handle, email) for a DM | |
| context | No | Small grey details shown under a divider at the bottom of the message, joined with ·. Example: [{label:"Jira", value:"VEC-123", url:"https://…"}, {label:"Comment", value:"#4521", url:"https://…"}] |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the annotations' destructiveHint=true by explaining exactly what is destroyed: text, context and blocks fully replace the old content, so callers must resend anything they want kept. It also discloses the Slack-side permission restriction that the bot can only edit its own messages — an auth constraint neither the schema nor annotations carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the action and identity, then the permission caveat, then the replacement warning. No filler and nothing repeated from the schema verbatim.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no output schema, it covers the essentials: what it mutates, what is lost, and who is allowed to call it. Failure modes (invalid ts, editing another user's message) and the resulting edit timestamp are not addressed, though those are secondary.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is already 100%, so baseline is 3; the description adds cross-parameter semantics the schema only partly implies — that text, context and blocks jointly overwrite rather than merge, and that ts must originate from send_message. It does not touch the format parameter, which the schema already covers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Replace the content of a message') and pins down the identifier ('channel and ts, as returned by send_message'). That naming distinguishes it cleanly from send_message, delete_message and reactions_* siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear precondition — the bot may only edit messages it posted — and tells the agent where the ts comes from ('as returned by send_message'). It does not explicitly contrast with delete_message or with sending a fresh message, but the context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_inboxGet messages sent to the botA
Return direct messages and @mentions the bot received while this MCP server was running. Only covers events delivered to this process: messages sent before it started, or delivered to another running instance of the same Slack app, are not here. To reliably fetch replies in a known channel or thread, use wait_for_reply or conversations_history.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of messages (most recent kept) | |
| since | No | Only messages after this time: Slack ts, ISO date, or relative (30m, 2h) | |
| channel | No | Only messages from this channel or DM (ID, #name, or user) | |
| mark_read | No | Mark returned messages as read | |
| unread_only | No | Only messages not returned by a previous get_inbox call |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior the annotations don't convey: the inbox is process-local and volatile, so history is incomplete by design. It does not explain why readOnlyHint=false, namely that mark_read defaults to true and mutates read state — that justification lives only in the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: capability first, caveat second, alternative routing third. Every sentence carries distinct information and the most decision-relevant constraint is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the critical risk for this tool — that results are an incomplete, process-scoped window — which is what an agent most needs to avoid misinterpreting an empty inbox. With no output schema, the return shape is only loosely implied, but message lists are conventional enough that this is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all five parameters (limit, since, channel, mark_read, unread_only) are already documented with formats and defaults. The description adds no parameter-level detail, which meets the baseline for fully covered schemas but no more.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Return direct messages and @mentions the bot received') plus the precise scope ('while this MCP server was running'). It also names the sibling tools that serve related needs, so an agent can distinguish it from conversations_history and wait_for_reply without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the exclusion case (messages before startup or delivered to another instance are absent) and routes the agent to wait_for_reply or conversations_history for reliable replies. It does not mention check_replies, a sibling that sounds closely related, leaving a small gap in the alternative-selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reactions_addAdd a Slack reactionBIdempotent
Add an emoji reaction to a message as the bot.
| Name | Required | Description | Default |
|---|---|---|---|
| ts | Yes | Timestamp of the message | |
| emoji | Yes | Emoji name without colons, e.g. thumbsup, eyes, white_check_mark | |
| channel | Yes | Channel ID, #channel-name, or user (ID, @handle, email) for a DM |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true, destructiveHint=false and openWorldHint=true, so safety and repeat-call behavior are covered. The description adds one genuinely useful behavioral fact beyond the annotations: the reaction is attributed to the bot, not the calling user. It says nothing about failure modes or permission requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence with the effect front-loaded and no filler. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-param, fully documented, annotation-backed tool, the description is nearly sufficient; the actor disclosure closes the main ambiguity. The remaining gap is prerequisites and error behavior, which matters less for an idempotent non-destructive call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, including a concrete emoji naming example ('thumbsup, eyes') and channel formats, so the schema carries the parameter semantics. The description adds nothing on top, which is the expected baseline here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb + resource ('Add an emoji reaction to a message') and it adds the actor identity ('as the bot'). It is clearly distinct from reactions_remove by name and verb direction, though it never names the sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no prerequisites (bot must be a member of the channel, reactions:write scope), and no pointer to reactions_remove for the inverse operation. Usage is only inferable from the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reactions_removeRemove a Slack reactionADestructiveIdempotent
Remove an emoji reaction the bot previously added to a message.
| Name | Required | Description | Default |
|---|---|---|---|
| ts | Yes | Timestamp of the message | |
| emoji | Yes | Emoji name without colons, e.g. thumbsup, eyes, white_check_mark | |
| channel | Yes | Channel ID, #channel-name, or user (ID, @handle, email) for a DM |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true and openWorldHint=true, so the safety profile is covered structurally. The description adds one genuinely useful behavioral constraint beyond them — that only the bot's own reactions qualify — but says nothing about what happens on failure (e.g., reaction absent) or whether removal triggers notifications.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the verb and resource, with zero filler. Nothing could be cut without losing the scope constraint.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple three-parameter mutation with complete schema docs, full annotation coverage and no output schema, the description covers what is needed to call it correctly. The only gap is failure-mode behavior when the reaction is not present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and all three parameters carry their own docs, including the emoji-without-colons format. The description adds no parameter-level detail, so this sits at the baseline for a fully documented schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Remove) and resource (an emoji reaction) with a meaningful scope constraint: only reactions the bot previously added. That scope distinguishes it from a general reaction-removal or from reactions_add, though it never names the sibling tool directly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the 'previously added by the bot' clause tells the agent this is the undo path for reactions_add, but there is no explicit when-to-use, when-not-to-use, or named alternative. An agent must infer that it cannot be used to remove other users' reactions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_messageSend a Slack messageA
Post a message as the bot to a channel, a thread, or a user's DM. target accepts a channel ID (C…), #channel-name, user ID (U…), @handle, email, or a person's name; users get a direct message. Use context to add small reference details under a divider at the bottom (Jira ticket, comment link, source, IDs). Use blocks only when you need a custom Block Kit layout (header, fields, images, etc.). Returns the message ts, which you can pass to wait_for_reply or use as thread_ts to reply in a thread.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Message content. When `blocks` is set, this is only the notification/fallback text, so keep it a short summary | |
| blocks | No | Custom Slack Block Kit blocks (https://docs.slack.dev/reference/block-kit/blocks), e.g. header, section with fields, image, markdown, context, divider. Replaces the rendered `text`; `context` is still appended. Do not use interactive elements (buttons, menus): this server does not handle clicks. | |
| format | No | markdown: standard Markdown rendered by Slack. plain: sent as-is | markdown |
| target | Yes | Channel ID, #channel-name, user ID, @handle, email, or name | |
| context | No | Small grey details shown under a divider at the bottom of the message, joined with ·. Example: [{label:"Jira", value:"VEC-123", url:"https://…"}, {label:"Comment", value:"#4521", url:"https://…"}] | |
| thread_ts | No | Timestamp of the parent message, to reply inside that thread | |
| expect_reply | No | Set true when the message asks something you need an answer to. The question is saved as pending, so check_replies can find the answer later, even from a new session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag this as a non-read-only, open-world write, so the description's added behavior carries the credit: it posts as the bot, resolves users to DMs, appends `context` under a divider, treats `text` as fallback when `blocks` is set, and explicitly warns that interactive elements are unsupported. Remaining gaps are permission requirements and failure modes (e.g., bot not in channel, ambiguous name resolution).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, front-loaded with the core action, then parameter guidance ordered by importance (target, context, blocks), then the return value. Every sentence carries distinct operational content with no restatement of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter write tool with no output schema, the description covers the send target, layout mode, and return value (`ts` usable as `thread_ts` or with wait_for_reply). It omits what failure looks like and any constraints on DMing users the bot has never interacted with, which an agent may need when a send silently fails.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns above that by clarifying target resolution semantics (email/name → DM) and giving a usage rule for `blocks` vs `text` that the schema doesn't state. It does not, however, explain precedence among identifier types or ambiguity handling for names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource+scope: 'Post a message as the bot to a channel, a thread, or a user's DM.' That single sentence distinguishes it from edit_message, delete_message, and the read-oriented siblings, and the DM-vs-channel outcome is stated explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real selection guidance: users get a DM (not a channel post), `context` is for small reference details, and `blocks` should be used 'only when you need a custom Block Kit layout.' It also points forward to wait_for_reply/thread_ts. It stops short of naming siblings it should not be used instead of (edit_message, delete_message), so no explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
user_infoGet Slack user detailsBRead-only
Get profile details for one Slack user, identified by user ID (U…), email, or @handle.
| Name | Required | Description | Default |
|---|---|---|---|
| user | Yes | User ID (U…), email address, or @handle |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, and the description adds nothing beyond that — no mention of permission requirements for reading profiles, rate limits, or what happens when the identifier fails to resolve.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence with the action, scope, and identifier forms in the first clause; nothing is padded. It is close to minimal but could carry one more clause of routing or behavior without bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter read with no output schema, the description still does not indicate what 'profile details' includes (display name, email, title, timezone) or the shape of the result, leaving the agent guessing at return contents.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter already documents 'User ID (U…), email address, or @handle'. The description restates the same accepted formats without adding new meaning such as precedence between them, so it sits at the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource ('Get profile details for one Slack user') and scopes it to a single user, which implicitly separates it from the list-oriented users_search. It never names that sibling, so the differentiation is inferred rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'one Slack user' versus the sibling users_search and whoami, but the description never says explicitly when to pick this tool over those alternatives, nor any prerequisite such as needing a user ID from a search first.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
users_searchSearch Slack usersARead-only
Find workspace members by email, real name, display name, @handle or job title. Returns user IDs to use with send_message and other tools. Exact matches come first.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of users to return | |
| query | Yes | Email address, full or partial name, display name, @handle, or job title | |
| include_bots | No | Include bot users in the results |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint. The description adds useful behavior beyond that: exact matches come first and results are user IDs intended for downstream tools.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with the core action and search fields, followed by the useful return-value context. No wasted wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only search tool with full schema coverage and no output schema, the description covers purpose, accepted identifiers, return IDs, and ordering. Minor gaps like pagination or bot inclusion are already handled by the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all three parameters are documented there. The description repeats the query field semantics and notes exact-match ordering, but adds no extra detail about limit or include_bots.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: finding workspace members. The search fields are enumerated, making the scope clear, though it does not explicitly distinguish itself from user_info or whoami.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage by saying the returned user IDs work with send_message and other tools, but does not explicitly state when to use this instead of user_info or whoami, nor when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wait_for_replyWait for a Slack replyA
Block for a short time until someone other than the bot replies in a channel, DM or thread, then return the new messages. Use it only when an answer is likely within a minute or two; every call costs a model turn. Pass since_ts = the ts of your question (from send_message). Replies both as new messages and inside the question's thread are found. On replied: false, follow the returned next_step: after a couple of timeouts, stop waiting, tell the user, and collect the answer later with check_replies. Keep timeout_seconds below your MCP client's tool-call timeout (often 60 seconds; Claude Code users can raise it with MCP_TOOL_TIMEOUT).
| Name | Required | Description | Default |
|---|---|---|---|
| channel | Yes | Channel ID, #channel-name, or user (ID, @handle, email) for their DM | |
| since_ts | No | ts of your question; only later messages count (default: now) | |
| from_user | No | Only count messages from this user (ID, @handle, or email) | |
| thread_ts | No | Thread to check; new top-level messages in the channel are checked too | |
| timeout_seconds | No | How long to wait; keep it below the MCP client's tool-call timeout | |
| poll_interval_seconds | No | How often to check Slack |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (readOnlyHint=false, destructiveHint=false, openWorldHint=true) by disclosing the blocking cost per call, the `replied: false` contract with `next_step`, the recommendation to cap retries, and the hard interaction with the MCP client's tool-call timeout. Nothing here contradicts the annotations — the tool does read Slack but consumes a model turn, so readOnlyHint=false is not inconsistent with the text.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first clause, and each subsequent sentence carries a distinct operational rule with no filler. It is dense but slightly long, with the Claude Code MCP_TOOL_TIMEOUT parenthetical being the only marginal content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter blocking poll tool with no output schema, it covers the blocking semantics, the failure return fields, the retry policy, and the client-side timeout ceiling. An agent can call this correctly and know what to do on a timeout without further information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: `since_ts` should be the ts of the question from send_message, and `timeout_seconds` must stay under the client's tool-call timeout. It also explains that replies both as top-level messages and inside the question's thread are matched, which is not evident from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with precise scope: blocks until a human (not the bot) replies in a channel, DM, or thread, then returns the new messages. It also implicitly distinguishes itself from the non-blocking sibling check_replies, which it names later.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly bounds when to use it ('only when an answer is likely within a minute or two; every call costs a model turn') and gives a decision path for the failure case: follow `next_step`, and after a couple of timeouts stop and use check_replies instead. That is when/when-not/alternative guidance in full.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whoamiSlack bot statusARead-only
Show the server version, which Slack bot and workspace this server is connected to, the connection mode, the OAuth scopes the bot has, and which tools are missing scopes. Call this first when a Slack action fails with a permission error.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds meaningful context beyond that: the tool surfaces scopes and specifically which tools are missing scopes, making it a diagnostic rather than an identity call. It does not describe output format or failure modes, but with annotations carrying the safety signal this is solid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence listing the returned fields, followed by one actionable routing sentence. Every clause earns its place; the field list is long but each item is a distinct diagnostic output. Front-loading the verb 'Show' keeps it readable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description carries the burden of explaining return values, and it does so explicitly by enumerating the six categories of information returned. Combined with the troubleshooting trigger, an agent has enough to call it correctly and interpret the result. It could be slightly more complete by noting that it is workspace/bot-scoped rather than user-scoped.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, which is the baseline-4 case: there is nothing for the description to disambiguate. The description correctly implies no arguments are needed and focuses on what the call reveals.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a concrete verb ("Show") and enumerates the exact resources returned: server version, connected bot, workspace, connection mode, granted scopes, and missing-scope tools. This clearly reframes the ambiguous name 'whoami' into a Slack diagnostic tool. It does not explicitly contrast with the sibling user_info, which sounds superficially similar, so it falls just short of 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a crisp trigger condition: "Call this first when a Slack action fails with a permission error." That is a genuine when-to-use rule tied to the sibling family of Slack actions. It stops short of naming a true alternative or stating when not to call it, so it is strong but not complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
14 tool updates
v0.6.1- First observed
channels_list - First observed
check_replies - First observed
conversations_history - First observed
conversations_replies - First observed
delete_message - First observed
edit_message - First observed
get_inbox - First observed
reactions_add - First observed
reactions_remove - First observed
send_message - First observed
user_info - First observed
users_search - First observed
wait_for_reply - First observed
whoami
TDQS
Scored across 14 tools
Most tools map to distinct resource+action pairs (send/edit/delete_message, reactions_add/remove, conversations_history/replies), and the descriptions explicitly explain boundaries. The one fuzzy cluster is read/wait behavior: check_replies, wait_for_reply, get_inbox and conversations_history all retrieve incoming messages and differ only in polling semantics and scope, which an agent must read carefully to pick correctly. user_info vs users_search is also mildly overlap-prone but clarified by the descriptions.
Conventions are mixed: verb_noun (send_message, edit_message, check_replies, get_inbox, wait_for_reply), noun_verb mirroring Slack's API (channels_list, reactions_add, reactions_remove, conversations_history, conversations_replies), a bare noun (user_info) and a bare verb-ish name (whoami). All names remain readable and most are guessable to anyone familiar with Slack's API, but there is no single predictable pattern to extrapolate from.
14 tools sit comfortably in the well-scoped 3-15 range, and each tool earns its place: identity/context, user & channel discovery, message lifecycle, reading, reactions, and reply-waiting. No obvious filler or redundant duplicate tools.
The core bot messaging lifecycle is fully covered: send, edit, delete, read history and thread replies, react/unreact, receive mentions/DMs, and wait/check for replies, plus discovery tools for users and channels. Gaps are minor-to-moderate: no file upload/download, no message search, no channel creation/invite or member listing, and edit/delete are limited to the bot's own messages, but agents can work around these for typical bot workflows.
Maintenance
Related MCP Connectors
Enable interaction with Slack workspaces. Supports subscribing to Slack events through Resources.
Messaging tools for AI agents: send messages, manage chats, groups and channels.
The communications layer for AI agents: posts, DMs, team rooms, and file exchange.
- mcp-serverOAuthcom.make
Give your AI agents the tools to build, manage, and run automation workflows.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables AI agents to interact with Slack workspaces through OAuth authentication, supporting message reading, posting to channels and threads, and channel discovery with popularity sorting.4MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to interact with Slack workspaces through comprehensive channel management, messaging, direct messages, search functionality, and user management capabilities.303 npm2MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Slack workspaces through natural language, supporting channel management, message operations, user profiles, reactions, and threaded conversations.-
- AlicenseAqualityCmaintenanceEnables AI assistants to interact with Slack workspaces, including listing channels, posting messages, replying to threads, adding reactions, and retrieving user information.1012 npmMIT