slack_search_messages
Search Slack messages using filters like keywords, users, channels, or dates to find specific conversations and information efficiently.
Instructions
Search for messages with specific criteria/filters. Use this when: 1) You need to find messages from a specific user, 2) You need messages from a specific date range, 3) You need to search by keywords, 4) You want to filter by channel. This tool is optimized for targeted searches. For general channel browsing without filters, use slack_get_channel_history instead.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Basic search query text only. Use this tool when you need to: search by keywords, filter by user/date/channel, find specific messages with criteria. For general channel browsing without filters, use slack_get_channel_history instead. Do NOT include modifiers like "from:", "in:", etc. - use the dedicated fields instead. | |
| in_channel | No | Search within a specific channel. Must be a Slack channel ID (e.g., "C1234567"). Use slack_list_channels to find channel IDs first. | |
| from_user | No | Search for messages from a specific user. IMPORTANT: You cannot use display names or usernames directly. First use slack_get_users to find the user by name and get their user ID (e.g., "U1234567"), then use that ID here. | |
| before | No | Search for messages before this date (YYYY-MM-DD) | |
| after | No | Search for messages after this date (YYYY-MM-DD) | |
| on | No | Search for messages on this specific date (YYYY-MM-DD) | |
| during | No | Search for messages during a specific time period (e.g., "July", "2023", "last week") | |
| highlight | No | Enable highlighting of search results | |
| sort | No | Search result sort method (score or timestamp) | score |
| sort_dir | No | Sort direction (ascending or descending) | desc |
| count | No | Number of results per page (max 100) | |
| page | No | Page number of results (max 100) |
Implementation Reference
- src/index.ts:347-439 (handler)Handler implementation for the 'slack_search_messages' tool. Parses input parameters, constructs a Slack search query incorporating channel, user, and date filters, calls the Slack search.messages API using the user token, applies optional safe search filtering to exclude private channels/DMs, parses the response, and returns the JSON stringified result.case 'slack_search_messages': { const parsedParams = SearchMessagesRequestSchema.parse( request.params.arguments ); let query = parsedParams.query || ''; if (parsedParams.in_channel) { // Resolve channel name from ID const channelInfo = await slackClient.conversations.info({ channel: parsedParams.in_channel, }); if (!channelInfo.ok || !channelInfo.channel?.name) { throw new Error( `Failed to get channel info: ${channelInfo.error}` ); } query += ` in:${channelInfo.channel.name}`; } // Handle from_user - always use user ID format if (parsedParams.from_user) { query += ` from:<@${parsedParams.from_user}>`; } // Date modifiers if (parsedParams.before) { query += ` before:${parsedParams.before}`; } if (parsedParams.after) { query += ` after:${parsedParams.after}`; } if (parsedParams.on) { query += ` on:${parsedParams.on}`; } if (parsedParams.during) { query += ` during:${parsedParams.during}`; } // Trim and log the final query for debugging query = query.trim(); console.log('Search query:', query); const response = await userClient.search.messages({ query: query, highlight: parsedParams.highlight, sort: parsedParams.sort, sort_dir: parsedParams.sort_dir, count: parsedParams.count, page: parsedParams.page, }); if (!response.ok) { throw new Error(`Failed to search messages: ${response.error}`); } // Apply safe search filtering if enabled (before parsing) if (safeSearchMode && response.messages?.matches) { const originalCount = response.messages.matches.length; response.messages.matches = response.messages.matches.filter( (msg: { channel?: { is_private?: boolean; is_im?: boolean; is_mpim?: boolean; }; }) => { // Exclude private channels, DMs, and multi-party DMs const channel = msg.channel; if (!channel) return true; // Keep if no channel info return !( channel.is_private || channel.is_im || channel.is_mpim ); } ); const filteredCount = originalCount - response.messages.matches.length; if (filteredCount > 0) { console.error( `Safe search: Filtered out ${filteredCount} messages from private channels/DMs` ); } } const parsed = SearchMessagesResponseSchema.parse(response); return { content: [{ type: 'text', text: JSON.stringify(parsed) }], }; }
- src/index.ts:158-163 (registration)Registration of the 'slack_search_messages' tool in the MCP server's listTools response, including name, description, and input schema reference.{ name: 'slack_search_messages', description: 'Search for messages with specific criteria/filters. Use this when: 1) You need to find messages from a specific user, 2) You need messages from a specific date range, 3) You need to search by keywords, 4) You want to filter by channel. This tool is optimized for targeted searches. For general channel browsing without filters, use slack_get_channel_history instead.', inputSchema: zodToJsonSchema(SearchMessagesRequestSchema), },
- src/schemas.ts:261-363 (schema)Zod schema for input validation of the 'slack_search_messages' tool, defining all parameters like query, channel, user, dates, sorting, and pagination with descriptions and constraints.export const SearchMessagesRequestSchema = z.object({ query: z .string() .optional() .default('') .describe( 'Basic search query text only. Use this tool when you need to: search by keywords, filter by user/date/channel, find specific messages with criteria. For general channel browsing without filters, use slack_get_channel_history instead. Do NOT include modifiers like "from:", "in:", etc. - use the dedicated fields instead.' ) .refine( (val) => { if (!val) return true; const modifierPattern = /\b(from|in|before|after|on|during|has|is|with):/i; return !modifierPattern.test(val); }, { message: 'Query field cannot contain modifiers (from:, in:, before:, etc.). Please use the dedicated fields for these filters.', } ), in_channel: z .string() .regex(/^C[A-Z0-9]+$/, { message: 'Must be a valid Slack channel ID (e.g., "C1234567")', }) .optional() .describe( 'Search within a specific channel. Must be a Slack channel ID (e.g., "C1234567"). Use slack_list_channels to find channel IDs first.' ), from_user: z .string() .regex(/^U[A-Z0-9]+$/, { message: 'Must be a valid Slack user ID (e.g., "U1234567")', }) .optional() .describe( 'Search for messages from a specific user. IMPORTANT: You cannot use display names or usernames directly. First use slack_get_users to find the user by name and get their user ID (e.g., "U1234567"), then use that ID here.' ), // Date modifiers before: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/, { message: 'Date must be in YYYY-MM-DD format', }) .optional() .describe('Search for messages before this date (YYYY-MM-DD)'), after: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/, { message: 'Date must be in YYYY-MM-DD format', }) .optional() .describe('Search for messages after this date (YYYY-MM-DD)'), on: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/, { message: 'Date must be in YYYY-MM-DD format', }) .optional() .describe('Search for messages on this specific date (YYYY-MM-DD)'), during: z .string() .optional() .describe( 'Search for messages during a specific time period (e.g., "July", "2023", "last week")' ), highlight: z .boolean() .optional() .default(false) .describe('Enable highlighting of search results'), sort: z .enum(['score', 'timestamp']) .optional() .default('score') .describe('Search result sort method (score or timestamp)'), sort_dir: z .enum(['asc', 'desc']) .optional() .default('desc') .describe('Sort direction (ascending or descending)'), count: z .number() .int() .min(1) .max(100) .optional() .default(20) .describe('Number of results per page (max 100)'), page: z .number() .int() .min(1) .max(100) .optional() .default(1) .describe('Page number of results (max 100)'), });
- src/schemas.ts:420-427 (schema)Zod schema for output validation/parsing of the 'slack_search_messages' tool response from Slack API.export const SearchMessagesResponseSchema = BaseResponseSchema.extend({ messages: z .object({ matches: z.array(SearchMessageSchema).optional(), pagination: SearchPaginationSchema.optional(), }) .optional(), });