Skip to main content

Agent Web Search

One web-search core for AI agents, backed by multiple independent providers.

English | 简体中文

Python 3.10+ PyPI CI MCP 2.x License: MIT

One-click remote MCP

Deploy with Vercel Deploy on Railway Deploy to Render Deploy on Zeabur

Works with Codex CLI, Claude Code, OpenCode, Hermes, ordinary shell scripts, Python applications, and remote Streamable HTTP MCP clients.

Use with an agent · Providers · Shared interface · Configuration · Other interfaces · Troubleshooting · Architecture · Development


Agent Web Search gives an agent two ways to reach the same provider-neutral search core: a native MCP tool, or a CLI taught through a standard Agent Skill. It is not a crawler-result aggregator. It is a natural-language search interface for agent-native backends — including LLM web grounding, neural/semantic search, and conventional search APIs — with one normalized contract.

Agent ──┬── MCP client ────── web_search ──┐
        │                                  │
        └── Shell + Skill ── CLI command ──┤
                                           ▼
                                      SearchEngine
                                           │
                     DDGS · Exa · Parallel · ARK · Brave
                     Gemini · Grok · Perplexity · Tavily · You.com

Why Agent Web Search

  • Concurrent, independent providers. All selected providers run at the same time, and one provider's failure never discards another provider's results.
  • Agent-native natural-language search. This project aggregates search interfaces designed for agents, not scraped pages: Doubao Search, Gemini Google Search grounding, Grok web/X search, neural search, and conventional result APIs all fit the same request surface.
  • Zero-key start. The default providers — DDGS, Exa, and Parallel — work without any API key.
  • Two clean agent integrations. Use MCP for a protocol-native tool, or pair the CLI with the included Skill for agents that already have shell access.
  • Focused responses. Every provider response contains only a generated answer when available and normalized results.
  • No telemetry, no shared secrets. Provider keys stay in runtime environment variables; there is no shared API-key service.

Providers

Free, keyless defaults: DDGS, Exa, and Parallel all work without an API key. Exa and Parallel automatically use their free MCP transports until a paid API key is provided.

Provider Website Search backend API key Enabled by default
DDGS DuckDuckGo DuckDuckGo search Free · no key required Yes
Exa Exa Paid Search API or free MCP fallback Free without key · optional EXA_API_KEY Yes
Parallel Parallel Free MCP or paid LLM-optimized search Free without key · optional PARALLEL_API_KEY Yes
ARK (Recommended) Volcengine Ark Doubao Search ARK_API_KEY No
Brave Brave Search Brave Search API BRAVE_SEARCH_API_KEY No
Gemini Google AI Google Search grounding GEMINI_API_KEY No
Grok xAI xAI web search and X Search XAI_API_KEY No
Perplexity Perplexity API Native structured Search API PERPLEXITY_API_KEY No
Tavily Tavily Tavily Search API TAVILY_API_KEY No
You.com You.com API Unified web and news search YDC_API_KEY No

The provider architecture is intentionally open: another search-capable backend can be added without changing the MCP, Hermes, CLI, or Python-facing interfaces.

Use with an agent

Requirements: Python 3.10+. The default providers — DDGS, Exa, and Parallel — need no API key. Choose one integration shape for your agent; both use the same package and search engine. The PyPI package installs both agent-web-search-mcp and agent-web-search commands.

Option 1: MCP

Choose MCP when the agent supports tool servers and you want typed discovery, protocol-level errors, or remote access. The same agent-web-search-mcp command supports local stdio and stateless Streamable HTTP.

Local stdio MCP

Install the package once:

# Recommended isolated installation
pipx install agent-web-search-mcp

# Or install into the active Python environment
python -m pip install agent-web-search-mcp

Then configure the MCP client to launch agent-web-search-mcp:

{
  "mcpServers": {
    "agent-web-search": {
      "command": "agent-web-search-mcp",
      "args": []
    }
  }
}

