brave-answers-mcp

brave-answers-mcp

MCP server that wraps the Brave Answers API, enabling synchronous Q&A and asynchronous deep research with job submission, status polling, and result retrieval.

Category
访问服务器

README

brave-answers-mcp

CI

TypeScript MCP server (stdio) wrapping the Brave Answers API (POST https://api.search.brave.com/res/v1/chat/completions, header X-Subscription-Token). The Brave Answers plan is billed separately from the Brave Search plan — the key is provided as the BRAVE_ANSWERS_KEY env var (never commit or print it).

Why it exists: no MCP wraps this endpoint (verified 2026-08), and research-mode calls run ~90–300s — far beyond a blocking agent tool call. This server adds the missing async submit → status → result semantics: the job lives in the MCP server process, so it outlives bash timeouts and turn boundaries. The SSE parser was ported from a working production browser implementation (streaming pass-through only) and extended with the <answer> tag and display normalization.

Quick start

npm install
npm run build
export BRAVE_ANSWERS_KEY=...
node dist/index.js    # speaks MCP over stdio

Register it in your agent's MCP config (opencode example below).

Tools

Tool Mode Latency Cost (all measured 2026-08-16)
answers sync single-search, streaming ~10–30s $0.051–0.055/call (citations on/off; entities n/a)
research_submit async research, returns research_id immediately ~90–312s (wall can exceed budget — see gotchas) $0.069–0.084 narrow, $0.771 for a 10-query broad run — see cost model
research_status poll job instant free
research_result fetch completed job instant free

answers params: query, country?, language?, enable_citations? (default true). (enable_entities exists in the API but is silently ignored — verified via raw SSE probe 2026-08-16: zero <enum_item> frames — so it is not exposed; the parser branch is kept in case it ships later.)

research_submit params: query, country?, language?, research_maximum_number_of_iterations? (1–5, default 4), research_maximum_number_of_seconds? (1–300, default 180; soft target), research_allow_thinking? (default true), research_maximum_number_of_queries? (1–50, default 20), research_maximum_number_of_tokens_per_query? (1024–16384, default 8192), research_maximum_number_of_results_per_query? (1–60, default 60). Research mode cannot mix with citations — enforced by omitting that key. research_status reports live progress (last <progress> frame) while the job runs; raw SSE is teed for every call.

Request body: model: "brave", exactly one user message, always stream: true (one tested code path). Timeouts: 60s simple / 600s research. Responses are routed to an internal brave-pro model.

Cost model (measured 2026-08-16)

<usage> breaks cost into four components:

Component Rate (derived) Example run
Input tokens ~$0.005 per 1K 9,210 tokens → $0.046 (dominant)
Output tokens ~$0.005 per 1K 153 tokens → $0.0008
Search queries ~$0.004 each 1 → $0.004
Requests $0 1 → $0.00

Research cost is driven by how many queries the engine actually runs (~$0.07/query effective, dominated by snippet tokens), not the iteration caps — those are ceilings, not targets:

Question type Queries run Cost Wall
Narrow (speculative decoding / MLX) 1 (of 4-iter cap) $0.079 136s
Narrow (forced 1 iteration) 1 $0.069 91s
Broad (solid-state batteries, 3-iter) 10 $0.771 312s (240s soft budget)

So the commonly cited ~$1+/call figure is reasonable for full default runs (20-query cap — historical multi-query runs measured $1–1.45) while early-terminating narrow questions are just cheap. Budget rule of thumb: ~$0.07 × expected queries.

Full <usage> fields: X-Request-Requests, X-Request-Queries, X-Request-Tokens-In/Out, X-Request-Requests-Cost, X-Request-Queries-Cost, X-Request-Tokens-In-Cost, X-Request-Tokens-Out-Cost, X-Request-Total-Cost.

SSE tags parsed: <citation>, <enum_item>, <usage>, <queries>, <analyzing>, <thinking>, <progress>, <blindspots> plus <answer> — in research mode the final answer arrives as <answer>{"answer": "..."}</answer> (a JSON object; also handled if it's a JSON string). Everything else accumulates as answer content. usage JSON carries X-Request-Total-Cost / X-Request-Queries / X-Request-Requests.

Display normalization (learned from live runs 2026-08-16): citations are deduped by URL (Brave emits one frame per inline occurrence — a 10-citation answer returned 21 frames); repeated <progress> frames for the same iteration are collapsed, last frame per iteration wins.

Job registry: in-memory Map, 1h TTL after completion. Raw SSE is teed for every call to $TMPDIR/brave-answers-mcp/<research_id>.sse (research jobs) or <uuid>.sse (simple calls) for debugging. Note $TMPDIR, not /tmp — hosts like opencode set a per-user temp dir for child processes. Wiped on reboot.

Build & test

npm install        # once
npm run build      # tsc → dist/  (re-run after source changes, then restart opencode)
npm run test:parser   # offline unit tests for the SSE parser (no API calls)
node dist/smoke.js    # end-to-end: tool listing, error path, one LIVE simple call (~$0.05)

Node 24, @modelcontextprotocol/sdk 1.30.0, zod 3.25. registerTool takes a zod shape (not z.object). The SDK's StdioClientTransport gives child processes a sanitized env by default (getDefaultEnvironment) — pass env: explicitly in any test client; see registration below for the opencode side.

SDK note (2026-08): 1.30.0 is the last v1-line release. The v2 line (split @modelcontextprotocol/server + /client packages) shipped with the 2026-07-28 MCP spec; v1 receives bug fixes for six months after the v2 release, so migration is not urgent.

opencode registration

In ~/.config/opencode/opencode.json (global) — replace the path with this repo's location:

"brave-answers": {
  "type": "local",
  "command": ["node", "<repo-root>/dist/index.js"],
  "environment": { "BRAVE_ANSWERS_KEY": "{env:BRAVE_ANSWERS_KEY}" },
  "enabled": true
}

environment (not env) is the key that works for local MCPs. The {env:VAR} interpolation reads from opencode's own environment. If a call returns 401 after restart, the interpolation didn't apply — delete the environment block and rely on shell-env inheritance instead (opencode launched from the terminal inherits ~/.zshrc exports). Restart opencode after any config change (not hot-reloaded).

A search skill for opencode (see references/ notes) documents the agent-facing workflow: answers for cited one-shot answers, research_submit → research_status → research_result for deep research.

Artifacts & references

  • artifacts/sse/ — raw SSE streams from the 2026-08-16 test runs (cost evidence, dedup evidence, enable_entities probe). See artifacts/README.md.
  • references/official-brave-skills/ — pinned copy of the official Brave answers skill (brave/brave-search-skills @ 62793e0), the source of truth for request parameters and tag formats.

API gotchas (from Brave docs + live testing)

  • Exactly one user message per request.
  • enable_research requires stream: true; incompatible with enable_citations and enable_entities (research has built-in citations).
  • enable_citations requires streaming; citations arrive as <citation> frames with number/url (+ optional start_index/end_index/snippet).
  • Progress frames repeat per iteration (multiple frames, same number_of_iterations); the cost-relevant fields are in the final <usage> frame — surface it to the user.
  • research_maximum_number_of_seconds is a soft target, not a hard wall-clock cap: a job submitted with a 30s budget ran 91s.
  • Iteration caps are ceilings, not targets: both observed research runs (1-iter-forced and 4-iter-default) executed exactly 1 query / 60 URLs and stopped. Cost follows actual queries/tokens — see the cost model above.
  • enable_entities is silently ignored by the API (no <enum_item> frames even when set; stream routes to brave-pro) — not exposed in the schema.
  • The <progress> payload's seconds field has been seen spelled elasped_seconds (upstream typo); the parser handles both.

License

MIT — see LICENSE.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选