Skip to main content
Glama

Apollo.io MCP Server

by adamanz
apollo-client.ts13 kB
import axios, { AxiosInstance } from 'axios'; import dotenv from 'dotenv'; // Load environment variables dotenv.config(); // Helper function to strip URL const stripUrl = (url?: string): string | undefined => { if (!url) return undefined; try { // Remove protocol (http://, https://) let stripped = url.replace(/^https?:\/\//, ''); // Remove www. stripped = stripped.replace(/^www\./, ''); // Remove trailing slash stripped = stripped.replace(/\/$/, ''); // Convert to lowercase stripped = stripped.toLowerCase(); return stripped; } catch (error) { console.error('Error stripping URL:', error); return url; } }; // Type definitions for Apollo.io API responses export interface PeopleEnrichmentQuery { first_name?: string; last_name?: string; email?: string; domain?: string; organization_name?: string; [key: string]: any; } export interface OrganizationEnrichmentQuery { domain?: string; name?: string; [key: string]: any; } export interface PeopleSearchQuery { q_organization_domains_list?: string[]; person_titles?: string[]; person_seniorities?: string[]; [key: string]: any; } export interface OrganizationSearchQuery { q_organization_domains_list?: string[]; organization_locations?: string[]; [key: string]: any; } export interface EmployeesOfCompanyQuery { company: string; website_url?: string; linkedin_url?: string; [key: string]: any; } export class ApolloClient { private apiKey: string; private baseUrl: string; private headers: Record<string, string>; private axiosInstance: AxiosInstance; constructor(apiKey?: string) { this.apiKey = apiKey || process.env.APOLLO_IO_API_KEY || ''; if (!this.apiKey) { throw new Error('APOLLO_IO_API_KEY environment variable is required'); } this.baseUrl = 'https://api.apollo.io/api/v1'; this.headers = { 'Content-Type': 'application/json', 'Cache-Control': 'no-cache', 'x-api-key': this.apiKey }; this.axiosInstance = axios.create({ baseURL: this.baseUrl, headers: this.headers }); } /** * Use the People Enrichment endpoint to enrich data for 1 person. * https://docs.apollo.io/reference/people-enrichment */ async peopleEnrichment(query: PeopleEnrichmentQuery): Promise<any> { try { const url = `${this.baseUrl}/people/match`; console.log('url', url); console.log('query', query); const response = await this.axiosInstance.post(url, query); if (response.status === 200) { return response.data; } else { console.error(`Error: ${response.status} - ${response.statusText}`); return null; } } catch (error: any) { console.error(`Error: ${error.response?.status} - ${error.response?.statusText || error.message}`); return null; } } /** * Use the Organization Enrichment endpoint to enrich data for 1 company. * https://docs.apollo.io/reference/organization-enrichment */ async organizationEnrichment(query: OrganizationEnrichmentQuery): Promise<any> { try { const url = `${this.baseUrl}/organizations/enrich`; const response = await this.axiosInstance.get(url, { params: query }); if (response.status === 200) { return response.data; } else { console.error(`Error: ${response.status} - ${response.statusText}`); return null; } } catch (error: any) { console.error(`Error: ${error.response?.status} - ${error.response?.statusText || error.message}`); return null; } } /** * Use the People Search endpoint to find people. * https://docs.apollo.io/reference/people-search */ async peopleSearch(query: PeopleSearchQuery): Promise<any> { try { const url = `${this.baseUrl}/mixed_people/search`; const response = await this.axiosInstance.post(url, query); if (response.status === 200) { return response.data; } else { console.error(`Error: ${response.status} - ${response.statusText}`); return null; } } catch (error: any) { console.error(`Error: ${error.response?.status} - ${error.response?.statusText || error.message}`); return null; } } /** * Use the Organization Search endpoint to find organizations. * https://docs.apollo.io/reference/organization-search */ async organizationSearch(query: OrganizationSearchQuery): Promise<any> { try { const url = `${this.baseUrl}/mixed_companies/search`; const response = await this.axiosInstance.post(url, query); if (response.status === 200) { return response.data; } else { console.error(`Error: ${response.status} - ${response.statusText}`); return null; } } catch (error: any) { console.error(`Error: ${error.response?.status} - ${error.response?.statusText || error.message}`); return null; } } /** * Use the Organization Job Postings endpoint to find job postings for a specific organization. * https://docs.apollo.io/reference/organization-jobs-postings */ async organizationJobPostings(organizationId: string): Promise<any> { try { const url = `${this.baseUrl}/organizations/${organizationId}/job_postings`; const response = await this.axiosInstance.get(url); if (response.status === 200) { return response.data; } else { console.error(`Error: ${response.status} - ${response.statusText}`); return null; } } catch (error: any) { console.error(`Error: ${error.response?.status} - ${error.response?.statusText || error.message}`); return null; } } /** * Get email address for a person using their Apollo ID */ async getPersonEmail(apolloId: string): Promise<any> { try { if (!apolloId) { throw new Error('Apollo ID is required'); } const baseUrl = `https://app.apollo.io/api/v1/mixed_people/add_to_my_prospects`; const payload = { entity_ids: [apolloId], analytics_context: 'Searcher: Individual Add Button', skip_fetching_people: true, cta_name: 'Access email', cacheKey: Date.now() }; const response = await axios.post(baseUrl, payload, { headers: { 'X-Api-Key': this.apiKey, 'Content-Type': 'application/json' } }); if (!response.data) { throw new Error('No data received from Apollo API'); } const emails = (response?.data?.contacts ?? []).map((item: any) => item.email); return emails; } catch (error: any) { console.error(`Error getting person email: ${error.message}`); return null; } } /** * Find employees of a company using company name or website/LinkedIn URL */ async employeesOfCompany(query: EmployeesOfCompanyQuery): Promise<any> { try { const { company, website_url, linkedin_url } = query; if (!company) { throw new Error('Company name is required'); } const strippedWebsiteUrl = stripUrl(website_url); const strippedLinkedinUrl = stripUrl(linkedin_url); // First search for the company const companySearchPayload = { q_organization_name: company, page: 1, limit: 100 }; const mixedCompaniesResponse = await axios.post( 'https://api.apollo.io/v1/mixed_companies/search', companySearchPayload, { headers: { 'Content-Type': 'application/json', 'X-Api-Key': this.apiKey } } ); if (!mixedCompaniesResponse.data) { throw new Error('No data received from Apollo API'); } let organizations = mixedCompaniesResponse.data.organizations; if (organizations.length === 0) { throw new Error('No organizations found'); } // Filter companies by website or LinkedIn URL if provided const companyObjs = organizations.filter((item: any) => { const companyLinkedin = stripUrl(item.linkedin_url); const companyWebsite = stripUrl(item.website_url); if (strippedLinkedinUrl && companyLinkedin && companyLinkedin === strippedLinkedinUrl) { return true; } else if (strippedWebsiteUrl && companyWebsite && companyWebsite === strippedWebsiteUrl) { return true; } return false; }); // If we have filtered results, use the first one, otherwise use the first from the original search const companyObj = companyObjs.length > 0 ? companyObjs[0] : organizations[0]; const companyId = companyObj.id; if (!companyId) { throw new Error('Could not determine company ID'); } // Now search for employees const peopleSearchPayload: any = { organization_ids: [companyId], page: 1, limit: 100 }; // Add optional filters if provided in the tool config if (query.person_seniorities) { peopleSearchPayload.person_titles = (query.person_seniorities ?? '').split(',').map((item: string) => item.trim()); } if (query.contact_email_status) { peopleSearchPayload.contact_email_status_v2 = (query.contact_email_status ?? '').split(',').map((item: string) => item.trim()); } const peopleResponse = await axios.post( 'https://api.apollo.io/v1/mixed_people/search', peopleSearchPayload, { headers: { 'Content-Type': 'application/json', 'X-Api-Key': this.apiKey } } ); if (!peopleResponse.data) { throw new Error('No data received from Apollo API'); } return peopleResponse.data.people || []; } catch (error: any) { console.error(`Error finding employees: ${error.message}`); return null; } } } // Example usage (for testing) async function main() { try { // Get API key from environment variable const apiKey = process.env.APOLLO_IO_API_KEY; if (!apiKey) { throw new Error('APOLLO_IO_API_KEY environment variable is required'); } const client = new ApolloClient(apiKey); // Example People Enrichment const peopleEnrichmentQuery: PeopleEnrichmentQuery = { first_name: "Tim", last_name: "Zheng" }; const peopleEnrichmentResponse = await client.peopleEnrichment(peopleEnrichmentQuery); if (peopleEnrichmentResponse) { console.log("People Enrichment Response:", JSON.stringify(peopleEnrichmentResponse, null, 2)); } else { console.log("People Enrichment failed."); } // Example Organization Enrichment const organizationEnrichmentQuery: OrganizationEnrichmentQuery = { domain: "apollo.io" }; const organizationEnrichmentResponse = await client.organizationEnrichment(organizationEnrichmentQuery); if (organizationEnrichmentResponse) { console.log("Organization Enrichment Response:", JSON.stringify(organizationEnrichmentResponse, null, 2)); } else { console.log("Organization Enrichment failed."); } // Example People Search const peopleSearchQuery: PeopleSearchQuery = { person_titles: ["Marketing Manager"], person_seniorities: ["vp"], q_organization_domains_list: ["apollo.io"] }; const peopleSearchResponse = await client.peopleSearch(peopleSearchQuery); if (peopleSearchResponse) { console.log("People Search Response:", JSON.stringify(peopleSearchResponse, null, 2)); } else { console.log("People Search failed."); } // Example Organization Search const organizationSearchQuery: OrganizationSearchQuery = { organization_locations: ["Japan", "Ireland"] }; const organizationSearchResponse = await client.organizationSearch(organizationSearchQuery); if (organizationSearchResponse) { console.log("Organization Search Response:", JSON.stringify(organizationSearchResponse, null, 2)); } else { console.log("Organization Search failed."); } // Example Organization Job Postings // Note: You need a valid organization ID for this to work const organizationId = "5e60b6381c85b4008c83"; // Replace with a valid organization ID const organizationJobPostingsResponse = await client.organizationJobPostings(organizationId); if (organizationJobPostingsResponse) { console.log("Organization Job Postings Response:", JSON.stringify(organizationJobPostingsResponse, null, 2)); } else { console.log("Organization Job Postings failed."); } } catch (error) { console.error("Error:", error); } } // Run the example if this file is executed directly if (process.argv[1] === import.meta.url) { main(); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/adamanz/apollo-io-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server