Static source inference · medium confidence · detected: Logging
Deprecated protocol patterns detected
Summary
14 tools with consistent naming patterns and documented input schemas. Descriptions are present but brief (avg ~90 chars, below production baseline of 194). All parameters have type definitions and basic descriptions, but lack detailed constraints, enums, and usage guidance. Output schemas are not documented. Error handling is minimal, no recovery guidance, retryability classification, or actionable error messages visible. No input validation details provided. Tool composition is reasonable (single responsibility) but lacks chaining metadata in responses. Security basics present (token via env var) but no explicit permission gates, audit trails, or scope declarations documented in tool definitions.
Descriptions too brief and lack LLM-optimized guidance. Average 90 chars vs production baseline 194 chars. Examples: 'Get information about a Slack channel' (44 chars) provides no context on when to call this vs similar tools or what fields are returned.
Output schemas are not documented. LLMs cannot infer what fields are returned, preventing proper chaining and forcing extra lookup calls. Pattern baseline: 100% of A+ tools have documented return types.
Expand tool descriptions to 150 - 250 chars, answering: What does it do? When should the LLM call it vs similar tools? What does it return? Example: 'Get detailed info about a Slack channel including topic, member count, and creation date. Call this after searching channels to retrieve full metadata before posting messages. Returns channel_id, name, topic, member_list, created_date.'
Document output schemas for all 14 tools. Include field names, types, and whether fields are always present or conditional. Example for read_channel_messages: 'Returns {messages: [{ts: string, user: string, text: string, thread_ts?: string}], channel_id: string, oldest: string, latest: string}'.
Add input validation guidance to descriptions: 'lookback_hours must be 1 - 744 (31 days); limit must be 1 - 1000' instead of vague 'default: 24'.
Convert comma-separated description values to enum constraints in inputSchema. Change list_my_channels 'types' param to: 'enum': ['public_channel', 'private_channel', 'mpim', 'im'], 'type': 'array'.
Add emoji validation: document that emoji param in add_reaction/remove_reaction must be a valid Slack emoji name without colons (e.g., 'thumbsup', not ':thumbsup:'). Consider a lookup tool or pre-validation.
Add destructiveHint: true and idempotentHint: false to write operations (send_message, add_reaction, remove_reaction, upload_file) to signal LLMs these operations modify state and should not be freely retried.
Implement error handling that returns: {error: string (category: 'not_found'|'permission_denied'|'rate_limited'|'invalid_input'), message: string (actionable guidance), recovery?: string (suggested next step)}. Example: {error: 'not_found', message: 'Channel C12345 not found.', recovery: 'Try list_my_channels() to see available channels.'}.
Spec posture evidence
Inferred effective spec: <=2025-11-25.
Relies on Logging (deprecated) - log to stderr or use OpenTelemetry
No enum constraints on parameters accepting fixed sets of values. Examples: 'types' param in list_my_channels accepts 'comma-separated' values but LLMs cannot parse the description, should be enum: ['public_channel', 'private_channel', 'mpim', 'im'] and allow array input. No constraints on emoji names, message formats, etc.
Parameters lack validation guidance in descriptions. No mention of min/max for numeric fields (lookback_hours, limit, count), no regex patterns for IDs or timestamps, no charset constraints. Pattern baseline: descriptions must state format, range, and allowed values explicitly.
Error handling is not visible in provided code. No recovery guidance, retryability classification, or actionable error messages documented. Pattern requires: 'Error responses must tell the LLM what to do next' and categorize as retryable/user-fixable/fatal.
Tool definitions lack annotations (readOnlyHint, destructiveHint, idempotentHint) that would signal to LLMs which operations are safe to retry and which modify state. send_message, add_reaction, remove_reaction, upload_file should be marked destructiveHint=true.
No permission gates or scope declarations visible. Tools should declare required permissions (read:channels, write:messages, etc.) and enforce least-privilege access per pattern baseline.
Parameters could accept natural identifiers (usernames, email) alongside system IDs but do not. Example: get_user_info accepts only 'user_id' but should also accept 'email' or 'username' to match chat data model where users reference each other by name, not opaque IDs.
No result limits enforced in list tools. list_my_channels and list_user_groups could return hundreds of items, exhausting context. Pattern requires capping results at 20-50 and offering pagination. No pagination parameters visible.
list_my_channelslist_user_groups
Add dry-run parameter to send_message, add_reaction, remove_reaction, and upload_file: 'dry_run': {type: 'boolean', description: 'If true, validate without executing. Useful for confirmation flows.'}.
Document pagination for list tools. Add 'limit' and 'cursor' params to list_my_channels and list_user_groups. Responses should include 'total_count' and 'next_cursor' to enable pagination.
Extend get_user_info to accept alternative identifiers: Add optional params user_email and user_name. Internally resolve to user_id before calling Slack API. Update description: 'Get user info by ID, email, or display name. Returns user_id, name, email, real_name, avatar_url, status, profile.'.
Add permission scope declarations in descriptions. Example for send_message: 'Requires chat:write scope. Verify sender has write access to the target channel before calling.'
Add audit logging notes in docstrings for sensitive tools (send_message, upload_file). Example: 'This operation is logged with sender ID, timestamp, and recipient.'
Document idempotency. Example: send_message with the same channel_id, text, and thread_ts called twice should create only one message. Add 'idempotent_key' param to enforce this.