Exa Ultra MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Exa Ultra MCPsearch the web for recent AI regulation news and cite the sources"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Exa Ultra MCP
A local stdio MCP server for the full Exa API, built for AI agents.
Covers every Exa surface on the free plan: search (all types), contents, find-similar, answer, Agent runs, Monitors.
Quality modes:
fast,auto(Exa standard) andmax(highest the free plan allows). Set one server-wide, or pass one per call.Pool of API keys with failover. On 401/402/429/5xx, timeouts or a broken response, the call moves to the next key. Bad requests (400) are not retried.
Budget guard. Spend per key comes from
costDollars. A key is skipped near its monthly budget ($10 on the free plan). Agent runs reserve their worst-case cost until Exa bills them.Shared state. Every process on the machine (one per chat session is common) shares the same budget, cooldowns and mode.
Lean output. Short Markdown for the model, typed JSON in
structuredContent, real errors flaggedisError: true, and the cost on every call.Keys stay private. Keys are read from a file or the environment. They are never logged or returned, and every error message is scrubbed of them.
Agents (OpenBot, Claude, Codex, …): read
AGENTS.mdfor setup and usage rules.
Quick start
git clone https://github.com/chocowarsky/exa-ultra-mcp.git
cd exa-ultra-mcp
npm install # also builds dist/
npm test # mock tests, no keys, no creditsPut your keys in a private file, one per line or comma-separated. Keep it outside the repo:
install -m 600 /dev/null ~/.config/exa-ultra/keys
$EDITOR ~/.config/exa-ultra/keysRegister the server with your MCP client:
{
"mcpServers": {
"exa-ultra": {
"command": "node",
"args": ["/absolute/path/to/exa-ultra-mcp/dist/index.js", "--keys-file=/home/you/.config/exa-ultra/keys"]
}
}
}More client configs (OpenBot, Claude Desktop/Code, Cursor, Codex, OpenCode) are in examples/.
Related MCP server: Exa MCP Server
Modes
Mode |
|
| Typical use |
|
|
| Autocomplete, tight agent loops |
|
|
| Exa's standard defaults |
|
|
| Best quality on the free plan |
An earlier rule wins over a later one:
An explicit
typeoreffortin the call.modein the call (fast/auto/max).The server mode saved with the
exa_modetool. It applies to every session on the machine and survives restarts.EXA_MODE, or--mode=, from the config.
A mode never breaks a call. If the mode's search type cannot handle the options you set, the server falls back to auto and adds a note. Two cases: lite with outputSchema or freshness options, and deep-* with Snapshot. An explicit invalid combination is rejected locally, before any credits are spent.
Tools
Tool | Exa endpoint | Notes |
|
| All types, filters, |
|
| text, highlights or summary; live crawl, subpages, links/images, Snapshot |
|
| Replaces the deprecated |
|
| Cited answer, optional schema |
|
| Create, wait, follow-up, list, events, cancel, delete |
|
| Off by default ( |
| local | Show or set the server mode |
| local | Key health, cooldowns, spend, reservations; |
Resources: exa://keys/status, exa://modes. Prompt: exa_research.
Configuration
Every setting is optional except the keys.
Variable | Default | Meaning |
| — | File with keys: commas, spaces or newlines; |
| — | Keys in the environment (comma-separated) |
|
|
|
|
| Cap per |
|
| How long |
|
| USD per key per month |
|
| Stop using a key this many USD before its budget |
|
|
|
|
| Requests per second per key (free plan: 10); |
|
| Timeout of one HTTP attempt |
|
| Keys tried per call |
|
| Default cap on the text returned to the model |
|
| In-memory cache of identical calls |
|
| Turn tool groups on or off |
|
| Shared state: fingerprints, spend, mode. Never keys |
|
| For proxies or tests |
Invalid values fall back to the default, with a warning on stderr.
Failover rules
Exa answer | What happens to the key | Retried on another key |
401 / 403 | Disabled for 6 h | ✓ |
403 "plan doesn't include …" | Nothing; the key is fine | — (every key on the plan would answer the same) |
402, or 429 about credits | Disabled until next month | ✓ |
429 rate limit | Cooldown ( | ✓ |
5xx, 408, timeout, network error, 200 with a non-JSON body | Cooldown with backoff | ✓ |
400 / 404 / 422 | Nothing | — (the request itself is wrong) |
Agent runs and monitors stay on the key that created them. A run with an unknown owner is found by asking each key.
Project layout
src/
index.ts CLI entry: config → server → stdio
server.ts createServer(config): builds the MCP server (used by the CLI and tests)
config.ts env/argv → Config, with validation
modes.ts fast / auto / max presets, efforts, prices
core/
client.ts HTTP client: failover, pacing, redaction, cancellation
keypool.ts key selection, budget, reservations, cooldowns
state.ts cross-process JSON state with a lock
cache.ts TTL cache
format.ts compact Markdown output
tools/
index.ts list of tool modules (add yours here)
shared.ts Ctx, schemas, helpers, cache + in-flight dedupe
search.ts exa_search, exa_find_similar
contents.ts exa_contents, exa_answer
agent.ts exa_agent_run / get / manage
monitors.ts exa_monitor
admin.ts exa_mode, exa_keys_status
test/ mock Exa API, unit + end-to-end + stress tests
scripts/ check-secrets.mjs
examples/ client configsTo add a tool, write a ToolModule ((server, ctx) => void) in src/tools/ and add it to toolModules() in src/tools/index.ts. To add a mode, add an entry to MODES in src/modes.ts. Schemas, docs and exa_mode pick it up automatically.
You can also use the server as a library:
import { createServer } from "exa-ultra-mcp";
import { loadConfig } from "exa-ultra-mcp/config";
const { server } = createServer(loadConfig({ ...process.env, EXA_MODE: "auto" }));Development
npm test # build + 38 mock tests (no credits)
npm run stress # 1000 concurrent calls with injected failures + 4 processes sharing state
npm run check:secrets # scan tracked files; add --history to scan every commit
EXA_API_KEYS_FILE=~/.config/exa-ultra/keys npm run smoke # live test of every tool, about $0.10Results on a laptop: 1000 concurrent calls with 19% injected failures (429, 5xx, timeouts, HTML) finished in about 3 s at an error rate of 0.4%. Across 4 processes, 400/400 requests and all spend were tracked. One process uses about 35 MB of RAM.
Security
Never commit keys.
.gitignoreblocks common key files, andnpm run check:secrets(also run in CI) fails on anything that looks like a key, including UUIDs, the format Exa uses.The state file stores sha256 fingerprints and the last 4 characters of each key, never the key itself, with mode
0600.Monitor webhook secrets are written to
monitor-secrets/in the state dir (0600) and are never returned to the model.
License
Available Tools
9 toolsexa_agent_getExa Agent run status/resultA
Get an Exa Agent run by id; with wait=true, keep polling until it finishes or waitSeconds pass.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| raw | No | Also return the full Exa JSON in structuredContent. Costs many tokens. | |
| wait | No | ||
| noCache | No | Skip the local cache. | |
| maxChars | No | Cap on the text returned to you (default 8000). | |
| waitSeconds | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It usefully discloses that wait=true polls until completion or waitSeconds, but it omits other behavioral details such as cache behavior, token cost of raw output, and error conditions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact sentence with the core operation front-loaded and no wasted wording. It efficiently conveys the id lookup and the optional polling behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and no annotations, the description is somewhat thin. It covers the core get-by-id and wait behavior, but it does not describe what the run result contains or how status/result data is returned.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%, and the description compensates by explaining the important wait and waitSeconds semantics. The remaining parameters are either self-explanatory or documented in the schema, though the description does not add meaning for raw, noCache, or maxChars.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: get an Exa Agent run by id. It is clearly a retrieval tool, but it does not explicitly distinguish itself from siblings like exa_agent_run or exa_agent_manage.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by saying to get a run by id and explains the wait=true polling behavior. It does not state when to use this versus exa_agent_run or exa_agent_manage, nor does it give exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exa_agent_manageExa Agent runs: list, events, cancel, deleteC
list = recent runs on every key · events = lifecycle events of a run · cancel = stop a running run · delete = remove a run.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Run id (events, cancel, delete). | |
| limit | No | ||
| action | Yes | ||
| cursor | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries the full behavioral burden and delivers almost none of it: it never says that delete is permanent or cancel is irreversible, whether either is idempotent, what permissions or key scope is needed, or what happens to a run's events after deletion. 'Remove a run' is the only hint of destructiveness, and it is euphemistic rather than explicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, no filler, each clause maps to exactly one action — structurally clean and easy to scan. The terseness borders on under-specification rather than verbosity, so the compactness is only mildly a virtue.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A four-mode tool with two destructive operations, no annotations, no output schema, and 25% schema coverage needs far more than one line. Nothing is said about return shapes, pagination, error conditions, or irreversibility, leaving significant gaps for anything beyond the happy path.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 25% — the id parameter is documented in the schema, but limit and cursor have bare types with no description in either place. The description does not compensate: it says list returns 'recent runs on every key' but never explains what limit does, how cursor pagination works, or whether cursor/limit are ignored by events/cancel/delete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Uses a compact glossary form to bind each of the four enum actions to a specific behavior ('cancel = stop a running run', 'delete = remove a run'), so the agent can tell what each branch of the tool does. It does not differentiate the tool from close siblings like exa_agent_get or exa_agent_run, which likely overlap on retrieving a single run.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The action glossary implies which action does what, but there is no explicit when-to-use guidance, no statement of which action to prefer over exa_agent_get/exa_agent_run, and no preconditions (e.g. that events/cancel/delete require an id, or that list is account-wide). The agent must infer selection rules from a single line.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exa_agent_runExa Agent research runA
Async multi-step Exa Agent run (deep research): list-building, enrichment of rows, multi-hop research, structured JSON with citations. Not for simple lookups (use exa_search or exa_answer). Effort comes from the mode unless you set it: fast = minimal ($0.012) · auto = low ($0.025) · max = ultra (usage-based, capped at $1/run). Waits up to waitSeconds (default 120); if still running, returns the run id for exa_agent_get.
| Name | Required | Description | Default |
|---|---|---|---|
| raw | No | Also return the full Exa JSON in structuredContent. Costs many tokens. | |
| mode | No | Quality preset for this call: fast (lite search, cheapest agent) · auto (Exa standard) · max (highest free-plan quality). Default: the server mode (see exa_mode). An explicit type/effort wins. | |
| wait | No | Wait for the result (default true). | |
| query | Yes | The research task in natural language. | |
| effort | No | Overrides the mode. ultra = exhaustive · auto = sized to the task (both usage-based, capped by maxCostDollars) · fixed: minimal $0.012 · low $0.025 · medium $0.10 · high $0.50 · xhigh $1.00. | |
| exclude | No | Entities the agent must not return again. | |
| noCache | No | Skip the local cache. | |
| maxChars | No | Cap on the text returned to you (default 8000). | |
| inputData | No | Existing rows to research or enrich. | |
| waitSeconds | No | ||
| outputSchema | No | JSON Schema for output.structured. Bound arrays with maxItems. | |
| previousRunId | No | Continue from a completed run (follow-up question). | |
| maxCostDollars | No | Spend ceiling for auto/ultra (default 1). A free key has $10/month in total. | |
| maxDurationSeconds | No | ultra only. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does well: it discloses async behavior, the default waitSeconds wait of 120, that a still-running call returns a run id for exa_agent_get, cost tiers per mode/effort, and a usage-based cap of $1/run. It does not cover auth/permissions or rate-limit behavior, so it is strong but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and exclusions, then packs cost and wait behavior into two dense but purposeful sentences. Every clause adds decision-relevant information for an agent; there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a 14-parameter, no-annotation, no-output-schema tool, the description covers the essential operational picture: async execution, waiting, fallback run id, cost model, and sibling alternatives. It leaves detailed parameter semantics and output schema usage to the well-documented input schema, so it is complete enough for correct invocation, though a bit more on structured output behavior could help.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 93%, so the baseline is 3, but the description adds real meaning beyond the schema by mapping mode and effort to cost/quality tiers ('fast = minimal ($0.012) · auto = low ($0.025) · max = ultra ... capped at $1/run') and by stating the waitSeconds default and run-id fallback. Minor parameters like inputData and outputSchema are left to the schema, which is acceptable given coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource — async multi-step Exa Agent run for deep research — and enumerates concrete use cases like list-building, row enrichment, multi-hop research, and structured JSON with citations. It explicitly distinguishes itself from exa_search and exa_answer, so an agent can route correctly without inspecting schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance via the deep research use cases and an explicit when-not-to-use clause: 'Not for simple lookups (use exa_search or exa_answer).' It also explains the wait/fallback path to exa_agent_get, covering alternatives and follow-up behavior.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exa_answerExa grounded answerA
Ask a question; Exa searches and writes a short cited answer itself ($0.005). Good for quick facts. For research where you read the sources yourself, use exa_search.
| Name | Required | Description | Default |
|---|---|---|---|
| raw | No | Also return the full Exa JSON in structuredContent. Costs many tokens. | |
| text | No | Include full source text in citations (large). | |
| query | Yes | ||
| noCache | No | Skip the local cache. | |
| maxChars | No | Cap on the text returned to you (default 8000). | |
| outputSchema | No | JSON Schema for a structured answer. | |
| systemPrompt | No | ||
| userLocation | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose two genuinely useful traits: the answer is model-synthesized with citations, and each call costs $0.005. However, it says nothing about the local cache that the noCache parameter implies, about latency/rate limits, or about how maxChars truncation affects the returned answer.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, zero waste, with the core behavior and the routing alternative both front-loaded. The parenthetical price is the only aside and it earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-param tool with a nested outputSchema object and no annotations, the description covers what the tool does and when to pick it, which is the main risk of misselection. It is thin on the behavioral envelope — caching, output size, and the customization parameters — but not inadequate for correct invocation of the required query.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Eight parameters at 63% schema description coverage, and the description mentions none of them. systemPrompt and userLocation are undocumented in both schema and description, and the cost/size tradeoffs of raw, text, and maxChars — the most decision-relevant knobs here — are left entirely to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource chain ('Ask a question; Exa searches and writes a short cited answer itself') and distinguishes the result shape from raw-source retrieval by naming exa_search. An agent knows immediately this returns a synthesized, cited answer rather than documents.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly gives the selection rule: 'Good for quick facts' here, and 'For research where you read the sources yourself, use exa_search' as the alternative with the condition that selects it. Cost is also disclosed, which is decision-relevant for an agent choosing between tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exa_contentsExa get page contentsA
Get clean content of known URLs (no search). Default returns page text. Supports live crawl (maxAgeHours 0), subpage crawling, link/image extraction, and Exa Snapshot (paid plans). Failed URLs are listed; the call fails only when every URL failed.
| Name | Required | Description | Default |
|---|---|---|---|
| raw | No | Also return the full Exa JSON in structuredContent. Costs many tokens. | |
| urls | Yes | ||
| links | No | Return up to N links found on each page. | |
| content | No | Page content to return. Pick one. highlights = short query-relevant excerpts (fewest tokens). | |
| noCache | No | Skip the local cache. | |
| maxChars | No | Cap on the text returned to you (default 8000). | |
| subpages | No | Also crawl up to N linked subpages per result. | |
| imageLinks | No | Return up to N image URLs per page. | |
| maxAgeHours | No | Cache freshness: 0 = always live crawl, -1 = cache only, N = accept cache up to N hours. Not a publish-date filter. | |
| snapshotAsOf | No | Exa Snapshot: the page as it was at this ISO date-time. Paid plans only. Not with maxAgeHours/livecrawlTimeout/subpages. | |
| summaryQuery | No | What the per-page summary should focus on (summary mode; one LLM call per page). | |
| maxCharacters | No | Per-page cap for text or highlights. Only for a hard budget. | |
| subpageTarget | No | Keywords that pick which subpages to crawl, e.g. 'pricing' or ['docs','api']. | |
| summarySchema | No | JSON Schema for a structured per-page summary (summary mode). | |
| highlightsQuery | No | Steer which excerpts are picked (highlights mode). | |
| livecrawlTimeout | No | Live crawl timeout in ms. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With zero annotations the description carries the full burden and does well: it discloses partial-failure semantics ("Failed URLs are listed; the call fails only when every URL failed"), a paid-plan restriction on Snapshot, and the default output mode. It omits auth/rate-limit behavior and per-URL cost expectations beyond the Snapshot note, which keeps it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight clauses, zero filler, front-loaded with the core purpose before capabilities and failure behavior. Every sentence carries distinct information an agent would otherwise have to infer.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 16-parameter tool with no annotations and no output schema, the description covers default behavior, failure semantics, plan gating, and capability modes. What it lacks is guidance on parameter interplay (e.g. content mode vs maxChars vs summaryQuery) and expected return shape, though the schema absorbs most of that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 94%, so the schema already explains nearly every parameter, including maxAgeHours semantics and Snapshot exclusivity. The description only restates the maxAgeHours=0 → live crawl mapping and the Snapshot paid-plan caveat, adding little beyond what the schema supplies; baseline 3 is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Get clean content of known URLs (no search)" states a specific verb and resource and explicitly carves out the boundary against exa_search. An agent can tell instantly that this is a fetch-by-URL tool, not a discovery tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The "(no search)" qualifier and the list of capability modes (live crawl, subpage crawl, link/image extraction, snapshot) give clear context for when this tool applies. It stops short of naming siblings like exa_search or exa_find_similar as explicit alternatives, and leaves the choice among modes to the schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exa_find_similarExa find similar pagesA
Find pages similar to a seed URL (competitors, alternatives, related papers). Reads the seed page, then runs a semantic search built from it. Replaces Exa's deprecated /findSimilar. Search type follows the mode like exa_search.
| Name | Required | Description | Default |
|---|---|---|---|
| raw | No | Also return the full Exa JSON in structuredContent. Costs many tokens. | |
| url | Yes | ||
| mode | No | Quality preset for this call: fast (lite search, cheapest agent) · auto (Exa standard) · max (highest free-plan quality). Default: the server mode (see exa_mode). An explicit type/effort wins. | |
| type | No | ||
| focus | No | What 'similar' means here, e.g. 'competing products' or 'papers on the same method'. | |
| content | No | ||
| noCache | No | Skip the local cache. | |
| maxChars | No | Cap on the text returned to you (default 8000). | |
| numResults | No | ||
| excludeSourceDomain | No | Drop results from the seed's own domain (default true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden; it does disclose the non-obvious side effect that the seed page is fetched/read before searching, plus the deprecated-endpoint lineage. It says nothing about cost, rate limits, permissions, or whether results are cached (cache behavior is only exposed as a parameter).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core purpose and mechanism before the deprecation and mode notes. The '/findSimilar' deprecation reference is useful for migration context but is the least load-bearing sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A 10-parameter tool with no annotations and no output schema: the description covers what it does and the mode/type interaction, but says nothing about what the results look like, cost of the call, or how to get full page content (e.g. via exa_contents). Adequate but with clear gaps for an agent deciding whether to call it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 60%, so the schema covers the well-documented params (mode, focus, maxChars, noCache, excludeSourceDomain). The description's real contribution is the non-obvious interaction that search type follows the mode the way exa_search does — which explains the otherwise undocumented 'type' enum. It adds little for content, numResults, or raw.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource ('Find pages similar to a seed URL') and grounds it with concrete use cases (competitors, alternatives, related papers). It also explains the mechanism — read the seed page, run a semantic search from it — which distinguishes it from a plain query-based search like exa_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the presence of a required seed URL tells the agent this is the tool for similarity-from-example, but the description never states when to prefer it over exa_search or exa_answer. The exa_search reference is about type-following behavior, not about tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exa_keys_statusExa key pool statusA
Show health, cooldowns, requests and tracked spend of each Exa key (keys shown as last 4 chars only). action=reset clears cooldowns and disables.
| Name | Required | Description | Default |
|---|---|---|---|
| alias | No | Key alias like k2, for reset of one key. | |
| action | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It usefully discloses key masking and that reset clears cooldowns and disables something, but it leaves important behavior ambiguous: what exactly is disabled, whether reset is destructive or reversible, and whether reset applies to all keys or only the aliased key.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with no filler. The key metrics and the reset side effect are front-loaded and easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the status metrics and reset effect, but for a mutation-capable tool with no annotations and no output schema, it should more completely specify reset scope, side effects, and default behavior. It is adequate but has clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50%, and the schema already documents alias while action lacks a schema description. The description adds meaning for action=reset, but does not clarify status behavior when action is omitted or how alias interacts with reset beyond what the schema says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb and resource: show health, cooldowns, requests, and tracked spend for each Exa key. It also distinguishes the reset mode, and the tool is obviously separate from the search/agent siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies status monitoring and describes what action=reset does, but it does not explicitly say when to use status versus reset, when reset is appropriate, or whether an alias is required when resetting a single key.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exa_modeExa Ultra modeA
Show or set the server-wide quality mode used when a call sets no type/effort: fast = Lowest latency and cost: lite search (<1 s, $0.004), agent effort minimal ($0.012). auto = Exa's standard defaults: auto search (~2 s, $0.007), agent effort low ($0.025). max = Highest quality the free plan allows: deep-reasoning search (7-20 s, $0.015), agent effort ultra (capped by EXA_AGENT_MAX_COST, default $1/run). Setting it applies to every agent and session on this machine. Only set it when the user asks.
| Name | Required | Description | Default |
|---|---|---|---|
| set | No | New server mode. Omit to show the current one. | |
| reset | No | Forget the saved mode and go back to EXA_MODE from the config. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations to lean on, the description carries the full burden and does so: it discloses the configuration is global ('applies to every agent and session on this machine'), quantifies latency and dollar cost per mode, and names the EXA_AGENT_MAX_COST cap (default $1/run) that bounds the max tier. That is exactly the blast-radius context an agent needs before mutating shared state.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the verb and resource, then the mode tiers, then the global-scope warning and the usage restriction. The cost/latency figures are dense but each is decision-relevant; the tier list reads as a single run-on block rather than scannable lines.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-param, zero-required configuration tool with no output schema, everything needed to call it safely is present: what the modes buy, what the setting affects globally, and when not to touch it. Return shape for the show case is the only minor omission and is inferable from the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description exceeds it by unpacking each enum value into concrete latency, cost, and downstream effect (lite vs auto vs deep-reasoning search, agent effort minimal/low/ultra). The reset parameter is left entirely to the schema, which keeps this short of a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific pair of verbs and a precise resource: show or set the server-wide default quality mode applied when a call omits type/effort. None of the exa_* siblings touch server configuration, so an agent can place it immediately without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit scoping on both sides: the mode only takes effect when a call sets no type/effort, and the description closes with the constraint 'Only set it when the user asks'. Omission-as-read is spelled out in the schema, so both the when and the when-not are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exa_searchExa web searchA
Search the live web with Exa; returns ranked pages with query-relevant highlights (10 results). Search type comes from the mode unless you set type: fast = lite (<1 s) · auto = auto (~2 s) · max = deep-reasoning (7-20 s, best quality). See exa_mode for the current server mode. Put recency and source preferences in the query text; use filters only when they must be enforced. Use outputSchema (+ systemPrompt for keep/drop rules) to get fields extracted from the pages.
| Name | Required | Description | Default |
|---|---|---|---|
| raw | No | Also return the full Exa JSON in structuredContent. Costs many tokens. | |
| mode | No | Quality preset for this call: fast (lite search, cheapest agent) · auto (Exa standard) · max (highest free-plan quality). Default: the server mode (see exa_mode). An explicit type/effort wins. | |
| type | No | Overrides the mode. deep-reasoning = strongest · deep = several searches, wide schemas · deep-lite · auto · lite = fastest, cached only. | |
| links | No | Return up to N links found on each page. | |
| query | Yes | What to retrieve, phrased like a search box entry. | |
| content | No | Page content to return. Pick one. highlights = short query-relevant excerpts (fewest tokens). | |
| noCache | No | Skip the local cache. | |
| category | No | Only when results must come from that index. Not for list-building (use exa_agent_run). | |
| maxChars | No | Cap on the text returned to you (default 8000). | |
| subpages | No | Also crawl up to N linked subpages per result. | |
| objective | No | The larger goal this search serves: what should rank first, what to exclude, which facts to pull. | |
| imageLinks | No | Return up to N image URLs per page. | |
| numResults | No | Default 10. Results above 10 cost $0.001 each. | |
| excludeText | No | Pages must not contain this phrase (1 phrase, up to 5 words). | |
| includeText | No | Pages must contain this phrase (1 phrase, up to 5 words). | |
| maxAgeHours | No | Cache freshness: 0 = always live crawl, -1 = cache only, N = accept cache up to N hours. Not a publish-date filter. | |
| outputSchema | No | JSON Schema for synthesized output in output.content. Keep it small. | |
| snapshotAsOf | No | Exa Snapshot: the page as it was at this ISO date-time. Paid plans only. Not with maxAgeHours/livecrawlTimeout/subpages. | |
| summaryQuery | No | What the per-page summary should focus on (summary mode; one LLM call per page). | |
| systemPrompt | No | Rules for synthesized output: keep/drop, source preference, what to do with unverifiable fields. | |
| userLocation | No | Two-letter ISO country code, e.g. ID. | |
| maxCharacters | No | Per-page cap for text or highlights. Only for a hard budget. | |
| subpageTarget | No | Keywords that pick which subpages to crawl, e.g. 'pricing' or ['docs','api']. | |
| summarySchema | No | JSON Schema for a structured per-page summary (summary mode). | |
| excludeDomains | No | Hard blocklist. | |
| includeDomains | No | Hard allowlist, e.g. ['openai.com/blog','*.substack.com']. | |
| highlightsQuery | No | Steer which excerpts are picked (highlights mode). | |
| endPublishedDate | No | ||
| livecrawlTimeout | No | Live crawl timeout in ms. | |
| startPublishedDate | No | Hard filter; drops undated pages. Only for a stated date window. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden, and it does well: it discloses latency per mode (fast <1s, auto ~2s, max 7-20s) and the default of 10 results. It omits auth/plan constraints (e.g. snapshotAsOf is paid-only, noted only in the schema) and caching behavior beyond a pointer.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph that front-loads what the tool returns and then layers mode guidance and filter advice. Every sentence carries information, though the inline mode latency list partially duplicates the `mode` enum description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 30-parameter tool with no output schema, the description covers the highest-leverage decisions: mode/type selection, content mode, filter discipline, and structured extraction via outputSchema. Per-parameter details like numResults defaults, raw, subpages, and snapshot constraints are left to the schema, which documents them at 97% coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 97%, so baseline is 3; the description still adds value by explaining the mode-vs-type precedence ('Search type comes from the mode unless you set `type`') and by advising that filters be reserved for enforced constraints rather than soft preferences. It also explains the outputSchema/systemPrompt pairing for extracted fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource: 'Search the live web with Exa; returns ranked pages with query-relevant highlights (10 results)', which also states the default result shape. It does not explicitly contrast itself with siblings like exa_answer, exa_find_similar, or exa_contents, so differentiation relies on names rather than the description.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real steering: 'Put recency and source preferences in the query text; use filters only when they must be enforced' and points to exa_mode for the current server mode. It lacks an explicit statement of when to prefer exa_answer or exa_find_similar over this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v0.2.0- First observed
exa_agent_get - First observed
exa_agent_manage - First observed
exa_agent_run - First observed
exa_answer - First observed
exa_contents - First observed
exa_find_similar - First observed
exa_keys_status - First observed
exa_mode - First observed
exa_search
TDQS
Scored across 9 tools
Each tool targets a clearly distinct capability: web search, cited answers, similarity search, URL content retrieval, agent-run lifecycle, mode configuration, and key status. Overlaps such as exa_search vs. exa_answer vs. exa_agent_run are explicitly differentiated by their descriptions.
All tools use a consistent exa_ prefix and snake_case, making the set predictable. Most are action-oriented, though config/admin tools like exa_mode and exa_keys_status are noun-based rather than verb_noun.
Nine tools is well-scoped for a search and research API with agent and admin functions. Each tool covers a meaningful operation without redundant surface area.
The set covers search, answer generation, similarity, content retrieval, asynchronous agent runs with get/manage lifecycle operations, mode configuration, and key health. No obvious dead ends remain for the stated Exa search/research domain.
Maintenance
Related MCP Connectors
Connect AI agents to Exa for web search, content fetching, and multi-step research.
Web search and page fetch for AI agents. Results come from a shared cache; cached calls cost less.
Web search for AI agents — one tool across 6 engines, routed to the cheapest + cached.
LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to perform real-time web searches, company research, content crawling, LinkedIn searches, and deep research using the Exa AI Search API. Provides comprehensive web information retrieval capabilities in a safe and controlled manner.233,632 npm1MIT
- AlicenseNot gradedqualityDmaintenanceConnects AI assistants to Exa AI's search capabilities for web search, code context retrieval from GitHub repos and documentation, company research, LinkedIn search, and deep research tasks.6 npmMIT
- AlicenseNot gradedqualityDmaintenanceConnects AI assistants to Exa's search capabilities, enabling web search, code search, and company research.33,632 npmMIT
- AlicenseAqualityCmaintenanceEnables MCP clients to connect to Exa for web search, retrieving URL contents, deep cited-answer search, and research-agent runs. It provides Exa search, content, and research tools with filtering, structured output, and cost reporting.5MIT