fetch-mcp
A stdio MCP server that lets AI assistants fetch and process web content over HTTP with strong SSRF protection.
Perform HTTP requests: GET, HEAD, OPTIONS, POST, PUT, PATCH, DELETE with headers, auth, timeouts, size caps, retries, and redirect handling.
Convert web pages to clean markdown or plain text for LLM-friendly reading.
Extract article content in reader mode: title, byline, markdown, and word count.
Pull page metadata: title, description, canonical, Open Graph, Twitter cards, JSON-LD, icons, and feed links.
List and classify all outbound links on a page as internal or external.
Parse sitemaps, including gzipped files and nested sitemap indexes.
Parse RSS 2.0 and Atom 1.0 feeds into structured entries.
Check robots.txt rules and determine whether a path is crawlable for a given user agent.
Protect against SSRF by blocking private, loopback, link-local, and other unsafe addresses; optional opt-in for private hosts when the operator enables it.
Provides tools for fetching and parsing RSS 2.0 and Atom 1.0 feeds into structured entries, including titles, links, dates, authors, summaries, content, and categories.
Click on "Deploy 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., "@fetch-mcpFetch https://example.com/blog and convert to markdown"
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.
@yawlabs/fetch-mcp
A comprehensive HTTP fetch MCP server for AI assistants. Bring-your-own client: runs as a stdio MCP server so any MCP-compatible client (Claude Code, Claude Desktop, Cursor, mcph, …) can fetch web content safely.
One click adds this to your local Yaw MCP config so it's available in every Yaw Terminal session. Or install manually below.
What it gives the model
Tool | What it does |
| Bare HTTP requests with headers, auth, timeout, size cap, retry |
| Write-method HTTP with JSON or raw body |
| GET a page and convert to clean markdown (3–8× smaller than raw HTML) |
| GET a page and convert to plain text with block structure preserved |
| Reader-mode extraction — isolates the article body and returns title + markdown |
| Extract |
| Extract every outbound link, resolved to absolute URLs, classified internal/external |
| Parse |
| Parse an RSS 2.0 or Atom 1.0 feed into entries |
| Parse a site's |
Related MCP server: cleanfetch
Safety
SSRF protection is on by default. The server refuses requests to:
Loopback (
127.0.0.0/8,::1)RFC1918 private ranges (
10/8,172.16/12,192.168/16)Link-local (
169.254/16,fe80::/10) — including the cloud metadata endpoint169.254.169.254CGNAT (
100.64/10)Unique-local IPv6 (
fc00::/7)Multicast / broadcast
IPv4-mapped IPv6 (
::ffff:0:0/96) re-checked against the IPv4 rules, and likewise the IPv4 embedded in IPv4-compatible (::/96), IPv4-translated (::ffff:0:0:0/96) and 6to4 (2002::/16) addressesTeredo (
2001::/32), NAT64 (64:ff9b::/96,64:ff9b:1::/48), site-local (fec0::/10) and discard-only (100::/64) IPv6Any other IPv6 outside global unicast (
2000::/3), and the non-global blocks inside it (3fff::/20,2001:2::/48,2001:10::/28)The Azure WireServer address
168.63.129.16Non-
http/httpsschemes (file://,gopher://,javascript:, …)Hostname
localhostand any*.localhost
Every redirect hop is re-validated against all of the above -- scheme, literal IP and localhost* -- before it is dialed, so a 302 from a public host to http://127.0.0.1, http://169.254.169.254 or ftp://… is caught. For hostnames, DNS is resolved once per hop, every returned address is checked, and the verified IP is pinned into the HTTP dispatcher so the subsequent TCP connection dials that exact address — closing the DNS-rebinding TOCTOU window. Authorization, Cookie and Proxy-Authorization headers are stripped on cross-origin redirects.
Reaching private hosts (development)
The model chooses tool arguments, and the model is not trusted: a prompt injected through a fetched page can ask for anything. So the per-call allow_private_hosts: true opt-in is refused unless the operator enables it by launching the server with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 (true/yes/on also work; any unrecognised value is treated as off and named on stderr). With the variable set, a call still has to ask: requests without allow_private_hosts stay guarded.
{
"mcpServers": {
"fetch": {
"command": "npx",
"args": ["-y", "@yawlabs/fetch-mcp@latest"],
"env": { "FETCH_MCP_ALLOW_PRIVATE_HOSTS": "1" }
}
}
}Only set it where the model may legitimately reach your internal network -- a local dev box, not a cloud VM with a metadata endpoint.
Install & run
# One-off (auto-updates each spawn via @latest)
npx -y @yawlabs/fetch-mcp@latest
# Or globally
npm i -g @yawlabs/fetch-mcp
fetch-mcpRequires Node 22.19 or newer when running on Node (the floor of its HTTP client, undici 8; the launcher refuses older Nodes with a clear message instead of crashing). Under oam, which the launcher prefers when installed, the Node version does not matter.
Configure in Claude Code / Claude Desktop
Add to your client's MCP config (usually claude_desktop_config.json or ~/.claude.json):
{
"mcpServers": {
"fetch": {
"command": "npx",
"args": ["-y", "@yawlabs/fetch-mcp@latest"]
}
}
}Or via mcph:
mcph add fetchTool reference
http_get, http_post, http_put, http_patch, http_delete, http_head, http_options
Common parameters:
Field | Type | Default | Meaning |
| string | — | Absolute URL |
| object | — | Custom request headers |
| int |
| Timeout for each attempt, covering DNS, every redirect hop and the body. Retries get a fresh budget; a whole call is capped at 5 minutes. Cancelling the tool call stops the request |
| int |
| Truncate body if larger |
| int |
| Redirect hops allowed |
| int |
| Retry count on 408/425/429/5xx with backoff (honors |
| string |
|
|
|
| — | Injects |
| string | — | Injects |
| bool |
| Opt this call into loopback / private / link-local targets. Refused unless the operator set |
| bool | auto | When unset, auto-detects by response Content-Type (text for text/*, JSON, XML, JS, form-urlencoded; binary otherwise). Set explicitly |
Body-capable tools (POST/PUT/PATCH/DELETE) also take:
Field | Type | Meaning |
| string | Raw request body |
| any | Structured body — encoded as JSON, |
| string | Overrides |
Response shape:
{
ok: boolean;
status: number;
statusText: string;
url: string; // final URL after redirects
headers: Record<string,string>;
body_text?: string;
body_base64?: string; // when decode_text=false
json?: unknown; // auto-parsed when response is application/json
truncated?: boolean; // set when max_bytes hit
redirects?: string[]; // chain of intermediate URLs
duration_ms: number;
error?: string;
}fetch_html_to_markdown
GET the URL, strip scripts/styles/iframes/svg/canvas plus <nav>, <footer>, <aside>, convert to atx-headed markdown with fenced code blocks and dash bullets. Intended for feeding pages into an LLM without blowing the context budget.
fetch_html_to_text
Same fetch, but emits plain text with block-level structure preserved as newlines. Useful when the model doesn't need markdown formatting.
fetch_reader
Isolates the main article body using, in order: <article>, <main>, itemprop="articleBody", common CMS class names (post-content, entry-content, etc.), then <body> as fallback. Returns:
{
url: string; // final URL after redirects
title?: string; // og:title, then <title>, then <h1>
byline?: string; // meta[name=author] / article:author
wordCount: number;
markdown: string; // main content converted to markdown
}fetch_meta
GET a URL and return its head metadata without downloading the full body (caps at 2 MiB by default):
{
url: string;
title?: string;
description?: string;
canonical?: string;
language?: string;
robots?: string;
og: Record<string, string>; // first value per key (og:title, og:image, og:type, ...)
twitter: Record<string, string>; // first value per key
article: Record<string, string>; // first value per key
ogAll: Record<string, string[]>; // only keys that appear > once (e.g. multiple og:image)
twitterAll: Record<string, string[]>;
articleAll: Record<string, string[]>;
icons: Array<{ rel: string; href: string; sizes?: string }>;
feeds: Array<{ href: string; title?: string; type?: string }>; // RSS/Atom
jsonLd: unknown[]; // parsed application/ld+json blocks
}fetch_links
GET a page and return every <a href> with text, resolved to absolute URLs. Respects <base href>. Skips #, javascript:, mailto:, tel:, data:, file:. Each link is classified internal or external vs. the page host. Optional filter/dedupe/limit.
fetch_sitemap
Fetch a sitemap.xml or sitemap-index and return the URL list:
{
sitemaps: string[]; // indexes followed, in order
urlCount: number;
truncated: boolean; // hit max_urls
childSitemaps: string[]; // listed but not fetched (past max_depth or max_sitemaps)
warnings: Array<{ url: string; error: string }>;
urls: Array<{
loc: string;
lastmod?: string;
changefreq?: string;
priority?: number;
}>;
}Gzipped .xml.gz sitemaps are auto-decompressed. max_depth controls how many levels of sitemap-index to follow (default 1). Setting max_depth: 0 on a sitemap-index returns the index's childSitemaps list without fetching any child (useful to discover structure cheaply). Partial failures — one child sitemap 500s while others succeed — are returned under warnings rather than aborting the whole call. max_sitemaps (default 50, max 1000) caps how many sitemap documents one call fetches, index included; children past it are listed under childSitemaps with a warning. The whole call is capped at 5 minutes. max_bytes (default 20 MiB) applies to each sitemap, and to the decompressed size of a gzipped one; a sitemap larger than that is an error (a warning for a child) rather than a silently partial URL list.
fetch_feed
Parse an RSS 2.0 or Atom 1.0 feed:
{
kind: "rss" | "atom" | "unknown";
title?: string;
description?: string;
link?: string;
updated?: string;
entryCount: number;
truncated: boolean; // hit limit
entries: Array<{
title?: string;
link?: string;
id?: string;
published?: string;
updated?: string;
author?: string;
summary?: string;
content?: string;
categories?: string[];
}>;
}fetch_robots
Fetches <origin>/robots.txt, parses it, and returns:
{
robotsUrl: string;
status: number;
userAgent: string;
path: string;
allowed: boolean;
matchedRule: string | null; // the longest-match Allow/Disallow that decided it
crawlDelay: number | null; // from the matched group
sitemaps: string[]; // top-level Sitemap: declarations
rawRobotsText: string; // first 512KB
note?: string; // only when robots.txt 404s
}A /robots.txt that returns 404 means there are no rules, so the verdict is allowed: true. The response keeps the same shape: status: 404, matchedRule: null, crawlDelay: null, sitemaps: [], rawRobotsText: "", plus the note. Any other non-2xx status is returned as an error.
The parser follows Google's rules: longest match wins, * is a wildcard segment, $ anchors the end of the path, specific user-agent group beats the * wildcard group when the UA matches (comparison uses the length of the actually-matched agent token, not the group's first agent). Allow beats Disallow on equal-length ties.
Development
npm install
npm run build
npm test # vitest
npm run lint # biome
npm run typecheckTests spin up a local loopback HTTP server on 127.0.0.1:0 to exercise the real request/response path — no mocking of HTTP. SSRF tests verify that the default-deny still applies to that local server unless the operator gate is on and the request opts into allow_private_hosts.
License
MIT © Yaw Labs
Links
Yaw Labs: https://yaw.sh
Available Tools
15 toolsfetch_feedARead-onlyIdempotent
Fetch and parse an RSS 2.0 or Atom 1.0 feed. Returns feed-level metadata (title, description, link, updated) plus a list of entries (title, link, id, published, updated, author, summary, content, contentType, categories). Auto-detects RSS vs Atom.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| limit | No | Max entries to return (default 50) | |
| max_bytes | No | Max bytes to read (default 10MiB) | |
| timeout_ms | No | ||
| user_agent | No | ||
| max_redirects | No | ||
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish this as a safe, read-only, idempotent operation. The description adds useful behavioral detail beyond that: it returns feed-level metadata plus structured entries and auto-detects RSS vs Atom. It does not discuss error or network edge cases, but the annotation safety profile lowers the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two tight sentences with no filler. It front-loads the core action, then efficiently provides the return contract and the auto-detection behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description responsibly enumerates the returned metadata and entry fields. For a network tool with several optional tuning parameters, it leaves default/error behavior to the schema, but the core invocation trigger and return shape are sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 43% schema description coverage and seven parameters, the description needed to compensate but does not. It says nothing about limit, max_bytes, timeout_ms, user_agent, max_redirects, or allow_private_hosts beyond what the schema already provides. The URL parameter is only implied by 'feed'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Fetch and parse') tied to a well-defined resource ('RSS 2.0 or Atom 1.0 feed') and enumerates the exact return shape. This clearly separates fetch_feed from the HTML, metadata, sitemap, and generic HTTP sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use case is implied by naming RSS/Atom feeds, but the description never explicitly says when to choose this over fetch_reader, http_get, or fetch_meta, nor does it state when not to use it. There's context, but no explicit routing or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_html_to_markdownARead-onlyIdempotent
GET a URL, decode the HTML, and convert to clean markdown (headings, lists, links, code fences). Scripts, styles, iframes, nav, footer, and aside elements are stripped. Intended for feeding web pages into an LLM cheaply -- markdown is usually 3-8x smaller than raw HTML. Follows redirects, respects size/timeout limits, and blocks private-host requests by default.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL to fetch | |
| max_bytes | No | Max response size in bytes (default 5MiB) | |
| timeout_ms | No | Timeout in ms for the request, covering DNS, every redirect hop and the body (default 10000) | |
| user_agent | No | User-Agent override | |
| max_redirects | No | Max redirect hops (default 5) | |
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, and non-destructive behavior. The description adds valuable context beyond that: stripping of scripts/styles/nav/footer elements, redirect following, size/timeout limits, and default private-host blocking. It enriches the agent's mental model without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no wasted words. The core action is front-loaded, followed by stripping behavior, use case, and safety characteristics. Every sentence contributes meaningful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 6 params and no output schema, the description covers the key behavior: input URL, output markdown, stripping rules, limits, and security. It doesn't detail error handling or edge cases, but the essential call semantics are clear. Slightly more on failure modes would push it to 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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's mention of 'size/timeout limits' and 'blocks private-host requests' aligns with parameters but adds no new syntax or format details beyond the schema. It does not compensate for anything missing, which is fine given full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'GET', the resource 'a URL', and the outcome 'convert to clean markdown', which distinguishes it from raw fetch tools. However, it does not explicitly differentiate from the sibling fetch_html_to_text, leaving the boundary between markdown and text extraction implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides a clear intended use ('feeding web pages into an LLM cheaply') and explains the size benefit, which signals when to use it. But it does not mention when NOT to use it or name alternatives like fetch_html_to_text, so the guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_html_to_textARead-onlyIdempotent
GET a URL, decode the HTML, and return plain text with block-level structure preserved as newlines. Scripts, styles, and comments stripped; HTML entities decoded. Lighter than markdown when you only need the reading content.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL to fetch | |
| max_bytes | No | Max response size in bytes (default 5MiB) | |
| timeout_ms | No | Timeout in ms for the request, covering DNS, every redirect hop and the body (default 10000) | |
| user_agent | No | User-Agent override | |
| max_redirects | No | Max redirect hops (default 5) | |
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral detail: it strips scripts, styles, and comments, decodes HTML entities, and preserves block-level structure as newlines. This goes beyond annotations and informs the agent of processing specifics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler. The first sentence delivers the core action and output format, and the second provides a concise comparative note. All information earns its place and is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple: it fetches HTML and returns plain text. The description covers the output format and processing, and the schema covers all parameters. Annotations cover safety. It could mention error handling or redirect behavior, but those are implied by parameters and not essential for a read-only fetch tool. Overall, it is complete enough for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, meaning every parameter (url, max_bytes, timeout_ms, user_agent, max_redirects, allow_private_hosts) already has a clear description. The tool description adds no additional parameter-specific semantics, so it stays at the baseline of 3 for fully documented schemas.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb-resource pair ('GET a URL, decode the HTML, and return plain text') and specifies the output format precisely. It also distinguishes itself from a sibling by noting it is 'Lighter than markdown when you only need the reading content,' which helps an agent pick between this and fetch_html_to_markdown.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a usage hint by contrasting with markdown ('when you only need the reading content'), implying when to prefer this tool. However, it does not explicitly state when not to use it or name alternatives beyond markdown, leaving some inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_linksARead-onlyIdempotent
Extract every outbound link from an HTML page, resolved to absolute URLs. Each entry includes href, anchor text, optional rel/title, and an internal/external classification (bare-domain and www. treated as the same host). Anchors (#), javascript:, mailto:, tel:, data:, and file: URIs are skipped. Respects .
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| limit | No | Cap on returned links (default 1000) | |
| dedupe | No | Drop duplicate hrefs (default true) | |
| filter | No | Filter by type (default 'all') | |
| max_bytes | No | ||
| timeout_ms | No | ||
| user_agent | No | ||
| max_redirects | No | ||
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnlyHint, openWorldHint, idempotentHint, and destructiveHint. The description adds valuable behavioral context: it skips certain URI schemes, respects <base href>, and treats bare-domain and www as the same host for internal/external classification. These details go beyond the annotations and help the agent understand edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured paragraph that front-loads the core purpose, then specifies output details, exclusions, and edge-case handling. Every sentence adds value, with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 9 parameters and no output schema, the description should explain more about parameter usage and the return format. It mentions the fields in each entry but not the overall structure (e.g., array vs object), nor does it address error handling, pagination, or timeouts. The description is adequate for basic use but incomplete for a tool with this many parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 44%, meaning most parameters (url, max_bytes, timeout_ms, user_agent, max_redirects) lack descriptions. The tool description does not compensate for this gap—it focuses on output behavior but does not explain any of the parameters. An agent would have to guess at the meaning of several parameters, making this a weak point.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Extract'), a clear resource ('outbound link from an HTML page'), and details the output fields and exclusions. It explicitly distinguishes itself from sibling tools like fetch_meta or fetch_html_to_text by focusing on link extraction and classification.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies the use case: when you need to extract outbound links from a page. It does not explicitly name alternatives or provide when-not guidance, but the purpose is unambiguous enough for an agent to select it over similar tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_metaARead-onlyIdempotent
GET a URL and extract its head metadata: title, description, canonical, language, robots directive, Open Graph / Twitter Card / article: properties, icon links, RSS/Atom feed links, and any JSON-LD (schema.org) blocks. Keys that appear more than once (e.g. multiple og:image tags) are additionally returned via ogAll/twitterAll/articleAll arrays. Ideal for previewing a page before fully reading it.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL to extract metadata from | |
| max_bytes | No | Default 2MiB — metadata lives in <head> | |
| timeout_ms | No | ||
| user_agent | No | ||
| max_redirects | No | ||
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds useful behavioral detail beyond that: it enumerates extracted metadata and the duplicate-key arrays (ogAll/twitterAll/articleAll), which are non-obvious and help the agent anticipate output shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: the main action, the duplicate-key return behavior, and the use-case guidance. The enumerated metadata list is dense but directly relevant, and the description is not padded with filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by itemizing what will be returned, including feed links, social metadata, and JSON-LD blocks. It does not explain error cases or redirect behavior, but the optional network parameters have schema descriptions and the overall invocation requirements are clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%, with url, max_bytes, and allow_private_hosts already documented in the schema. The tool description does not add parameter details beyond 'GET a URL', and the undocumented params (timeout_ms, user_agent, max_redirects) are left to name-based inference, making this minimally adequate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb and resource: 'GET a URL and extract its head metadata', then enumerates the exact metadata types returned. It clearly separates this tool from siblings like fetch_reader ('previewing… before fully reading it') and http_get, so an agent can distinguish it without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'Ideal for previewing a page before fully reading it' establishes a clear context for when fetch_meta should be chosen over full-content readers. It does not explicitly name alternatives or say when not to use it, so it falls short of the top score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_readerARead-onlyIdempotent
GET a URL, locate the main article body (prefers , , itemprop=articleBody, or known CMS class names; falls back to ), strip navigation/footer/aside chrome, and convert to clean markdown. Returns { title, byline, markdown, wordCount }. Optimized for feeding long-form articles into an LLM without header/footer/sidebar noise.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| max_bytes | No | ||
| timeout_ms | No | ||
| user_agent | No | ||
| max_redirects | No | ||
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, idempotent, non-destructive), the description openly details the extraction strategy: preferred selectors, fallback to <body>, chrome stripping, and the exact return shape. This adds meaningful behavioral context that annotations alone do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences with no filler. The core behavior is front-loaded, the selector strategy and fallback are compactly summarized, and the use case is stated last without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the main purpose, return fields, and typical use case, which is substantial for a tool with no output schema. It omits edge-case behavior such as what happens when extraction fails or how optional limits like max_bytes interact with the returned markdown, but these are minor gaps given the complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 17%, with only allow_private_hosts explained in the schema. The tool description does not compensate: it mentions the URL target and output but adds no detail about max_bytes, timeout_ms, user_agent, or max_redirects behavior. The parameter names are suggestive, but the description itself contributes little semantic value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'GET a URL, locate the main article body... and convert to clean markdown.' It clearly differentiates itself from siblings like http_get and fetch_html_to_markdown by emphasizing article extraction, chrome-stripping, and LLM-oriented output.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: it is 'optimized for feeding long-form articles into an LLM without header/footer/sidebar noise,' which tells an agent when to prefer it. It does not explicitly name alternatives or state when not to use it, but the usage context is strong enough to guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_robotsARead-onlyIdempotent
Fetch and parse the robots.txt for a given origin, then tell the caller whether a target URL is crawlable by a given user-agent. Follows the Google-style longest-match rule with Allow-wins-on-tie. Returns the raw robots.txt, parsed groups, sitemap references, and the allow/deny verdict with the matching rule.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Target URL to check. We derive origin + path automatically. | |
| timeout_ms | No | ||
| user_agent | No | User-agent string to match against groups (default '*') | |
| max_redirects | No | ||
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, openWorld, idempotent, non-destructive), the description adds the specific parsing rule (longest-match with Allow-wins-on-tie) and the returned data (raw robots.txt, parsed groups, sitemap references, and verdict). It does not conflict with annotations and adds meaningful behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core purpose, then the matching rule, then the return contents. Every sentence adds necessary information with no filler. It is well-structured and appropriately sized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description appropriately covers the return values (raw robots.txt, parsed groups, sitemap references, verdict). It also explains the matching logic. It does not mention error handling or network behavior, but these are likely not critical for a read-only tool with annotations indicating no side effects. The description is sufficient for an agent to know what the tool does and what it returns.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes url, user_agent, and allow_private_hosts. The description only indirectly references url and user_agent without adding new meaning. The timeout_ms and max_redirects parameters lack descriptions in both schema and description, and the description does not compensate for this gap. With 60% schema coverage, the baseline is 3, and the description adds little parameter-specific value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it fetches and parses robots.txt and returns a crawlability verdict for a URL and user-agent. It uses specific verbs and resources, and the function is distinct from sibling fetch tools by focusing on robots.txt, not generic content or sitemaps.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the primary use case: checking crawlability for a given URL and user-agent. It provides clear context for when to use this tool, though it does not explicitly name alternatives or provide exclusions. Since no sibling handles robots.txt specifically, the implied usage is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_sitemapARead-onlyIdempotent
Fetch a sitemap.xml (or sitemap-index) and return the contained URLs with their lastmod / changefreq / priority. Follows sitemap-index chaining up to max_depth levels. Gzipped .xml.gz payloads are auto-decompressed. Partial failures (one child sitemap 500s while others work) are returned under 'warnings' without aborting the whole request. SSRF-protected by default.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Sitemap URL (sitemap.xml, sitemap.xml.gz, or a sitemap index) | |
| max_urls | No | Cap on total URLs returned (default 5000) | |
| max_bytes | No | Max bytes to read per sitemap response (default 20MiB) | |
| max_depth | No | How many sitemap-index levels to follow (default 1). 0 keeps the top-level index flat and only returns its childSitemaps list. | |
| timeout_ms | No | ||
| user_agent | No | ||
| max_sitemaps | No | Cap on sitemap documents fetched -- the index plus every child (default 50, max 1000). Children past the cap are listed under childSitemaps, unfetched. | |
| max_redirects | No | ||
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses substantial behavioral details beyond the annotations: it follows index chaining up to max_depth, auto-decompresses .gz payloads, returns partial failures as 'warnings' without aborting the request, and is SSRF-protected by default. This goes well beyond the readOnly/idempotent hints and gives the agent a clear model of what happens during execution.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: the main purpose is front-loaded, followed by a few brief, high-value behavior notes (chaining, decompression, partial failures, SSRF). No redundant sentences or fluff; every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 9 parameters and no output schema, the description covers the core return data (URLs, lastmod, etc.), explains special behaviors like warnings and childSitemaps, and touches on SSRF safety. It does not fully describe the output JSON structure, but it gives enough context to understand what to expect, especially since 'warnings' is mentioned. The missing parameter details are partially covered by schema, so the overall picture is reasonably complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already covers 67% of parameters with descriptions. The tool description adds meaningful context for max_depth by explaining chaining behavior, and indirectly clarifies the url format (supports .gz). However, it does not add semantic value for the less-documented parameters (timeout_ms, user_agent, max_redirects), which remain self-explanatory but unaddressed. Overall the description adds some value but does not fully compensate for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Fetch', the resource ('sitemap.xml or sitemap-index'), and what is returned (URLs with lastmod/changefreq/priority). It also mentions distinguishing features like index chaining, which separates it from generic HTTP fetch tools and the other sitemap-adjacent tools (fetch_robots, fetch_meta) — it is obviously the sitemap-specific tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly compare to sibling tools or state when to prefer this over alternatives. It implies usage via its focus on sitemap parsing, but there is no direct 'use this when you need sitemap URLs' or a note about when not to use it (e.g., for non-sitemap XML). The guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
http_deleteADestructiveIdempotent
Perform an HTTP DELETE. Idempotent (per spec): a repeated DELETE on an already-deleted resource typically returns 404/410.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Target URL (http:// or https://) | |
| body | No | Raw request body as a string | |
| headers | No | Extra request headers as a key/value object | |
| retries | No | Retries on 408/425/429/500/502/503/504 with exponential backoff (default 0) | |
| body_json | No | Request body as a JSON value — sets content-type to application/json if none given | |
| max_bytes | No | Max response body size in bytes before the body is truncated (default 5MiB, ceiling 100MiB) | |
| basic_auth | No | HTTP Basic auth credentials | |
| timeout_ms | No | Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes. | |
| user_agent | No | User-Agent override (default identifies as @yawlabs/fetch-mcp) | |
| decode_text | No | Force text decoding (true) or binary base64 (false). Defaults to auto — text for text/*, json, xml, etc; binary otherwise. | |
| bearer_token | No | Bearer token sent as Authorization: Bearer <token> | |
| content_type | No | Content-Type header to send with the body (e.g. application/json, text/plain, application/x-www-form-urlencoded) | |
| max_redirects | No | Max redirect hops to follow (default 5) | |
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true. The description adds the specific behavioral note that repeated DELETEs typically return 404/410, which is not covered by annotations. This is useful additional context beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence, front-loaded with the core operation and a relevant behavioral note. No filler or redundancy. It earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is minimal, covering the core operation and idempotency, but does not mention return format, error handling, or response structure. However, since no output schema exists and the tool is an HTTP client, the expected behavior (status code, body) is standard. The description is adequate but could be enriched with a note about the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents all 14 parameters. The description adds no parameter-specific meaning, which is acceptable given the high schema coverage. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the operation: 'Perform an HTTP DELETE.' This identifies the specific verb and resource (an HTTP endpoint), which differentiates it from sibling tools like http_get, http_put, etc. It also mentions idempotency, adding useful semantic context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use DELETE vs. other HTTP verbs or alternatives. The intent is implied by the method name and the general HTTP semantics, but the description does not state any conditions, exclusions, or alternatives. With many sibling HTTP tools, explicit routing would be helpful.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
http_getARead-onlyIdempotent
Perform an HTTP GET. Returns status, headers, and body. Automatically parses JSON when the server responds with application/json. Follows redirects (each hop re-validated against SSRF rules). Refuses URLs that resolve to private/loopback/link-local addresses unless the operator enabled FETCH_MCP_ALLOW_PRIVATE_HOSTS and the call sets allow_private_hosts.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Target URL (http:// or https://) | |
| headers | No | Extra request headers as a key/value object | |
| retries | No | Retries on 408/425/429/500/502/503/504 with exponential backoff (default 0) | |
| max_bytes | No | Max response body size in bytes before the body is truncated (default 5MiB, ceiling 100MiB) | |
| basic_auth | No | HTTP Basic auth credentials | |
| timeout_ms | No | Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes. | |
| user_agent | No | User-Agent override (default identifies as @yawlabs/fetch-mcp) | |
| decode_text | No | Force text decoding (true) or binary base64 (false). Defaults to auto — text for text/*, json, xml, etc; binary otherwise. | |
| bearer_token | No | Bearer token sent as Authorization: Bearer <token> | |
| max_redirects | No | Max redirect hops to follow (default 5) | |
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal read-only, idempotent, non-destructive behavior, so the description adds valuable context on top: automatic JSON parsing, redirect-following with SSRF re-validation on every hop, and refusal of private/loopback/link-local addresses unless both operator-level and per-call opt-ins are set. This discloses non-obvious security and parsing behavior beyond what annotations or schema convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences deliver the core action, return payload, parsing behavior, redirect policy, and SSRF restrictions with zero filler. The most important operational facts are front-loaded before the safety caveat, making it easy for an agent to quickly decide and invoke.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having 11 parameters and no output schema, the description covers the returned shape, JSON parsing, redirect handling, and SSRF constraints, while the schema documents every parameter. The agent has enough to invoke the tool correctly and interpret its response; there are no material gaps requiring additional inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and every parameter including url, retries, timeout_ms, max_bytes, basic_auth, bearer_token, and allow_private_hosts already has a meaningful schema description. The description adds only a brief echo of the allow_private_hosts SSRF nuance, so the baseline of 3 is appropriate; it neither hurts nor substantially compensates for schema documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Perform an HTTP GET') and adds the return shape ('Returns status, headers, and body'), which makes the tool immediately identifiable among siblings like http_post, http_head, and fetch_html_to_markdown. The description goes beyond the tool name by specifying response contents and JSON parsing behavior.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given about when to prefer http_get over the many sibling tools, such as fetch_reader or fetch_html_to_markdown, or when it should be avoided. The description implies use for raw HTTP GET retrieval, but it never states exclusions or alternatives, leaving the agent to infer selection from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
http_headARead-onlyIdempotent
Perform an HTTP HEAD. Returns status + headers with no body. Useful for checking a resource exists, getting its size (Content-Length), or polling for changes cheaply.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Target URL (http:// or https://) | |
| headers | No | Extra request headers as a key/value object | |
| retries | No | Retries on 408/425/429/500/502/503/504 with exponential backoff (default 0) | |
| max_bytes | No | Max response body size in bytes before the body is truncated (default 5MiB, ceiling 100MiB) | |
| basic_auth | No | HTTP Basic auth credentials | |
| timeout_ms | No | Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes. | |
| user_agent | No | User-Agent override (default identifies as @yawlabs/fetch-mcp) | |
| decode_text | No | Force text decoding (true) or binary base64 (false). Defaults to auto — text for text/*, json, xml, etc; binary otherwise. | |
| bearer_token | No | Bearer token sent as Authorization: Bearer <token> | |
| max_redirects | No | Max redirect hops to follow (default 5) | |
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, so the bar is lower. The description adds meaningful behavioral context beyond annotations: the response includes status and headers with no body, and the operation is cheap because it avoids transferring content.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The core semantics (HTTP HEAD, no body, returns status/headers) are front-loaded, followed by practical use cases.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only HTTP HEAD tool, the description covers what it returns and why an agent would use it. There is no output schema, but 'status + headers with no body' adequately communicates the response shape, and the parameter schema covers invocation details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 11 parameters are already documented structurally. The description does not repeat or add parameter-level meaning, but it does not need to; the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Perform an HTTP HEAD') and clearly distinguishes it from sibling methods by noting it returns status and headers with no body. This immediately differentiates it from http_get, http_post, and the fetch_* family.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete use cases: checking resource existence, reading Content-Length, and cheap polling. It does not explicitly name alternatives or state when not to use it, but the no-body distinction and listed use cases provide clear contextual guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
http_optionsARead-onlyIdempotent
Perform an HTTP OPTIONS. Returns the server's supported methods and CORS policy for a resource. Helpful for API discovery.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Target URL (http:// or https://) | |
| headers | No | Extra request headers as a key/value object | |
| retries | No | Retries on 408/425/429/500/502/503/504 with exponential backoff (default 0) | |
| max_bytes | No | Max response body size in bytes before the body is truncated (default 5MiB, ceiling 100MiB) | |
| basic_auth | No | HTTP Basic auth credentials | |
| timeout_ms | No | Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes. | |
| user_agent | No | User-Agent override (default identifies as @yawlabs/fetch-mcp) | |
| decode_text | No | Force text decoding (true) or binary base64 (false). Defaults to auto — text for text/*, json, xml, etc; binary otherwise. | |
| bearer_token | No | Bearer token sent as Authorization: Bearer <token> | |
| max_redirects | No | Max redirect hops to follow (default 5) | |
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, covering the safety profile. The description adds the output behavior (supported methods and CORS policy) but does not disclose additional traits such as behavior when OPTIONS is unsupported or response variability. This is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler. The action is front-loaded, followed by return value and use case. Every sentence contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich schema and safety annotations, the description is mostly complete. It explains the return value in the absence of an output schema, though it could mention edge cases like servers that omit CORS headers. Overall it is sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents all 11 parameters. The description adds no parameter-level meaning beyond the schema, which aligns with the baseline score of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource ('Perform an HTTP OPTIONS'), states the return value (supported methods and CORS policy), and names a clear use case (API discovery). This makes it readily distinguishable from sibling HTTP method tools like http_get or http_head.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool ('Helpful for API discovery') and explains what it returns. It does not explicitly name alternatives or exclusions, but the use case is clear enough for an agent to select it over siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
http_patchADestructive
Perform an HTTP PATCH. Use for partial updates. Spec-wise NOT guaranteed idempotent — depends on the server's patch semantics.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Target URL (http:// or https://) | |
| body | No | Raw request body as a string | |
| headers | No | Extra request headers as a key/value object | |
| retries | No | Retries on 408/425/429/500/502/503/504 with exponential backoff (default 0) | |
| body_json | No | Request body as a JSON value — sets content-type to application/json if none given | |
| max_bytes | No | Max response body size in bytes before the body is truncated (default 5MiB, ceiling 100MiB) | |
| basic_auth | No | HTTP Basic auth credentials | |
| timeout_ms | No | Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes. | |
| user_agent | No | User-Agent override (default identifies as @yawlabs/fetch-mcp) | |
| decode_text | No | Force text decoding (true) or binary base64 (false). Defaults to auto — text for text/*, json, xml, etc; binary otherwise. | |
| bearer_token | No | Bearer token sent as Authorization: Bearer <token> | |
| content_type | No | Content-Type header to send with the body (e.g. application/json, text/plain, application/x-www-form-urlencoded) | |
| max_redirects | No | Max redirect hops to follow (default 5) | |
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=false and destructiveHint=true, so the bar is lower. The description adds genuine value by explaining WHY idempotency isn't guaranteed — "depends on the server's patch semantics" — which is beyond the bare annotation. But it contributes little else: no side-effect scope, auth requirements, or response-behavior disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Roughly three short clauses — action, usage context, and one critical caveat — with zero filler. The core purpose is front-loaded and every sentence earns its place. This is appropriately sized given that the schema carries all parameter detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a powerful open-world HTTP tool with 14 parameters, nested objects, and no output schema, the description is thin: it omits response-format hints, truncation/error behavior, and explicit when-not-to-use guidance. The unusually rich schema (defaults, bounds, per-param semantics) and annotations compensate substantially, keeping it adequate but not complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds nothing about parameters — all 14 (url, body, headers, retries, body_json, allow_private_hosts, etc.) are documented entirely in the schema with defaults and bounds. No bonus, no penalty beyond baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Perform an HTTP PATCH" states a specific verb and resource, and "Use for partial updates" pins down the exact use case that separates it from siblings like http_put (full replacement) and http_post (creation). The idempotency caveat further differentiates it from http_put, which is conventionally idempotent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use for partial updates" is a direct, clear usage directive, and the idempotency warning functions as a caution against relying on safe retries. However, it never names alternatives (e.g., "use http_put for full replacement") or states explicit exclusions, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
http_postADestructive
Perform an HTTP POST. Body can be given as a raw string (body) or as a JSON value (body_json — auto-sets content-type to application/json). NOT idempotent: calling twice submits twice.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Target URL (http:// or https://) | |
| body | No | Raw request body as a string | |
| headers | No | Extra request headers as a key/value object | |
| retries | No | Retries on 408/425/429/500/502/503/504 with exponential backoff (default 0) | |
| body_json | No | Request body as a JSON value — sets content-type to application/json if none given | |
| max_bytes | No | Max response body size in bytes before the body is truncated (default 5MiB, ceiling 100MiB) | |
| basic_auth | No | HTTP Basic auth credentials | |
| timeout_ms | No | Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes. | |
| user_agent | No | User-Agent override (default identifies as @yawlabs/fetch-mcp) | |
| decode_text | No | Force text decoding (true) or binary base64 (false). Defaults to auto — text for text/*, json, xml, etc; binary otherwise. | |
| bearer_token | No | Bearer token sent as Authorization: Bearer <token> | |
| content_type | No | Content-Type header to send with the body (e.g. application/json, text/plain, application/x-www-form-urlencoded) | |
| max_redirects | No | Max redirect hops to follow (default 5) | |
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false, and destructiveHint=true, so the safety profile is covered. The description reinforces this with 'NOT idempotent: calling twice submits twice,' which adds a concrete consequence, but it adds little beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler; the core action, the key body-format choice, and the idempotency warning are all front-loaded and every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 14-parameter tool this is concise, but the input schema is unusually thorough and the annotations carry the read/write and destructive profile. The description covers the main cross-parameter decision and the most important side-effect caveat; only explicit response/return behavior is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already documents each parameter well. The description still adds value by framing body and body_json as the two mutually exclusive body-format options and highlighting that body_json auto-selects application/json.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb and resource: 'Perform an HTTP POST.' This unambiguously identifies the operation and, together with the tool name, separates it from the GET/PUT/PATCH/DELETE siblings. It lacks an explicit contrast with those siblings, so it stops just short of a top score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given about when to choose POST over the sibling HTTP methods or the fetch_* helpers, and no exclusions or alternatives are mentioned. The non-idempotency warning is a behavioral caution, not a selection rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
http_putADestructiveIdempotent
Perform an HTTP PUT. Use for full-resource replacement. Idempotent: the same PUT applied twice leaves the resource in the same state.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Target URL (http:// or https://) | |
| body | No | Raw request body as a string | |
| headers | No | Extra request headers as a key/value object | |
| retries | No | Retries on 408/425/429/500/502/503/504 with exponential backoff (default 0) | |
| body_json | No | Request body as a JSON value — sets content-type to application/json if none given | |
| max_bytes | No | Max response body size in bytes before the body is truncated (default 5MiB, ceiling 100MiB) | |
| basic_auth | No | HTTP Basic auth credentials | |
| timeout_ms | No | Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes. | |
| user_agent | No | User-Agent override (default identifies as @yawlabs/fetch-mcp) | |
| decode_text | No | Force text decoding (true) or binary base64 (false). Defaults to auto — text for text/*, json, xml, etc; binary otherwise. | |
| bearer_token | No | Bearer token sent as Authorization: Bearer <token> | |
| content_type | No | Content-Type header to send with the body (e.g. application/json, text/plain, application/x-www-form-urlencoded) | |
| max_redirects | No | Max redirect hops to follow (default 5) | |
| allow_private_hosts | No | Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true, destructiveHint=true, and readOnlyHint=false. The description restates idempotency ('the same PUT applied twice leaves the resource in the same state') and adds 'full-resource replacement' as semantic context, but does not disclose additional behaviors like error handling or response format. It does not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with no filler. The core action is front-loaded ('Perform an HTTP PUT'), followed by the key semantic reason to use it and a clarifying idempotency note.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The schema is rich and annotations cover safety and idempotency, making the tool callable correctly. However, there is no output schema and the description does not explain what the tool returns (e.g., response status, headers, body) or edge cases like SSRF blocking, leaving some contextual ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with thorough parameter descriptions including defaults, retries, SSRF protection, and timeout behavior. The description itself adds no parameter-level information, so the baseline score of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Perform an HTTP PUT') plus its semantic role ('full-resource replacement'), which clearly distinguishes it from siblings like http_patch (partial update) and http_post (create/submit). The description is unambiguous about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a clear usage context: 'Use for full-resource replacement.' This tells the agent when to prefer this tool over sibling methods, though it does not explicitly name alternatives or state when not to use it.
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.
15 tool updates
v0.8.0- Changed
fetch_feed1 field changed- added
Input schema / properties / allow_private_hosts / descriptionAdded value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way."
- Changed
fetch_html_to_markdown2 fields changed- changed
Input schema / properties / allow_private_hosts / descriptionPrevious value: -"Allow loopback / private / link-local addresses (default false)"New value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way." - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in ms (default 10000)"New value: +"Timeout in ms for the request, covering DNS, every redirect hop and the body (default 10000)"
- Changed
fetch_html_to_text2 fields changed- changed
Input schema / properties / allow_private_hosts / descriptionPrevious value: -"Allow loopback / private / link-local addresses (default false)"New value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way." - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in ms (default 10000)"New value: +"Timeout in ms for the request, covering DNS, every redirect hop and the body (default 10000)"
- Changed
fetch_links1 field changed- added
Input schema / properties / allow_private_hosts / descriptionAdded value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way."
- Changed
fetch_meta1 field changed- added
Input schema / properties / allow_private_hosts / descriptionAdded value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way."
- Changed
fetch_reader1 field changed- added
Input schema / properties / allow_private_hosts / descriptionAdded value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way."
- Changed
fetch_robots1 field changed- added
Input schema / properties / allow_private_hosts / descriptionAdded value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way."
- Changed
fetch_sitemap2 fields changed- added
Input schema / properties / allow_private_hosts / descriptionAdded value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way." - added
Input schema / properties / max_sitemapsAdded value: +{ + "description": "Cap on sitemap documents fetched -- the index plus every child (default 50, max 1000). Children past the cap are listed under childSitemaps, unfetched.", + "maximum": 1000, + "minimum": 1, + "type": "integer" +}
- Changed
http_delete2 fields changed- changed
Input schema / properties / allow_private_hosts / descriptionPrevious value: -"Allow requests to loopback / private / link-local addresses. SSRF protection is on by default — only flip this when intentionally talking to localhost."New value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way." - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in ms (default 10000, max 120000)"New value: +"Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes."
- Changed
http_get2 fields changed- changed
Input schema / properties / allow_private_hosts / descriptionPrevious value: -"Allow requests to loopback / private / link-local addresses. SSRF protection is on by default — only flip this when intentionally talking to localhost."New value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way." - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in ms (default 10000, max 120000)"New value: +"Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes."
- Changed
http_head2 fields changed- changed
Input schema / properties / allow_private_hosts / descriptionPrevious value: -"Allow requests to loopback / private / link-local addresses. SSRF protection is on by default — only flip this when intentionally talking to localhost."New value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way." - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in ms (default 10000, max 120000)"New value: +"Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes."
- Changed
http_options2 fields changed- changed
Input schema / properties / allow_private_hosts / descriptionPrevious value: -"Allow requests to loopback / private / link-local addresses. SSRF protection is on by default — only flip this when intentionally talking to localhost."New value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way." - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in ms (default 10000, max 120000)"New value: +"Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes."
- Changed
http_patch2 fields changed- changed
Input schema / properties / allow_private_hosts / descriptionPrevious value: -"Allow requests to loopback / private / link-local addresses. SSRF protection is on by default — only flip this when intentionally talking to localhost."New value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way." - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in ms (default 10000, max 120000)"New value: +"Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes."
- Changed
http_post2 fields changed- changed
Input schema / properties / allow_private_hosts / descriptionPrevious value: -"Allow requests to loopback / private / link-local addresses. SSRF protection is on by default — only flip this when intentionally talking to localhost."New value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way." - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in ms (default 10000, max 120000)"New value: +"Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes."
- Changed
http_put2 fields changed- changed
Input schema / properties / allow_private_hosts / descriptionPrevious value: -"Allow requests to loopback / private / link-local addresses. SSRF protection is on by default — only flip this when intentionally talking to localhost."New value: +"Allow loopback / private / link-local targets for this call (default false). Refused unless the server operator launched fetch-mcp with FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 -- SSRF protection stays on by default either way." - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in ms (default 10000, max 120000)"New value: +"Timeout in ms for each attempt, covering DNS, every redirect hop and the body (default 10000, max 120000). Retries get a fresh budget; a whole call is capped at 5 minutes."
15 tool updates
v0.6.1- First observed
fetch_feed - First observed
fetch_html_to_markdown - First observed
fetch_html_to_text - First observed
fetch_links - First observed
fetch_meta - First observed
fetch_reader - First observed
fetch_robots - First observed
fetch_sitemap - First observed
http_delete - First observed
http_get - First observed
http_head - First observed
http_options - First observed
http_patch - First observed
http_post - First observed
http_put
TDQS
Scored across 15 tools
Most tools are clearly distinct (each HTTP method, and each fetch utility has a unique purpose). The three HTML conversion tools (fetch_reader, fetch_html_to_markdown, fetch_html_to_text) have overlapping goals but are differentiated by output format and focus (main article vs full page vs plain text). This slight ambiguity prevents a perfect score.
Tools follow two clear prefixes: http_ for raw HTTP methods and fetch_ for high-level fetch operations. Within each group, naming is consistent (e.g., http_get, http_post; fetch_meta, fetch_links). The mixed prefixes are intentional and predictable, but not a single uniform convention, so a 4 is appropriate.
15 tools is within the ideal range and each tool addresses a distinct need: seven HTTP methods and eight fetch utilities (reader, markdown, text, robots, sitemap, meta, links, feed). No tool feels redundant; the count is well-scoped for a comprehensive fetch/HTTP server.
The tool surface is complete for the domain: all standard HTTP methods are covered, and the fetch tools cover common web scraping needs (reading, converting, metadata, links, robots, sitemaps, feeds). There are no obvious gaps that would cause agent failures; http_get provides raw access when needed.
Maintenance
Related MCP Connectors
Read any web page as clean Markdown for AI agents: fetch, search, metadata, links. SSRF-safe.
Read a URL as clean markdown, screenshot a website, url to PDF. Web access for agents, no signup.
Web scraping for AI agents. Converts URLs to clean, LLM-ready Markdown with anti-bot bypass.
Fetch pages as markdown, search web and news, extract structured data. For AI agents.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables fetching and converting web content to markdown with built-in prompt injection safeguards that detect and block malicious content attempting to manipulate the LLM.12MIT
- AlicenseAqualityCmaintenanceEnables AI agents to read web pages reliably, returning clean markdown content, hyperlinks, and metadata without navigation or ad noise.36 npmMIT
- AlicenseAqualityDmaintenanceEnables AI agents to fetch any web page as clean markdown or screenshot it, turning URLs into LLM-ready context.21 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to crawl and scrape websites, converting HTML to clean Markdown and structured metadata with support for JavaScript rendering, bot evasion, and SSRF protection.178MIT