www-search-mcp
MCP server for web search, HTTP fetch, file download, API requests, and package search (PyPI, GitHub).
Optimized for batching: every tool accepts lists (multi-query / multi-URL) to reduce round-trips.
Quick Install
# Run without installing (recommended)
uvx www-search-mcp
# Or install as a global tool
uv tool install www-search-mcp
VS Code / Cursor config:
{
"mcpServers": {
"www-search": {
"command": "uvx",
"args": ["www-search-mcp"]
}
}
}
Tools Overview
| Tool | What it does |
|---|---|
web_search |
General web search (DuckDuckGo) |
web_search_images |
Image search |
web_search_github |
GitHub repo search |
web_search_pypi |
PyPI package search |
web_fetch |
Fetch URL as Markdown |
web_download |
Download files to disk |
web_request |
REST/GraphQL API calls + load tests |
mcp_info |
Server config and tool docs (gated: MCP_INFO=true) |
mcp_status |
Real-time diagnostics |
mcp_tasks |
Background task list/cancel (gated: MCP_TASKS=true) |
mcp_cache |
Cache list/delete/clear (gated: MCP_CACHE=true) |
Batching: pass queries=["q1", "q2"] or urls=["url1", "url2"] instead of calling one-by-one. Every tool also accepts output_format ("object" default, "json", "yaml"; web_fetch additionally supports "markdown" — the full cached page text, no metadata wrapper, for re-calling after a truncated fetch).
Search Tools
web_search
queries: str | list[str]
max_results: int = 5
Returns title, url, snippet. Safe search disabled.
web_search_images
queries: str | list[str]
max_results: int = 5
Returns title, image, thumbnail, height, width, source.
web_search_github
queries: str | list[str]
max_results: int = 5
Returns title, url, stars, forks, language. Uses GitHub REST API (rate-limited to ~10/min without token).
web_search_pypi
queries: str | list[str]
max_results: int = 5
Returns name, version, summary, author, license, requires_python, dependencies.
Fetch & Download Tools
web_fetch
urls: str | list[str] # up to 50 per call
fetch_div: str = "" # CSS selector (e.g. "article")
save_path: str = "" # absolute path for full content (single URL)
cache: "always" | "none" | "replace" = "always"
max_chars: int = 25000 # inline text cap per URL; with N URLs split your budget
Returns Markdown per URL in results[]. Per-item cache_key and truncated-flag; when inline text is cut, full content goes to the reported channel (save_path / download_url on HTTP). Binary content is rejected — use web_download for files.
web_download
urls: str | list[str]
save_path: str | list[str] # required; absolute path(s), one per URL
stdio-only tool (absent in HTTP transport). Downloads files to disk and reports save_path, bytes, mime_type per item; binary content is never returned inline.
API Tool
web_request
queries: dict | list[dict]
Spec fields per query:
type:"rest" | "graphql"method:"GET" | "POST" | ...url: target URLheaders: optional dictrequests: repeat count (default 1)concurrency: async workers (default 1)time: duration in seconds (0 = fixed count)
REST: body: dict|list|str
GraphQL: query: str, variables: dict, operationName: str
Auth: WEB_REQUEST_TOKEN used as default Authorization if not provided in headers.
Output: status_counts, http_status_counts, latency_ms percentiles. Small runs (<=3) include response samples.
Diagnostic Tools
mcp_info
Server configuration, tool descriptions, environment variables.
mcp_status
Real-time diagnostics:
uptime_seconds,pid,python_versionthrottle: last request, intervalsessions: total, staleconnections: niquests version, pool sizeresources: FD limit, memory RSS, event loop taskscounters: requests, errors, timeoutsconfig: transport, timeoutshealth: DDGS availabilitymetrics: latency percentiles (p50/p95/p99), subtask stats
Privileged status server: A separate Starlette-based HTTP server runs on a daemon thread (default port 8081), providing /status, /healthz, and /tasks endpoints. This server remains responsive even under heavy load because it operates independently from the main event loop. Configure via WEB_STATUS_PORT (set to 0 to disable).
Diagnostic HTTP Routes
When running in HTTP transport mode (WEB_TRANSPORT=streamable-http):
GET /healthz— Health checkGET /readyz— Readiness probe (200/503)GET /status— Same JSON asweb_mcp_statusGET /tasks— Active event loop tasks (debugging)GET /memory— Memory breakdown (RSS, arenas)GET /error-types— Error hierarchy for client introspection
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
WEB_TIMEOUT_TOTAL |
60 |
Total operation timeout (sec) |
WEB_TIMEOUT_CONNECT |
5 |
Connect timeout (sec) |
WEB_TIMEOUT_READ |
25 |
Read timeout (sec) |
WEB_MAX_RESULTS |
5 |
Default search results |
WEB_REQUEST_LIMIT |
50 |
Max concurrent requests |
WEB_MIN_INTERVAL |
1.0 |
Throttle gap (sec) |
WEB_ATTEMPTS |
3 |
Total tries per operation (first included) |
WEB_MAX_FETCH_CHARS |
200000 |
Max fetch body length |
WEB_MAX_DOWNLOAD_MB |
50 |
Max download size |
WEB_DEBUG |
false |
Debug logging |
WEB_LOG_FORMAT |
text |
text or json |
WEB_SESSION_ENABLED |
false |
Persistent cookies |
WEB_TRANSPORT |
stdio |
stdio or streamable-http |
WEB_HTTP_HOST |
127.0.0.1 |
HTTP bind host |
WEB_HTTP_PORT |
8000 |
HTTP bind port |
WEB_MCP_IDLE_LIFETIME |
300 |
stdio idle timeout (sec), 0 to disable |
WEB_DNS_RESOLVER |
system |
google, cloudflare, yandex, quad9, system |
WEB_DNS_STRATEGY |
— | only_ipv4, only_ipv6, or dual-stack |
WEB_PROXY |
— | HTTP proxy URL |
WEB_SSL_VERIFY |
true |
TLS verification |
WEB_SSL_PATH |
— | Extra CA certs |
WEB_USER_AGENT |
Chrome 135 | Custom UA |
WEB_UA_ROTATION |
false |
Rotate UA pool |
WEB_UA_LIST |
— | Custom UA list (||| separated) |
WEB_GITHUB_TOKEN |
— | GitHub API token |
WEB_REQUEST_TOKEN |
— | Default auth token |
WEB_STATUS_PORT |
8081 |
Privileged status server port (0 to disable) |
WEB_MAX_URLS_PER_CALL |
50 |
Maximum URLs per web_fetch call |
WEB_FETCH_SUBTASK_TIMEOUT |
15 |
Per-subtask timeout for fetch (sec) |
WEB_SUBTASK_TIMEOUT |
5 |
Per-subtask timeout for generic ops (sec) |
WEB_SUBTASK_ATTEMPTS |
3 |
Total tries per subtask (first included) |
WEB_STREAM_CHUNK_SIZE |
65536 |
HTTP stream chunk size (bytes) |
WEB_SESSION_IDLE_TIMEOUT |
5 |
Session idle timeout (sec) |
WEB_SESSION_CLEANUP_INTERVAL |
5 |
Session cleanup interval (sec) |
WEB_MAX_LATENCY_SAMPLES |
20000 |
Maximum latency samples to track |
WEB_METRICS_MAX_SAMPLES |
1000 |
Maximum metrics samples to track |
WEB_SEARCH_CACHE_TTL |
300 |
Search cache TTL (sec) |
WEB_SEARCH_CACHE_MAXSIZE |
100 |
Search cache max entries |
WEB_FETCH_CACHE_TTL |
60 |
Fetch cache TTL (sec) |
WEB_FETCH_CACHE_MAXSIZE |
50 |
Fetch cache max entries |
WEB_API_CACHE_TTL |
300 |
API cache TTL (sec) |
WEB_API_CACHE_MAXSIZE |
200 |
API cache max entries |
Session Persistence
Per-MCP-session niquests.AsyncSession is reused automatically (cookies, connection
pool). Sessions are scoped to the MCP session (FastMCP Context), not global; idle
sessions are evicted after WEB_SESSION_LIFETIME seconds.
HTTP Mode
export WEB_TRANSPORT=streamable-http
export WEB_HTTP_HOST=127.0.0.1
export WEB_HTTP_PORT=8000
www-search-mcp
Operational endpoints:
GET /healthz—{ "status": "ok" }GET /readyz— readiness probe (200/503)GET /status— same JSON asweb_mcp_statusGET /error-types— error hierarchy
MCP endpoint:
POST /mcp— streamable-http
Idle Timeout (stdio)
stdio process auto-terminates after WEB_MCP_IDLE_LIFETIME seconds of inactivity (default 5 min). Set to 0 to disable.
Development
# Setup
git clone https://github.com/naifs/www-search-mcp.git
cd www-search-mcp
uv sync --all-groups
# Format + lint
uv run ruff format src/ tests/
uv run ruff check src/ tests/
# Type check
uv run ty check src/
# Tests
uv run pytest tests/ -q # parallel (default)
uv run pytest tests/ -q -n0 # sequential
# Security
uv run bandit -r src/
# Build + install
rm -rf dist/
uv build
uv tool install --force dist/*.whl
Troubleshooting
| Problem | Fix |
|---|---|
uv not found |
Install from astral.sh |
| GitHub rate limit | Set WEB_GITHUB_TOKEN |
Binary in web_fetch |
Use web_download instead |
| Tools not showing | Check config JSON, reload client, enable WEB_DEBUG |
License
MIT
Metadata
Release files for www-search-mcp 1.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| www_search_mcp-1.4.0.tar.gz | 263.8 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| www_search_mcp-1.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 369.4 kB
Release files / www_search_mcp-1.4.0.tar.gz
| Download URL | www_search_mcp-1.4.0.tar.gz |
|---|---|
| Size | 263.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b7465c8f137e180e3f0044824f6a61ad6f38f21fb5f666886cd60a08b3bc6834
|
|
BLAKE2b-256 checksum How to use checksums |
bd88dd06d5eb42cc4960ed6ff074b7ff718a2e199dd16fa5501d0514fa9b254d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 21, 2026.
Transparency logRelease files / www_search_mcp-1.4.0-py3-none-any.whl
| Download URL | www_search_mcp-1.4.0-py3-none-any.whl |
|---|---|
| Size | 105.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fc95949b026a644ee8b6252bf77e195134abd763c5f4623de6ac16e4f2380cc5
|
|
BLAKE2b-256 checksum How to use checksums |
4f2ffd2c3d1d546824b47da5f33f0db845d0394e0aad0134b8c2332580640396
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 21, 2026.
Transparency logSecurity for www-search-mcp 1.4.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for www_search_mcp-1.4.0.tar.gz
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 Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.