searchpin
Searchpin
Self-hosted web search for AI agents — zero API keys, zero cost. In 2026, the center of gravity in AI development is shifting from "chatting" to "autonomous task execution" — locally deployed, long-running agents are becoming the norm. When an agent runs 24/7, every web search must not be interrupted by API quotas or billing. Searchpin was designed for this from day one: zero external dependencies, zero usage limits. Agents can search, fetch, and verify without restriction, and developers never worry about cost.
Why Searchpin
🇨🇳 Optimized for Chinese Network Environments
Defaults to Baidu, Sogou, Bing CN, and Bing Intl — four search engines queried in parallel. Works natively within China's network, no proxy or VPN needed. Most overseas alternatives rely on Google, DuckDuckGo, or Brave, which are largely inaccessible inside China.
🧠 Semantic Re-ranking — a Differentiator Few Offer
Results from all four engines are not simply concatenated. They are merged and re-ranked by an embedding model based on semantic similarity to the query. What your AI receives is a curated list of high-quality results, not a pile of noisy links. Among free MCP search servers, very few offer this capability.
💰 Completely Free, Zero Barrier
No account registration, no API key application, no usage limits. No dependency on any commercial API — no risk of sudden paywalls or quota restrictions. The entire pipeline runs on your own machine.
🔍 Built for Modern Websites
Built-in SSR content extraction can parse pages rendered by Next.js, Nuxt, and similar frameworks, and extract JSON-LD structured data and microdata. Plain HTML scraping gets nothing from these sites.
🛡️ Pollution Detection + Cross-Verification
Automatically detects and flags results unrelated to your query. Four independent search engines provide cross-verifiable results, enabling your LLM to corroborate information across sources for more credible answers.
⚡ Deliberate Engineering Trade-offs
Every design decision was made with real-world usage in mind:
Token-conscious — Search results return only titles, URLs, and snippets. Structured extraction data is compact and truncated. Your LLM decides which pages are worth fetching in full, without wasting context window.
Fast response — Four engines queried asynchronously in parallel. Total time depends on the slowest engine, not the sum of all four. A typical search completes in 1–2 seconds.
Memory-friendly — The embedding model (~118MB) is downloaded once through hf-mirror.com (HuggingFace mirror for China), then reused from local cache.
Related MCP server: Argus
Quick Start
pip install searchpin && searchpin-setupOn first run, the embedding model (~118MB) is downloaded once via hf-mirror.com (HuggingFace mirror for China). That is the only one-time setup.
Configuration
Claude Desktop / Cursor / any MCP client
Add to your mcpServers config:
{
"mcpServers": {
"Searchpin": {
"command": "searchpin-server",
"args": []
}
}
}VS Code
Or manually, add to .vscode/mcp.json:
{
"servers": {
"Searchpin": {
"command": "searchpin-server",
"args": []
}
}
}Docker
docker run -i --rm ghcr.io/telly6/searchpin:latestPython API
from searchpin import SearchEngine
engine = SearchEngine()
results = engine.search("Python 3.13 新特性")
page = engine.fetch("https://docs.python.org/3/whatsnew/3.13.html")
engine.close()Available Tools
2 toolsweb_fetchA
Fetch a URL and return clean, extracted text content (boilerplate, ads, and nav removed). Use to read articles, documentation pages, or API responses in full. For broad queries, use web_search first, then fetch specific URLs from its results. After fetching, look for technical terms, names, or references you can use as keywords for a better follow-up search.
⚠️ FAILURE IS NORMAL — DO NOT GIVE UP AFTER 1-2 FAILED FETCHES:
If a fetch returns empty body, 403, or obvious JS-template garbage, try the NEXT URL from the search results immediately. Each retry costs only ~0.5s.
Common failure causes: JS-rendered SPA shells (stock pages, forums), Chinese paywalls/captchas (wenku.baidu.com, zhihu.com), government site timeouts.
Rule of thumb: try at least 3 URLs from 3 different domains before concluding the content is unreachable. Skipping this wastes the search you already paid for.
When retrying, pick a URL from a DIFFERENT domain — same-domain failures often share the same root cause (e.g., all pages behind the same Cloudflare/WAF).
RETRY SILENTLY: When a fetch fails, retry with the next URL immediately as another tool call. Do NOT narrate each failure to the user ('this one failed, trying another…'). Only mention failures in your final reply if ALL attempts were exhausted.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The URL to fetch |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so description carries full burden. It discloses failure modes (JS-rendered SPAs, paywalls, timeouts), latency (~0.5s per retry), and the expected retry behavior. It also explains the cleanup of boilerplate/ads/nav, so the agent knows what to expect.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: purpose first, then usage guidance, then a detailed failure handling section with bullet points. Each sentence adds value, and the length is justified by the complexity of the tool's failure behavior. No fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single parameter and no output schema, the description covers everything needed: input, output, failure modes, retry strategy, and integration with web_search. It is self-contained and leaves no ambiguity for the agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has one parameter 'url' with description 'The URL to fetch'. The tool description adds contextual usage (e.g., URLs come from search results) but no new format constraints or additional semantics. Since schema coverage is 100%, baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Fetch'), resource ('URL'), and output ('clean, extracted text content'). It distinguishes from sibling tool 'web_search' by advising to use search first then fetch specific URLs. The purpose is precise and actionable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use web_search first and then fetch, and provides a detailed retry strategy: try at least 3 URLs from different domains, retry silently, and common failure causes. This is comprehensive guidance beyond a simple description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
web_searchA
Search the web via multiple engines (Baidu, Sogou, Bing CN, Bing Intl). Returns ranked titles, URLs, and snippets (no full page content — use web_fetch to get the full text of any result). Results re-ranked by embedding similarity — the top results are the most relevant.
Iterative search is normal: search → read → refine → search → read → synthesize. Search returns only titles + snippets. Read snippets to identify promising results, then call web_fetch to get full page content for the URLs that look most useful.
BEFORE FETCHING, READ THE SNIPPETS FIRST:
Search results come with title + URL + snippet only (no full content). Read snippets to decide which URLs are worth fetching.
Fetch only the 1-3 most promising URLs — do not blindly fetch everything. Each unnecessary web_fetch wastes 1-3s per call.
⛔ WHEN RESULTS LOOK WRONG, DO NOT GIVE UP — ITERATE IMMEDIATELY: If search results are all irrelevant (wrong topic, wrong domain, generic encyclopedia entries, piracy sites, brand pages, file format tools, or dictionary entries), DO NOT conclude the information is unavailable. The fix is almost always a query reformulation. The most common root cause is Bing's tokenizer splitting your query words into fragments that collide with unrelated content. Replace fragile/generic terms with INSEPARABLE identifiers — proper nouns, compound terms, subdomain names, or acronyms that the tokenizer CANNOT split. Then immediately re-search. Do not narrate the failure — just try a different formulation. The PRINCIPLE (not the specific domain) matters:
A law query: 'GDPR enforcement tracker 2026' not 'GDPR fine'
A car query: '全固态电池量产线' not 'solid state battery'
A finance query: 'USDJPY exchange rate' not 'yen dollar'
A programming query: 'rustc 1.87 changelog' not 'Rust release notes'
FOR CHINESE: no spaces around Chinese chars! '2026年新能源汽车补贴' ✓, '新能源汽车补贴 2026' ✗
SEARCH STRATEGY (patterns drawn from real-world use):
DATE TERMS HIJACK QUERIES — Putting year numbers or month names ("2026年", "June") directly in query text often backfires: the engine weights them as the primary topic and you get calendar summaries or current-events roundups instead of your actual topic. PREFER the 'freshness' parameter to control recency — it filters by publication date without polluting the query text.
SHORT COMMON WORDS COLLIDE — In Chinese, single characters that are also standalone dictionary headwords get tokenized independently and matched to dictionary/encyclopedia entries, regardless of surrounding context. In English, short common words that also name major products/services (credit card brands, consumer goods) cause the same problem. RECOGNISE THE PATTERN: if any word in your query could appear as a dictionary headword or a product name on its own, it WILL collide. Embed such terms inside longer inseparable compounds.
LONG PROPER NOUNS ARE ANTI-NOISE ANCHORS — Full institutional names, drug trade names, legal case codes, product model numbers resist tokenizer fragmentation. They act as unbreakable signals that pull results toward the right topic. When a shorter query goes off-target, try a version built around a specific long-form name.
LANGUAGE-SWITCH ESCAPES TOKENIZER TRAPS — When a Chinese query keeps hitting noise despite retries, switch the query to English. English-language media covers many China-specific topics, and the English tokenizer does not fragment CJK characters into dictionary entries.
REPLACE THE ANCHOR — Adding another word to a noisy query rarely fixes it (the original offending token still dominates the ranking). Instead, restructure the query around a DIFFERENT anchor term entirely — a proper noun, a model number, or a multi-word technical phrase that the tokenizer cannot split.
THE VOCABULARY BRIDGE — Chinese search engines match on LEXICOGRAPHIC (word-level), NOT semantic. The words you use MUST match how the target documents actually phrase things. This creates a critical gap:
User language (descriptive): 极端天气, 气候灾害, 高温热浪
Source language (operational): 暴雨橙警, 三级应急响应, 解除预警 These are two entirely different vocabulary systems and the engine CANNOT automatically map between them. When abstract category terms return only encyclopedia definitions and year-old retrospectives, switch to the OPERATIONAL terms that the institutions/sources themselves use — alert levels, government response codes, proper institutional names, numeric thresholds ("四十度"), or named entities ("台风蔷薇").
Abstract: '2026年极端天气气候灾害' → only dictionaries & retrospectives
Operational: '暴雨橙警 应急响应 中央气象台' → nmc.cn real-time alerts This is not a data-coverage problem. The documents exist in the index. They just use a different vocabulary than you searched for.
⚡ NUMERIC DATA CROSS-VERIFICATION:
When a critical number appears in one result, confirm it against at least one other source before accepting it as fact. Different aggregators can lag; conflicting values demand a third source.
⛔ DO NOT STOP EARLY — PERSISTENCE IS REQUIRED:
When a search returns 10 irrelevant results, that does NOT mean the information doesn't exist. It means the current query formulation failed to reach it. Real-world testing shows: the same engine (baidu/bing_cn) that returned 100% calendar-dictionary noise for '2026年极端天气' returned nmc.cn real-time severe weather alerts (rerank 0.908) when reformulated as '暴雨洪涝 应急响应 中央气象台 预警'.
Top-10 failure is a QUERY PROBLEM, not a content-availability problem. The valid pages are likely at positions 11-30, pushed out of view by noise that matched your abstract terms. Do not conclude 'information unavailable' from a failed top 10.
EXHAUST AT LEAST 3-4 DISTINCT STRATEGIES before any 'not found' verdict:
Different vocabulary (descriptive → operational)
Different language (CN ↔ EN)
Different anchors (category term → proper name/number)
Site-restricted search (site:target-source.tld)
Never stop after 1-2 rounds just because the first attempts returned noise. The difference between 'completely unsolvable' and 'fully answered in 1 round' is often a single query reformulation — changing '极端天气' to '暴雨橙警'.
CONDUCT ALL ITERATIONS SILENTLY: When you need multiple rounds of searching and fetching to gather information, run all iterations as tool calls without narrating each step in your reply. Present only the final synthesized answer to the user. Do NOT say things like 'let me search again' or 'I tried searching for X but got Y, let me try Z instead' — just do it and deliver the result.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query keywords | |
| topic | No | Search vertical. 'general' (default, web search) or 'news' (Bing News — prioritises recent articles from mainstream media; best for earnings, sports scores, political events, breaking stories). Also useful as an escape hatch: when 'general' returns Chinese dictionary entries for a query that should have news coverage, switching to 'news' can bypass the dictionary index entirely. | |
| freshness | No | Time filter. One of: d (past day), w (past week), m (past month), y (past year). PREFER this over putting years/months in the query text — date words in queries get weighted as the primary topic and cause noise. This parameter filters by publication date without polluting the query. Omit for no filter. | |
| max_results | No | Max results to return (default 10, max 20). Controls output count only. | |
| exclude_domains | No | Domains to filter OUT of results before re-ranking. Use when a previous search returned pages from a noise domain (e.g. a dictionary site, a brand page, a mirror). Example: ['zidian.gushici.net', 'hancibao.com']. Supply at runtime only — no permanent blocklist. | |
| include_domains | No | Limit results to ONLY these domains (whitelist). Use when you want results from specific sources (e.g. ['docs.python.org', 'python.org'] for Python docs only). Applied before re-ranking. Empty/omitted = no restriction. Supplied by the LLM at runtime — no hardcoded list. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, but description fully discloses re-ranking by embedding similarity, multiple engines, tokenizer issues, noise causes, and the lack of full content. Also mentions numeric data cross-verification and failure handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Very long but well-structured with sections, examples, and warnings. Each sentence adds value, though some repetition exists. Impressive detail without being bloated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema but explicitly states returns titles, URLs, snippets. Covers edge cases, iteration strategies, query reformulation, and cross-verification. Highly complete for a complex search tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but description adds significant meaning: explains topic parameter's use to bypass dictionary, freshness parameter's advantage over date terms, and real-world use cases for exclude/include domains.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool searches the web via multiple engines returning ranked titles, URLs, and snippets. Explicitly distinguishes from sibling web_fetch by noting it does not return full page content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides extensive guidance: iterative search strategy, when to fetch vs search, query reformulation patterns, language switching, and domain filtering. Explicitly contrasts with web_fetch and advises on when to use each.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v1.0.8- First observed
web_fetch - First observed
web_search
TDQS
Scored across 2 tools
web_search and web_fetch have clearly distinct purposes: one handles query-based web search, the other fetches and extracts content from specific URLs. No overlap or ambiguity.
Both tool names follow a consistent verb_noun pattern in snake_case: web_search, web_fetch. The naming is predictable and clear.
With only 2 tools, the server is minimal but appropriate for its focused search-and-fetch domain. The count is not excessive, though a few more specialized search utilities could be added.
The server covers the essential search and fetch operations. The extensive instructions compensate for missing advanced features, but minor gaps like image search exist.
Maintenance
Related MCP Connectors
Web search for AI agents — one tool across 6 engines, routed to the cheapest + cached.
Multi-engine search for AI agents. Trust scoring, local corpus, MCP-native. Self-hostable, BYOK.
The best web search for your AI Agent
Agent-native search engine with live web research optimized for AI agents.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn advanced web browsing server enabling headless browser interactions via a secure API, providing features like navigation, content extraction, element interaction, and screenshot capture.627MIT
- AlicenseBqualityAmaintenanceOne endpoint, five search providers. Search broker for AI agents with automatic fallback, RRF ranking, and budget enforcement. The LiteLLM of web search.135MIT
- AlicenseAqualityDmaintenanceWeb search for AI agents across 6 engines (Serper, Brave, Exa, Tavily, Firecrawl, Perplexity) through one search tool. Routes each query to the cheapest engine that clears a quality bar and caches repeats. Hosted, streamable-HTTP, BYOK supported.11MIT
- AlicenseAqualityFmaintenanceFree multi-source web search server for AI agents, with confidence scoring and token optimization.356 npmApache 2.0