evolution-api-mcp
Version:
MCP Server for Evolution API v2 - Integrate WhatsApp functionality with Claude Desktop and other MCP clients
745 lines (744 loc) • 30.6 kB
JavaScript
"use strict";
/**
* Profile and Webhook Management MCP Tools Implementation
* Implements tools for profile management, privacy settings, webhook configuration, and API information
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProfileWebhookTools = void 0;
const zod_1 = require("zod");
const evolution_http_client_1 = require("../../clients/evolution-http-client");
const profile_endpoints_1 = require("../../registry/endpoints/profile-endpoints");
const webhook_endpoints_1 = require("../../registry/endpoints/webhook-endpoints");
const information_endpoints_1 = require("../../registry/endpoints/information-endpoints");
/**
* Profile and Webhook Management tool implementations
*/
class ProfileWebhookTools {
constructor(httpClient) {
this.httpClient = httpClient;
}
// ===== PROFILE MANAGEMENT TOOLS =====
/**
* Fetch profile information
*/
createFetchProfileTool() {
const endpoint = profile_endpoints_1.profileEndpoints.find(e => e.name === 'fetch-profile');
return {
name: 'evolution_fetch_profile',
description: 'Fetch profile information for a WhatsApp instance',
controller: 'profile',
endpoint,
schema: zod_1.z.object({
instance: zod_1.z.string()
.min(1, 'Instance name is required')
.describe('Name of the WhatsApp instance'),
number: zod_1.z.string()
.optional()
.describe('Phone number to fetch profile for (optional, defaults to instance owner)')
}),
handler: this.fetchProfileHandler.bind(this),
examples: {
usage: 'Fetch profile information for the instance or a specific number',
parameters: {
instance: 'my_whatsapp_bot',
number: '5511999999999'
}
}
};
}
async fetchProfileHandler(params) {
try {
const requestData = params.number ? { number: params.number } : {};
const response = await this.httpClient.post(`/chat/fetchProfile/${params.instance}`, requestData);
if (!response.success) {
return this.handleApiError(response.error, 'fetch profile');
}
return {
success: true,
data: {
message: `Profile information fetched successfully`,
instance: params.instance,
targetNumber: params.number || 'instance owner',
profile: response.data,
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'fetch profile');
}
}
/**
* Update profile name
*/
createUpdateProfileNameTool() {
const endpoint = profile_endpoints_1.profileEndpoints.find(e => e.name === 'update-profile-name');
return {
name: 'evolution_update_profile_name',
description: 'Update the profile name for a WhatsApp instance',
controller: 'profile',
endpoint,
schema: zod_1.z.object({
instance: zod_1.z.string()
.min(1, 'Instance name is required')
.describe('Name of the WhatsApp instance'),
name: zod_1.z.string()
.min(1, 'Profile name is required')
.max(25, 'Profile name cannot exceed 25 characters')
.describe('New profile name to set')
}),
handler: this.updateProfileNameHandler.bind(this),
examples: {
usage: 'Update the display name for the WhatsApp profile',
parameters: {
instance: 'my_whatsapp_bot',
name: 'My Business Bot'
}
}
};
}
async updateProfileNameHandler(params) {
try {
const requestData = { name: params.name };
const response = await this.httpClient.put(`/chat/updateProfileName/${params.instance}`, requestData);
if (!response.success) {
return this.handleApiError(response.error, 'update profile name');
}
return {
success: true,
data: {
message: `Profile name updated successfully to "${params.name}"`,
instance: params.instance,
newName: params.name,
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'update profile name');
}
}
/**
* Update profile status
*/
createUpdateProfileStatusTool() {
const endpoint = profile_endpoints_1.profileEndpoints.find(e => e.name === 'update-profile-status');
return {
name: 'evolution_update_profile_status',
description: 'Update the profile status message for a WhatsApp instance',
controller: 'profile',
endpoint,
schema: zod_1.z.object({
instance: zod_1.z.string()
.min(1, 'Instance name is required')
.describe('Name of the WhatsApp instance'),
status: zod_1.z.string()
.min(1, 'Profile status is required')
.max(139, 'Profile status cannot exceed 139 characters')
.describe('New profile status message to set')
}),
handler: this.updateProfileStatusHandler.bind(this),
examples: {
usage: 'Update the status message for the WhatsApp profile',
parameters: {
instance: 'my_whatsapp_bot',
status: 'Available for business inquiries 24/7'
}
}
};
}
async updateProfileStatusHandler(params) {
try {
const requestData = { status: params.status };
const response = await this.httpClient.put(`/chat/updateProfileStatus/${params.instance}`, requestData);
if (!response.success) {
return this.handleApiError(response.error, 'update profile status');
}
return {
success: true,
data: {
message: `Profile status updated successfully`,
instance: params.instance,
newStatus: params.status,
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'update profile status');
}
}
/**
* Update profile picture
*/
createUpdateProfilePictureTool() {
const endpoint = profile_endpoints_1.profileEndpoints.find(e => e.name === 'update-profile-picture');
return {
name: 'evolution_update_profile_picture',
description: 'Update the profile picture for a WhatsApp instance',
controller: 'profile',
endpoint,
schema: zod_1.z.object({
instance: zod_1.z.string()
.min(1, 'Instance name is required')
.describe('Name of the WhatsApp instance'),
picture: zod_1.z.string()
.min(1, 'Picture URL or base64 is required')
.describe('Profile picture URL (https://...) or base64 encoded image data')
}),
handler: this.updateProfilePictureHandler.bind(this),
examples: {
usage: 'Update the profile picture for the WhatsApp instance',
parameters: {
instance: 'my_whatsapp_bot',
picture: 'https://example.com/profile-picture.jpg'
}
}
};
}
async updateProfilePictureHandler(params) {
try {
const requestData = { picture: params.picture };
const response = await this.httpClient.put(`/chat/updateProfilePicture/${params.instance}`, requestData);
if (!response.success) {
return this.handleApiError(response.error, 'update profile picture');
}
return {
success: true,
data: {
message: `Profile picture updated successfully`,
instance: params.instance,
pictureSource: params.picture.startsWith('http') ? 'URL' : 'Base64',
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'update profile picture');
}
}
// ===== PRIVACY SETTINGS TOOLS =====
/**
* Fetch privacy settings
*/
createFetchPrivacySettingsTool() {
const endpoint = profile_endpoints_1.profileEndpoints.find(e => e.name === 'fetch-privacy-settings');
return {
name: 'evolution_fetch_privacy_settings',
description: 'Fetch privacy settings for a WhatsApp instance',
controller: 'profile',
endpoint,
schema: zod_1.z.object({
instance: zod_1.z.string()
.min(1, 'Instance name is required')
.describe('Name of the WhatsApp instance')
}),
handler: this.fetchPrivacySettingsHandler.bind(this),
examples: {
usage: 'Get current privacy settings for the WhatsApp instance',
parameters: {
instance: 'my_whatsapp_bot'
}
}
};
}
async fetchPrivacySettingsHandler(params) {
try {
const response = await this.httpClient.get(`/chat/fetchPrivacySettings/${params.instance}`);
if (!response.success) {
return this.handleApiError(response.error, 'fetch privacy settings');
}
return {
success: true,
data: {
message: `Privacy settings fetched successfully`,
instance: params.instance,
privacySettings: response.data,
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'fetch privacy settings');
}
}
/**
* Update privacy settings
*/
createUpdatePrivacySettingsTool() {
const endpoint = profile_endpoints_1.profileEndpoints.find(e => e.name === 'update-privacy-settings');
return {
name: 'evolution_update_privacy_settings',
description: 'Update privacy settings for a WhatsApp instance',
controller: 'profile',
endpoint,
schema: zod_1.z.object({
instance: zod_1.z.string()
.min(1, 'Instance name is required')
.describe('Name of the WhatsApp instance'),
privacySettings: zod_1.z.object({
readreceipts: zod_1.z.enum(['all', 'none']).optional()
.describe('Who can see read receipts'),
profile: zod_1.z.enum(['all', 'contacts', 'contact_blacklist', 'none']).optional()
.describe('Who can see profile photo'),
status: zod_1.z.enum(['all', 'contacts', 'contact_blacklist', 'none']).optional()
.describe('Who can see status updates'),
online: zod_1.z.enum(['all', 'match_last_seen']).optional()
.describe('Who can see online status'),
last: zod_1.z.enum(['all', 'contacts', 'contact_blacklist', 'none']).optional()
.describe('Who can see last seen'),
groupadd: zod_1.z.enum(['all', 'contacts', 'contact_blacklist', 'none']).optional()
.describe('Who can add to groups')
}).describe('Privacy settings to update')
}),
handler: this.updatePrivacySettingsHandler.bind(this),
examples: {
usage: 'Update privacy settings for the WhatsApp instance',
parameters: {
instance: 'my_whatsapp_bot',
privacySettings: {
readreceipts: 'all',
profile: 'contacts',
status: 'contacts',
online: 'all',
last: 'contacts',
groupadd: 'contacts'
}
}
}
};
}
async updatePrivacySettingsHandler(params) {
try {
const requestData = { privacySettings: params.privacySettings };
const response = await this.httpClient.put(`/chat/updatePrivacySettings/${params.instance}`, requestData);
if (!response.success) {
return this.handleApiError(response.error, 'update privacy settings');
}
return {
success: true,
data: {
message: `Privacy settings updated successfully`,
instance: params.instance,
updatedSettings: params.privacySettings,
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'update privacy settings');
}
}
// ===== BUSINESS PROFILE TOOLS =====
/**
* Fetch business profile
*/
createFetchBusinessProfileTool() {
const endpoint = profile_endpoints_1.profileEndpoints.find(e => e.name === 'fetch-business-profile');
return {
name: 'evolution_fetch_business_profile',
description: 'Fetch business profile information for a WhatsApp Business instance',
controller: 'profile',
endpoint,
schema: zod_1.z.object({
instance: zod_1.z.string()
.min(1, 'Instance name is required')
.describe('Name of the WhatsApp Business instance')
}),
handler: this.fetchBusinessProfileHandler.bind(this),
examples: {
usage: 'Get business profile information for a WhatsApp Business account',
parameters: {
instance: 'my_business_bot'
}
}
};
}
async fetchBusinessProfileHandler(params) {
try {
const response = await this.httpClient.get(`/chat/fetchBusinessProfile/${params.instance}`);
if (!response.success) {
return this.handleApiError(response.error, 'fetch business profile');
}
return {
success: true,
data: {
message: `Business profile information fetched successfully`,
instance: params.instance,
businessProfile: response.data,
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'fetch business profile');
}
}
/**
* Update business profile
*/
createUpdateBusinessProfileTool() {
const endpoint = profile_endpoints_1.profileEndpoints.find(e => e.name === 'update-business-profile');
return {
name: 'evolution_update_business_profile',
description: 'Update business profile information for a WhatsApp Business instance',
controller: 'profile',
endpoint,
schema: zod_1.z.object({
instance: zod_1.z.string()
.min(1, 'Instance name is required')
.describe('Name of the WhatsApp Business instance'),
business: zod_1.z.object({
description: zod_1.z.string()
.max(512, 'Business description cannot exceed 512 characters')
.optional()
.describe('Business description'),
category: zod_1.z.string()
.optional()
.describe('Business category'),
email: zod_1.z.string()
.email('Invalid email format')
.optional()
.describe('Business email address'),
website: zod_1.z.array(zod_1.z.string().url('Invalid website URL'))
.max(2, 'Cannot have more than 2 websites')
.optional()
.describe('Business website URLs'),
address: zod_1.z.string()
.max(256, 'Address cannot exceed 256 characters')
.optional()
.describe('Business address')
}).describe('Business profile information to update')
}),
handler: this.updateBusinessProfileHandler.bind(this),
examples: {
usage: 'Update business profile information for a WhatsApp Business account',
parameters: {
instance: 'my_business_bot',
business: {
description: 'We provide excellent customer service and quality products',
category: 'Technology',
email: 'contact@mybusiness.com',
website: ['https://mybusiness.com'],
address: '123 Business Street, City, State'
}
}
}
};
}
async updateBusinessProfileHandler(params) {
try {
const requestData = { business: params.business };
const response = await this.httpClient.put(`/chat/updateBusinessProfile/${params.instance}`, requestData);
if (!response.success) {
return this.handleApiError(response.error, 'update business profile');
}
return {
success: true,
data: {
message: `Business profile updated successfully`,
instance: params.instance,
updatedFields: Object.keys(params.business),
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'update business profile');
}
}
// ===== WEBHOOK MANAGEMENT TOOLS =====
/**
* Set webhook configuration
*/
createSetWebhookTool() {
const endpoint = webhook_endpoints_1.webhookEndpoints.find(e => e.name === 'set-webhook');
return {
name: 'evolution_set_webhook',
description: 'Configure webhook settings for a WhatsApp instance',
controller: 'webhook',
endpoint,
schema: zod_1.z.object({
instance: zod_1.z.string()
.min(1, 'Instance name is required')
.describe('Name of the WhatsApp instance'),
webhook: zod_1.z.object({
url: zod_1.z.string()
.url('Invalid webhook URL format')
.describe('Webhook URL to receive events'),
enabled: zod_1.z.boolean()
.optional()
.default(true)
.describe('Whether the webhook is enabled'),
webhookByEvents: zod_1.z.boolean()
.optional()
.default(true)
.describe('Send webhook by events'),
webhookBase64: zod_1.z.boolean()
.optional()
.default(false)
.describe('Send media in base64 format'),
events: zod_1.z.array(zod_1.z.enum([
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'CONNECTION_UPDATE',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS'
])).optional()
.describe('List of events to send to webhook')
}).describe('Webhook configuration')
}),
handler: this.setWebhookHandler.bind(this),
examples: {
usage: 'Configure webhook to receive WhatsApp events',
parameters: {
instance: 'my_whatsapp_bot',
webhook: {
url: 'https://myserver.com/webhook',
enabled: true,
webhookByEvents: true,
webhookBase64: false,
events: [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'CONNECTION_UPDATE',
'MESSAGES_UPSERT',
'SEND_MESSAGE'
]
}
}
}
};
}
async setWebhookHandler(params) {
try {
// Validate webhook URL format
try {
new URL(params.webhook.url);
}
catch {
return {
success: false,
error: {
type: evolution_http_client_1.ErrorType.VALIDATION_ERROR,
message: 'Invalid webhook URL format. Ensure the URL starts with http:// or https:// and is properly formatted.'
}
};
}
const requestData = { webhook: params.webhook };
const response = await this.httpClient.post(`/webhook/set/${params.instance}`, requestData);
if (!response.success) {
return this.handleApiError(response.error, 'set webhook');
}
return {
success: true,
data: {
message: `Webhook configured successfully for ${params.instance}`,
instance: params.instance,
webhookUrl: params.webhook.url,
enabled: params.webhook.enabled,
eventsCount: params.webhook.events?.length || 0,
selectedEvents: params.webhook.events || [],
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'set webhook');
}
}
/**
* Get webhook configuration
*/
createGetWebhookTool() {
const endpoint = webhook_endpoints_1.webhookEndpoints.find(e => e.name === 'get-webhook');
return {
name: 'evolution_get_webhook',
description: 'Get current webhook configuration for a WhatsApp instance',
controller: 'webhook',
endpoint,
schema: zod_1.z.object({
instance: zod_1.z.string()
.min(1, 'Instance name is required')
.describe('Name of the WhatsApp instance')
}),
handler: this.getWebhookHandler.bind(this),
examples: {
usage: 'Retrieve current webhook settings for an instance',
parameters: {
instance: 'my_whatsapp_bot'
}
}
};
}
async getWebhookHandler(params) {
try {
const response = await this.httpClient.get(`/webhook/find/${params.instance}`);
if (!response.success) {
return this.handleApiError(response.error, 'get webhook');
}
return {
success: true,
data: {
message: `Webhook configuration retrieved successfully`,
instance: params.instance,
webhookConfig: response.data,
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'get webhook');
}
}
// ===== API INFORMATION TOOL =====
/**
* Get Evolution API information
*/
createGetInformationTool() {
const endpoint = information_endpoints_1.informationEndpoints.find(e => e.name === 'get-information');
return {
name: 'evolution_get_information',
description: 'Get Evolution API information including version, status, and available features',
controller: 'information',
endpoint,
schema: zod_1.z.object({
// No parameters required for this endpoint
}),
handler: this.getInformationHandler.bind(this),
examples: {
usage: 'Get Evolution API server information and status',
parameters: {}
}
};
}
async getInformationHandler(params) {
try {
const response = await this.httpClient.get('/get-information');
if (!response.success) {
return this.handleApiError(response.error, 'get API information');
}
return {
success: true,
data: {
message: `Evolution API information retrieved successfully`,
apiInfo: response.data,
result: response.data
}
};
}
catch (error) {
return this.handleUnexpectedError(error, 'get API information');
}
}
// ===== UTILITY METHODS =====
/**
* Get all profile and webhook tools
*/
getAllTools() {
return [
// Profile Management Tools
this.createFetchProfileTool(),
this.createUpdateProfileNameTool(),
this.createUpdateProfileStatusTool(),
this.createUpdateProfilePictureTool(),
// Privacy Settings Tools
this.createFetchPrivacySettingsTool(),
this.createUpdatePrivacySettingsTool(),
// Business Profile Tools
this.createFetchBusinessProfileTool(),
this.createUpdateBusinessProfileTool(),
// Webhook Management Tools
this.createSetWebhookTool(),
this.createGetWebhookTool(),
// API Information Tool
this.createGetInformationTool()
];
}
/**
* Handle API errors with user-friendly messages
*/
handleApiError(error, operation) {
const statusCode = error.statusCode || error.status || 500;
switch (statusCode) {
case 400:
return {
success: false,
error: {
type: evolution_http_client_1.ErrorType.VALIDATION_ERROR,
message: `Invalid request parameters for ${operation}. Check that all required parameters are provided and verify parameter formats.`
}
};
case 401:
return {
success: false,
error: {
type: evolution_http_client_1.ErrorType.AUTHENTICATION_ERROR,
message: `Authentication failed for ${operation}. Check that EVOLUTION_API_KEY is correct and has proper permissions.`
}
};
case 404:
return {
success: false,
error: {
type: evolution_http_client_1.ErrorType.API_ERROR,
message: `Instance not found for ${operation}. Verify the instance name is correct and that it exists.`
}
};
case 422:
return {
success: false,
error: {
type: evolution_http_client_1.ErrorType.VALIDATION_ERROR,
message: `Invalid data provided for ${operation}. Check parameter formats and ensure required fields are provided.`
}
};
case 500:
return {
success: false,
error: {
type: evolution_http_client_1.ErrorType.API_ERROR,
message: `Server error during ${operation}. Try the operation again or check Evolution API server status.`
}
};
default:
return {
success: false,
error: {
type: evolution_http_client_1.ErrorType.API_ERROR,
message: `Failed to ${operation}: ${error.message || 'Unknown error'}. Check the Evolution API server status and network connection.`
}
};
}
}
/**
* Handle unexpected errors
*/
handleUnexpectedError(error, operation) {
return {
success: false,
error: {
type: evolution_http_client_1.ErrorType.API_ERROR,
message: `Unexpected error during ${operation}: ${error.message || 'Unknown error'}. Check your network connection and try again.`
}
};
}
}
exports.ProfileWebhookTools = ProfileWebhookTools;