Skip to main content
Glama
index.ts10.7 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, Tool } from '@modelcontextprotocol/sdk/types.js'; import { HubSpotClient } from './hubspot-client.js'; import dotenv from 'dotenv'; import { parseArgs } from 'node:util'; // Load environment variables dotenv.config(); // Parse command line arguments const { values } = parseArgs({ options: { 'access-token': { type: 'string' } } }); // Initialize HubSpot client const accessToken = values['access-token'] || process.env.HUBSPOT_ACCESS_TOKEN; if (!accessToken) { throw new Error('HUBSPOT_ACCESS_TOKEN environment variable is required'); } class HubSpotServer { // Core server properties private server: Server; private hubspot: HubSpotClient; constructor() { this.server = new Server( { name: 'hubspot-manager', version: '0.1.0', }, { capabilities: { resources: {}, tools: {}, }, } ); this.hubspot = new HubSpotClient(accessToken); this.setupToolHandlers(); this.setupErrorHandling(); } private setupErrorHandling(): void { this.server.onerror = (error) => { console.error('[MCP Error]', error); }; process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); process.on('uncaughtException', (error) => { console.error('Uncaught exception:', error); }); process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled rejection at:', promise, 'reason:', reason); }); } private setupToolHandlers(): void { this.server.setRequestHandler(ListToolsRequestSchema, async () => { // Define available tools const tools: Tool[] = [ { name: 'hubspot_create_contact', description: 'Create a new contact in HubSpot', inputSchema: { type: 'object', properties: { firstname: { type: 'string', description: "Contact's first name" }, lastname: { type: 'string', description: "Contact's last name" }, email: { type: 'string', description: "Contact's email address" }, properties: { type: 'object', description: 'Additional contact properties', additionalProperties: true } }, required: ['firstname', 'lastname'] } }, { name: 'hubspot_create_company', description: 'Create a new company in HubSpot', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Company name' }, properties: { type: 'object', description: 'Additional company properties', additionalProperties: true } }, required: ['name'] } }, { name: 'hubspot_get_company_activity', description: 'Get activity history for a specific company', inputSchema: { type: 'object', properties: { company_id: { type: 'string', description: 'HubSpot company ID' } }, required: ['company_id'] } }, { name: 'hubspot_get_recent_engagements', description: 'Get recent engagement activities across all contacts and companies', inputSchema: { type: 'object', properties: { days: { type: 'number', description: 'Number of days to look back (default: 7)', default: 7 }, limit: { type: 'number', description: 'Maximum number of engagements to return (default: 50)', default: 50 } } } }, { name: 'hubspot_get_active_companies', description: 'Get most recently active companies from HubSpot', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'Maximum number of companies to return (default: 10)', default: 10 } } } }, { name: 'hubspot_get_active_contacts', description: 'Get most recently active contacts from HubSpot', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'Maximum number of contacts to return (default: 10)', default: 10 } } } }, { name: 'hubspot_update_contact', description: 'Update an existing contact in HubSpot (ignores if contact does not exist)', inputSchema: { type: 'object', properties: { contact_id: { type: 'string', description: 'HubSpot contact ID to update' }, properties: { type: 'object', description: 'Contact properties to update', additionalProperties: true } }, required: ['contact_id', 'properties'] } }, { name: 'hubspot_update_company', description: 'Update an existing company in HubSpot (ignores if company does not exist)', inputSchema: { type: 'object', properties: { company_id: { type: 'string', description: 'HubSpot company ID to update' }, properties: { type: 'object', description: 'Company properties to update', additionalProperties: true } }, required: ['company_id', 'properties'] } } ]; return { tools }; }); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const args = request.params.arguments ?? {}; switch (request.params.name) { case 'hubspot_create_contact': { const result = await this.hubspot.createContact( args.firstname as string, args.lastname as string, args.email as string | undefined, args.properties as Record<string, any> | undefined ); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } case 'hubspot_create_company': { const result = await this.hubspot.createCompany( args.name as string, args.properties as Record<string, any> | undefined ); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } case 'hubspot_get_company_activity': { const result = await this.hubspot.getCompanyActivity(args.company_id as string); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } case 'hubspot_get_recent_engagements': { const result = await this.hubspot.getRecentEngagements( args.days as number | undefined, args.limit as number | undefined ); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } case 'hubspot_get_active_companies': { const result = await this.hubspot.getRecentCompanies(args.limit as number | undefined); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } case 'hubspot_get_active_contacts': { const result = await this.hubspot.getRecentContacts(args.limit as number | undefined); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } case 'hubspot_update_contact': { const result = await this.hubspot.updateContact( args.contact_id as string, args.properties as Record<string, any> ); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } case 'hubspot_update_company': { const result = await this.hubspot.updateCompany( args.company_id as string, args.properties as Record<string, any> ); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } default: throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); } } catch (error: any) { console.error(`Error executing tool ${request.params.name}:`, error); return { content: [{ type: 'text', text: `HubSpot API error: ${error.message}` }], isError: true, }; } }); } async run(): Promise<void> { const transport = new StdioServerTransport(); await this.server.connect(transport); console.log('HubSpot MCP server started'); } } export async function serve(): Promise<void> { const client = new HubSpotServer(); await client.run(); } const server = new HubSpotServer(); server.run().catch(console.error);

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/lkm1developer/hubspot-mcp-server'

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