Skip to main content
Glama
lalit9168

Website Scraper MCP Server

by lalit9168

Website Scraper MCP Server

A production-ready MCP (Model Context Protocol) server that allows any MCP-compatible AI agent to scrape websites, crawl internal pages, clean content, chunk it, and index everything into Azure AI Search — all through a clean, typed tool interface.


Table of Contents


Related MCP server: Crawl4AI RAG MCP Server

Architecture

website_scraper_mcp/
├── app.py                   ← Entry point (stdio / SSE transport)
├── server.py                ← MCP server + tool dispatcher
├── config.py                ← Pydantic Settings (env vars)
├── models.py                ← Input/Output Pydantic models
└── tools/
    ├── scrape.py            ← Tool 1 – static/dynamic detection + scraping
    ├── crawl.py             ← Tool 2 – BFS crawler, robots.txt aware
    ├── clean.py             ← Tool 3 – Trafilatura + BS4 content cleaning
    ├── chunk.py             ← Tool 4 – sliding window chunking
    └── azure_ai_search.py   ← Tools 5 & 7 – index + search

Tools

#

Tool

Description

1

scrape_website

Detect static/dynamic, scrape title/content/links

2

crawl_website

BFS crawl with depth limit + robots.txt

3

clean_content

Strip noise HTML, return readable text

4

chunk_content

Sliding window chunks (~1 000 chars, 200 overlap)

5

index_to_ai_search

Upload chunks to Azure AI Search

6

index_website

End-to-end pipeline: crawl → clean → chunk → index

7

search_index

Full-text search on the Azure AI Search index


Installation

Prerequisites

  • Python 3.11+

  • Azure AI Search service (free tier works for testing)

Steps

# 1. Clone the repo
git clone https://github.com/your-org/website-scraper-mcp.git
cd website-scraper-mcp

# 2. Create and activate a virtual environment
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux/Mac
source .venv/bin/activate

# 3. Install dependencies
pip install -r requirements.txt

# 4. Install Playwright browsers (Chromium)
playwright install chromium

# 5. Copy and fill environment variables
cp .env.example .env
# Edit .env with your Azure credentials

Running Locally

stdio mode (default — for MCP clients / AI agents)

python -m website_scraper_mcp.app
# or
python -m website_scraper_mcp.app --transport stdio

SSE mode (HTTP endpoint for browser-based / HTTP clients)

python -m website_scraper_mcp.app --transport sse --port 8000
# Server available at http://localhost:8000/sse

Running with Docker

# Build and start in SSE mode
docker compose up --build

# Stop
docker compose down

The container exposes port 8000 for SSE transport.


Environment Variables

Variable

Default

Description

AZURE_SEARCH_ENDPOINT

(required)

Azure AI Search service URL

AZURE_SEARCH_KEY

(required)

Admin API key

AZURE_SEARCH_INDEX_NAME

website-content

Target index name

PLAYWRIGHT_TIMEOUT_MS

30000

Playwright page load timeout (ms)

PLAYWRIGHT_HEADLESS

true

Run Chromium headless

MAX_CRAWL_DEPTH

2

Maximum crawl depth

MAX_PAGES_PER_SITE

100

Hard cap on pages per crawl

CRAWL_DELAY_SECONDS

0.5

Polite delay between requests

CHUNK_SIZE

1000

Characters per chunk

CHUNK_OVERLAP

200

Overlap between consecutive chunks

LOG_LEVEL

INFO

Python logging level


Sample MCP Client

Run the included example after starting the server in SSE mode:

python examples/mcp_client_example.py

Or configure it in your MCP-compatible agent (e.g. Claude Desktop mcp_config.json):

{
  "mcpServers": {
    "website-scraper": {
      "command": "python",
      "args": ["-m", "website_scraper_mcp.app", "--transport", "stdio"],
      "cwd": "/path/to/website-scraper-mcp",
      "env": {
        "AZURE_SEARCH_ENDPOINT": "https://your-service.search.windows.net",
        "AZURE_SEARCH_KEY": "your-key",
        "AZURE_SEARCH_INDEX_NAME": "website-content"
      }
    }
  }
}

Example API Requests

Via MCP client (Python SDK)

import asyncio
from mcp import ClientSession
from mcp.client.sse import sse_client

async def demo():
    async with sse_client("http://localhost:8000/sse") as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()

            # Scrape a single page
            result = await session.call_tool("scrape_website", {"url": "https://example.com"})
            print(result)

            # Full pipeline
            result = await session.call_tool("index_website", {
                "url": "https://example.com",
                "max_depth": 2
            })
            print(result)

            # Search
            result = await session.call_tool("search_index", {
                "query": "What services does the company provide?",
                "top": 5
            })
            print(result)

