mcp-web-tools-server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-web-tools-serverfetch the readable content from https://example.com/blog"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-web-tools-server
A custom Model Context Protocol (MCP) server that gives an AI agent real, working tools for fetching web pages and extracting content from them: clean readable article text, structured data by CSS selector, and a robots.txt permission check.
What is MCP?
MCP is an open protocol, originally published by Anthropic, that standardizes how AI applications (like Claude Desktop or Claude Code) connect to external tools and data sources. Instead of every AI app inventing its own plugin format, an MCP server exposes a fixed set of tools (and optionally resources and prompts) over a simple JSON-RPC interface, and any MCP-compatible client can discover and call them the same way. This repo is one such server: it runs as a small local process and speaks MCP over stdio, so any MCP client can list its tools and call them without knowing anything about httpx, selectolax, or trafilatura underneath.
Why this is useful
Out of the box, an LLM cannot fetch a live web page. This server plugs that gap with a small, tested, well-scoped toolset: an agent can pull the readable text out of an article, pull specific fields out of a page by CSS selector (price, title, tags, whatever the page structure is), and check whether a site's robots.txt allows the request before making it. It is deliberately narrow rather than a general-purpose scraping framework, on the theory that a few tools that work correctly and fail predictably are more useful to an agent than a large surface area that sometimes doesn't.
Tools
fetch_and_extract(url: str) -> str
Fetches a URL and returns clean, readable main-content text: scripts, styles, nav, ads, and footers stripped out. Uses trafilatura for article extraction, with a paragraph-density heuristic (built on selectolax) as a fallback for pages trafilatura doesn't confidently handle.
extract_structured(url: str, css_selectors: dict) -> dict
Fetches a URL and extracts fields by CSS selector, e.g.:
{"title": "h1", "price": ".price", "tags": ".tag-list a"}returns:
{"title": "Trail Blazer 29 Mountain Bike", "price": "$1,249.00", "tags": ["mountain", "hardtail", "29er"]}A selector matching one element returns its text, matching several returns a list of their texts, matching none returns null. Parsing is done with selectolax.
check_robots_txt(url: str) -> dict
Fetches the target site's robots.txt and reports whether this server's user agent is allowed to request the given URL, using Python's standard urllib.robotparser. If no robots.txt is found, it reports that explicitly (robots_txt_found: false) rather than silently assuming permission was actually granted.
This exists because scraping etiquette should be a first-class concern, not an afterthought: an agent (or the person driving it) should be able to check permission before fetching, not just when things go wrong.
Design principles
Honest identification. Requests use a real User-Agent string identifying this tool and linking back to this repo, not a spoofed browser UA.
Bounded requests. Every fetch has a fixed timeout (10 seconds by default) so a slow or hanging server can't stall the whole session.
robots.txt is a tool, not silently enforced.
check_robots_txtis provided so an agent (or the person driving it) can check permission before scraping, but it does not currently blockfetch_and_extractorextract_structuredautomatically. See Limitations below.No crashing on bad input. Network failures, timeouts, and invalid URLs are caught and returned as clean error text or an
{"error": ...}dict, never an unhandled exception that kills the server process.
Project layout
mcp_web_tools/
server.py MCP server definition and the three tool entry points
extractors.py Pure HTML-parsing logic (no network), used for readable-text and CSS-selector extraction
robots.py robots.txt fetching and permission checking
http_client.py Shared httpx fetch helper: user agent, timeout, error handling
tests/
test_extractors.py Unit tests against local HTML fixtures, no network
test_robots.py Unit tests with the network call mocked out
test_http_client.py Unit tests for URL validation
test_integration.py Integration tests against live public sites, marked and run separately
fixtures/ Static HTML used by the unit tests
scripts/
test_client.py Standalone script that launches the server and talks real MCP protocol to itRunning the server
python -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate
pip install -r requirements.txt
python -m mcp_web_tools.serverThe server communicates over stdio using the MCP protocol; running it directly from a terminal will just sit there waiting for a client to connect. Use it through an MCP client (see below) or the included test client script.
Configuring it as an MCP server in Claude Desktop or Claude Code
Add an entry to your MCP client's server config, pointing command at the venv's Python interpreter and args at the module. For Claude Desktop, this goes in claude_desktop_config.json:
{
"mcpServers": {
"web-tools": {
"command": "C:\\path\\to\\mcp-web-tools-server\\venv\\Scripts\\python.exe",
"args": ["-m", "mcp_web_tools.server"],
"cwd": "C:\\path\\to\\mcp-web-tools-server"
}
}
}On macOS/Linux, command would be /path/to/mcp-web-tools-server/venv/bin/python.
For Claude Code, run:
claude mcp add web-tools -- /path/to/mcp-web-tools-server/venv/bin/python -m mcp_web_tools.server(substitute the Windows venv path if applicable), or add the equivalent entry to your project's .mcp.json.
Running the tests
Unit tests run against local HTML fixtures and do not touch the network:
pytestIntegration tests hit real, stable, public test sites (example.com and books.toscrape.com, standard public scraping test/demo targets) and are excluded from the default run. Run them explicitly when you have network access:
pytest -m integrationThere is also a standalone script that launches the server as a real subprocess and drives it through the actual MCP client/server protocol, rather than calling the Python functions directly:
python scripts/test_client.pyLimitations and what I'd add next
No JavaScript rendering. This server fetches raw HTML with httpx. Pages that render their content client-side (heavy React/Vue SPAs) will return little or nothing useful. A fourth tool wrapping Playwright for a headless-browser fetch would be the natural next addition, at the cost of being much heavier to run.
No rate limiting. Each tool call makes one request when called. There is no built-in per-domain throttling or request queue if an agent calls the tools in a tight loop against the same host.
check_robots_txtdoes surfacecrawl_delay_secondswhen a site publishes one, but nothing currently enforces it.robots.txt is advisory, not enforced.
fetch_and_extractandextract_structureddo not automatically consultcheck_robots_txtbefore fetching. That's a deliberate scope decision for this version (an agent should callcheck_robots_txtitself first), but a stricter mode that refuses disallowed fetches automatically would be a reasonable addition.Readability heuristic is basic. The selectolax fallback used when trafilatura doesn't produce a confident result is a simple paragraph-density scorer. It is good enough for typical article and blog layouts, but will do worse on unusual page structures than a purpose-built readability library.
No caching. Every call re-fetches, even for the same URL moments apart. Fine for a demo/portfolio server, not ideal for heavier use.
Single transport in practice. The server is set up for stdio, which is what Claude Desktop and Claude Code use. The
mcpSDK also supports SSE and streamable-HTTP transports; wiring one of those up would be needed to run this as a hosted service rather than a local subprocess.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
An MCP server that gives your AI access to the source code and docs of all public github repos
Pocket Agent (aipocketagent.com) MCP server — read tools for personas, apps, and product info.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ZephyraRR/mcp-web-tools-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server