If uvx is already available, a client can run the package without a persistent install by using command uvx with args ["agent-web-search-mcp"].

Codex CLI, Claude Code, and OpenCode examples
# Codex CLI
codex mcp add agent-web-search -- agent-web-search-mcp

# Claude Code
claude mcp add agent-web-search -- agent-web-search-mcp

OpenCode:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "agent-web-search": {
      "type": "local",
      "command": ["agent-web-search-mcp"],
      "enabled": true
    }
  }
}

Remote MCP over HTTPS

Use one of the deployment buttons at the top of this README, or run the same server yourself:

python -c "import secrets; print(secrets.token_urlsafe(32))"
export AGENT_WEB_SEARCH_AUTH_TOKEN="replace-with-the-generated-token"
agent-web-search-mcp --transport http

The server exposes authenticated POST /mcp and public GET /healthz. A remote MCP client connects like this:

{
  "mcpServers": {
    "agent-web-search": {
      "url": "https://your-deployment.example/mcp",
      "headers": {
        "Authorization": "Bearer your-deployment-token"
      }
    }
  }
}

Every public deployment must set AGENT_WEB_SEARCH_AUTH_TOKEN to at least 32 characters. The server is stateless and does not create MCP-Session-Id values.

Option 2: CLI + Skill

Choose this shape when the agent already has shell access and supports Agent Skills. The Skill teaches the agent how to invoke the CLI, select controls, interpret results, and handle structured failures; no MCP configuration is needed.

  1. Install the CLI:

    pipx install agent-web-search-mcp
    # Or: python -m pip install agent-web-search-mcp
    
  2. Install the included agent-web-search Skill:

    npx skills add JerryLiu369/agent-web-search --skill agent-web-search
    

    If the agent does not use the skills installer, copy skills/agent-web-search into that client's Skills directory.

  3. Verify the CLI, then let the agent search:

    agent-web-search --version
    agent-web-search "What changed in the latest OpenAI Codex CLI?"
    

The CLI writes one JSON document to stdout on success. If every provider fails, it writes the shared all_providers_failed JSON to stderr and exits with status 1, so shell-capable agents can distinguish a real failure from empty results.

| CLI option | MCP argument | Values | Default | | --- | --- | --- | | positional QUERY | query | 1–4,000 character natural-language question | required | | --provider (repeatable) | providers | enabled provider names | all enabled | | --max-results | max_results | 1–20 | 10 | | --time-range | time_range | d, w, m, y | — | | --grok-search-mode | grok_search_mode | web_search, x_search, both | web_search |

Install the latest development version from GitHub
pipx install 'git+https://github.com/JerryLiu369/agent-web-search.git'

[!IMPORTANT] Do not place API keys in shell history, source code, Git commits, screenshots, or checked-in MCP configuration. Supply them through server-side or local environment variables.

Shared request and response

MCP exposes one tool named web_search; the CLI maps to the same inputs.

Argument Type Required Default Description
query string, 1–4,000 characters Yes — Complete natural-language search question
max_results integer, 1–20 No 10 Desired maximum number of results
time_range d, w, m, y No — Past day, week, month, or year
providers string array No All enabled Narrow the request to enabled providers
grok_search_mode web_search, x_search, both No web_search Available only when Grok is enabled

Example call:

{
  "query": "GPU kernel generation papers from the past month",
  "max_results": 5,
  "time_range": "m",
  "providers": ["ddgs", "exa"]
}

Provider selection has two levels:

  1. AGENT_WEB_SEARCH_PROVIDERS defines the provider set when the process starts.
  2. The request-level providers argument may narrow that set, but cannot enable a provider that was disabled at startup.

Response format

Each selected provider that succeeds appears under providers; failed providers are omitted:

