- 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
532 lines
12 KiB
JavaScript
532 lines
12 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Apollo.io MCP Server
|
|
* Provides tools for interacting with the Apollo.io sales engagement platform
|
|
*/
|
|
|
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
import {
|
|
CallToolRequestSchema,
|
|
ListToolsRequestSchema,
|
|
ErrorCode,
|
|
McpError,
|
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
import { ApolloClient } from './client/apollo-client.js';
|
|
|
|
// Import all tool definitions
|
|
import {
|
|
listContactsTool,
|
|
getContactTool,
|
|
searchContactsTool,
|
|
createContactTool,
|
|
updateContactTool,
|
|
deleteContactTool,
|
|
} from './tools/contacts.js';
|
|
import {
|
|
listAccountsTool,
|
|
getAccountTool,
|
|
searchAccountsTool,
|
|
createAccountTool,
|
|
updateAccountTool,
|
|
} from './tools/accounts.js';
|
|
import {
|
|
listSequencesTool,
|
|
getSequenceTool,
|
|
createSequenceTool,
|
|
addContactsToSequenceTool,
|
|
removeContactsFromSequenceTool,
|
|
} from './tools/sequences.js';
|
|
import {
|
|
sendEmailTool,
|
|
listEmailAccountsTool,
|
|
listEmailThreadsTool,
|
|
getEmailThreadTool,
|
|
} from './tools/emails.js';
|
|
import {
|
|
listTasksTool,
|
|
createTaskTool,
|
|
updateTaskTool,
|
|
} from './tools/tasks.js';
|
|
import {
|
|
listOpportunitiesTool,
|
|
createOpportunityTool,
|
|
updateOpportunityTool,
|
|
} from './tools/opportunities.js';
|
|
|
|
// Collect all tools
|
|
const ALL_TOOLS = [
|
|
// Contacts (6 tools)
|
|
listContactsTool,
|
|
getContactTool,
|
|
searchContactsTool,
|
|
createContactTool,
|
|
updateContactTool,
|
|
deleteContactTool,
|
|
// Accounts (5 tools)
|
|
listAccountsTool,
|
|
getAccountTool,
|
|
searchAccountsTool,
|
|
createAccountTool,
|
|
updateAccountTool,
|
|
// Sequences (5 tools)
|
|
listSequencesTool,
|
|
getSequenceTool,
|
|
createSequenceTool,
|
|
addContactsToSequenceTool,
|
|
removeContactsFromSequenceTool,
|
|
// Emails (4 tools)
|
|
sendEmailTool,
|
|
listEmailAccountsTool,
|
|
listEmailThreadsTool,
|
|
getEmailThreadTool,
|
|
// Tasks (3 tools)
|
|
listTasksTool,
|
|
createTaskTool,
|
|
updateTaskTool,
|
|
// Opportunities (3 tools)
|
|
listOpportunitiesTool,
|
|
createOpportunityTool,
|
|
updateOpportunityTool,
|
|
];
|
|
|
|
// Initialize Apollo client
|
|
const apiKey = process.env.APOLLO_API_KEY;
|
|
if (!apiKey) {
|
|
throw new Error('APOLLO_API_KEY environment variable is required');
|
|
}
|
|
|
|
const apolloClient = new ApolloClient({ apiKey });
|
|
|
|
// Create MCP server
|
|
const server = new Server(
|
|
{
|
|
name: 'apollo-server',
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
capabilities: {
|
|
tools: {},
|
|
},
|
|
}
|
|
);
|
|
|
|
// Register tool list handler
|
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
return {
|
|
tools: ALL_TOOLS,
|
|
};
|
|
});
|
|
|
|
// Register tool call handler
|
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
const { name, arguments: args } = request.params;
|
|
|
|
try {
|
|
switch (name) {
|
|
// Contact tools
|
|
case 'list_contacts':
|
|
return await handleListContacts(args);
|
|
case 'get_contact':
|
|
return await handleGetContact(args);
|
|
case 'search_contacts':
|
|
return await handleSearchContacts(args);
|
|
case 'create_contact':
|
|
return await handleCreateContact(args);
|
|
case 'update_contact':
|
|
return await handleUpdateContact(args);
|
|
case 'delete_contact':
|
|
return await handleDeleteContact(args);
|
|
|
|
// Account tools
|
|
case 'list_accounts':
|
|
return await handleListAccounts(args);
|
|
case 'get_account':
|
|
return await handleGetAccount(args);
|
|
case 'search_accounts':
|
|
return await handleSearchAccounts(args);
|
|
case 'create_account':
|
|
return await handleCreateAccount(args);
|
|
case 'update_account':
|
|
return await handleUpdateAccount(args);
|
|
|
|
// Sequence tools
|
|
case 'list_sequences':
|
|
return await handleListSequences(args);
|
|
case 'get_sequence':
|
|
return await handleGetSequence(args);
|
|
case 'create_sequence':
|
|
return await handleCreateSequence(args);
|
|
case 'add_contacts_to_sequence':
|
|
return await handleAddContactsToSequence(args);
|
|
case 'remove_contacts_from_sequence':
|
|
return await handleRemoveContactsFromSequence(args);
|
|
|
|
// Email tools
|
|
case 'send_email':
|
|
return await handleSendEmail(args);
|
|
case 'list_email_accounts':
|
|
return await handleListEmailAccounts(args);
|
|
case 'list_email_threads':
|
|
return await handleListEmailThreads(args);
|
|
case 'get_email_thread':
|
|
return await handleGetEmailThread(args);
|
|
|
|
// Task tools
|
|
case 'list_tasks':
|
|
return await handleListTasks(args);
|
|
case 'create_task':
|
|
return await handleCreateTask(args);
|
|
case 'update_task':
|
|
return await handleUpdateTask(args);
|
|
|
|
// Opportunity tools
|
|
case 'list_opportunities':
|
|
return await handleListOpportunities(args);
|
|
case 'create_opportunity':
|
|
return await handleCreateOpportunity(args);
|
|
case 'update_opportunity':
|
|
return await handleUpdateOpportunity(args);
|
|
|
|
default:
|
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
}
|
|
} catch (error) {
|
|
if (error instanceof McpError) throw error;
|
|
throw new McpError(
|
|
ErrorCode.InternalError,
|
|
`Tool execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
);
|
|
}
|
|
});
|
|
|
|
// Tool implementation functions
|
|
async function handleListContacts(args: any) {
|
|
const result = await apolloClient.getPaginated('/contacts', args, args.page, args.per_page);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleGetContact(args: any) {
|
|
const result = await apolloClient.get(`/contacts/${args.id}`);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleSearchContacts(args: any) {
|
|
const result = await apolloClient.searchContacts(args, args.page, args.per_page);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleCreateContact(args: any) {
|
|
const result = await apolloClient.post('/contacts', args);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleUpdateContact(args: any) {
|
|
const { id, ...updateData } = args;
|
|
const result = await apolloClient.patch(`/contacts/${id}`, updateData);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleDeleteContact(args: any) {
|
|
const result = await apolloClient.delete(`/contacts/${args.id}`);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify({ success: true, id: args.id }, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleListAccounts(args: any) {
|
|
const result = await apolloClient.getPaginated('/accounts', args, args.page, args.per_page);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleGetAccount(args: any) {
|
|
const result = await apolloClient.get(`/accounts/${args.id}`);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleSearchAccounts(args: any) {
|
|
const result = await apolloClient.searchAccounts(args, args.page, args.per_page);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleCreateAccount(args: any) {
|
|
const result = await apolloClient.post('/accounts', args);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleUpdateAccount(args: any) {
|
|
const { id, ...updateData } = args;
|
|
const result = await apolloClient.patch(`/accounts/${id}`, updateData);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleListSequences(args: any) {
|
|
const result = await apolloClient.getPaginated('/emailer_campaigns', args, args.page, args.per_page);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleGetSequence(args: any) {
|
|
const result = await apolloClient.get(`/emailer_campaigns/${args.id}`);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleCreateSequence(args: any) {
|
|
const result = await apolloClient.post('/emailer_campaigns', args);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleAddContactsToSequence(args: any) {
|
|
const result = await apolloClient.post('/emailer_campaigns/add_contact_ids', args);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleRemoveContactsFromSequence(args: any) {
|
|
const result = await apolloClient.post('/emailer_campaigns/remove_contact_ids', args);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleSendEmail(args: any) {
|
|
const result = await apolloClient.post('/emailer_messages', args);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleListEmailAccounts(args: any) {
|
|
const result = await apolloClient.get('/email_accounts');
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleListEmailThreads(args: any) {
|
|
const result = await apolloClient.getPaginated('/emailer_threads', args, args.page, args.per_page);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleGetEmailThread(args: any) {
|
|
const result = await apolloClient.get(`/emailer_threads/${args.id}`);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleListTasks(args: any) {
|
|
const result = await apolloClient.getPaginated('/tasks', args, args.page, args.per_page);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleCreateTask(args: any) {
|
|
const result = await apolloClient.post('/tasks', args);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleUpdateTask(args: any) {
|
|
const { id, ...updateData } = args;
|
|
const result = await apolloClient.patch(`/tasks/${id}`, updateData);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleListOpportunities(args: any) {
|
|
const result = await apolloClient.getPaginated('/opportunities', args, args.page, args.per_page);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleCreateOpportunity(args: any) {
|
|
const result = await apolloClient.post('/opportunities', args);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
async function handleUpdateOpportunity(args: any) {
|
|
const { id, ...updateData } = args;
|
|
const result = await apolloClient.patch(`/opportunities/${id}`, updateData);
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
// Start the server
|
|
async function main() {
|
|
const transport = new StdioServerTransport();
|
|
await server.connect(transport);
|
|
console.error('Apollo MCP Server running on stdio');
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error('Fatal error in main():', error);
|
|
process.exit(1);
|
|
});
|