Skip to content

Commit 5859ef3

Browse files
committed
fix(fetch): preserve page titles in markdown output
1 parent b1e1eb1 commit 5859ef3

2 files changed

Lines changed: 46 additions & 1 deletion

File tree

src/fetch/src/mcp_server_fetch/server.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,15 @@ def extract_content_from_html(html: str) -> str:
4141
content = markdownify.markdownify(
4242
ret["content"],
4343
heading_style=markdownify.ATX,
44-
)
44+
).lstrip()
45+
title = ret.get("title")
46+
if title:
47+
title_markdown = f"# {title.strip()}"
48+
# Readability often omits the document title when the article body does
49+
# not repeat it. Include it once so callers can identify fetched pages,
50+
# while avoiding duplicate headings when the title is already present.
51+
if title_markdown.casefold() not in content[: len(title_markdown) + 32].casefold():
52+
content = f"{title_markdown}\n\n{content}"
4553
return content
4654

4755

src/fetch/tests/test_server.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,43 @@ def test_simple_html(self):
6767
# readabilipy may extract different parts depending on the content
6868
assert "test paragraph" in result
6969

70+
def test_html_includes_document_title_when_omitted_from_article(self):
71+
"""Test that simplified markdown preserves the page title."""
72+
html = """
73+
<html>
74+
<head><title>What’s new in 2.1.0 (Aug 30, 2023)</title></head>
75+
<body>
76+
<article>
77+
<p>These are the release notes.</p>
78+
</article>
79+
</body>
80+
</html>
81+
"""
82+
83+
result = extract_content_from_html(html)
84+
85+
assert result.startswith("# What’s new in 2.1.0 (Aug 30, 2023)")
86+
assert "These are the release notes." in result
87+
88+
def test_html_does_not_duplicate_existing_title_heading(self):
89+
"""Test that a page title already present as the first heading is not duplicated."""
90+
html = """
91+
<html>
92+
<head><title>Existing Title</title></head>
93+
<body>
94+
<article>
95+
<h1>Existing Title</h1>
96+
<p>Article body.</p>
97+
</article>
98+
</body>
99+
</html>
100+
"""
101+
102+
result = extract_content_from_html(html)
103+
104+
assert result.count("# Existing Title") == 1
105+
assert "Article body." in result
106+
70107
def test_html_with_links(self):
71108
"""Test that links are converted to markdown."""
72109
html = """

0 commit comments

Comments
 (0)