Model or dataset
Episkey-G/GrokSearch-rs avatar
Episkey-G/GrokSearch-rs

GrokSearch-rs: a Rust MCP server that puts Grok search and a provider chain inside your MCP client

Rust MCP server for Grok web search and Tavily-backed source retrieval

455 stars50 forksRustMIT

At a glance

What is it?
GrokSearch-rs exposes web_search, get_sources, web_fetch, web_map and doctor over stdio or Streamable HTTP, with Tavily, Exa, TinyFish and Firecrawl as an ordered fallback chain for sources and fetching. The design is opinionated about context budgets and thin on rollback.
Who is it for?
Adopt GrokSearch-rs if you already run an MCP client and want Grok-backed search with cited sources and paged retrieval instead of pasting search results into a prompt. Skip it if you need a general-purpose URL fetcher without a source provider key, since the README states ordinary URLs cannot be fetched at all in that configuration, or if you want a documented rollback path between releases.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 22 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap GrokSearch-rs fills for MCP clients

An MCP client can call tools, but it cannot browse. GrokSearch-rs is an MCP server that gives the client one set of tools (web_search, get_sources, web_fetch, web_map, doctor) and hides two upstream transports behind them: xAI's native Responses API at /v1/responses, or any OpenAI-compatible chat-completions gateway at /v1/chat/completions. The transport is chosen by environment variables, not a command-line flag.

The intended user is someone who already has an MCP client (Claude, Codex, or anything that speaks the protocol) and wants search results with citations that survive into a follow-up call. That second part matters more than it sounds. A normal search tool returns text and forgets it. GrokSearch-rs caches sources so get_sources can page through them later with offset and limit, which means an agent can ask for the top three sources now and pull the rest only if it needs them.

It is not a search engine of its own. Grok answers the query; Tavily, Exa, TinyFish and Firecrawl supply supplemental sources, fetch, and map. If you have no Grok-compatible key, the search half does not work at all.

How the tool set and the provider chain actually fit together

web_search is the entry point and is enabled by default. It returns cited sources and caches them. The opt-in include_content flag enriches the top sources with full extracted text in the same call, which saves a round trip but costs context.

Response budgeting is the most deliberate part of the design. Only the top max_inline_sources carry inline text. A whole-response character budget, response_max_chars, defaults to 45k and is described as sized to stay under the MCP client token ceiling after JSON serialization. Tail sources beyond that are trimmed with recovery notes rather than dropped silently, and the session cache always keeps the full content, so nothing is lost from the server's side. response_format accepts "concise" or "detailed".

web_fetch is where the architecture gets interesting. GitHub issues, pull requests and releases, StackExchange and MathOverflow, arXiv, and Wikipedia URLs are parsed by specialist extractors that need no API key. Everything else falls back to the generic source chain, walking Tavily, Exa, TinyFish, Firecrawl in the configured order, and the first provider with results wins. GROK_SEARCH_SOURCE_PROVIDERS reorders that chain. The README is explicit that with no source provider configured, ordinary URLs cannot be fetched at all, only the specialist families above. Output carries source_type and a fallback_reason when a specialist was skipped.

On the stdio transport, up to 8 tool calls run concurrently; anything beyond that queues rather than being refused, and responses come back in completion order paired to requests by JSON-RPC id. That is a real behavior difference from servers that serialize everything.

Installing GrokSearch-rs and getting a first search out of it

The npm package ships a native Rust binary, so the global install is the shortest path. The grok-search-rs command is what your MCP client launches, not something you run yourself for normal operation.

bash
npm install -g grok-search-rs

After that, add the server entry to your client config. The README gives this JSON shape, with empty values you are meant to fill in:

json
{
  "grok-search-rs": {
    "command": "grok-search-rs",
    "args": [],
    "env": {
      "GROK_SEARCH_API_KEY": "",
      "GROK_SEARCH_URL": "",
      "GROK_SEARCH_MODEL": "grok-4.20-fast",
      "TAVILY_API_KEY": "",
      "TAVILY_API_URL": "https://api.tavily.com",
      "FIRECRAWL_API_KEY": ""
    }
  }
}

For Codex, the README shows the equivalent TOML under mcp_servers.grok-search-rs with type = "stdio". If your client expects a top-level mcpServers or mcp_servers object, the grok-search-rs entry goes under that section.

Rather than duplicating env blocks in every client, you can scaffold a shared global config file. Both commands are from the README:

bash
grok-search-rs --init
$EDITOR ~/.config/grok-search-rs/config.toml

The verification step is not a shell command. The README says to ask your assistant to call doctor. Successful output shows reachable: true for each enabled upstream and transport: Responses or transport: ChatCompletions. doctor also reports whether your config file was found, loaded, or rejected, and why, with redacted config.

If you would rather not install anything, the README documents a hosted endpoint where you pass your own keys as headers:

bash
claude mcp add --transport http grok-search https://mcp.episkeyai.com/groksearch_rs/mcp \
  --header "X-Grok-Api-Key: xai-..." \
  --header "X-Tavily-Api-Key: tvly-..."

The default gateway there is xAI official at api.x.ai. For another Grok-compatible gateway, the README says to add an X-Grok-Base-Url header with a matching key and optionally X-Grok-Model, noting that model ids are gateway-specific. No keys are stored server-side, and availability is described as best-effort.

The fetch gap, the key handling, and where the docs go quiet

The sharpest limitation is stated plainly in the README: with no source provider configured, ordinary URLs cannot be fetched at all. The specialist extractors cover GitHub, StackExchange, arXiv and Wikipedia, and that is the whole list. If your agent spends its time reading vendor documentation, blog posts or changelogs, the free path does not cover you, and you are choosing a paid provider whether you meant to or not.

