create-draft
Save messages as drafts in Zulip for later editing or sending, supporting both stream channels and private conversations with proper user/channel ID configuration.
Instructions
š CREATE DRAFT: Save a message as draft for later editing or sending. For user IDs in the 'to' field, use search-users or get-users tool to discover available users and their IDs.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Draft message type: 'stream' for channels, 'private' for direct messages | |
| to | Yes | Array of user IDs for private messages, or single channel ID for stream messages | |
| topic | Yes | Topic for stream messages (required even for private messages in API) | |
| content | Yes | Draft message content with Markdown formatting | |
| timestamp | No | Unix timestamp for draft creation (optional, defaults to current time) |
Implementation Reference
- src/server.ts:688-710 (registration)Registers the MCP tool 'create-draft' with description, input schema (CreateDraftSchema), and handler function that delegates to ZulipClient.createDraft and formats MCP response.server.tool( "create-draft", "š CREATE DRAFT: Save a message as draft for later editing or sending. For user IDs in the 'to' field, use search-users or get-users tool to discover available users and their IDs.", CreateDraftSchema.shape, async ({ type, to, topic, content, timestamp }) => { try { const result = await zulipClient.createDraft({ type, to, topic, content, timestamp }); return createSuccessResponse(JSON.stringify({ success: true, draft_ids: result.ids, message: `Draft created successfully! IDs: ${result.ids.join(', ')}` }, null, 2)); } catch (error) { return createErrorResponse(`Error creating draft: ${error instanceof Error ? error.message : 'Unknown error'}`); } } );
- src/types.ts:169-175 (schema)Zod schema defining input parameters for the create-draft tool, used for validation in MCP server.tool registration.export const CreateDraftSchema = z.object({ type: z.enum(["stream", "private"]).describe("Draft message type: 'stream' for channels, 'private' for direct messages"), to: z.array(z.number()).describe("Array of user IDs for private messages, or single channel ID for stream messages"), topic: z.string().describe("Topic for stream messages (required even for private messages in API)"), content: z.string().describe("Draft message content with Markdown formatting"), timestamp: z.number().optional().describe("Unix timestamp for draft creation (optional, defaults to current time)") });
- src/zulip/client.ts:464-497 (helper)ZulipClient.createDraft method: core implementation that constructs the draft payload and makes the POST /drafts API call to Zulip server.async createDraft(params: { type: 'stream' | 'private'; to: number[]; topic: string; content: string; timestamp?: number; }): Promise<{ ids: number[] }> { const draftObject: any = { type: params.type, to: params.to, topic: params.topic, content: params.content }; // Only include timestamp if provided, otherwise let server set it if (params.timestamp !== undefined) { draftObject.timestamp = params.timestamp; } const payload = [draftObject]; const response = await this.client.post('/drafts', {}, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, transformRequest: [() => { const params = new URLSearchParams(); params.append('drafts', JSON.stringify(payload)); return params.toString(); }] }); return response.data; }