Feat: Web-Fetch MCP-Server (trafilatura, kein API-Key)
- mcp/mcp_web.py: fetch_url + fetch_urls Tools - Hermes kann jetzt Seiteninhalte lesen ohne externen API-Key - trafilatura für saubere Textextraktion aus HTML Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Mission Control 2.0 — Web Fetch MCP Server.
|
||||
|
||||
Stdio-MCP-Server. Läuft als Subprocess von Hermes Gateway (AI Box).
|
||||
Fetcht URLs und extrahiert sauberen Text — kein API-Key nötig.
|
||||
"""
|
||||
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP("hermes-web-fetch")
|
||||
|
||||
HEADERS = {
|
||||
"User-Agent": (
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
|
||||
"(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def fetch_url(url: str, max_chars: int = 8000) -> str:
|
||||
"""Lädt eine URL und extrahiert den Haupttext (Artikel, News, Seiteninhalte).
|
||||
Nutze dies wenn du den vollen Inhalt einer Webseite lesen willst.
|
||||
Gibt sauberen Text zurück — kein HTML-Rauschen.
|
||||
max_chars: maximale Zeichenanzahl des Ergebnisses (default 8000)."""
|
||||
try:
|
||||
import trafilatura
|
||||
|
||||
resp = httpx.get(url, headers=HEADERS, timeout=20, follow_redirects=True)
|
||||
resp.raise_for_status()
|
||||
|
||||
text = trafilatura.extract(
|
||||
resp.text,
|
||||
include_comments=False,
|
||||
include_tables=True,
|
||||
no_fallback=False,
|
||||
)
|
||||
|
||||
if not text:
|
||||
# Fallback: strip HTML tags manually
|
||||
import re
|
||||
text = re.sub(r"<[^>]+>", " ", resp.text)
|
||||
text = re.sub(r"\s+", " ", text).strip()
|
||||
|
||||
if len(text) > max_chars:
|
||||
text = text[:max_chars] + f"\n\n[... gekürzt auf {max_chars} Zeichen]"
|
||||
|
||||
return text or "Kein Text extrahierbar."
|
||||
|
||||
except httpx.TimeoutException:
|
||||
return f"FEHLER: Timeout beim Laden von {url}"
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"FEHLER: HTTP {e.response.status_code} für {url}"
|
||||
except Exception as e:
|
||||
return f"FEHLER: {e}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def fetch_urls(urls: list[str], max_chars_each: int = 4000) -> str:
|
||||
"""Lädt mehrere URLs gleichzeitig und gibt die Texte zurück.
|
||||
Nützlich um mehrere Suchergebnisse auf einmal zu lesen.
|
||||
urls: Liste von URLs (max 5)
|
||||
max_chars_each: max Zeichen pro Seite"""
|
||||
if len(urls) > 5:
|
||||
urls = urls[:5]
|
||||
|
||||
results = []
|
||||
for url in urls:
|
||||
text = fetch_url(url, max_chars_each)
|
||||
results.append(f"=== {url} ===\n{text}")
|
||||
|
||||
return "\n\n".join(results)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run()
|
||||
Reference in New Issue
Block a user