hermes-web-mcp
hermes-web-mcp
Web powers for any MCP client — no API keys required.
hermes-web-mcp is an MCP (Model Context Protocol) server that gives DSH Desktop and any MCP client a complete web toolkit:
web_search — keyless search via cn.bing direct, with a DuckDuckGo-over-proxy fallback; no search API key needed.
web_extract — scrape any page with full JS rendering (local playwright-service + html-to-md chain over dual CDP Chrome) and return clean Markdown.
7 × page_* — real browser automation on a shared CDP Chrome inside an isolated context (never touches your host browser tabs):
page_open,page_click,page_type,page_read,page_shot,page_back,page_close.
Tools
Tool | Purpose | Key arguments |
| Keyless web search (cn.bing direct, DDG fallback) → title/URL/snippet list |
|
| Render + scrape a page to Markdown via playwright-service + html-to-md; dual-CDP failover, then plain-fetch degrade |
|
| Open a URL in the shared CDP Chrome; returns the first 4000 chars of body text |
|
| Click an element matched by a CSS selector |
|
| Fill an input field (optionally press Enter) |
|
| Read up to 12000 chars of the current page body | — |
| Screenshot the current page into |
|
| Navigate back one page | — |
| Close the isolated browser context (cleanup) | — |
9 tools in total: web_search + web_extract + 7 page_* tools.
How it works
┌──────────────┐ stdio (MCP) ┌────────────────────── hermes-web-mcp ──────────────────────┐
│ MCP client │ ───────────────▶ │ web_search → cn.bing (keyless) / DDG fallback │
│ (DSH, etc.) │ │ web_extract → playwright-service (:3003) → html-to-md │
└──────────────┘ │ (:8080) ⇄ CDP Chrome 9333 (direct) / │
│ 9334 (via HTTP proxy) │
│ page_* → playwright chromium.connectOverCDP │
└───────────────────────────────────────────────────────────┘web_extract never needs a scraper API key: a local playwright-service renders the page over CDP, and an html-to-md service converts the HTML to Markdown. Two Chrome instances back it:
CDP direct (default,
127.0.0.1:9333) — for domestic sites and pages where your normal login session lives.CDP proxied (
127.0.0.1:9334) — Chrome with traffic routed through your local HTTP proxy, for overseas/restricted sites.
web_extract tries your preferred CDP first and fails over to the other automatically; if both fail it degrades to a plain fetch (no JS rendering). The page_* tools use Playwright's connectOverCDP against the same shared Chrome in an isolated context — host tabs are never touched.
Environment variables
Variable | Default | Meaning |
|
| Path to a Playwright install whose |
|
| playwright-service scrape endpoint (POST |
|
| html-to-md endpoint (POST |
|
| CDP endpoint of the direct Chrome |
|
| CDP endpoint of the proxied Chrome |
All variables are optional — omit them and the defaults above are used.
Prerequisites (deployment)
Node.js ≥ 22, then
npm installin this repo (only runtime dependency:@modelcontextprotocol/sdk).playwright-service — a local service exposing
POST /scrape{url, wait_after_load, cdp_url}→{content, pageStatusCode, contentType}, rendering the page with Playwright against the target CDP. (The firecrawl-lite project has a reference implementation.)html-to-md — a local service exposing
POST /convert{html}→{markdown}.Two CDP Chrome instances:
chrome --remote-debugging-port=9333(direct)chrome --remote-debugging-port=9334launched with traffic routed through your local HTTP proxy (for sites not directly reachable).
A Playwright install resolvable at
WEBMCP_PW(or the default path) for thepage_*tools.
The defaults assume services on
127.0.0.1:3003/127.0.0.1:8080and Chrome on9333/9334. Different setup? Just set the env vars.
Registering the server
Generic MCP config (e.g. Claude Desktop claude_desktop_config.json):
{
"mcpServers": {
"hermes-web": {
"command": "node",
"args": ["D:/path/to/hermes-web-mcp/hermes-web-mcp.js"],
"env": {
"WEBMCP_PW": "D:/path/to/playwright-service/node_modules/playwright",
"WEBMCP_SCRAPE": "http://127.0.0.1:3003/scrape",
"WEBMCP_CONVERT": "http://127.0.0.1:8080/convert",
"WEBMCP_CDP_DIRECT": "http://127.0.0.1:9333",
"WEBMCP_CDP_PROXY": "http://127.0.0.1:9334"
}
}
}
}dsh-mcp-client (SQLite registry, insert example — adapt column names to your schema):
INSERT INTO mcp_servers (name, command, args, env) VALUES (
'hermes-web',
'node',
JSON_ARRAY('D:/path/to/hermes-web-mcp/hermes-web-mcp.js'),
JSON_OBJECT(
'WEBMCP_PW', 'D:/path/to/playwright-service/node_modules/playwright',
'WEBMCP_SCRAPE', 'http://127.0.0.1:3003/scrape',
'WEBMCP_CONVERT', 'http://127.0.0.1:8080/convert',
'WEBMCP_CDP_DIRECT', 'http://127.0.0.1:9333',
'WEBMCP_CDP_PROXY', 'http://127.0.0.1:9334'
)
);Smoke test
With all prerequisites running:
npm install
node smoke.jssmoke.js spawns the server over real MCP stdio, lists the registered tools, then calls web_search, web_extract, page_open (proxied) and page_shot, printing each output. It requires the playwright-service, the html-to-md service and both CDP Chrome instances to be up.
License
MIT — Copyright (c) 2026 ShadowMiner.