Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Brave Ask

FreeNot checked

Unofficial MCP server exposing Brave Ask with full GRAIL ranking signals - stdio, no API key, free

GitHubEmbed

About

Unofficial MCP server exposing Brave Ask with full GRAIL ranking signals - stdio, no API key, free

README

CI License: MIT Python 3.11+ MCP

Unofficial MCP server that queries Brave Ask (Brave's AI-assisted search) and exposes the 22+ GRAIL ranking signals Brave's frontend leaks per result.

No API key. No account. No rate-limited Brave Search API quota. Just the same endpoint your browser hits when you visit search.brave.com/ask, parsed end-to-end so you get back the AI synthesis, the inline citations, the initial top-10 web results, and — for each augmentation tool call the LLM makes — the full raw bo_debug.grail payload (tree_score, fit_for_enhancement, GTE_*, QA_Model_small, popularity, boost, ...).

Useful for: SEO research, GEO / AI-search visibility audits, understanding which signals push a page into Brave's AI synthesis.


What you get back

For one query, ~15-30 seconds, you receive:

Field Description
answer Full markdown synthesis from Brave's LLM (Qwen3 / Claude Haiku)
table_of_content Section titles the LLM structured the answer into
citations All inline-citation URLs (deduped) with title + snippet
initial_results Top-10 web results from the synchronous initial response
fanout_calls[] One per augment_with_* LLM tool call, each with results[] carrying full GRAIL signals
followups Suggested follow-up queries
duration_ms End-to-end latency
conversation_id Brave's internal conversation id (for debug / share-link reconstruction)

GRAIL signals per result (24 fields, with extra="allow" so future Brave additions don't break parsing):

  • Composite: model_score, score, additional_boost, score_without_boost, tree_score, fit_for_enhancement (high|medium|low)
  • Semantic similarity (5 GTE): GTE_Titles, GTE_Url, GTE_Snippets, GTE_Official, GTEReranker
  • Neural reranking (3): QA_Model_small, Top_N_Queries_Cosine_MiniLM_0, TR_All
  • Popularity (5): popularity, fresh_popularity, super_fresh_popularity, wdp_global_popularity, wdp_country_popularity
  • Boost (5): boost, fresh_boost, boost_factor, wdp_boost_factor, wdp_boost

Quickstart

Option A — uvx (recommended, zero install)

uv downloads, isolates, and runs the package on first call. Nothing to install ahead of time.

{
  "mcpServers": {
    "brave-ask": {
      "command": "uvx",
      "args": ["mcp-brave-ask"]
    }
  }
}

Option B — pipx

pipx install mcp-brave-ask
{
  "mcpServers": {
    "brave-ask": {
      "command": "mcp-brave-ask"
    }
  }
}

Option C — pip in a virtualenv

python -m venv .venv && source .venv/bin/activate   # or .\.venv\Scripts\activate on Windows
pip install mcp-brave-ask

Then point your MCP client at the mcp-brave-ask script in .venv/bin/.


Configure your MCP client

Claude Desktop

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "brave-ask": {
      "command": "uvx",
      "args": ["mcp-brave-ask"]
    }
  }
}

Restart Claude Desktop. The ask_brave tool will appear in the tools menu.

Cursor

.cursor/mcp.json (project) or ~/.cursor/mcp.json (global):

{
  "mcpServers": {
    "brave-ask": { "command": "uvx", "args": ["mcp-brave-ask"] }
  }
}

VSCode + Continue

In ~/.continue/config.json, add to the mcpServers array:

{
  "name": "brave-ask",
  "command": "uvx",
  "args": ["mcp-brave-ask"]
}

Codex CLI

~/.codex/config.toml:

[mcp_servers.brave-ask]
command = "uvx"
args = ["mcp-brave-ask"]

Tool reference

ask_brave

ask_brave(
    query: str,
    country: str = "fr",
    language: str = "fr",
    ui_lang: str = "fr-fr",
    safesearch: str = "moderate",      # off | moderate | strict
    enable_research: bool = False,     # Brave's deeper research mode (slower)
    include_grail: bool = True,        # set False to skip /run_tool replays (faster, no GRAIL)
) -> AskBraveResponse

include_grail=False returns only answer, citations, initial_results, table_of_content, followups — about 4× faster than the full GRAIL trip.

Sample response (truncated)