Key handling has its own asymmetry. On stdio, credentials arrive as environment variables. On remote HTTP they arrive as per-request headers, and the server stores no keys. The docker-compose file repeats that warning in capitals: never put *_API_KEY in the operator environment, because credentials come from per-request headers and the server strips any server-side keys from the per-request config. Anyone deploying the HTTP build should treat that as a configuration invariant, not a suggestion.

Tavily keys accept a comma-separated list and rotate round-robin with automatic failover on key-scoped errors (401, 403, 429, 432, 433). That is a practical answer to per-key quotas, and it only applies to Tavily.

What the README does not document is rollback. There is a CHANGELOG.md and a RELEASING.md in the repository, and releases are tagged, but the README does not describe how to move back to an earlier version if an upgrade breaks a client. The Cargo.toml pins rust-version = "1.78", so source builds have a floor, but the npm package is the documented install path and its downgrade story is not spelled out in the README.

GrokSearch-rs compared with a single-provider search MCP server

The obvious alternative is a search MCP server built around one provider: a Tavily-only or Exa-only server that exposes a search tool and a fetch tool and stops there. The difference is not the number of vendors. It is what happens when the first provider fails or returns nothing useful.

A single-provider server has one failure mode: the provider is down or the key is exhausted, and the tool call fails. GrokSearch-rs walks an ordered chain and takes the first provider with results, so a Tavily outage can be absorbed by Exa, TinyFish or Firecrawl depending on how you ordered GROK_SEARCH_SOURCE_PROVIDERS. The cost of that resilience is configuration surface: four API key variables, four optional base URLs, four enable flags, plus the ordering variable, and a behavior difference between the specialist extractors and the generic chain that you have to explain to whoever reads the tool output.

A second alternative is skipping the MCP layer and calling the xAI API directly from your own application. That gives you full control over retries and payload shape, and it removes the 45k response budget that GrokSearch-rs imposes. It also means you write the caching, paging and specialist extraction yourself. The project's value is concentrated in those three things, not in the API call.

Optional Grok OAuth mode is worth noting for a different reason. The login, status and logout commands store a local xAI OAuth token so the server can run without GROK_SEARCH_API_KEY. That is a convenience for a single developer on a laptop and a poor fit for a shared server, where the header-based key model is the documented path.

Licence, upgrade cost, and the maintenance picture

The licence is MIT, declared in both Cargo.toml and the repository root. MIT is permissive: it allows commercial use, modification and redistribution with the licence text retained. It provides no patent grant and no warranty. This is a description of what the licence says, not advice about your situation; if you are redistributing the binary inside a product, have someone qualified read the LICENSE file.

The last push to the default branch was on 2026-09-09, and v0.1.26 was tagged the same day. v0.1.25 came on 2026-08-27 and v0.1.24 on 2026-08-05. That is a steady cadence across three releases in roughly five weeks, and the repository is not archived.

Upgrade cost is mostly configuration drift. The npm package is the documented install, so upgrading means reinstalling the global package and restarting whatever MCP client launches it. The Cargo.toml carries rust-version = "1.78" for anyone building from source. The HTTP feature is off by default, so a stdio user who upgrades never pulls axum or the multi-threaded runtime; the Cargo.toml comment says the default build stays a pure stdio binary so local users are entirely unaffected. The Dockerfile builds with --profile release-http and --features http, and notes that profile uses panic=unwind so a handler panic cannot abort the whole process, which the default release profile (panic = "abort") would do. That distinction matters if you self-host: the image and the npm binary are not built the same way.

Editorial conclusion

Adopt GrokSearch-rs if you already run an MCP client and want Grok-backed search with cited sources and paged retrieval instead of pasting search results into a prompt. Skip it if you need a general-purpose URL fetcher without a source provider key, since the README states ordinary URLs cannot be fetched at all in that configuration, or if you want a documented rollback path between releases. Before wiring it into a shared client, run doctor and confirm reachable: true for each upstream you enabled, and check whether the version you installed matches v0.1.26 from 2026-09-09.

Frequently asked questions

Do I need a Tavily or Firecrawl key to use GrokSearch-rs?

Not for the specialist extractors. GitHub issues, pull requests and releases, StackExchange and MathOverflow, arXiv and Wikipedia URLs are parsed without any API key. For anything else, the README states that with no source provider configured, ordinary URLs cannot be fetched at all.

How do I check that GrokSearch-rs is configured correctly?

Call the doctor tool. The README says to ask your assistant to call doctor, and successful output shows reachable: true for each enabled upstream plus transport: Responses or transport: ChatCompletions. doctor also reports whether your config file was found, loaded, or rejected, and why.

Can I run GrokSearch-rs on a server instead of locally?

Yes, by building with the http feature to serve the same tools over Streamable HTTP. In that mode each request carries the caller's own keys as headers such as X-Grok-Api-Key and X-Tavily-Api-Key, and the server stores no keys.

What happens when one of the source providers fails?

The supplemental sources and generic fetch walk an ordered chain of Tavily, Exa, TinyFish and Firecrawl, and the first provider with results wins. GROK_SEARCH_SOURCE_PROVIDERS reorders that chain, and Tavily keys accept a comma-separated list that rotates round-robin with automatic failover on key-scoped errors.

Official sources

  1. Episkey-G/GrokSearch-rs on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/episkey-g-groksearch-rs.svg)](https://hysenlabs.com/projects/episkey-g-groksearch-rs)