- READMEs added: asana, close, freshdesk, google-console, gusto, square - main.ts + server.ts (lazy loading): activecampaign, clickup, klaviyo, mailchimp, pipedrive, trello, touchbistro, closebot, close, google-console - All 13 compile with 0 TSC errors
176 lines
4.7 KiB
TypeScript
176 lines
4.7 KiB
TypeScript
/**
|
|
* Klaviyo MCP Server Class
|
|
* Implements lazy-loaded tool modules for optimal performance
|
|
*/
|
|
|
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
import {
|
|
CallToolRequestSchema,
|
|
ListToolsRequestSchema,
|
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
import { KlaviyoClient } from './client/index.js';
|
|
|
|
type ToolModule = any[];
|
|
|
|
export class KlaviyoMCPServer {
|
|
private server: Server;
|
|
private client: KlaviyoClient;
|
|
private toolModules: Map<string, () => Promise<ToolModule>>;
|
|
private loadedTools: any[] | null = null;
|
|
|
|
constructor(client: KlaviyoClient) {
|
|
this.client = client;
|
|
this.toolModules = new Map();
|
|
|
|
this.server = new Server(
|
|
{
|
|
name: '@mcpengine/klaviyo',
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
capabilities: {
|
|
tools: {},
|
|
},
|
|
}
|
|
);
|
|
|
|
this.setupToolModules();
|
|
this.setupHandlers();
|
|
}
|
|
|
|
private setupToolModules() {
|
|
// Register lazy-loaded tool modules
|
|
this.toolModules.set('profiles', async () => {
|
|
const module = await import('./tools/klaviyo_profiles.js');
|
|
return module.profileTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('lists', async () => {
|
|
const module = await import('./tools/klaviyo_lists.js');
|
|
return module.listTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('segments', async () => {
|
|
const module = await import('./tools/klaviyo_segments.js');
|
|
return module.segmentTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('campaigns', async () => {
|
|
const module = await import('./tools/klaviyo_campaigns.js');
|
|
return module.campaignTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('flows', async () => {
|
|
const module = await import('./tools/klaviyo_flows.js');
|
|
return module.flowTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('templates', async () => {
|
|
const module = await import('./tools/klaviyo_templates.js');
|
|
return module.templateTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('metrics', async () => {
|
|
const module = await import('./tools/klaviyo_metrics.js');
|
|
return module.metricTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('events', async () => {
|
|
const module = await import('./tools/klaviyo_events.js');
|
|
return module.eventTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('catalogs', async () => {
|
|
const module = await import('./tools/klaviyo_catalogs.js');
|
|
return module.catalogTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('forms', async () => {
|
|
const module = await import('./tools/klaviyo_forms.js');
|
|
return module.formTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('tags', async () => {
|
|
const module = await import('./tools/klaviyo_tags.js');
|
|
return module.tagTools(this.client);
|
|
});
|
|
|
|
this.toolModules.set('reporting', async () => {
|
|
const module = await import('./tools/klaviyo_reporting.js');
|
|
return module.reportingTools(this.client);
|
|
});
|
|
}
|
|
|
|
private async loadAllTools(): Promise<any[]> {
|
|
if (this.loadedTools) {
|
|
return this.loadedTools;
|
|
}
|
|
|
|
const allTools: any[] = [];
|
|
|
|
for (const [name, loader] of this.toolModules.entries()) {
|
|
const tools = await loader();
|
|
allTools.push(...tools);
|
|
}
|
|
|
|
this.loadedTools = allTools;
|
|
return allTools;
|
|
}
|
|
|
|
private setupHandlers() {
|
|
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
const allTools = await this.loadAllTools();
|
|
|
|
return {
|
|
tools: allTools.map((tool) => ({
|
|
name: tool.name,
|
|
description: tool.description,
|
|
inputSchema: tool.inputSchema,
|
|
})),
|
|
};
|
|
});
|
|
|
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
const allTools = await this.loadAllTools();
|
|
const tool = allTools.find((t) => t.name === request.params.name);
|
|
|
|
if (!tool) {
|
|
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
}
|
|
|
|
try {
|
|
const result = await tool.execute(request.params.arguments || {});
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(
|
|
{
|
|
error: error.message || 'Unknown error',
|
|
details: error.response?.data || error.toString(),
|
|
},
|
|
null,
|
|
2
|
|
),
|
|
},
|
|
],
|
|
isError: true,
|
|
};
|
|
}
|
|
});
|
|
}
|
|
|
|
async connect(transport: any) {
|
|
await this.server.connect(transport);
|
|
}
|
|
}
|