Slack MCP server for Claude Code ↔ User communication via Slack channels, enabling multi-agent team coordination with approval workflows, task tracking, and background message polling.
This server has 26 tools with significant quality gaps. Descriptions are present but often translated (Korean text), lack clarity about WHEN to use each tool vs alternatives, and many lack actionable error guidance. Parameter schemas are present but lack proper constraints (enums, ranges, min/max). Output schemas are not documented. Critical issue: many tools are stateful operations (loops, polling, waiting) without confirmation patterns or clear idempotence documentation. The codebase is complex with team-management and approval flows, but the tool interface is not optimized for LLM composition. Tools like slack_command_loop and slack_wait_for_reply are blocking operations that could cause context starvation. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite many irreversible operations (team_close, delete operations implied). Parameter naming is inconsistent: some use channel_id, others use channel; some use thread_ts, others use different conventions. The server file references index.old.ts, suggesting the actual implementation may differ.
Blocking polling operations (slack_wait_for_reply, slack_command_loop, slack_team_wait) lack timeout documentation and can exhaust context or hang agents. No confirmation/dry-run pattern for irreversible operations.
Descriptions are translated to Korean and often lack WHEN to use the tool. For example, 'slack_send_message' and 'slack_reply_thread' both send messages but descriptions do not clarify the distinction or when to prefer one over the other.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). slack_team_close and slack_team_report are destructive/state-modifying but lack explicit destructiveHint annotation. Agents cannot infer safety from schema alone.
Translate all descriptions to English and rewrite to be LLM-optimized. For each tool, answer: WHAT does it do? WHEN should I call it instead of similar tools? WHAT do I get back? Example: 'slack_send_message sends a new message to a channel; use slack_reply_thread to respond within an existing thread. Returns message timestamp for later reference.'
Add output schema documentation for all tools. For read tools, document the field structure, example response, and pagination (if applicable). Example: 'Returns: {messages: [{ts, user, text, thread_ts}, ...], has_more: boolean, cursor: string}'
Add tool annotations. Mark all read-only tools with readOnlyHint. Mark slack_team_close, slack_team_report, slack_send_message as destructiveHint. Mark idempotent tools (those safe to retry) with idempotentHint.
Convert free-form string parameters to enums where options are known. Add to slack_send_code: language enum (bash, rust, typescript, python, javascript, etc.). Add to slack_team_register: role enum (leader, member, specialist). Add to slack_team_report: status enum (in_progress, completed, blocked, on_hold).
Standardize parameter naming across all tools. Use channel_id and thread_ts consistently. If both ID and name are valid, provide separate parameters (channel_id, channel_name) to avoid type confusion.
Add error handling documentation. For each tool, document: what errors can occur (not found, permission denied, timeout), how to identify them, and what to do next. Example: 'If channel not found, try slack_list_channels() to find the correct channel name.'
Parameter schemas lack enums and constraints. 'language' in slack_send_code should be an enum (bash, rust, typescript, etc.). 'role' in slack_team_register should be an enum (leader, member, specialist, etc.). Free-form strings invite hallucinated values.
Output schemas are not documented. Tools like slack_read_messages, slack_get_thread, slack_team_read do not declare what fields they return (structure, field types, pagination). LLMs cannot plan downstream tool calls without knowing response structure.
Parameter naming inconsistency: some tools use 'channel', others use 'channel_id'; some use 'thread_ts', others may use different names. This forces LLMs to reason about field mappings and increases tool misuse.
slack_save_state and slack_load_state have empty or minimal input/output schemas. This makes it unclear what state is persisted, when to call these tools, and what they return.
Many tools accept optional parameters (thread_ts, title, blocks, options) but lack guidance on when they are required vs optional. Descriptions do not explain dependencies or mutual exclusivity.
No error handling documentation. Tools do not describe what errors they return or how agents should recover (retry, lookup, ask user). E.g., what happens if a channel is not found or user lacks permissions?
slack_request_approval has a complex input schema (title, description, team_id, sender, options, channel, timeout_seconds, poll_interval_seconds) but lacks clear guidance on which parameters are required for different scenarios (simple approval vs multi-choice).
slack_request_approval
Implement confirmation pattern for irreversible operations. slack_team_close should require explicit confirmation or a dry_run preview before archiving. Add a 'confirm=true' parameter that must be set to proceed.
Document state management tools (slack_save_state, slack_load_state) with clear input/output schemas. What state is saved? When should it be called? What fields are restored?
Add pagination support and limits to list/read tools. Document: 'Returns up to 50 messages by default. Use limit parameter (1-100) and cursor from previous response for pagination.'
Clarify parameter dependencies in descriptions. For slack_request_approval, specify: 'If options is omitted, agent defaults to approval/rejection only. If team_id and sender are provided, the approval is posted to the team channel; otherwise, the main channel.'
For blocking operations (slack_wait_for_reply, slack_command_loop), document timeout behavior and add explicit guidance: 'This tool blocks until a reply is received or timeout_seconds elapses. Use with timeout_seconds <= 300 to avoid context starvation. If the agent needs to continue other work, consider using slack_check_inbox instead.'
Create a discovery tool or documentation that lists all available channels, team_ids, and their metadata. Agents should not have to guess IDs. Example: 'Call slack_list_channels() first to get a list of channel_ids and channel_names.'
Batch operations where agents often iterate. Instead of separate add_label calls in a loop, offer slack_send_message_batch for sending multiple messages at once.
Document which tools are idempotent (safe to retry) and which are not. Mark non-idempotent tools clearly to prevent duplicate messages, duplicate team creation, etc.