SlackMCP
Provides tools for interacting with a Slack workspace via Slack's Web API, including listing and reading channels, DMs, and threads; searching messages; listing users; sending and editing messages; opening DMs; getting permalinks; and adding reactions.
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., "@SlackMCPsend a message in #general saying I'll be 10 minutes late to standup"
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.
SlackMCP
A self-hosted Model Context Protocol server for Slack. SlackMCP gives AI assistants such as Codex, Claude, and other MCP clients direct access to your Slack workspace. Your assistant can read, search, and send messages as you, with no signatures, footers, or attribution added.
SlackMCP runs on your own machine and talks directly to Slack's Web API. It uses no hosted proxy and sends no telemetry, and your token stays on your machine.
Why SlackMCP
Messages are sent exactly as written. SlackMCP never adds "sent by" text, signatures, footers, branding blocks, or attribution metadata. What you write is what your colleagues see.
It acts as you. With a User OAuth Token, messages come from your own Slack account, not a bot.
Data goes only to Slack. Requests go only to
https://slack.com/api/, redirects are refused, and tokens and message bodies are never logged.Results are readable. Read and search results replace raw user IDs with display names, so assistants can follow a conversation without extra lookups.
Writes are handled safely. Writes are never retried automatically, so a failed or uncertain send cannot produce a duplicate. Rate limits come back with Slack's suggested retry delay.
It follows the standard. It is built on the official MCP SDK and works with both earlier and current (2026-07-28) MCP stdio clients.
Related MCP server: Slack MCP Server
Features
Tool | Description | Required scopes |
| Verify the connected workspace and account | None |
| List channels, private channels, DMs, and group DMs |
|
| Read channel or DM history |
|
| Read a message and its thread replies | Matching |
| Search every conversation the token can see |
|
| List workspace members and their IDs |
|
| Send a message, optionally as a thread reply |
|
| Replace the text of an existing message |
|
| Open or resume a DM or group DM |
|
| Get a shareable link to a message | None |
| Add an emoji reaction to a message |
|
Each tool carries MCP annotations (read-only, destructive, idempotent), so clients can tell safe reads from writes and ask for confirmation before writes.
Requirements
Node.js 22.16 or later
A Slack workspace where you can install apps (some workspaces need admin approval)
An MCP-compatible client, such as Codex, Claude Desktop, Claude Code, or Cursor
Installation
git clone https://github.com/jaggerjack61/SlackMCP.git
cd SlackMCP
npm ci --ignore-scriptsConfiguration
1. Create the Slack app
Go to api.slack.com/apps and choose Create New App → From a manifest.
Select your workspace and paste the contents of
slack-app-manifest.json. The manifest requests every user scope listed above. If you only need to send messages, you can trim it tochat:write.Under OAuth & Permissions, click Install to Workspace and approve.
Copy the User OAuth Token (starts with
xoxp-).
User or bot token? A User OAuth Token (
xoxp-) acts as your own account and is required for search and for reading channel threads. A Bot User OAuth Token (xoxb-) acts as the app's bot user. Either way, Slack decides the sender name and any app labels it shows; SlackMCP cannot change these.
2. Store the token
cp .env.example .env
chmod 600 .envEdit .env:
SLACK_TOKEN=xoxp-your-token-hereSlackMCP loads the .env file next to package.json, whatever directory your client starts it from. A SLACK_TOKEN already set in the process environment takes precedence. Never commit .env or paste your token into a chat.
3. Register the server with your MCP client
Codex. Add the following to ~/.codex/config.toml (template: config/codex.toml.example):
[mcp_servers.slack_local]
command = "node"
args = ["/absolute/path/to/SlackMCP/src/index.js"]Claude Desktop, Cursor, and other JSON-configured clients. Merge the following into the client's mcpServers object (template: config/mcp.json.example):
{
"mcpServers": {
"slack-local": {
"command": "node",
"args": ["/absolute/path/to/SlackMCP/src/index.js"]
}
}
}If your client can't find node, replace it with the full path printed by command -v node.
4. Verify
Restart or reload your MCP client, then ask your assistant to run slack_auth_test. It should report your workspace and Slack user. If another Slack integration is also installed, tell your assistant to use slack-local for messaging.
Usage
Once connected, ask your assistant in plain language:
"Summarise what I missed in #engineering today."
"Find the thread where we discussed the Q3 launch date."
"Reply in that thread: 'Confirmed for the 14th, I'll update the tracker.'"
"DM Priya the link to that message."
Formatting
Messages use Slack's mrkdwn syntax (*bold*, _italic_, <https://example.com|label>), not standard Markdown. Set mrkdwn: false on slack_send_message to send plain text. Link and media previews (unfurls) are off by default and can be turned on per message. Messages can be up to 40,000 characters.
Addressing conversations
Send and edit tools take a conversation ID (starting with C, G, or D), not a user ID. To message a person, call slack_open_dm first to get their DM conversation ID. Message timestamps (ts) are passed as strings.
User names
slack_read_channel, slack_read_thread, and slack_search_messages replace user IDs with names:
<@U…>mentions in message text become@Nameeach message gets a
user_namefielda top-level
user_namesmap keeps the original IDs, so your assistant can still write<@ID>mentions when replying
Names are fetched with users.info and cached for as long as the server runs. If a name can't be fetched, the ID is left as it is and the read still succeeds.
Pagination
Read and list tools return one page at a time. To get the next page, pass response_metadata.next_cursor as cursor. Search pages through results with page and reports the total in paging.pages.
Network and proxy configuration
On Node.js 24 or later, set NODE_USE_ENV_PROXY=1 when launching to send requests through HTTP_PROXY / HTTPS_PROXY. Configure your MCP client to pass these variables on to the server (along with NO_PROXY and NODE_EXTRA_CA_CERTS if needed). Don't write proxy credentials into client config files.
Security
Your token is read once at startup from
.envor the environment. Restart the server after changing it.Requests are sent only to
https://slack.com/api/, and redirects are refused.Tokens and message bodies are never logged. Errors return only Slack's error code and, where relevant, the missing scopes.
Writes are never retried automatically. If a send fails because of a network error, check the conversation before sending again.
Search can return results from private channels and DMs your account can access. Grant only the scopes you need.
To report a vulnerability, please open a private security advisory on GitHub rather than a public issue.
Development
npm start # run the stdio server (waits for an MCP client)
npm test # run the test suiteThe test suite runs a real MCP client against the server over stdio, with Slack's responses mocked. It covers protocol negotiation for earlier and current MCP clients, exact message preservation, edit behaviour, pagination, input validation, user-name resolution, missing credentials, rate limiting, and failures where delivery is unknown. No real Slack messages are sent.
Project structure
src/
index.js Entry point: loads .env and starts the stdio transport
server.js Registers the MCP tools and handles errors
tools.js Tool definitions, input schemas, and Slack method mapping
slack.js Slack Web API client
users.js User ID → display name resolution with caching
test/ Node test runner suites and a stdio test fixture
config/ Sample client configurationsTroubleshooting
Symptom | Resolution |
|
|
| The error lists the scopes needed. Add them in the Slack app settings and reinstall the app. |
| The account is not a member of that channel. Join it first. |
| Check the conversation ID. To message a person, call |
Search or thread reads fail with a bot token | These need a User OAuth Token ( |
Client reports | Use the absolute path from |
References
License
Released under the MIT License.
Available Tools
11 toolsslack_add_reactionB
Add an authorized emoji reaction to a message. Use an emoji name without colons.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| channel | Yes | Slack conversation ID. Resolve the intended channel or DM before sending. | |
| timestamp | Yes | Slack message timestamp, kept as a string. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly=false, destructive=false, idempotent=false and openWorld=true, so the mutation and non-idempotency profile is covered structurally. The description adds only the word 'authorized', hinting that the emoji must exist/permitted in the workspace, but it does not say what happens on duplicate reactions or on invalid emoji — the two most likely failure modes for a non-idempotent write.
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 short sentences, zero waste, with the core action front-loaded and the parameter hint trailing. Nothing to trim and nothing buried.
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 small 3-parameter mutation with no output schema, the description is minimal but workable: it names the action and the one undocumented parameter. It omits the duplicate-reaction behavior and the success response, which matter for a non-idempotent write with no output schema to fall back on.
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 67%: channel and timestamp are already documented in the schema, leaving only 'name' undocumented there. The description addresses exactly that gap by saying 'use an emoji name without colons', which is useful guidance (though the pattern already excludes ':'). It adds nothing about how to obtain the message timestamp or channel ID beyond what the schema says.
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: 'Add an authorized emoji reaction to a message.' An agent immediately knows the operation. No sibling tool touches reactions, so explicit differentiation from siblings is less critical, though it never says how it relates to the message-read/send tools.
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?
There is no statement of when to use this versus other tools, no prerequisites beyond the ambiguous word 'authorized', and no mention of what to do if the reaction already exists. The agent must infer usage entirely from the tool name and schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slack_auth_testARead-onlyIdempotent
Check the configured token and identify the connected Slack workspace and account.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds that it inspects the configured token and surfaces connected identity, but says nothing about what happens on an invalid or expired token (error vs. structured negative result) or what data is returned.
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 front-loaded sentence with the diagnostic action first and the yielded information second; no filler, no repetition of the tool name.
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 no-parameter, no-output-schema diagnostic, the description covers both purpose and the identity information obtained. The only gap is failure behavior, which matters for a test-style tool but is a minor omission.
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 and the schema is an empty object, so there is nothing for the description to disambiguate. Baseline 4 applies for a no-parameter definition.
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 uses two specific verbs, 'check' the configured token and 'identify' the connected workspace and account, so the resource and outcome are unambiguous. It doesn't name any sibling, but none of the listed Slack tools perform authentication, so an agent can still tell it apart from them.
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 only implied: an agent can infer this is a diagnostic to run before or when other Slack calls fail, but the description never states when to call it, when not to, or that it precedes the read/write siblings. No prerequisites or failure conditions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slack_edit_messageADestructiveIdempotent
Replace an editable message with the exact supplied body. No signature or attribution is added. Only edit when authorized. Sending blocks:[] clears existing structured message blocks; Slack may retain an edited indicator.
| Name | Required | Description | Default |
|---|---|---|---|
| ts | Yes | Slack message timestamp, kept as a string. | |
| text | Yes | Exact message body. Use Slack mrkdwn (*bold*, _italic_) unless mrkdwn is false. Never append a signature or attribution. | |
| parse | No | none | |
| channel | Yes | Slack conversation ID. Resolve the intended channel or DM before sending. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and openWorldHint=true, but the description adds real behavioral context beyond them: no signature/attribution is appended, existing structured blocks are wiped by blocks:[], and Slack may retain an edited indicator. The mention of a blocks:[] argument that does not exist in the input schema creates some ambiguity about what the tool actually accepts.
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 front-loaded sentences with the core behavior first and side effects after; little waste. The blocks:[] clause is the only part that is not self-explanatory in context.
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?
Annotations cover the mutation/safety profile and no output schema exists, and the description covers side effects like block clearing. It omits failure behavior (what happens when a message is not editable or ts is stale) and references a blocks parameter not present in the schema, leaving a gap for a destructive write 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 75%, so the schema already explains ts, text, and channel including the 'never append a signature' rule that the description repeats. The description adds nothing about parse or the missing blocks field, so it neither compensates for the gap nor contributes new parameter meaning.
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+resource ('Replace an editable message') and pins down the semantics with 'exact supplied body'. It implicitly separates itself from slack_send_message (edit vs. create) but never names or explicitly contrasts that sibling.
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?
'Only edit when authorized' is the sole usage constraint and it is vague about what authorization means or how to verify it. No explicit alternative is offered (e.g., use slack_send_message for new messages, slack_search_messages to locate ts), so routing must be inferred from the sibling list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slack_get_permalinkARead-onlyIdempotent
Get the Slack URL for a message using its channel and timestamp.
| Name | Required | Description | Default |
|---|---|---|---|
| channel | Yes | Slack conversation ID. Resolve the intended channel or DM before sending. | |
| message_ts | Yes | Slack message timestamp, kept as a string. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds that the result is a 'Slack URL', which is useful, but says nothing about failure modes (e.g., missing message or inaccessible channel) or any rate-limit behavior.
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 front-loaded sentence with zero filler. Everything it says is relevant and it gets to the operation immediately.
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 read-only lookup with complete schema coverage, rich annotations, and no output schema, this is nearly sufficient. A note on what happens when the message cannot be found or on how to obtain a timestamp would close the remaining 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 coverage is 100%, so both parameters are fully documented in the schema, including ID patterns and the timestamp-as-string convention. The description merely restates the two parameter names without adding format or resolution guidance, so baseline 3 applies.
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 ('Get') and resource ('the Slack URL for a message'), which unambiguously identifies the operation. It does not differentiate itself from siblings like slack_search_messages or slack_read_channel, but the action is distinct enough to be recognizable.
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 only implied: the agent can infer it should call this when it needs a shareable link to a known message. There is no explicit 'when to use' guidance, no mention of alternatives such as searching for a message first if the timestamp is unknown, and no prerequisites stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slack_list_conversationsBRead-onlyIdempotent
List visible Slack channels and DMs. Follow response_metadata.next_cursor for more pages.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| types | No | public_channel,private_channel,im,mpim | |
| cursor | No | next_cursor from the previous page; omit for the first page. | |
| exclude_archived | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the operation as read-only, idempotent, open-world, and non-destructive. The description adds useful pagination behavior via response_metadata.next_cursor and clarifies the visibility scope, but it does not explain what 'visible' means, authentication requirements, rate limits, or the return structure.
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 two short sentences with no wasted text. The core purpose and pagination instruction are front-loaded and easy to scan.
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 four optional parameters, a moderate schema, and no output schema, the description is adequate but incomplete. Defaults reduce the burden, yet the description does not explain how limit, types, or exclude_archived affect results, leaving gaps for callers relying on the description.
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 only 25%, with just the cursor parameter documented. The description mentions channels and DMs, loosely mapping to the types parameter, but it does not explain the allowed type values, the limit parameter, or exclude_archived, so it fails to compensate for the low 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?
The description uses a specific verb and resource: 'List visible Slack channels and DMs.' It clearly identifies the object being listed and its scope, though it does not explicitly differentiate itself from siblings such as slack_read_channel or slack_search_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?
Usage is implied for discovering visible conversations, and the pagination instruction is explicit. However, there is no guidance on when to use this instead of alternatives like slack_search_messages or slack_read_channel, nor are there any exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slack_list_usersBRead-onlyIdempotent
List workspace users to resolve user IDs. Follow response_metadata.next_cursor for more pages.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | next_cursor from the previous page; omit for the first page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and openWorld, so the safety profile is covered. The description adds a genuinely useful behavioral cue about pagination via response_metadata.next_cursor, but says nothing about Slack rate limits (users.list is heavily throttled), what user types/statuses are returned, or result size.
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 short sentences, purpose front-loaded followed by the pagination instruction. Nothing wasted and nothing buried.
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 listing tool with annotations and no output schema, the description covers purpose and paging but leaves the limit parameter and the composition of the returned user list (bots, deactivated accounts) unexplained. Adequate but with clear gaps.
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 only 50%: cursor is documented in the schema, but limit (default 15, max 100) is undocumented everywhere. The description contributes no parameter meaning at all, not even hinting at page size behavior, so it fails to compensate for the coverage gap.
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+resource ("List workspace users") and adds the reason ("to resolve user IDs"), which makes it clearly distinct from siblings like slack_list_conversations or slack_search_messages. It does not explicitly name an alternative tool, 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?
The phrase "to resolve user IDs" implies the use case, so an agent can infer when this beats slack_search_messages. But there are no explicit when-to-use/when-not conditions and no mention of alternatives or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slack_open_dmAIdempotent
Open or resume a direct message with explicitly authorized users. Returns a conversation ID for sending. Does not send a message.
| Name | Required | Description | Default |
|---|---|---|---|
| users | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotency, open-world behavior, and non-destructiveness. The description adds useful context by stating that it returns a conversation ID and does not send a message, but it omits important behavioral details such as what happens when multiple users are supplied.
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 purpose and followed immediately by the return value and the non-send caveat. Every sentence adds distinct information.
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?
The description covers purpose, return value, and the crucial fact that it does not send a message. However, for a tool with a single 0%-documented array parameter, it leaves out parameter semantics and multi-user behavior that an agent needs to invoke it correctly.
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 0%, and the description does not explain the 'users' parameter at all—not the Slack ID format, the 1–8 item limit, or whether multiple users create a group DM. It only vaguely refers to 'explicitly authorized users.'
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+resource ('Open or resume a direct message'), identifies the target population ('explicitly authorized users'), and explicitly distinguishes itself from slack_send_message by saying it 'Does not send a message.'
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?
The description makes the intended workflow clear: use it to obtain a conversation ID before sending. It does not name an alternative tool or state exclusions beyond 'explicitly authorized users,' so it falls short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slack_read_channelARead-onlyIdempotent
Read a page of channel or DM history, newest first. Requires access to the conversation. Follow next_cursor for more pages. User mentions in text are shown as @name; user_names maps user IDs to names (use <@ID> to mention someone when sending).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | next_cursor from the previous page; omit for the first page. | |
| latest | No | Slack message timestamp, kept as a string. | |
| oldest | No | Slack message timestamp, kept as a string. | |
| channel | Yes | Slack conversation ID. Resolve the intended channel or DM before sending. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the description's value is the extra behavior it adds: results come newest-first, pages are chained through next_cursor, and mentions are rendered as @name with a user_names map for resolving IDs. These are concrete traits an agent would not get from the annotations or schema, though access-failure behavior is not described.
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 with the core action and ordering front-loaded, followed by prerequisites and pagination. The trailing parenthetical about how to mention someone is slightly tangential to a read operation but is genuinely useful cross-context and costs only a clause.
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 no output schema, the description carries the burden of explaining the response, and it does so for the key pieces: next_cursor, the user_names map, and mention formatting. What remains unstated is the shape of the message objects themselves and what happens when the channel is inaccessible.
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 80%, so cursor, oldest, latest and channel are already documented in the schema. The description reinforces the cursor pattern and explains the user_names/mention convention, but adds nothing about limit bounds or how oldest/latest interact with newest-first ordering. Baseline 3 is appropriate.
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 first sentence gives a specific verb and resource ('Read a page of channel or DM history') plus ordering ('newest first'), which lets an agent distinguish this from message-sending or search tools. It does not explicitly name the closest sibling, slack_read_thread, so the boundary between reading a whole channel and reading one thread is left implicit.
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 only implied: the tool is for pulling conversation history and 'Requires access to the conversation.' The pagination instruction ('Follow next_cursor for more pages') is operational guidance rather than a when-to-use rule. There is no statement about when to prefer slack_read_thread or slack_search_messages instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slack_read_threadARead-onlyIdempotent
Read a parent message and its thread replies. A user token is needed for public/private channel threads. Follow next_cursor for more pages. User mentions in text are shown as @name; user_names maps user IDs to names (use <@ID> to mention someone when sending).
| Name | Required | Description | Default |
|---|---|---|---|
| ts | Yes | Parent message timestamp. | |
| limit | No | ||
| cursor | No | next_cursor from the previous page; omit for the first page. | |
| channel | Yes | Slack conversation ID. Resolve the intended channel or DM before sending. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive), so the description's added value is real: it discloses the auth requirement for private channels and the pagination contract via next_cursor. It also explains how mentions are rendered and what user_names contains, which is behavioral detail an agent cannot get from annotations or 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?
Four short sentences, front-loaded with the core action and pagination immediately after. The closing note about user_names and <@ID> mentioning drifts toward slack_send_message usage, but it is brief and still informs interpretation of this tool's output.
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 no output schema, the description carries the burden of explaining returns, and it does so for the parts an agent must handle: pagination cursor, mention rendering, and the user_names mapping. It does not describe the overall response shape (e.g., whether the parent message is included in the list), which is the main remaining 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 coverage is 75%, with limit left undescribed, so the schema does most of the work. The description still adds meaning beyond it by tying cursor to the next_cursor value returned from the previous page, which is the one non-obvious parameter interaction.
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: reads a parent message plus its thread replies. That scope ('thread replies') implicitly distinguishes it from slack_read_channel and slack_search_messages, but no sibling is named explicitly, so 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?
Gives one real prerequisite (a user token is needed for public/private channel threads), which is genuinely useful selection context. However, it never says when to choose this over slack_read_channel or slack_search_messages, so the usage guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slack_search_messagesARead-onlyIdempotent
Search messages visible to the token, including private conversations it can access. Requires a user token with search:read. Use Slack search operators to limit the query. Follow paging.pages using page. User mentions in text are shown as @name; user_names maps user IDs to names (use <@ID> to mention someone when sending).
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| sort | No | timestamp | |
| count | No | ||
| query | Yes | ||
| sort_dir | No | desc | |
| highlight | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly, idempotent, non-destructive, and openWorld behavior. The description adds useful operational context beyond that: the user-token auth requirement, the search:read scope, and pagination via paging.pages/page.
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?
Front-loaded with purpose and auth requirement, then the query and pagination guidance. Most sentences earn their place, though the trailing user_names/mention note is tangential to search itself and slightly compresses multiple ideas into one sentence.
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 no output schema, the description does explain result-adjacent details like @name rendering and the user_names mapping. It also covers auth and pagination, but omits result contents and the semantics of the sort, count, and highlight parameters.
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 0%, so the description must carry the burden for six parameters. It explains query format (operators, @name and <@ID> mention syntax) and page, but leaves sort, sort_dir, count, and highlight entirely undocumented.
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 ('Search messages') plus a precise scope: messages visible to the token, including private conversations it can access. This distinguishes it from read-oriented siblings like slack_read_channel and slack_read_thread, which are scoped to a single conversation.
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?
Provides clear usage context: search operators to constrain the query and a required user token with search:read. It does not explicitly say when to prefer slack_read_channel or slack_read_thread, or when not to use search.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slack_send_messageA
Send the exact supplied message body to an authorized Slack channel or DM, with no added signature, footer, blocks, or attribution metadata. Only send when the user authorized the content and destination. Do not retry blindly after an uncertain result.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Exact message body. Use Slack mrkdwn (*bold*, _italic_) unless mrkdwn is false. Never append a signature or attribution. | |
| parse | No | none | |
| mrkdwn | No | ||
| channel | Yes | Slack conversation ID. Resolve the intended channel or DM before sending. | |
| thread_ts | No | Slack message timestamp, kept as a string. | |
| unfurl_links | No | ||
| unfurl_media | No | ||
| reply_broadcast | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond annotations by specifying that nothing is appended (no signature, footer, blocks, or attribution), that user authorization is a precondition, and that retries after uncertain outcomes are dangerous — context the idempotentHint=false flag only hints at. These are the exact failure modes for a messaging tool.
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, front-loaded with the core action, followed by authorization and retry constraints. No filler or restatement of the tool name.
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?
The auth/retry guidance is valuable, but with no output schema the description never says what is returned (e.g., the message ts needed for threading or permalinks), and it leaves six of eight parameters undocumented. Adequate for a safe send, incomplete for correct invocation of threading and formatting options.
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 only 38%: thread_ts, mrkdwn, parse, unfurl_links, unfurl_media, and reply_broadcast have no documentation in either the schema or description. The description clarifies the 'text' semantics (exact body, no blocks) but leaves half the parameters, including threading and link unfurling, unexplained.
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 ('Send the exact supplied message body to an authorized Slack channel or DM') with clear scope that separates it from read/search siblings. It never names slack_edit_message, so an agent must infer that this tool creates new messages rather than modifying existing ones.
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 explicit gating conditions — only send when the user authorized content and destination — plus a caution against blind retries after an uncertain result. It does not name alternatives (e.g., use slack_edit_message to revise an already-sent message), which would have taken this to a 5.
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.
11 tool updates
v1.0.0- First observed
slack_add_reaction - First observed
slack_auth_test - First observed
slack_edit_message - First observed
slack_get_permalink - First observed
slack_list_conversations - First observed
slack_list_users - First observed
slack_open_dm - First observed
slack_read_channel - First observed
slack_read_thread - First observed
slack_search_messages - First observed
slack_send_message
TDQS
Scored across 11 tools
Tools mostly target distinct resources/actions (list vs read vs send vs search vs edit). The only mild overlaps are slack_read_channel vs slack_read_thread and slack_open_dm vs slack_send_message, but descriptions clearly differentiate them (history vs thread replies, and opening vs sending).
All tools use a consistent slack_ prefix and follow verb_noun ordering (list_conversations, read_channel, send_message). The only minor deviation is slack_auth_test, where the noun/verb order is inverted, but it remains readable.
Eleven tools is well within the 3-15 sweet spot for a Slack messaging surface. Each tool covers a distinct operation (auth, list, read, search, send, edit, react, permalink, open DM) without redundancy.
Core read/write workflows (list, read, search, send, edit, react, permalink, open DM) are covered. Minor gaps remain: no delete/remove message, no documented way to send a thread reply (thread_ts not exposed), and no file upload support.
Maintenance
Related MCP Connectors
Hosted Slack MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
One MCP server for all your work accounts: Slack, Teams, Google Chat chats and Jira/ClickUp tickets.
71MCP server that lets your AI assistant build and deploy apps, hosting each one at a live URL.
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA read-only MCP server that enables AI assistants to access Slack workspace data, including channels, messages, threads, and user information.49,032 npm3MIT
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol (MCP) server for Slack workspace integration. This server allows AI assistants to interact directly with your Slack workspace, providing tools to manage channels, send messages, list users, and upload files.49,032 npm1MIT
- FlicenseNot gradedqualityDmaintenanceA Slack MCP server that gives AI assistants tools to read, search, and interact with Slack workspaces.-
- AlicenseAqualityCmaintenanceAn MCP server that enables AI agents to read and write Slack messages as the user, not as a bot, using Slack user tokens for authentic actions across multiple workspaces.101MIT