mcp-web-tools-server
A custom MCP server that provides AI agents with tools to fetch web pages, extract readable article text, extract structured data by CSS selector, and check robots.txt permissions.
README
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 it
Running 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.server
The 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:
pytest
Integration 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 integration
There 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.py
Limitations 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.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。