get-messages
Retrieve Zulip messages in bulk with filtering, pagination, and search to browse conversations, find content, or access message history.
Instructions
📋 BULK RETRIEVAL: Get multiple messages with filtering, pagination, and search. Use this to browse conversations, search for content, or get message history. Returns array of messages with basic details.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| anchor | No | Starting point: message ID, 'newest', 'oldest', or 'first_unread' | |
| num_before | No | Number of messages before anchor (max 1000) | |
| num_after | No | Number of messages after anchor (max 1000) | |
| narrow | No | Filters: [['stream', 'channel-name'], ['topic', 'topic-name'], ['sender', 'email'], ['search', 'query']] | |
| message_id | No | Get specific message by ID instead of using anchor/num parameters |
Implementation Reference
- src/server.ts:434-460 (handler)The main handler function for the 'get-messages' tool. It invokes the ZulipClient.getMessages method with provided parameters, processes the response by mapping message fields and formatting timestamps, and returns a JSON-formatted success response or an error response.
async ({ anchor, num_before, num_after, narrow, message_id }) => { try { const result = await zulipClient.getMessages({ anchor, num_before, num_after, narrow, message_id }); return createSuccessResponse(JSON.stringify({ message_count: result.messages.length, messages: result.messages.map(msg => ({ id: msg.id, sender: msg.sender_full_name, timestamp: new Date(msg.timestamp * 1000).toISOString(), content: msg.content, type: msg.type, topic: msg.topic || msg.subject, stream_id: msg.stream_id, reactions: msg.reactions })) }, null, 2)); } catch (error) { return createErrorResponse(`Error retrieving messages: ${error instanceof Error ? error.message : 'Unknown error'}`); } } - src/types.ts:120-126 (schema)Zod schema defining the input validation for the 'get-messages' tool parameters including anchor, pagination options (num_before, num_after), filtering (narrow), and single message retrieval (message_id).
export const GetMessagesSchema = z.object({ anchor: z.union([z.number(), z.enum(["newest", "oldest", "first_unread"])]).optional().describe("Starting point: message ID, 'newest', 'oldest', or 'first_unread'"), num_before: z.number().max(1000).optional().describe("Number of messages before anchor (max 1000)"), num_after: z.number().max(1000).optional().describe("Number of messages after anchor (max 1000)"), narrow: z.array(z.array(z.string())).optional().describe("Filters: [['stream', 'channel-name'], ['topic', 'topic-name'], ['sender', 'email'], ['search', 'query']]"), message_id: z.number().optional().describe("Get specific message by ID instead of using anchor/num parameters") }); - src/server.ts:430-461 (registration)MCP tool registration using server.tool(), including the tool name 'get-messages', description, input schema, and handler function.
server.tool( "get-messages", "📋 BULK RETRIEVAL: Get multiple messages with filtering, pagination, and search. Use this to browse conversations, search for content, or get message history. Returns array of messages with basic details.", GetMessagesSchema.shape, async ({ anchor, num_before, num_after, narrow, message_id }) => { try { const result = await zulipClient.getMessages({ anchor, num_before, num_after, narrow, message_id }); return createSuccessResponse(JSON.stringify({ message_count: result.messages.length, messages: result.messages.map(msg => ({ id: msg.id, sender: msg.sender_full_name, timestamp: new Date(msg.timestamp * 1000).toISOString(), content: msg.content, type: msg.type, topic: msg.topic || msg.subject, stream_id: msg.stream_id, reactions: msg.reactions })) }, null, 2)); } catch (error) { return createErrorResponse(`Error retrieving messages: ${error instanceof Error ? error.message : 'Unknown error'}`); } } ); - src/zulip/client.ts:157-182 (helper)ZulipClient helper method that handles the actual HTTP API requests to Zulip's /messages endpoint, supporting both bulk retrieval with anchors/narrowing and single message by ID.
async getMessages(params: { anchor?: number | string; num_before?: number; num_after?: number; narrow?: string[][]; message_id?: number; } = {}): Promise<{ messages: ZulipMessage[] }> { if (params.message_id) { const response = await this.client.get(`/messages/${params.message_id}`); return { messages: [response.data.message] }; } const queryParams: any = {}; // Only set parameters that are provided, with appropriate defaults queryParams.anchor = params.anchor !== undefined ? params.anchor : 'newest'; queryParams.num_before = params.num_before !== undefined ? params.num_before : 20; queryParams.num_after = params.num_after !== undefined ? params.num_after : 0; if (params.narrow) { queryParams.narrow = JSON.stringify(params.narrow); } const response = await this.client.get('/messages', { params: queryParams }); return response.data; }