Skip to main content
Glama

Exa MCP Server

by joerup
server.ts5.47 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js'; import { ExaClient } from './client.js'; import { getToolDefinitions, handleToolCall } from './tools/index.js'; import { log } from './utils/logger.js'; /** * Main server class for Exa MCP integration * @class ExaServer */ export class ExaServer { private client: ExaClient; private server: Server; private enabledTools: string[]; private debug: boolean; /** * Creates a new ExaServer instance * @param {string} apiKey - Exa API key for authentication * @param {string[]} enabledTools - List of enabled tool IDs * @param {boolean} debug - Enable debug logging */ constructor(apiKey: string, enabledTools?: string[], debug: boolean = false) { this.client = new ExaClient(apiKey); this.enabledTools = enabledTools || [ 'web_search_exa', 'company_research_exa', 'crawling_exa', 'linkedin_search_exa', 'deep_researcher_start', 'deep_researcher_check' ]; this.debug = debug; this.server = new Server( { name: 'exa-search-server', version: '2.0.3', }, { capabilities: { tools: {}, }, } ); this.setupHandlers(); this.setupErrorHandling(); if (this.debug) { log(`ExaServer initialized with ${this.enabledTools.length} tools`); } } /** * Sets up MCP request handlers for tools * @private */ private setupHandlers(): void { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { const tools = getToolDefinitions(this.enabledTools); if (this.debug) { log(`Listing ${tools.length} available tools`); } return { tools }; }); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const toolName = request.params.name; if (!this.enabledTools.includes(toolName)) { throw new McpError( ErrorCode.MethodNotFound, `Unknown or disabled tool: ${toolName}` ); } if (this.debug) { log(`Executing tool: ${toolName}`); } try { return await handleToolCall(this.client, toolName, request.params.arguments); } catch (error) { if (this.debug) { log(`Tool execution failed: ${error}`); } throw error; } }); } /** * Configures error handling and graceful shutdown * @private */ private setupErrorHandling(): void { this.server.onerror = (error) => { console.error('[MCP Error]', error); if (this.debug) { log(`Server error: ${error}`); } }; process.on('SIGINT', async () => { if (this.debug) { log('Shutting down server...'); } await this.server.close(); process.exit(0); }); } /** * Returns the underlying MCP server instance * @returns {Server} MCP server instance */ getServer(): Server { return this.server; } } /** * Factory function for creating standalone server instances * Used by HTTP transport for session-based connections * @param {string} apiKey - Exa API key for authentication * @param {string[]} enabledTools - List of enabled tool IDs * @param {boolean} debug - Enable debug logging * @returns {Server} Configured MCP server instance */ export function createStandaloneServer(apiKey: string, enabledTools?: string[], debug: boolean = false): Server { const server = new Server( { name: "exa-search-server", version: "2.0.3", }, { capabilities: { tools: {}, }, }, ); const client = new ExaClient(apiKey); const tools = enabledTools || [ 'web_search_exa', 'company_research_exa', 'crawling_exa', 'linkedin_search_exa', 'deep_researcher_start', 'deep_researcher_check' ]; // Set up handlers server.setRequestHandler(ListToolsRequestSchema, async () => { const toolDefs = getToolDefinitions(tools); if (debug) { log(`Listing ${toolDefs.length} available tools`); } return { tools: toolDefs }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { const toolName = request.params.name; if (!tools.includes(toolName)) { throw new McpError( ErrorCode.MethodNotFound, `Unknown or disabled tool: ${toolName}` ); } if (debug) { log(`Executing tool: ${toolName}`); } return await handleToolCall(client, toolName, request.params.arguments); }); return server; }

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/joerup/exa-mcp'

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