Skip to main content
Glama

Crunchbase MCP Server

#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ErrorCode, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListToolsRequestSchema, McpError, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { CrunchbaseAPI } from './crunchbase-api.js'; import { SearchCompaniesInput, GetCompanyDetailsInput, GetFundingRoundsInput, GetAcquisitionsInput, SearchPeopleInput } from './types.js'; // Get API key from environment variable const API_KEY = process.env.CRUNCHBASE_API_KEY; if (!API_KEY) { throw new Error('CRUNCHBASE_API_KEY environment variable is required'); } // At this point, API_KEY is guaranteed to be a string const apiKey: string = API_KEY; class CrunchbaseMcpServer { private server: Server; private crunchbaseApi: CrunchbaseAPI; constructor() { this.server = new Server( { name: 'crunchbase-mcp-server', version: '0.1.0', }, { capabilities: { resources: {}, tools: {}, }, } ); this.crunchbaseApi = new CrunchbaseAPI(apiKey); this.setupResourceHandlers(); this.setupToolHandlers(); // Error handling this.server.onerror = (error) => console.error('[MCP Error]', error); process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } private setupResourceHandlers() { // List available resources this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({ resources: [ { uri: 'crunchbase://trending/companies', name: 'Trending Companies', mimeType: 'application/json', description: 'List of trending companies on Crunchbase', }, ], })); // List resource templates this.server.setRequestHandler( ListResourceTemplatesRequestSchema, async () => ({ resourceTemplates: [ { uriTemplate: 'crunchbase://companies/{name}', name: 'Company Details', mimeType: 'application/json', description: 'Detailed information about a specific company', }, { uriTemplate: 'crunchbase://companies/{name}/funding', name: 'Company Funding Rounds', mimeType: 'application/json', description: 'Funding rounds for a specific company', }, { uriTemplate: 'crunchbase://companies/{name}/acquisitions', name: 'Company Acquisitions', mimeType: 'application/json', description: 'Acquisitions made by or of a specific company', }, ], }) ); // Handle resource requests this.server.setRequestHandler( ReadResourceRequestSchema, async (request) => { try { const uri = request.params.uri; // Handle trending companies resource if (uri === 'crunchbase://trending/companies') { const companies = await this.crunchbaseApi.searchCompanies({ limit: 10 }); return { contents: [ { uri, mimeType: 'application/json', text: JSON.stringify(companies, null, 2), }, ], }; } // Handle company details resource template const companyMatch = uri.match(/^crunchbase:\/\/companies\/([^/]+)$/); if (companyMatch) { const companyName = decodeURIComponent(companyMatch[1]); const company = await this.crunchbaseApi.getCompanyDetails({ name_or_id: companyName }); return { contents: [ { uri, mimeType: 'application/json', text: JSON.stringify(company, null, 2), }, ], }; } // Handle company funding rounds resource template const fundingMatch = uri.match(/^crunchbase:\/\/companies\/([^/]+)\/funding$/); if (fundingMatch) { const companyName = decodeURIComponent(fundingMatch[1]); const fundingRounds = await this.crunchbaseApi.getFundingRounds({ company_name_or_id: companyName }); return { contents: [ { uri, mimeType: 'application/json', text: JSON.stringify(fundingRounds, null, 2), }, ], }; } // Handle company acquisitions resource template const acquisitionsMatch = uri.match(/^crunchbase:\/\/companies\/([^/]+)\/acquisitions$/); if (acquisitionsMatch) { const companyName = decodeURIComponent(acquisitionsMatch[1]); const acquisitions = await this.crunchbaseApi.getAcquisitions({ company_name_or_id: companyName }); return { contents: [ { uri, mimeType: 'application/json', text: JSON.stringify(acquisitions, null, 2), }, ], }; } throw new McpError( ErrorCode.InvalidRequest, `Invalid URI: ${uri}` ); } catch (error) { console.error('Error handling resource request:', error); if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, error instanceof Error ? error.message : 'Unknown error' ); } } ); } private setupToolHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'search_companies', description: 'Search for companies based on various criteria', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query (e.g., company name, description)', }, location: { type: 'string', description: 'Filter by location (e.g., "San Francisco", "New York")', }, category: { type: 'string', description: 'Filter by category (e.g., "Artificial Intelligence", "Fintech")', }, founded_after: { type: 'string', description: 'Filter by founding date (YYYY-MM-DD)', }, founded_before: { type: 'string', description: 'Filter by founding date (YYYY-MM-DD)', }, status: { type: 'string', description: 'Filter by company status (e.g., "active", "closed")', }, limit: { type: 'number', description: 'Maximum number of results to return (default: 10)', }, }, }, }, { name: 'get_company_details', description: 'Get detailed information about a specific company', inputSchema: { type: 'object', properties: { name_or_id: { type: 'string', description: 'Company name or UUID', }, }, required: ['name_or_id'], }, }, { name: 'get_funding_rounds', description: 'Get funding rounds for a specific company', inputSchema: { type: 'object', properties: { company_name_or_id: { type: 'string', description: 'Company name or UUID', }, limit: { type: 'number', description: 'Maximum number of results to return (default: 10)', }, }, required: ['company_name_or_id'], }, }, { name: 'get_acquisitions', description: 'Get acquisitions made by or of a specific company', inputSchema: { type: 'object', properties: { company_name_or_id: { type: 'string', description: 'Company name or UUID', }, limit: { type: 'number', description: 'Maximum number of results to return (default: 10)', }, }, }, }, { name: 'search_people', description: 'Search for people based on various criteria', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query (e.g., person name)', }, company: { type: 'string', description: 'Filter by company name', }, title: { type: 'string', description: 'Filter by job title', }, limit: { type: 'number', description: 'Maximum number of results to return (default: 10)', }, }, }, }, ], })); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const { name, arguments: args } = request.params; switch (name) { case 'search_companies': { if (!args || typeof args !== 'object') { throw new McpError(ErrorCode.InvalidParams, 'Invalid parameters'); } const params: SearchCompaniesInput = { query: typeof args.query === 'string' ? args.query : undefined, location: typeof args.location === 'string' ? args.location : undefined, category: typeof args.category === 'string' ? args.category : undefined, founded_after: typeof args.founded_after === 'string' ? args.founded_after : undefined, founded_before: typeof args.founded_before === 'string' ? args.founded_before : undefined, status: typeof args.status === 'string' ? args.status : undefined, limit: typeof args.limit === 'number' ? args.limit : undefined }; const companies = await this.crunchbaseApi.searchCompanies(params); return { content: [ { type: 'text', text: JSON.stringify(companies, null, 2), }, ], }; } case 'get_company_details': { if (!args || typeof args !== 'object' || !('name_or_id' in args) || typeof args.name_or_id !== 'string') { throw new McpError(ErrorCode.InvalidParams, 'Missing or invalid name_or_id parameter'); } const params: GetCompanyDetailsInput = { name_or_id: args.name_or_id }; const company = await this.crunchbaseApi.getCompanyDetails(params); return { content: [ { type: 'text', text: JSON.stringify(company, null, 2), }, ], }; } case 'get_funding_rounds': { if (!args || typeof args !== 'object' || !('company_name_or_id' in args) || typeof args.company_name_or_id !== 'string') { throw new McpError(ErrorCode.InvalidParams, 'Missing or invalid company_name_or_id parameter'); } const params: GetFundingRoundsInput = { company_name_or_id: args.company_name_or_id, limit: typeof args.limit === 'number' ? args.limit : undefined }; const fundingRounds = await this.crunchbaseApi.getFundingRounds(params); return { content: [ { type: 'text', text: JSON.stringify(fundingRounds, null, 2), }, ], }; } case 'get_acquisitions': { if (!args || typeof args !== 'object') { throw new McpError(ErrorCode.InvalidParams, 'Invalid parameters'); } const params: GetAcquisitionsInput = { company_name_or_id: typeof args.company_name_or_id === 'string' ? args.company_name_or_id : undefined, limit: typeof args.limit === 'number' ? args.limit : undefined }; const acquisitions = await this.crunchbaseApi.getAcquisitions(params); return { content: [ { type: 'text', text: JSON.stringify(acquisitions, null, 2), }, ], }; } case 'search_people': { if (!args || typeof args !== 'object') { throw new McpError(ErrorCode.InvalidParams, 'Invalid parameters'); } const params: SearchPeopleInput = { query: typeof args.query === 'string' ? args.query : undefined, company: typeof args.company === 'string' ? args.company : undefined, title: typeof args.title === 'string' ? args.title : undefined, limit: typeof args.limit === 'number' ? args.limit : undefined }; const people = await this.crunchbaseApi.searchPeople(params); return { content: [ { type: 'text', text: JSON.stringify(people, null, 2), }, ], }; } default: throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${name}` ); } } catch (error) { console.error('Error handling tool call:', error); return { content: [ { type: 'text', text: error instanceof Error ? error.message : 'Unknown error', }, ], isError: true, }; } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('Crunchbase MCP server running on stdio'); } } const server = new CrunchbaseMcpServer(); 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/Cyreslab-AI/crunchbase-mcp-server'

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