{
  "query": "GPU kernel generation papers from the past month",
  "providers": {
    "ddgs": {
      "results": [
        {
          "title": "Example result",
          "url": "https://example.com/paper",
          "description": "Excerpt of the matching page",
          "published_at": "2026-08-02"
        }
      ]
    }
  }
}
Field Meaning
answer Provider-generated prose answer, when the backend produces one; omitted otherwise
results Result rows: title, url, description, plus optional published_at and author

If every selected provider fails, MCP returns a tool error. The CLI writes the same payload to stderr and exits with status 1. Both use the stable code all_providers_failed and include per-provider diagnostics:

{
  "error": {
    "code": "all_providers_failed",
    "message": "All enabled search providers failed. Check provider configuration, credentials, quotas, and network access.",
    "provider_errors": {
      "ddgs": "RuntimeError: rate limited"
    }
  },
  "query": "GPU kernel generation papers from the past month"
}

Python API

The CLI, MCP servers, and Hermes plugin are thin wrappers around agent_web_search.SearchEngine, which is the public Python API. SearchRequest accepts the same fields as the MCP tool arguments:

from agent_web_search import SearchEngine, SearchRequest

engine = SearchEngine()  # reads AGENT_WEB_SEARCH_* variables at construction

response = engine.search(
    SearchRequest(query="latest MCP spec changes", max_results=5, time_range="m")
)

for name, provider in response.providers.items():
    print(f"{name}: searched={provider.searched}, results={len(provider.results)}")

if response.all_providers_failed:
    print(response.failed_provider_errors)

Configuration

Configuration is read from environment variables when the CLI, MCP server, or Hermes plugin starts. Restart the process after changing provider settings. See .env.example for a commented template of every variable.

General settings

Variable Default Purpose
AGENT_WEB_SEARCH_PROVIDERS ddgs,exa,parallel Comma-separated startup-enabled provider set
AGENT_WEB_SEARCH_TIMEOUT 60 Socket timeout for a single upstream HTTP call. Multi-step providers multiply it: keyless Parallel makes up to 3 calls (worst case 3×), ARK may append a continuation call (worst case 2×), so the whole search can take up to 3 × this value

Example:

export AGENT_WEB_SEARCH_PROVIDERS="ddgs,exa,brave"
export AGENT_WEB_SEARCH_TIMEOUT="30"
$env:AGENT_WEB_SEARCH_PROVIDERS = "ddgs,exa,brave"
$env:AGENT_WEB_SEARCH_TIMEOUT = "30"

HTTP transport settings

Variable Default Purpose
AGENT_WEB_SEARCH_MCP_TRANSPORT stdio stdio or http; --transport may override it
AGENT_WEB_SEARCH_HTTP_HOST 0.0.0.0 HTTP bind host for container deployments
AGENT_WEB_SEARCH_HTTP_PORT PORT or 8000 HTTP bind port; explicit value overrides platform PORT
AGENT_WEB_SEARCH_AUTH_TOKEN — Required HTTP Bearer Token, at least 32 characters
AGENT_WEB_SEARCH_ALLOW_ANONYMOUS false Explicitly disables HTTP auth for trusted/demo environments
AGENT_WEB_SEARCH_HTTP_ALLOWED_HOSTS — Optional comma-separated Host allowlist
AGENT_WEB_SEARCH_HTTP_ALLOWED_ORIGINS — Optional comma-separated Origin allowlist; requires allowed hosts
AGENT_WEB_SEARCH_HTTP_LOG_LEVEL info Uvicorn log level for the container server

HTTP settings remain environment-only; the deployment files do not introduce a second application configuration format.

Provider settings

Default providers are listed first; optional providers then follow alphabetical order.

1. DDGS

DDGS uses DuckDuckGo and requires no API key or provider-specific environment variables. The ddgs Python dependency is installed with the package.

2. Exa

Exa supports both paid and keyless modes.

Variable Required Purpose
EXA_API_KEY No Uses the paid Search API when present
EXA_MCP_URL No Overrides the free MCP endpoint when no API key is set

