{
  "markdown": "# Odysseus Web MCP — Secure Web Search and Fetch Server for AI Assistants\n\nOdysseus Web MCP is a standalone [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server for safe public-web search and URL fetching. It runs locally over stdio and gives MCP-compatible AI assistants two retrieval tools: `web_search` to discover sources and `web_fetch` to retrieve and extract public URLs.\n\nBuilt for clients such as Claude Code, Cursor, and Codex, it combines search-provider fallback, readable HTML/PDF/text extraction, optional JavaScript rendering, and SSRF protections including DNS validation and redirect rechecks.\n\n![Live web search terminal demo](assets/web-search-demo.gif)\n\n![Live web fetch terminal demo](assets/web-fetch-demo.gif)\n\n## Features\n\n- Search the public web with provider fallback and ranked, attributed sources.\n- Fetch and extract HTML, PDF, and text content from public URLs.\n- Protect against SSRF with public-network checks, DNS validation, and redirect revalidation.\n- Return bounded, evidence-oriented output with cursors, quality signals, and discovered links.\n- Optionally render JavaScript-heavy pages in isolated Playwright.\n\n## Install in minutes\n\nRequirements: Python 3.11+ and [uv](https://docs.astral.sh/uv/).\n\n```bash\n# after downloading/extracting this folder (or cloning your copy)\ncd odysseus-web-mcp\nuv venv .venv\nuv pip install -e '.[dev]'\n./run-web-mcp.sh\n```\n\nThe server communicates over stdio, so it does not open a web port and does\nnot need to be installed into your host application's Python environment.\nRegister the absolute launcher path in your MCP client:\n\n```json\n{\n  \"name\": \"odysseus-web-mcp\",\n  \"command\": \"/absolute/path/to/odysseus-web-mcp/run-web-mcp.sh\",\n  \"args\": [],\n  \"cwd\": \"/absolute/path/to/odysseus-web-mcp\"\n}\n```\n\nThe launcher automatically uses the package's `.venv`. State defaults to\n`~/.local/share/odysseus-web-mcp`; set `WEB_MCP_DATA_DIR` to place it\nelsewhere. No API key is required for the default fallback path, though Brave,\nTavily, and Serper keys can be added when you want those providers.\n\n## The two tools\n\n### `web_search`\n\nUse it to discover sources for a focused question. It accepts one to three\nqueries plus optional mode, vertical, and freshness controls.\n\n```json\n{\n  \"queries\": \"Model Context Protocol Python SDK\",\n  \"mode\": \"discovery\",\n  \"vertical\": \"general\"\n}\n```\n\nThe response contains ranked URLs, titles, snippets, provider attempts,\ncache state, a plain-text display projection, and an `evidence_id`. A host can\ntake any returned URL directly into `web_fetch`.\n\n### `web_fetch`\n\nUse it to read a known public URL or a bounded batch of URLs.\n\n```json\n{\n  \"url\": \"https://example.com\",\n  \"focus\": \"the page's purpose\",\n  \"render\": \"auto\"\n}\n```\n\nIt returns extracted text, title and document kind, content quality, link\ndiscovery, redirect history, HTTP status, truncation/continuation metadata,\nand an `evidence_id`. Private and special-use destinations are rejected before\ntransport by default.\n\n## Example: how an agent uses the MCP\n\nAn agent normally uses the tools as a two-step retrieval loop: search first,\nthen fetch the source it wants to inspect. The payloads below show the shape\nof a real MCP interaction; IDs and result text are abbreviated for readability.\n\n### 1. Agent searches for sources\n\n```json\n{\n  \"name\": \"web_search\",\n  \"arguments\": {\n    \"queries\": \"official Model Context Protocol architecture\",\n    \"mode\": \"grounding\",\n    \"vertical\": \"general\"\n  }\n}\n```\n\nThe MCP returns a text content block containing structured JSON:\n\n```json\n{\n  \"status\": \"ok\",\n  \"query\": \"official Model Context Protocol architecture\",\n  \"sources\": [\n    {\n      \"title\": \"Architecture - Model Context Protocol\",\n      \"url\": \"https://modelcontextprotocol.io/docs/concepts/architecture\",\n      \"snippet\": \"Understand the architecture and communication model...\",\n      \"provider\": \"duckduckgo\",\n      \"relevance_score\": 1.0\n    }\n  ],\n  \"provider_attempts\": {\n    \"searxng\": \"empty\",\n    \"duckduckgo\": \"ok\"\n  },\n  \"evidence_id\": \"a1b2c3d4...\",\n  \"exit_code\": 0\n}\n```\n\n### 2. Agent fetches the selected source\n\nThe agent takes the returned URL and calls the second tool:\n\n```json\n{\n  \"name\": \"web_fetch\",\n  \"arguments\": {\n    \"url\": \"https://modelcontextprotocol.io/docs/concepts/architecture\",\n    \"focus\": \"How do clients and servers communicate?\",\n    \"render\": \"auto\"\n  }\n}\n```\n\nThe MCP returns bounded, extracted evidence:\n\n```json\n{\n  \"success\": true,\n  \"url\": \"https://modelcontextprotocol.io/docs/concepts/architecture\",\n  \"final_url\": \"https://modelcontextprotocol.io/docs/concepts/architecture\",\n  \"http_status\": 200,\n  \"document_kind\": \"html\",\n  \"content_quality\": \"good\",\n  \"content\": \"The Model Context Protocol defines how clients and servers...\",\n  \"links\": [\n    {\n      \"url\": \"https://modelcontextprotocol.io/docs/concepts/transports\",\n      \"text\": \"Transports\"\n    }\n  ],\n  \"evidence_id\": \"e5f6g7h8...\",\n  \"exit_code\": 0\n}\n```\n\nThe agent can now answer the user from the extracted content, preserve the\n`evidence_id` for traceability, and continue with another `web_fetch` using a\nreturned cursor if the page was longer than the output budget.\n\n## How it works locally\n\n```text\nMCP host ──stdio──▶ mcp_server.py\n                       ├─ web_search → provider chain → ranked evidence\n                       └─ web_fetch  → security → HTTP/extract/render → evidence\n```\n\nAll persistent state is rooted under `WEB_MCP_DATA_DIR`. The package has no\nruntime imports from Odysseus and no access to its credentials, database,\nmemory, browser profiles, scheduler, or agent loop.\n\nRead the full local system design in\n[`docs/TECHNICAL_DESIGN.md`](docs/TECHNICAL_DESIGN.md), and see how the GIFs\nwere recorded in [`docs/INTERACTIVE_DEMO.md`](docs/INTERACTIVE_DEMO.md).\n\n## Search providers and configuration\n\nThe default provider chain is:\n\n```text\nSearXNG → Brave → Tavily → Serper → DuckDuckGo → Wikipedia → Bing\n```\n\nConfigure it with `WEB_MCP_SEARCH_PROVIDER_CHAIN`. Optional credentials are\n`DATA_BRAVE_API_KEY`, `TAVILY_API_KEY`, and `SERPER_API_KEY`. Copy\n[`.env.example`](.env.example) as a reference, but keep secrets in the host\nenvironment rather than committing them.\n\nThe optional browser path is disabled by default:\n\n```bash\nuv pip install -e '.[render]'\n./.venv/bin/python -m playwright install chromium\nexport WEB_MCP_RENDER_ENABLED=true\n```\n\n## Distribution and discovery\n\nThe server is published in the [official MCP Registry](https://registry.modelcontextprotocol.io/?q=io.github.AceAtDev%2Fodysseus-web-mcp)\nunder `io.github.AceAtDev/odysseus-web-mcp`.\n\nFor Claude Desktop and other MCPB-compatible clients, download the validated\n[MCPB release bundle](https://github.com/AceAtDev/odysseus-web-mcp/releases/download/v0.1.0/odysseus-web-mcp.mcpb)\nfrom the [v0.1.0 GitHub Release](https://github.com/AceAtDev/odysseus-web-mcp/releases/tag/v0.1.0).\nThe bundle uses the `uv` runtime to resolve the declared Python dependencies\nwithout shipping a machine-specific virtual environment.\n\n## Verify it yourself\n\nThe project has a focused test suite and a live qualification runner:\n\n```bash\n./.venv/bin/python -m pytest -q\n./.venv/bin/python tests/live_20_cases.py --output reports/live-20-cases.json\n```\n\nThe live qualification runs 10 searches and 10 fetches through the real MCP\nlauncher with disposable state. The latest verification record is in\n[`VERIFICATION.md`](VERIFICATION.md).\n\nTo re-record the terminal previews from fresh live calls (requires\nImageMagick's `convert` command):\n\n```bash\n./.venv/bin/python demos/record_terminal_demos.py\n```\n\nEach GIF is intentionally under ten seconds and shows a real MCP handshake\nand result shape, not a static product mockup.\n\n## Project boundaries\n\nThis package is a retrieval primitive, not an agent loop, general-purpose\ncrawler, scheduler, memory store, browser-profile manager, or credential\nvault. It is designed to be downloaded and connected as an independent MCP\nserver.\n\n## License and status\n\nThis is the standalone extraction workspace for the Odysseus web search/fetch\ncapability. See [`MIGRATION_MAP.md`](MIGRATION_MAP.md) for the source-to-module\nmapping and [`VERIFICATION.md`](VERIFICATION.md) for the current evidence-based\nstatus.\n",
  "bytes": 8234,
  "sha": "6c5536566674cf05cad8d54561484ef0e2024f34159d14596908827ecf89c3d6",
  "repo_slug": "aceatdev/odysseus-web-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_aceatdev_odysseus_web_mcp_07bd7581/readme"
}