smartlead-mcp-by-leadmagic
Version:
💜 The Premier Model Context Protocol Server for SmartLead's Cold Email Automation Platform - Complete API coverage with 116+ tools for campaign management, lead tracking, smart delivery, and analytics. Beautiful purple-gradient installer, zero-config set
223 lines • 9.27 kB
JavaScript
/**
* SmartLead MCP Server - Client Management Client
*
* Client module for client management API endpoints.
* Handles all client-related operations including creation, updates, and management.
*
* @author LeadMagic Team
* @version 1.5.0
*/
import { BaseSmartLeadClient } from '../../client/base.js';
/**
* Client Management Client
*
* Provides methods for managing SmartLead clients including:
* - Creating and updating clients
* - Managing client settings and permissions
* - Client analytics and reporting
* - Client team management
*/
export class ClientManagementClient extends BaseSmartLeadClient {
// ================================
// CLIENT MANAGEMENT METHODS
// ================================
/**
* Add Client To System (Whitelabel or not)
* POST /client
*/
async addClientToSystem(params) {
const response = await this.withRetry(() => this.apiClient.post('/client', params), 'add client to system');
return response.data;
}
/**
* Create a new client (alias for addClientToSystem)
*/
async createClient(params) {
return this.addClientToSystem(params);
}
/**
* Fetch all clients
* GET /client
*/
async getAllClients() {
const response = await this.withRetry(() => this.apiClient.get('/client'), 'get all clients');
return response.data;
}
/**
* Create New Client API Key
* POST /client/api-key
*/
async createClientApiKey(params) {
const response = await this.withRetry(() => this.apiClient.post('/client/api-key', params), 'create client API key');
return response.data;
}
/**
* Get Clients API Keys
* GET /client/api-key
*/
async getClientApiKeys() {
const response = await this.withRetry(() => this.apiClient.get('/client/api-key'), 'get client API keys');
return response.data;
}
/**
* Delete Client API Key
* DELETE /client/api-key/{api_key_id}
*/
async deleteClientApiKey(apiKeyId) {
const response = await this.withRetry(() => this.apiClient.delete(`/client/api-key/${apiKeyId}`), 'delete client API key');
return response.data;
}
/**
* Reset Client API Key
* PUT /client/api-key/{api_key_id}/reset
*/
async resetClientApiKey(apiKeyId) {
const response = await this.withRetry(() => this.apiClient.put(`/client/api-key/${apiKeyId}/reset`), 'reset client API key');
return response.data;
}
/**
* Get team details - Aggregates team information from various sources
* This is a wrapper method that provides simplified team information
* without requiring date ranges like the analytics endpoints
*
* @param {string} [teamId] - Optional team ID to filter results (defaults to 'default')
* @returns {Promise<TeamDetailsResponse>} Team details including members, campaigns, and performance metrics
* @throws {Error} If team details cannot be retrieved or if provided teamId is invalid
*
* @example
* // Get default team details
* const teamDetails = await client.getTeamDetails();
* console.log(`Team: ${teamDetails.data.team_name} with ${teamDetails.data.members_count} members`);
*
* @example
* // Get specific team details
* const teamDetails = await client.getTeamDetails('team_123');
* console.log(`Active campaigns: ${teamDetails.data.active_campaigns}`);
*
* @description
* This method aggregates data from multiple endpoints:
* - Client list for team member information
* - Team board analytics for performance metrics
* - Campaign list for active campaign count
*
* Returns a unified response with fallback values if any endpoint fails,
* ensuring the method remains robust and reliable.
*/
async getTeamDetails(teamId) {
try {
// Validate teamId if provided
if (teamId && typeof teamId !== 'string') {
throw new Error('Invalid team ID: must be a string');
}
// Initialize response structure with defaults
const defaultStats = {
sent: 0,
opened: 0,
replied: 0,
bounced: 0,
};
// Get basic client/team information
let clients = [];
try {
clients = await this.getAllClients();
// Ensure clients is an array
if (!Array.isArray(clients)) {
console.warn('[SmartLead] getAllClients returned non-array:', typeof clients);
clients = [];
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
console.warn('[SmartLead] Failed to fetch clients:', errorMessage);
// Continue with empty clients array
}
// Get overall stats for the last 30 days as a default
const endDate = new Date().toISOString().split('T')[0];
const startDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
// Get analytics data - we need to access the analytics client through the parent
let teamStats = null;
try {
// Note: This requires the analytics module to be available
const analyticsClient = this.apiClient;
const statsResponse = await this.withRetry(() => analyticsClient.get('/analytics/team-board/overall-stats', {
params: {
start_date: startDate,
end_date: endDate,
full_data: true,
},
}), 'get team board stats for team details');
teamStats = statsResponse.data;
// Validate the stats response
if (!teamStats || typeof teamStats !== 'object') {
console.warn('[SmartLead] Invalid team board stats response');
teamStats = null;
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
console.warn('[SmartLead] Could not fetch team board stats:', errorMessage);
}
// Get campaign count
let campaignCount = 0;
try {
const campaignsResponse = await this.withRetry(() => this.apiClient.get('/campaigns'), 'get campaigns for team details');
const campaignsData = campaignsResponse.data;
campaignCount = Array.isArray(campaignsData) ? campaignsData.length : 0;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
console.warn('[SmartLead] Could not fetch campaigns:', errorMessage);
}
// Extract stats with fallbacks
let extractedStats = defaultStats;
try {
const statsData = teamStats?.data
?.team_board_stats;
if (Array.isArray(statsData) && statsData.length > 0) {
const firstStat = statsData[0];
extractedStats = {
sent: parseInt(String(firstStat.sent)) || 0,
opened: parseInt(String(firstStat.opened)) || 0,
replied: parseInt(String(firstStat.replied)) || 0,
bounced: parseInt(String(firstStat.bounced)) || 0,
};
}
}
catch (error) {
console.warn('[SmartLead] Error extracting team stats:', error);
}
// Aggregate the response
const teamDetails = {
team_id: teamId || 'default',
team_name: clients?.[0]?.name || 'Your Team',
organization: clients?.[0]?.organization || null,
members_count: clients?.length || 0,
clients: clients || [],
active_campaigns: campaignCount,
recent_performance: {
period: '30_days',
stats: extractedStats,
},
created_at: clients?.[0]?.created_at || null,
last_updated: new Date().toISOString(),
};
return {
success: true,
message: 'Team details retrieved successfully',
data: teamDetails,
};
}
catch (error) {
// Enhance error message
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
const enhancedError = new Error(`Failed to get team details: ${errorMessage}`);
// Add error properties in a type-safe way
Object.assign(enhancedError, {
status: error?.status || 500,
code: error?.code || 'TEAM_DETAILS_ERROR',
});
throw enhancedError;
}
}
}
//# sourceMappingURL=client.js.map