{
  "query": "qu'est-ce que le SEO sémantique",
  "answer": "## Définition du SEO sémantique\n\nLe **SEO sémantique** est ...",
  "table_of_content": [
    "Définition du SEO sémantique",
    "Fonctionnement et intention de recherche",
    "Outils et techniques clés"
  ],
  "citations": [
    { "url": "https://fr.oncrawl.com/...", "title": "Qu'est-ce que le SEO sémantique ?", "snippet": "..." }
  ],
  "initial_results": [
    { "url": "https://semji.com/...", "title": "...", "description": "...", "subtype": null,
      "fit_for_enhancement": null, "tree_score": null, "grail": null }
  ],
  "fanout_calls": [
    {
      "tool": "augment_with_web",
      "sub_query": "outil optimisation texte seo",
      "results": [
        {
          "url": "https://www.example.com/seo-tool",
          "title": "...",
          "description": "...",
          "subtype": "faq",
          "fit_for_enhancement": "high",
          "tree_score": 5.61,
          "grail": {
            "model_score": 1.234,
            "score": 5.61,
            "GTE_Titles": 0.78, "GTE_Url": 0.42, "GTE_Snippets": 0.65,
            "GTE_Official": 0.12, "GTEReranker": 0.71,
            "QA_Model_small": 0.83, "Top_N_Queries_Cosine_MiniLM_0": 0.69, "TR_All": 0.91,
            "popularity": 0.0, "fresh_popularity": 0.0, "super_fresh_popularity": 0.0,
            "wdp_global_popularity": 0.0, "wdp_country_popularity": 0.0,
            "boost": 0.0, "fresh_boost": 0.0, "boost_factor": 0.0,
            "wdp_boost_factor": 0.0, "wdp_boost": 0.0,
            "additional_boost": 0.0, "score_without_boost": 5.61
          }
        }
      ]
    }
  ],
  "followups": [
    "Comment créer un cocon sémantique ?",
    "Quel est le rôle de l'IA dans le SEO sémantique ?"
  ],
  "duration_ms": 18420,
  "conversation_id": "0905..."
}

How it works

Brave Ask's frontend uses a 5-step flow which this MCP replays in pure HTTP (no headless browser, no Selenium):

  1. WarmupGET /ask as a navigation request (else immediate 429)
  2. BootstrapGET /ask/__data.json?q=... returns a SvelteKit data payload that contains a server-pre-signed nonce + sig for this query
  3. SessionGET /api/tap/v1/new?...&symmetric_key=<random>&q=...&nonce=...&sig=... returns a conversation_id. The symmetric_key is just an opaque session token the client picks (32 random bytes, base64url-encoded)
  4. StreamGET /api/tap/v1/stream?id=...&query=...&symmetric_key=... pushes NDJSON events: initial_response, text_start/delta/stop, augment_with_inline_citation, augment_with_* tool_uses (with server-pre-signed signed_params), followups, ...
  5. Replay — for each augment_with_* event, POST /api/tap/v1/run_tool with the tool_use payload verbatim. The response carries service_response.web.results[i].bo_debug.grail — the gold

No client-side cryptography is needed: every signature is server-generated and relayed by us untouched.


Troubleshooting

[RATE_LIMITED] /stream rate-limited after 3 retries — your IP made too many calls in a short window. Wait a few minutes. Brave throttles /stream more aggressively than the bootstrap endpoints. The client already retries with 15 s / 45 s / 90 s backoff before giving up.

[BOOTSTRAP_PARSE_FAILED] — Brave changed the SvelteKit data format. The client tries to find {"q":N,"nonce":M,"sig":K} dynamically (no hardcoded positions), but a deeper rewrite would still break it. Open an issue with the exact error and the date you saw it.

Long answers / timeout — increase timeout (default 60 s) by passing enable_research=False (research mode can take 60-120 s). include_grail=False also shortens the trip if you don't need ranking signals.

Empty fanout_calls — the LLM didn't decide to call any augmentation tools for that query. Some short factual questions ("capital of France") answer purely from initial_response without fan-out.

Overflow files: when the response exceeds max_inline_chars (default 25 000) the full payload is written to a JSON file. By default the file goes to your OS temp directory (%TEMP% on Windows, /tmp or $TMPDIR on macOS/Linux). To redirect to a persistent folder, set:

export MCP_BRAVE_ASK_OUTPUT_DIR="$HOME/brave-ask-cache"

The directory is auto-created on first use.

Set MCP_BRAVE_ASK_DEBUG=1 for verbose logging on stderr.


Disclaimer

This project is not affiliated with Brave Software. It uses public endpoints in the same way a browser does. Use it responsibly:

  • Don't hammer Brave's infrastructure. Cache responses on your side if you need to query the same thing repeatedly.
  • Respect Brave's Terms of Service.
  • The GRAIL signals are exposed by Brave's own frontend through bo_debug — this tool just makes them programmatically accessible. They are not documented and may disappear at any time if Brave decides to strip them.

License

MIT — see LICENSE.

from github.com/JuJu78/mcp-brave-ask

Installing Brave Ask

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/JuJu78/mcp-brave-ask

FAQ

Is Brave Ask MCP free?

Yes, Brave Ask MCP is free — one-click install via Unyly at no cost.

Does Brave Ask need an API key?

No, Brave Ask runs without API keys or environment variables.

Is Brave Ask hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Brave Ask in Claude Desktop, Claude Code or Cursor?

Open Brave Ask on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Brave Ask with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All ai MCPs