Without EXA_API_KEY, Exa falls back to its free MCP endpoint on a best-effort basis. The paid API generally provides higher quota and reliability.

3. Parallel

Parallel returns information-dense excerpts ranked for LLM context. One parallel provider automatically selects its transport:

  • Without a key, it uses Parallel's free Search MCP.
  • With PARALLEL_API_KEY, it uses the paid Search REST API.

Both transports map excerpts into the common result description, so the calling agent does not need to distinguish parallel-free from parallel.

Variable Required Purpose
PARALLEL_API_KEY No Enables the paid API; omit it to use the free MCP

Parallel is enabled by default and its key is optional.

4. ARK (Recommended)

Volcengine ARK uses model-backed search grounding through the Responses API. Add ark to AGENT_WEB_SEARCH_PROVIDERS after providing the key.

Variable Required Purpose
ARK_API_KEY Yes One key, or multiple comma/newline-separated keys
AGENT_WEB_SEARCH_ARK_MODELS No Comma/newline-separated ARK model IDs

One model stays fixed; multiple models are selected round-robin for successive requests. When multiple ARK keys are configured, a key is selected per request.

Optional Volcengine collaboration rewards information

Agent Web Search does not require participation in a rewards program. ARK users may optionally review the official Volcengine Collaboration Rewards Program. Quota, supported models, validity periods, and data-authorization terms can change. Check the official terms before opting in. Participation is not required to use Agent Web Search.

5. Brave

Variable Required Purpose
BRAVE_SEARCH_API_KEY Yes Brave Web Search API credential

Add brave to AGENT_WEB_SEARCH_PROVIDERS after providing the key.

6. Gemini

Variable Required Purpose
GEMINI_API_KEY Yes Google AI API credential
AGENT_WEB_SEARCH_GEMINI_MODELS No Comma/newline-separated Gemini model IDs

Gemini maps common result and time controls into best-effort prompt constraints. One configured model stays fixed; multiple models are selected round-robin for successive requests.

7. Grok

Variable Required Purpose
XAI_API_KEY Yes xAI API credential
AGENT_WEB_SEARCH_GROK_MODELS No Comma/newline-separated Grok model IDs

One configured model stays fixed; multiple models are selected round-robin for successive requests.

When Grok is enabled, the public tool schema adds grok_search_mode:

  • web_search searches the web.
  • x_search searches X with native date filters when available.
  • both exposes both server-side tools in one request and lets Grok choose; it does not issue two independent model requests.

8. Perplexity

This provider uses Perplexity's native structured Search API. It returns result rows rather than a Sonar-generated prose answer; OpenRouter compatibility is intentionally outside this provider's scope.

Variable Required Purpose
PERPLEXITY_API_KEY Yes Perplexity Search API credential

Add perplexity to AGENT_WEB_SEARCH_PROVIDERS after providing the key.

9. Tavily

Variable Required Purpose
TAVILY_API_KEY Yes Tavily Search API credential

Add tavily to AGENT_WEB_SEARCH_PROVIDERS after providing the key.

10. You.com

You.com returns unified web and news sections. Agent Web Search merges both, deduplicates URLs, and applies max_results to the combined result list.

Variable Required Purpose
YDC_API_KEY Yes You.com Search API credential

Add you to AGENT_WEB_SEARCH_PROVIDERS after providing the key.

Common search controls

Each provider maps the shared controls to its native API when possible and ignores unsupported controls.

Provider max_results time_range
DDGS Native max_results Native timelimit
Exa Native result count Native publish date
Parallel REST: native max_results; keyless MCP: client-side truncation (results[:max_results]) Ignored
ARK Native limit Prompt constraint
Brave Native count Native freshness
Gemini Prompt constraint Prompt constraint
Grok Prompt constraint Prompt; X Search also uses native dates
Perplexity Native max_results Native recency filter
Tavily Native max_results Native time_range
You.com Native count, combined cap Native freshness

