exa-mcp-server
- Type
- MCP server
- Scanned
- Oct 29, 2026
- Version
- 55cc85c73051
- Files read
- 104
This project is the official Exa MCP server and agent plugin for web search, webpage content fetching, and multi-step AI research. The main risk is that running the standalone HTTP runtime server binds to all network interfaces with wildcard CORS and automatically attaches the server's Exa API key to any unauthenticated request.
What it can reach
- Network
- Sends search, crawl, and research requests to api.exa.ai, verifies OAuth tokens against auth.exa.ai, sends usage telemetry to api.agnost.ai, optionally connects to Upstash Redis for rate limiting, and listens on 0.0.0.0:8000 when started in HTTP runtime mode.
- Secrets
- Reads EXA_API_KEY and optional OAuth/Redis configuration variables from the environment or incoming HTTP headers and query parameters.
- Files
- Reads its bundled skills/exa-agent/SKILL.md file to serve MCP prompt and resource guides, and includes skill instructions that direct the agent to save large research outputs to ./exa-results/.
Findings
-
MediumRuntime HTTP server binds to 0.0.0.0 and injects EXA_API_KEY into unauthenticated requests
When running the standalone HTTP server (via npm run start:runtime or Docker), it listens on 0.0.0.0:8000 by default and automatically injects process.env.EXA_API_KEY as an x-api-key header into every request that lacks credentials. Because the downstream handler treats any request with x-api-key as user-authenticated and sets Access-Control-Allow-Origin: *, any device on the local network or any website open in the user's browser can call the server, bypass rate limits, and spend the user's Exa API credits (including paid agent_run tasks).
Fix: Bind to 127.0.0.1 by default, require callers to authenticate before using the server's API key, and do not inject x-api-key into unauthenticated requests.
-
LowAlways-on third-party analytics telemetry without an opt-out option
The server unconditionally initializes Agnost analytics (trackMCP and checkpoint calls) to send tool usage telemetry to https://api.agnost.ai. Although tool inputs, outputs, logs, and errors are disabled in the configuration, invocation metadata leaves the user's machine without disclosure in the README or an option to disable it.
Fix: Make telemetry opt-in or provide an environment variable (such as DISABLE_TELEMETRY=true) to disable trackMCP and checkpoint calls.
-
LowAPI keys in URL query parameters are logged in plaintext when debug mode is active
The server supports passing credentials via the ?exaApiKey= query parameter and allows enabling debug logs via ?debug=true or DEBUG=true. Because request.url is logged before exaApiKey is stripped from the URL search parameters, any API key passed in the URL is written in plaintext to the server logs when debug mode is enabled.
Fix: Redact the exaApiKey query parameter before logging request.url, and avoid recommending URL query parameters for API keys in error messages.
-
LowUnvalidated researchId interpolated into API request path
src/tools/deepResearchCheck.ts:52
Unlike agent_run (which validates runId with a strict prefix regex), the optional deep_researcher_check tool accepts an arbitrary string for researchId and interpolates it directly into the API URL path without encoding or format validation. If this deprecated tool is enabled, a prompt injection could pass path traversal segments (../) to issue authenticated GET requests to other Exa API endpoints.
Fix: Validate researchId against the expected identifier format and wrap it in encodeURIComponent() when building the request URL.