Refactor MCP resources to tools, add chat deletion
This commit implements two main changes based on your feedback:
1. Refactors all Model Context Protocol (MCP) resources into tools:
- In `whatsappIntegration.js`:
- `whatsapp.chat` (resource) -> `whatsapp.list-chats` (tool) & `whatsapp.get-chat-details` (tool)
- `whatsapp.contact` (resource) -> `whatsapp.get-contact-details` (tool)
- `whatsapp.blocklist` (resource) -> `whatsapp.get-blocklist` (tool)
- In `conversationIntegration.js`:
- `conversation` (resource) -> `conversation.list-conversations` (tool) & `conversation.get-conversation-details` (tool)
This change aligns with current Gemini SDK capabilities for MCP.
2. Implements chat deletion functionality:
- In `whatsapp-router`:
- Added `deleteChat` function to `whatsappClient.ts`. This function calls an assumed OpenWA endpoint (`POST /deleteChat`) and will require verification against the actual OpenWA API.
- Added a `DELETE /chats/:chatId` route to `whatsappActions.ts` that utilizes the new `deleteChat` client function.
- In `conversation-layer-mcp`:
- Added a new `whatsapp.delete-chat` tool to `whatsappIntegration.js`. This tool calls the new `DELETE /chats/:chatId` endpoint in `whatsapp-router`.
Additionally, the existing `conversation.delete` MCP tool was verified to be correctly implemented.
This commit is contained in:
211
mcp/modules/whatsappIntegration.js
Normal file
211
mcp/modules/whatsappIntegration.js
Normal file
@@ -0,0 +1,211 @@
|
||||
// mcp/modules/whatsappIntegration.js
|
||||
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { z } from "zod";
|
||||
import { fetchJSON } from "../lib/api.js";
|
||||
|
||||
const log = (...args) => console.log("[MCP WhatsAppIntegration]", ...args); // Changed log prefix
|
||||
|
||||
export default function registerWhatsappIntegration(server) {
|
||||
// --- WhatsApp Actions ---
|
||||
|
||||
// Tool: whatsapp.send-text
|
||||
server.tool(
|
||||
"whatsapp.send-text",
|
||||
"Sends a text message via WhatsApp.",
|
||||
{
|
||||
to: z.string().describe("Recipient ID (e.g., 1234567890@c.us)"),
|
||||
content: z.string().describe("Text message content"),
|
||||
},
|
||||
async (params) => {
|
||||
log("Tool invoked", "whatsapp.send-text", params);
|
||||
const result = await fetchJSON("/send-text", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
// Tool: whatsapp.send-image
|
||||
server.tool(
|
||||
"whatsapp.send-image",
|
||||
"Sends an image message via WhatsApp.",
|
||||
{
|
||||
to: z.string().describe("Recipient ID"),
|
||||
path: z.string().describe("Path or URL to the image"),
|
||||
caption: z.string().optional().describe("Image caption"),
|
||||
},
|
||||
async (params) => {
|
||||
log("Tool invoked", "whatsapp.send-image", params);
|
||||
const result = await fetchJSON("/send-image", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
// Tool: whatsapp.send-file
|
||||
server.tool(
|
||||
"whatsapp.send-file",
|
||||
"Sends a file message via WhatsApp.",
|
||||
{
|
||||
to: z.string().describe("Recipient ID"),
|
||||
path: z.string().describe("Path or URL to the file"),
|
||||
filename: z.string().optional().describe("Name of the file"),
|
||||
caption: z.string().optional().describe("File caption"),
|
||||
},
|
||||
async (params) => {
|
||||
log("Tool invoked", "whatsapp.send-file", params);
|
||||
const result = await fetchJSON("/send-file", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
// Tool: whatsapp.list-chats
|
||||
server.tool(
|
||||
"whatsapp.list-chats",
|
||||
"Retrieves a list of all chats.",
|
||||
{}, // No input parameters
|
||||
async () => {
|
||||
log("Tool invoked", "whatsapp.list-chats");
|
||||
const result = await fetchJSON("/chats");
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
// Tool: whatsapp.get-chat-details
|
||||
server.tool(
|
||||
"whatsapp.get-chat-details",
|
||||
"Retrieves details for a specific chat by its ID.",
|
||||
{
|
||||
chatId: z.string().describe("ID of the chat (e.g., 1234567890@c.us)"),
|
||||
},
|
||||
async (params) => {
|
||||
log("Tool invoked", "whatsapp.get-chat-details", params);
|
||||
const result = await fetchJSON(`/chats/${params.chatId}`);
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
// Tool: whatsapp.get-chat-messages
|
||||
server.tool(
|
||||
"whatsapp.get-chat-messages",
|
||||
"Retrieves messages for a specific chat.",
|
||||
{
|
||||
chatId: z.string().describe("ID of the chat"),
|
||||
limit: z.number().optional().describe("Number of messages to retrieve"),
|
||||
includeMe: z.boolean().optional().describe("Include messages sent by me"),
|
||||
includeNotifications: z.boolean().optional().describe("Include notification messages"),
|
||||
},
|
||||
async ({ chatId, ...queryParams}) => {
|
||||
log("Tool invoked", "whatsapp.get-chat-messages", { chatId, queryParams });
|
||||
const qs = new URLSearchParams(
|
||||
Object.entries(queryParams)
|
||||
.filter(([, v]) => v !== undefined)
|
||||
.map(([k, v]) => [k, String(v)])
|
||||
);
|
||||
const result = await fetchJSON(`/chats/${chatId}/messages?${qs.toString()}`);
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
server.tool(
|
||||
"whatsapp.delete-chat",
|
||||
"Deletes a chat by its ID. (Note: The underlying OpenWA endpoint for this is assumed and might need verification)",
|
||||
{
|
||||
chatId: z.string().describe("ID of the chat to delete (e.g., 1234567890@c.us)"),
|
||||
},
|
||||
async (params) => {
|
||||
log("Tool invoked", "whatsapp.delete-chat", params);
|
||||
const result = await fetchJSON(`/chats/${params.chatId}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
// Consider what a successful deletion should return.
|
||||
// OpenWA might return a success message or just a 200/204.
|
||||
// For now, we'll return the full result.
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
// Tool: whatsapp.create-group
|
||||
server.tool(
|
||||
"whatsapp.create-group",
|
||||
"Creates a new WhatsApp group.",
|
||||
{
|
||||
groupName: z.string().describe("Name of the group"),
|
||||
contactIds: z.array(z.string()).describe("Array of contact IDs to add to the group"),
|
||||
},
|
||||
async (params) => {
|
||||
log("Tool invoked", "whatsapp.create-group", params);
|
||||
const result = await fetchJSON("/groups", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
// Tool: whatsapp.get-contact-details
|
||||
server.tool(
|
||||
"whatsapp.get-contact-details",
|
||||
"Retrieves details for a specific contact by ID.",
|
||||
{
|
||||
contactId: z.string().describe("ID of the contact (e.g., 1234567890@c.us)"),
|
||||
},
|
||||
async (params) => {
|
||||
log("Tool invoked", "whatsapp.get-contact-details", params);
|
||||
const result = await fetchJSON(`/contacts/${params.contactId}`);
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
// Tool: whatsapp.get-blocklist
|
||||
server.tool(
|
||||
"whatsapp.get-blocklist",
|
||||
"Retrieves the blocklist.",
|
||||
{}, // No input parameters
|
||||
async () => {
|
||||
log("Tool invoked", "whatsapp.get-blocklist");
|
||||
const result = await fetchJSON("/blocklist");
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
// Tool: whatsapp.block-contact
|
||||
server.tool(
|
||||
"whatsapp.block-contact",
|
||||
"Blocks a contact on WhatsApp.",
|
||||
{
|
||||
contactId: z.string().describe("ID of the contact to block"),
|
||||
},
|
||||
async (params) => {
|
||||
log("Tool invoked", "whatsapp.block-contact", params);
|
||||
const result = await fetchJSON("/blocklist/block", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
|
||||
// Tool: whatsapp.unblock-contact
|
||||
server.tool(
|
||||
"whatsapp.unblock-contact",
|
||||
"Unblocks a contact on WhatsApp.",
|
||||
{
|
||||
contactId: z.string().describe("ID of the contact to unblock"),
|
||||
},
|
||||
async (params) => {
|
||||
log("Tool invoked", "whatsapp.unblock-contact", params);
|
||||
const result = await fetchJSON("/blocklist/unblock", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
}
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user