asyncio.run(demo())

Tool input/output examples

scrape_website

// Input
{"url": "https://example.com"}

// Output
{
  "title": "Example Domain",
  "url": "https://example.com",
  "content": "This domain is for use in illustrative examples...",
  "links": ["https://www.iana.org/domains/example"],
  "is_dynamic": false,
  "metadata": {"description": "..."}
}

index_website

// Input
{"url": "https://example.com", "max_depth": 2}

// Output
{
  "url": "https://example.com",
  "pages_crawled": 4,
  "total_chunks": 38,
  "indexed_documents": 38,
  "failed_documents": 0,
  "status": "success",
  "errors": []
}

search_index

// Input
{"query": "What services does the company provide?", "top": 5}

// Output
{
  "query": "What services does the company provide?",
  "total_results": 3,
  "hits": [
    {
      "id": "abc123",
      "url": "https://example.com/services",
      "title": "Our Services",
      "content": "We provide cloud, AI, and data services...",
      "chunk_number": 0,
      "score": 9.8
    }
  ]
}

Error Handling

The server handles all errors gracefully and returns structured JSON error responses:

{
  "error": "HTTP 404 when fetching https://example.com/missing",
  "tool": "scrape_website"
}

Handled errors include: invalid URLs, HTTP 4xx/5xx, timeouts, Playwright failures, Azure Search quota errors, network issues, and duplicate document IDs.


License

MIT

Available Tools

5 tools
chunk_contentA

Split clean text into overlapping chunks (~1 000 characters each, 200-character overlap). Each chunk has a unique deterministic ID derived from the URL and position. Useful for preparing text for vector embedding or search indexing.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoSource URL to embed in each chunk.
textYesClean plain text to split.
titleNoPage title to embed in each chunk.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses key behavioral traits: overlapping chunks, deterministic IDs from URL and position. No annotations are provided, so the description carries the full burden. It does not mention edge cases or side effects, but for a text transformation tool, the behavior is sufficiently transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded, with three sentences that each serve a purpose: stating the action, detailing the chunk characteristics, and suggesting use cases. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity, the description covers all necessary information: what it does, how it operates (overlap, chunk size, ID generation), and its intended use. No output schema exists, but the behavior is clear enough.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by explaining how parameters are used: overlapping mechanics, deterministic ID derivation from URL, and the general split strategy, which enriches the meaning of the parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Split clean text into overlapping chunks'), specifies chunk size (~1000 characters) and overlap (200 characters), and distinguishes from sibling tools (cleaning, crawling, scraping) by focusing on the chunking process.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions use cases ('preparing text for vector embedding or search indexing'), providing clear context. However, it does not explicitly state when not to use the tool or compare to alternatives, though the sibling tool names imply distinct purposes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

clean_contentA

Clean raw HTML by removing scripts, styles, navigation bars, footers, cookie banners, ads, and other noise. Returns readable plain text keeping only main article content, headings, paragraphs, tables, and lists.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoOptional source URL (helps with relative link resolution).
htmlYesRaw HTML string to clean.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It explains the transformation (removing noise, keeping text) and return type (readable plain text). However, it does not mention edge cases like malformed HTML, performance, idempotency, or whether the input is mutated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, front-loaded with the action 'Clean raw HTML'. Every sentence serves a purpose: specifying what is removed, what is kept, and the return type. No fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description adequately explains the return value (plain text with structure). It covers both parameters and the core behavior. Missing details on error handling or potential performance implications, but overall sufficient for the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description does not add new meaning beyond the schema: 'url' is for relative link resolution (as schema notes), 'html' is the input. No parameter-specific elaboration in the description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Clean raw HTML' by removing specific elements (scripts, styles, navigation, etc.) and keeping meaningful content (headings, paragraphs, tables, lists). It distinguishes itself from siblings like scrape_website or chunk_content by focusing on cleaning/transforming HTML to plain text.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use after scraping HTML, but it does not explicitly state when to use versus alternatives like chunk_content (which splits text) or when not to use (e.g., if HTML is already clean). No exclusions or specific context cues are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

crawl_websiteA

