171 lines
4.5 KiB
Markdown
171 lines
4.5 KiB
Markdown
# 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`:
|
|
```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`:
|
|
```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`):
|
|
```typescript
|
|
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`):
|
|
```typescript
|
|
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:
|
|
```bash
|
|
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
|
|
```bash
|
|
# 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`
|