send_interactive_message
Send WhatsApp messages with interactive buttons or selection lists to engage recipients and collect responses through structured options.
Instructions
Send an interactive message with buttons or a selection list.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Recipient phone number | |
| interactive_type | Yes | Type of interactive message | |
| body_text | Yes | Main body text of the message | |
| buttons | No | Buttons array (max 3) for button type. Each needs id and title. | |
| sections | No | Sections for list type. Each section has title and rows. | |
| header_text | No | Header text | |
| footer_text | No | Footer text | |
| button_text | No | Button label for list type | Menu |
Implementation Reference
- src/whatsapp-client.ts:161-177 (handler)The core implementation of the interactive message logic, performing the actual API request.
async sendInteractiveMessage( to: string, interactiveType: "button" | "list", interactive: { header?: unknown; body: { text: string }; footer?: { text: string }; action: unknown; } ) { return this.request(`/${this.config.phoneNumberId}/messages`, "POST", { messaging_product: "whatsapp", to, type: "interactive", interactive: { type: interactiveType, ...interactive }, }); } - src/index.ts:188-230 (registration)The MCP tool definition and registration for "send_interactive_message", which validates input parameters and calls the WhatsApp client handler.
server.tool( "send_interactive_message", "Send an interactive message with buttons or a selection list.", { to: z.string().describe("Recipient phone number"), interactive_type: z.enum(["button", "list"]).describe("Type of interactive message"), body_text: z.string().describe("Main body text of the message"), buttons: z .array(z.object({ id: z.string(), title: z.string() })) .optional() .describe("Buttons array (max 3) for button type. Each needs id and title."), sections: z .array( z.object({ title: z.string(), rows: z.array(z.object({ id: z.string(), title: z.string(), description: z.string().optional() })), }) ) .optional() .describe("Sections for list type. Each section has title and rows."), header_text: z.string().optional().describe("Header text"), footer_text: z.string().optional().describe("Footer text"), button_text: z.string().optional().default("Menu").describe("Button label for list type"), }, async ({ to, interactive_type, body_text, buttons, sections, header_text, footer_text, button_text }) => { const action: Record<string, unknown> = interactive_type === "button" ? { buttons: (buttons || []).map((b) => ({ type: "reply", reply: b })) } : { button: button_text, sections: sections || [] }; return executeWithHooks( "send_interactive_message", { to, interactive_type, body_text }, config, () => wa.sendInteractiveMessage(to, interactive_type, { ...(header_text ? { header: { type: "text", text: header_text } } : {}), body: { text: body_text }, ...(footer_text ? { footer: { text: footer_text } } : {}), action, }) ); }