BFS-crawl an entire website starting from the given root URL. Only follows internal (same-domain) links. Respects robots.txt. Avoids duplicate URLs. Limits crawl depth and total page count. Returns every scraped page with title, content, and links.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesRoot URL to start crawling from.
max_depthNoHow many link-hops deep to crawl (default 2).

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, description fully discloses crawl behavior: BFS algorithm, internal links only, respects robots.txt, avoids duplicates, limits depth and page count. Also states returned data (title, content, links). Lacks details on rate limiting or performance impact but is still thorough.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely concise: two sentences covering purpose, behavior, constraints, and output. No redundancy or filler. Information-dense and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description adequately explains return values (title, content, links). Covers all input parameters, behavior, constraints, and output format. No missing critical information for a crawl tool with two params.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and both parameters are well-described in the schema. The description adds minimal extra context (e.g., 'link-hops' for max_depth) but does not enhance understanding beyond schema defaults and bounds.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the tool's purpose: BFS-crawl an entire website from a root URL. It specifies algorithm, constraints (internal links, robots.txt, duplicate avoidance, depth/count limits), and output (title, content, links). This distinguishes it from sibling tools like 'scrape_website' (presumably single-page) and 'scrape_full_site'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: use for full-site crawling. However, no explicit guidance on when to use this tool versus alternatives like 'scrape_website' or 'scrape_full_site'. No when-not-to-use or prerequisite info provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scrape_full_siteA

End-to-end pipeline: crawl every internal page of a website, clean the HTML of each page, and optionally split into chunks. Returns a structured result with every page's title, clean content, links, metadata, and (if requested) text chunks. Handles both static and dynamic pages automatically.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesRoot website URL to start from.
chunkNoWhether to split page content into chunks.
cleanNoWhether to clean HTML before returning content.
max_depthNoMaximum crawl depth (default 2).

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It details the pipeline steps (crawl, clean, optionally chunk) and the return structure (title, content, links, metadata, chunks). It also mentions handling both static and dynamic pages, adding valuable context. However, it does not address resource consumption, rate limits, or authentication.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences: first describes the pipeline, second defines the return. No wasted words and front-loaded with the key action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of crawling and cleaning, the description covers the main outputs and mentions dynamic page handling. It lacks details on the cleaning process, max_depth behavior, or prerequisites like authentication, but remains largely complete for selection purposes.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents each parameter. The description does not add additional meaning beyond what the schema provides, placing it at the baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it's an end-to-end pipeline for crawling every internal page, cleaning HTML, and optionally chunking. It distinguishes from siblings like crawl_website, scrape_website, chunk_content, and clean_content by combining all steps.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains what the tool does and implies use cases for full-site scraping, but does not explicitly state when not to use it or list alternatives such as crawl_website or scrape_website for simpler tasks.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scrape_websiteA

Scrape a single web page. Automatically detects whether the page is static (uses httpx + BeautifulSoup) or dynamic/JS-rendered (uses Playwright headless Chromium). Returns the page title, clean content, all internal/external links, and page metadata.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesFull URL of the page to scrape (e.g. https://example.com).

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses auto-detection of static vs dynamic pages and the return payload. With no annotations, it covers key behaviors but omits error handling, rate limits, or consent requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero redundancy. Front-loaded with purpose, then technical details. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a single required parameter and no output schema, the description adequately explains functionality and outputs. Could mention pagination or size limits, but overall sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the description adds no extra meaning to the URL parameter beyond what the schema provides. Baseline score applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Scrape a single web page' and lists specific outputs (title, content, links, metadata). It distinguishes from sibling tools by focusing on a single page, not crawling or content processing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies single-page usage but does not explicitly tell when to use alternatives like crawl_website or scrape_full_site. No exclusion criteria are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv1.0.0
    • First observedchunk_content
    • First observedclean_content
    • First observedcrawl_website
    • First observedscrape_full_site
    • First observedscrape_website

TDQS

A4.3/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a unique purpose: single-page scrape, full-site crawl, cleaning, chunking, and an end-to-end pipeline. No two tools overlap in functionality.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (e.g., scrape_website, clean_content), making them predictable and easy to distinguish.

Tool Count5/5

Five tools is appropriate for a website scraping server: it covers the essential operations without being overly sparse or bloated.

Completeness5/5

The tool surface covers the full workflow: scraping single pages, crawling entire sites, cleaning HTML, and chunking text. No essential operation is missing for the stated domain.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides AI agents and coding assistants with advanced web crawling and RAG capabilities, allowing them to scrape websites and leverage that knowledge through various retrieval strategies.
    2
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to crawl websites, extract and store web content with semantic search capabilities using vector embeddings, and retrieve information through natural language queries with tag-based filtering and intelligent content cleaning.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides web crawling and RAG capabilities for AI agents, enabling scraping of websites, storing content in a vector database (Supabase), and performing semantic search over crawled data.
    MIT