Back to the catalog

io.github.lennney/agent-search-mcp

Free-first Chinese and English web search MCP using zero-key sources and inspectable evidence.

Open source Open in the app JSON README (API)

About

Free-first Chinese and English web search MCP using zero-key sources and inspectable evidence.

Details

Kind
MCP servers
Topic
Web search, scraping & browser
Publisher
lennney
Origin
official
Category
ferramentas
Transport
local
Version
3.2.1
Stars
108
Forks
9
Open pull requests
5
Last push
2026-08-17T13:37:14Z
Repository state
ativo
Language
TypeScript
License
Apache-2.0
Added
2026-08-29 04:00:23
Updated
2026-08-29 04:00:23
Origin id
io.github.lennney/agent-search-mcp

README

# Agent Search MCP: Free-first Web Search with Inspectable Evidence

**A Node.js MCP server and CLI for English and Chinese web search.**

Agent Search MCP starts without an API key. It returns compact multi-source
evidence, records provider failures, and bounds work with request and evidence
budgets. Paid providers run only when policy and credentials allow.

[![npm version](https://img.shields.io/npm/v/agent-search-mcp)](https://www.npmjs.com/package/agent-search-mcp)
[![npm downloads](https://img.shields.io/npm/dm/agent-search-mcp)](https://www.npmjs.com/package/agent-search-mcp)
[![GitHub stars](https://img.shields.io/github/stars/lennney/agent-search-mcp)](https://github.com/lennney/agent-search-mcp/stargazers)
[![CI](https://github.com/lennney/agent-search-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/lennney/agent-search-mcp/actions)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
[![Glama](https://glama.ai/mcp/servers/lennney/agent-search-mcp/badges/score.svg)](https://glama.ai/mcp/servers/lennney/agent-search-mcp)

[中文文档](README_zh.md) · [Product page](https://take-a-deep-breath0.com/en/agent-search-mcp) · [Benchmarks](./benchmarks/) · [Architecture](./docs/architecture.md) · [CHANGELOG](./CHANGELOG.md)

---

## Install

```bash
npx -y agent-search-mcp
```

Requires Node.js >= 18.17. The default runtime does not require a browser,
database, Python, or a search API account.

### Connect an MCP client

Use this stdio configuration in MCP clients that accept `mcpServers` JSON,
including Claude Desktop, Cursor, VS Code, and Windsurf:

```json
{
  "mcpServers": {
    "agent-search": {
      "command": "npx",
      "args": ["-y", "agent-search-mcp"]
    }
  }
}
```

Claude Code and Codex can register the same `npx -y agent-search-mcp` stdio
command through their MCP settings.

### Add the optional Agent Skill

After connecting the MCP server, Agent Skills-compatible clients can install
the repository-owned routing guide:

```bash
npx skills add lennney/agent-search-mcp --skill agent-search
```

Invoke it with a request such as `Use $agent-search to verify this claim with
official sources.` The [Agent Search Skill](./skills/agent-search/SKILL.md)
chooses one of four bounded paths: quick discovery, stricter verification,
Chinese-source search, or extraction of a selected URL. It checks that the
needed MCP tool exists and asks before any install or configuration change.
Installing the Skill does not start or configure the MCP server.

### Example: inspect a bounded search result

After building the local package, run a CLI query without adding a provider key:

```bash
npm run build
fasm search "MCP server without an API key" --json
```

The response contract keeps result evidence, `meta.execution`, and
`partialFailures` separate. A provider timeout or challenge remains visible to
the agent instead of being converted into an unexplained empty result. This is
a contract example, not a live availability or search-quality benchmark.

After a global install, check the local runtime without making a search request:

```bash
npm install -g agent-search-mcp
fasm doctor
```

## Why Agent Search MCP

| Need | Product behavior |
|---|---|
| Free web search | Zero-key sources work without an API account |
| Provider cost control | Paid providers run only under an explicit routing policy |
| Token cost control | Compact output and one evidence budget bound response size |
| Multi-source evidence | Results retain provenance, relevance, provider-family count, and partial failures |
| Chinese web search | Sogou and Baidu handle Chinese queries without a translation layer |
| Lightweight self-hosting | Pure Node.js runtime with stdio, Streamable HTTP, and CLI access |

### The difference from a plain multi-engine wrapper

| Plain multi-engine aggregation | Agent Search MCP |
|---|---|
| Returns N deduplicated results | Returns results plus the number of **independent sources** (provider families, not adapter names) |
| A provider failure quietly drops some results | Every failure stays in `partialFailures` (timeout, rate limit, challenge, permission, budget) |
| Stops when the result count looks sufficient | Stops only after a quality gate (count, relevance, confidence, source coverage) and returns the `stop_reason` |
| Fixed-size output | One shared evidence budget bounds response tokens; compact text keeps provenance |
| One adapter counts as one source | The same upstream through several adapters never inflates `source_count` |

The one-minute offline demo replays these differences through the production
evidence scorer and formatter:

### Inspect the search evidence

Each JSON response includes one Search Evidence Packet. It answers the routing
questions an agent needs before it uses a result:

| Question | Response field |
|---|---|
| Which adapters ran? | `meta.execution.searched_engines` |
| Why did the router stop? | `meta.execution.stop_reason` and `meta.execution.quality_gate` |
| Did the request hit a work limit? | `meta.execution.budget` |
| Was evidence truncated? | `meta.evidence_budget` |
| Did an upstream provider fail? | `partialFailures` |
| Do multiple adapters represent independent sources? | `results[].source_count` counts provider families, not adapter names |

Run the one-minute offline contract demo:

```bash
npm run demo:evidence
npm run demo:evidence -- --json
```

It replays three synthetic scenarios through the production evidence scorer,
formatter, and MCP output helper: same-family adapter overlap, visible fallback
failure, and a bounded quality-gate stop. It makes no live availability or
search-quality claim and performs no network request.

The default `free_first` policy never spends a configured API credential.
`free_only` blocks paid providers. `quality_escalation` can call one configured
paid provider after free evidence misses the quality gate, while `paid_first`
tries that provider before the free fallback.

Request budgets cap adapter attempts, elapsed time, and admitted results.
The evidence budget caps query-relevant passages across the complete response.
Compact mode keeps full detail for the first results and reduces later entries
to source-preserving references.

### Measured token reduction

The checked-in bilingual fixture measures formatting with a locked tokenizer:

| Output | Average tokens per query | Savings vs normal |
|---|---:|---:|
| Normal | 2396.0 | |
| Compact | 1650.1 | 31.1% |
| Compact+ | 1633.0 | 31.8% |

This fixture verifies output formatting and evidence-packet behavior. It does
not measure live engine availability or search quality. See the
[benchmark method and limitations](./benchmarks/#reproducible-fixture-replay).

## How the search router works

```mermaid
flowchart LR
    A["AI agent"] --> M["MCP search tools"]
    M --> P["Provider and request policy"]
    P --> F["Zero-key sources"]
    P --> O["Optional paid provider"]
    F --> E["Deduplicate, rank, and preserve failures"]
    O --> E
    E --> B["Evidence and token budget"]
    B --> R["Compact multi-source result"]
```

The router evaluates each search batch against separate result, relevance,
confidence, and provider-family gates. It stops after the evidence passes those
gates and exposes the decision in `meta.execution`. Provider failures stay
visible in `partialFailures`, so an empty result cannot hide an upstream error.

The [competitive landscape (2026-08-07)](./docs/research/2026-08-07-competitive-landscape-and-product-gaps.md)
maps the crowded baseline and the product gaps. It records source dates and
fixed commits for facts that can change. The
[2026-08-10 update](./docs/research/2026-08-10-competitive-landscape-update.md)
adds competitor activity since then: direct local competitors are dormant, and
token-efficient evidence is becoming an industry-explicit lever. The earlier
[source-level product comparison](./docs/research/2026-07-26-agent-search-product-architecture.md)
contains the architecture-specific evidence.

---

<!-- BEGIN GENERATED CAPABILITY MATRIX -->
## Engines

The runtime registers 16 adapters: 9 zero-key adapters and 7 optional API adapters.

| Engine | Access | Languages | Role |
|---|---|---|---|
| DuckDuckGo | Zero-key | en | General Web Search |
| Sogou Search | Zero-key | zh | Chinese Web Search |
| Bing | Zero-key | en, zh | Multilingual Web Search |
| Baidu | Zero-key | zh | Chinese Web Search |
| Wikipedia | Zero-key | en, zh, ja, de, fr, es, auto | Encyclopedic references |
| Startpage | Zero-key | en, auto | Privacy-oriented Web Search |
| Yandex | Zero-key | ru, en, auto | Russian and international Web Search |
| Mojeek | Zero-key | en, auto | Independent privacy-oriented index |
| Wiby | Zero-key | en | Independent small-Web index |
| Brave Search | `BRAVE_API_KEY` | en, zh | Optional commercial Web Search |
| Tavily Search | `TAVILY_API_KEY` | en, zh | Optional agent-oriented Search |
| Exa Search | `EXA_API_KEY` | en, zh | Optional neural Search |
| You.com Search | `YDC_API_KEY` | en, zh | Optional commercial Web Search |
| Tencent Web Search API | `TENCENT_WSA_API_KEY` | zh | Optional official Chinese Web Search |
| Bocha Web Search | `BOCHA_API_KEY` | zh, en | Optional Chinese-first AI Search |
| Serper Google Search | `SERPER_API_KEY` | en, zh, auto | Optional Google SERP Search |

## Tools

| Tool | Description | Best for |
|---|---|---|
| `free_search` | Multi-engine Web Search with bounded fallback | Quick facts and general discovery |
| `free_search_advanced` | Filtered waterfall search and optional enrichment | Domain policy and progressive verification |
| `free_extract` | Extract a URL as clean Markdown | Reading complete source pages |
| `fetch_github_readme` | Fetch a public GitHub repository README | Project documentation |
| `fetch_csdn_article` | Fetch a CSDN article | Chinese technical articles |
| `fetch_juejin_article` | Fetch a Juejin article | Chinese developer articles |
| `search_with_synthesis` | Search evidence with an LLM synthesis hint | Agent-authored answers from cited evidence |

### Capability controls

| Environment | Default | Purpose |
|---|---|---|
| `ENABLED_TOOLS / DISABLED_TOOLS` | all / none | Tool registration allowlist and denylist; deny wins |
| `ALLOWED_ENGINES / DENIED_ENGINES` | all / none | Engine execution allowlist and denylist; deny wins |
| `SEARCH_PROVIDER_MODE` | free_first | Default routing: free_first, quality_escalation, paid_first, or free_only |
| `PAID_ENGINE_ORDER` | brave,exa,tavily,youcom,tencent_wsa,bocha,serper | Selects the first configured optional provider; not a quality claim |
| `SEARCH_BUDGET_MAX_CALLS` | 16 | Adapter-attempt budget |
| `SEARCH_BUDGET_MAX_ELAPSED_MS` | 30000 | End-to-end elapsed-time budget |
| `SEARCH_BUDGET_MAX_RESULTS` | 100 | Admitted raw-result budget |
| `EVIDENCE_BUDGET_CHARS` | 1200 | Evidence-character budget |
<!-- END GENERATED CAPABILITY MATRIX -->

`search_with_synthesis` uses the same canonical `structuredContent` evidence
packet as the primary search tools and adds `prompt_hint`; its text content is
only a compact compatibility view. Execution metadata distinguishes scheduled
adapters from retry-inclusive adapter attempts. `http_requests` is `null` until
all adapter transports can report it without false precision.

Wiby is a genuine zero-key source backed by its official JSON API and is used
late in the free waterfall as an independent small-Web supplement. Optional
providers require user credentials; any signup credit or trial quota is
provider-controlled and is not treated as permanent free access.

All tools are read-only and idempotent. Search cancellation reaches rate-limit
waits, retries, provider requests, and optional enrichment. Enrichment can
improve a snippet but cannot increase source confidence or independent source
count.

`free_search_advanced.time_range` remains in the compatibility schema. The
server returns `UNSUPPORTED_FILTER` before searching because the general web
providers do not share one enforceable recency contract.

---

## Configuration

The generated capability table above lists the default request budgets. These
settings cover the common deployment choices:

| Goal | Environment variables |
|---|---|
| Add an optional provider | `BRAVE_API_KEY`, `TAVILY_API_KEY`, `EXA_API_KEY`, `YDC_API_KEY`, `TENCENT_WSA_API_KEY`, `BOCHA_API_KEY`, or `SERPER_API_KEY` |
| Choose spend policy | `SEARCH_PROVIDER_MODE`, `PAID_ENGINE_ORDER` |
| Reduce response tokens | `OUTPUT_STYLE=compact`, `MAX_FULL_RESULTS`, `SNIPPET_LENGTH`, `EVIDENCE_BUDGET_CHARS` |
| Restrict tools or engines | `ENABLED_TOOLS`, `DISABLED_TOOLS`, `ALLOWED_ENGINES`, `DENIED_ENGINES` |
| Use an explicit proxy | `DUCKDUCKGO_PROXY_URL`, `SOGOU_PROXY_URL`, `MOJEEK_PROXY_URL`, `WIBY_PROXY_URL`, or `USE_PROXY=true` with `PROXY_URL` |
| Use a user-owned proxy pool | `DUCKDUCKGO_PROXY_URLS`, `SOGOU_PROXY_URLS`, `MOJEEK_PROXY_URLS`, or `WIBY_PROXY_URLS` as a JSON array of 2-16 HTTP(S) proxy URLs |
| Persist the exact-result cache | `SEARCH_CACHE_DIRECTORY`, `SEARCH_CACHE_TTL_MS`, `SEARCH_CACHE_MAX_ENTRIES` |
| Enable optional semantic processing | `SEMANTIC_DEDUP`, `SEMANTIC_RERANK`, `DEDUP_THRESHOLD`, `RERANK_TOP_K` |

Adding an API key does not authorize paid traffic. The routing policy controls
provider use. The default exact-result cache stays in memory; setting
`SEARCH_CACHE_DIRECTORY` opts into local persistence. Semantic processing is
the only optional feature that uses Python and Model2Vec.

Proxy pools select a deterministic first exit from the logical query and keep
multi-step provider requests sticky. Only a transport failure can move to the
next configured exit; a failed transport is cooled for 60 seconds. HTTP
responses, including 403, 429, and challenge pages, never trigger proxy
switching and continue through the provider's existing cooldown contract.
Engine-specific single-proxy variables take precedence over their pool. Proxy
credentials are never printed by `fasm doctor`.

### HTTP deployment

HTTP mode requires `HTTP_AUTH_TOKEN` unless you set
`HTTP_ALLOW_UNAUTHENTICATED=true`. Browser requests with an `Origin` header must
match `ALLOWED_ORIGINS`. See the [HTTP deployment guide](./docs/http-deployment.md)
for TLS termination, token rotation, and reverse-proxy examples.

---

## CLI

The package includes the `fasm` CLI:

```bash
fasm search "TypeScript MCP server"
fasm search "query" --count 5 --engines bing,baidu,youcom --json
fasm extract "https://example.com"
fasm extract "https://example.com" --json
fasm doctor
fasm doctor --json
HTTP_AUTH_TOKEN=change-me MODE=http npx agent-search-mcp
```

`fasm doctor` reads local configuration without network probes and never prints
credential or proxy values.

---

## Documentation and evidence

| Document | Contents |
|---|---|
| [System architecture](./docs/architecture.md) | Routing, evidence, provider families, and configuration |
| [Competitive landscape (2026-08-10)](./docs/research/2026-08-10-competitive-landscape-update.md) | Competitor activity through 2026-08-10, positioning, and improvement priorities |
| [Competitive landscape (2026-08-07)](./docs/research/2026-08-07-competitive-landscape-and-product-gaps.md) | Baseline competitors, expectations, and product gaps snapshot |
| [Product comparison](./docs/research/2026-07-26-agent-search-product-architecture.md) | Source-level review of Agent search products |
| [Benchmarks](./benchmarks/) | Token fixture, live-run scope, and quality evaluation method |
| [v3.2.0 release notes](./docs/releases/v3.2.0.md) | Provider policy, budgets, and migration notes |
| [Earlier release candidate evidence](./docs/evidence/2026-07-26-release-candidate-smoke.md) | Pre-expansion packed-install matrix and limitations |
| [MCP 2026 readiness](./docs/plans/2026-07-25-mcp-ecosystem-and-2026-readiness.md) | Isolated protocol experiment and remaining gates |

## Companion: Slim Guard

Agent Search controls retrieval work and compresses search evidence.
[mcp-slim-guard](https://github.com/lennney/mcp-slim-guard) sits between an
agent and MCP servers to handle tool-schema compression and security policy.

```bash
npm install -g mcp-slim-guard
```

---

## Development

```bash
git clone https://github.com/lennney/agent-search-mcp.git
cd agent-search-mcp
npm install
npm run build
npm test
npm run dev        # stdio mode
npm run dev:http   # HTTP mode (port 3000)
```

The stable package supports Node.js 18, 20, and 22. The isolated MCP 2026
experiment requires Node.js 20 or newer.

---

## License

[Apache 2.0](LICENSE)

Based on [open-websearch](https://github.com/Aas-ee/open-websearch) by Aas-ee.

If Agent Search MCP helps your agent, [star the repository](https://github.com/lennney/agent-search-mcp)
so other developers can find the project.

More