mcp-server-fetch: missing Content-Type header forces non-HTML payloads into readability extraction, failing with error
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
调研方向
从 src/fetch/src/mcp_server_fetch/server.py 第335–341行附近的内容类型检查开始,并将其与原始内容返回路径进行比较。检查当前如何识别没有内容类型的 HTML 响应,然后运行或添加针对缺少 header 的 HTML 和非 HTML 响应的测试。完成标准是:非 HTML 负载以原始形式返回,同时 HTML 仍会被简化。
由索引模型根据 Issue 内容生成。
描述
Which server?
fetch (mcp-server-fetch)
Server version
2026.10.10 (PyPI / commit bbb701e)
How did you run the server?
uvx (Python package)
Transport
stdio
Protocol era
Current (2024-11-05 spec or newer)
MCP client and version
Direct reproduction script / Claude Desktop 0.8.0
Operating system and runtime
Linux 5.15 / Python 3.11
Server configuration
Standard mcp-server-fetch execution.
Steps to reproduce
In src/fetch/src/mcp_server_fetch/server.py lines 335–341:
content_type = response.headers.get("content-type", "")
is_page_html = (
"<html" in page_raw[:100] or "text/html" in content_type or not content_type
)
if is_page_html and not force_raw:
return extract_content_from_html(page_raw), ""
Notice the clause or not content_type.
When fetching an HTTP endpoint that does not include an explicit Content-Type header (common with static files, raw S3/CDN buckets, embedded/IoT servers, or internal microservices returning plain text or raw JSON):
response.headers.get("content-type", "")returns"".not content_typeevaluates toTrue.is_page_htmlbecomesTrueregardless of what the payload actually contains.extract_content_from_html(page_raw)is invoked on non-HTML content (e.g. JSON{"status": 200}, plain text, CSV, or Markdown).readabilipy.simple_json.simple_json_from_html_string()cannot extract readability content from non-HTML text.- The tool returns
<error>Page failed to be simplified from HTML</error>instead of returning the raw payload.
Contrast this with the exact same payload returned with Content-Type: text/plain:
- With
Content-Type: text/plain:is_page_htmlisFalse-> returnspage_rawsuccessfully. - Without
Content-Typeheader:is_page_htmlisTrue-> fails with<error>Page failed to be simplified from HTML</error>.
Minimal reproduction:
def classify_page(page_raw: str, content_type: str):
is_page_html = (
"<html" in page_raw[:100] or "text/html" in content_type or not content_type
)
return is_page_html
# text/plain with header: False -> raw content returned
assert classify_page("hello world", "text/plain") is False
# plain text without header: True -> wrongly forced into HTML extractor!
assert classify_page("hello world", "") is True
# JSON without header: True -> wrongly forced into HTML extractor!
assert classify_page('{"status": "ok"}', "") is True
Expected behavior
Responses lacking a Content-Type header should NOT automatically be assumed to be HTML. Unless the payload contains unambiguous HTML markup (e.g. starting with <!DOCTYPE html or <html), it should be treated as non-HTML and fall back to returning page_raw.
Actual behavior
Any non-HTML endpoint without a Content-Type header is coerced into HTML simplification and fails with:
<error>Page failed to be simplified from HTML</error>
Logs or error output
<error>Page failed to be simplified from HTML</error>
From src/fetch/src/mcp_server_fetch/server.py:158-160:
ret = readabilipy.simple_json.simple_json_from_html_string(html, use_readability=True)
if not ret["content"]:
return "<error>Page failed to be simplified from HTML</error>"
Already prototyped a fix?
In src/fetch/src/mcp_server_fetch/server.py, remove or not content_type and check for HTML markers properly:
content_type_lower = content_type.lower()
page_start = page_raw.lstrip()[:100].lower()
is_page_html = (
"text/html" in content_type_lower
or "application/xhtml+xml" in content_type_lower
or page_start.startswith(("<html", "<!doctype html"))
)
This ensures:
- Valid HTML documents (with or without headers) are still simplified.
- Payloads without a
Content-Typeheader that are NOT HTML fall through to the raw content return block instead of returning an error string.
Before you submit
- I searched existing issues and this is not a duplicate.
- This is not a security vulnerability report (those go through the private advisory form).
- 主要语言
- JavaScript
- 星标
- 91.2k
- 派生
- 11.8k
- 平均合并
- 6 小时 20 分钟
- 30 天内合并 PR
- 117
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
modelcontextprotocol/servers 的其他 Issue
-
memory: create_entities, create_relations and add_observations could declare idempotentHint: true未关闭enhancement v2
难度 1/5 1 小时以内 新手友好度 78/100
modelcontextprotocol/servers#5153 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 75/100
modelcontextprotocol/servers#5071 · 2 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 85/100
modelcontextprotocol/servers#5059 · 2 条评论 ·
维护者通常 1 天内回复
-
mcp-server-fetch: `fetch` prompt returns JSON-RPC error code 0 with the raw exception text for an invalid URL可能重新可做 关联的 PR 已关闭且未合并。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
modelcontextprotocol/servers#4914 · 1 条评论 ·
维护者通常 1 天内回复
-
CLAUDE.md: tool-naming rule (kebab-case) disagrees with filesystem and memory servers可能已有人在做 @liang0417 于 16 天前认领。 未关闭
难度 1/5 1 小时以内 新手友好度 92/100
modelcontextprotocol/servers#4892 · 1 条评论 ·
维护者通常 1 天内回复
查看 modelcontextprotocol/servers 的全部 Issue
相似的 Issue
-
Four problem loader browser tests fail on Windows可能已有人在做 @Patriciaath999 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 88/100
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 85/100
juice-shop/juice-shop#3686 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 72/100
TheOdinProject/curriculum#31465 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 88/100
TurboDocx/html-to-docx#254 ·
-
enhancement
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复