Prompt-based controls are best-effort and are not strict guarantees.

Other interfaces

Native Hermes plugin

Install the native plugin directly from GitHub:

pip install 'ddgs>=9.0'
hermes plugins install JerryLiu369/agent-web-search --no-enable
hermes plugins enable agent-web-search --allow-tool-override

The plugin intentionally replaces Hermes' built-in web_search tool, so the explicit --allow-tool-override grant is required. Start a new Hermes session after enabling it; restart the gateway when using a messaging channel.

Hermes can also connect through its generic MCP integration instead of the native plugin.

Troubleshooting

  • all_providers_failed — every selected provider errored. MCP marks the call as an error; the CLI writes diagnostics to stderr and exits 1. Check keys, quotas, and network access. A single retry may help a transient limit.
  • agent-web-search is not found — install the PyPI package with pipx or pip, then start a new shell so its scripts directory is on PATH.
  • HTTP 401 invalid_token — the Authorization: Bearer … header must match AGENT_WEB_SEARCH_AUTH_TOKEN, which must be at least 32 characters.
  • A provider is missing from a response — failed providers are omitted from successful responses. The Python API exposes the reasons in response.failed_provider_errors.
  • Provider changes have no effect — provider settings are read once at startup; restart the CLI, MCP server, or Hermes plugin after changing them.
  • MCP client times out before the tool returns — AGENT_WEB_SEARCH_TIMEOUT bounds a single upstream HTTP call, not the whole search. Keyless Parallel issues up to 3 calls and ARK may append a continuation request, so the worst case is 3 × AGENT_WEB_SEARCH_TIMEOUT; configure your MCP client's tool timeout accordingly.

Development

Using uv keeps the development environment isolated and reproducible:

git clone https://github.com/JerryLiu369/agent-web-search.git
cd agent-web-search
uv venv
uv pip install -e '.[dev]'
uv run pytest -q
uv run ruff check .
Standard venv + pip alternative
python -m venv .venv
# Linux/macOS: source .venv/bin/activate
# Windows PowerShell: .venv\Scripts\Activate.ps1
python -m pip install -e '.[dev]'
pytest -q
ruff check .

ARCHITECTURE.md is the design source of truth, and AGENTS.md lists the non-negotiable invariants. Read both before changing transports, configuration, authentication, deployment, providers, or tool schemas, keep stdio and HTTP behavior identical, and keep pytest and ruff green in the same change.

License

MIT

Metadata

Release files for agent-web-search-mcp 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-web-search-mcp 0.6.0
File Size Uploaded
agent_web_search_mcp-0.6.0.tar.gz 64.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-web-search-mcp 0.6.0
File Interpreter ABI Platform
agent_web_search_mcp-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 106.8 kB

Release files / agent_web_search_mcp-0.6.0.tar.gz

Download URL agent_web_search_mcp-0.6.0.tar.gz
Size 64.0 kB
Tags Source
SHA-256 checksum
How to use checksums
24daa34971ad0dde6067ebded6c90bf12b421cd75ead59d09b489c23048587dd
BLAKE2b-256 checksum
How to use checksums
ccfb3b52cd61e89deecf4d74234d41a0fe90a67adffab5578df96687784c4199
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.

Transparency log

Release files / agent_web_search_mcp-0.6.0-py3-none-any.whl

Download URL agent_web_search_mcp-0.6.0-py3-none-any.whl
Size 42.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
920577fd664d51581a7afcd4afabeb47603c439accdfa173b97deb1e1de1157a
BLAKE2b-256 checksum
How to use checksums
02c938b723c9efc5c3cda5e2caee166fb2f8df090597d6bf3521d21e58d2afb4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.

Transparency log

Release history Release notifications | RSS feed

0.8.0

2 release files

0.7.5

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

This release

0.6.0 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page