glam/EXA_BUG_FIX.md
2025-11-19 23:25:22 +01:00

4.5 KiB

EXA MCP Server Bug Fix

Problem Summary

The exa_web_search_exa and exa_get_code_context_exa tools were returning 400 errors on all requests, even though the EXA API itself worked perfectly when called directly with curl.

Root Cause

The issue was NOT a bug in the exa-mcp-server package. The source code is correct and properly formatted.

The actual problem: The OpenCode configuration file used an environment variable reference {env:EXA_API_KEY} but the environment variable was not set in the shell where OpenCode runs.

Configuration Files

Before (BROKEN)

/Users/kempersc/.config/opencode/opencode.json:

{
  "mcp": {
    "exa": {
      "type": "local",
      "command": ["npx", "-y", "exa-mcp-server"],
      "enabled": true,
      "environment": {
        "EXA_API_KEY": "{env:EXA_API_KEY}"   This env var wasn't set
      }
    }
  }
}

After (FIXED)

/Users/kempersc/.config/opencode/opencode.json:

{
  "mcp": {
    "exa": {
      "type": "local",
      "command": ["npx", "-y", "exa-mcp-server"],
      "enabled": true,
      "environment": {
        "EXA_API_KEY": "dba69040-f87e-46a2-85d7-5b2e9fe17497"   Direct API key
      }
    }
  }
}

How the EXA MCP Server Works

Source Code Analysis

Repository: https://github.com/exa-labs/exa-mcp-server

Key files:

  • src/index.ts - Main server initialization
  • src/tools/webSearch.ts - Web search tool implementation
  • src/tools/exaCode.ts - Code context search implementation
  • src/tools/config.ts - API configuration

API Configuration (src/tools/config.ts:1-11):

export const API_CONFIG = {
  BASE_URL: 'https://api.exa.ai',
  ENDPOINTS: {
    SEARCH: '/search',
    RESEARCH_TASKS: '/research/v0/tasks',
    CONTEXT: '/context'
  },
  DEFAULT_NUM_RESULTS: 8,
  DEFAULT_MAX_CHARACTERS: 2000
} as const;

HTTP Request Format (from src/tools/webSearch.ts:24-52):

const axiosInstance = axios.create({
  baseURL: API_CONFIG.BASE_URL,
  headers: {
    'accept': 'application/json',
    'content-type': 'application/json',
    'x-api-key': config?.exaApiKey || process.env.EXA_API_KEY || ''
  },
  timeout: 25000
});

const searchRequest: ExaSearchRequest = {
  query,
  type: "auto",
  numResults: numResults || API_CONFIG.DEFAULT_NUM_RESULTS,
  contents: {
    text: {
      maxCharacters: API_CONFIG.DEFAULT_MAX_CHARACTERS
    },
    livecrawl: 'preferred'
  }
};

const response = await axiosInstance.post<ExaSearchResponse>(
  API_CONFIG.ENDPOINTS.SEARCH,
  searchRequest,
  { timeout: 25000 }
);

This exactly matches our working curl command:

curl -X POST "https://api.exa.ai/search" \
  -H "Content-Type: application/json" \
  -H "x-api-key: dba69040-f87e-46a2-85d7-5b2e9fe17497" \
  -d '{"query": "Belgium ISIL registry", "numResults": 3}'

Why the Error Occurred

When EXA_API_KEY environment variable is not set:

  1. OpenCode spawns npx -y exa-mcp-server with EXA_API_KEY="" (empty string)
  2. The axios request includes header: x-api-key: "" (empty)
  3. EXA API rejects the request with 400 Bad Request

Solution

Option 1 (APPLIED): Set API key directly in OpenCode config

  • Simple, works immediately after OpenCode restart
  • API key visible in config file (but it's in your home directory)

Option 2: Set shell environment variable globally

# In ~/.zshrc or ~/.bashrc
export EXA_API_KEY=dba69040-f87e-46a2-85d7-5b2e9fe17497
  • More secure (not in config files)
  • Requires shell restart, affects all processes

Option 3: Load from project .env file

  • Would require modifying exa-mcp-server to load .env
  • Not practical for this use case

Next Steps

  1. Restart OpenCode to reload MCP server with new configuration
  2. Test the tools:
    Use exa_web_search_exa to search for "Belgium ISIL registry"
    
  3. Verify we get proper search results instead of 400 errors

Verification Commands

After restarting OpenCode, test with:

Search for "Belgium heritage institutions ISIL registry"

Expected: JSON results with Belgian GLAM institution URLs

Source Code Findings

The exa-mcp-server package (v3.0.7) is correctly implemented:

  • Proper HTTP headers (x-api-key)
  • Correct API endpoints (/search, /context)
  • Valid request formatting
  • Error handling with detailed messages
  • Timeout handling (25-30 seconds)

No bugs found in the source code. The issue was purely configuration.


Date: November 6, 2025 Fixed by: Configuration update to /Users/kempersc/.config/opencode/opencode.json