Skip to main content
Glama

🛠️ DevTools MCP Server

Ein leichtgewichtiger Model Context Protocol (MCP)-Server, der jedem MCP-kompatiblen LLM-Client (Claude Desktop, Claude Code, Cursor usw.) eine Entwickler-Werkzeugkiste bietet: Web-Scraping, Log-Inspektion, Live-Websuche und schreibgeschützte SQL-Abfragen gegen SQLite oder Postgres/Supabase – alles über einen einzigen Server.

MCP Python Tests License

🔗 Live-Playground: Glama MCP Link — teste die Tools direkt im Browser, sobald sie gelistet sind (siehe Deployment).


📖 Übersicht

DevTools MCP stellt über MCP vier Tools bereit, sodass ein LLM-Assistent Folgendes kann:

  • Sauberen, lesbaren Text von jeder Webseite abrufen

  • Lokale Logdateien mit tail verfolgen, um Fehler zu debuggen

  • Das Live-Web nach aktueller Dokumentation durchsuchen, bevor du Code schreibst

  • Schreibgeschützte SELECT-Abfragen gegen eine lokale SQLite-Datei oder eine Live-Postgres/Supabase-Datenbank ausführen

Jedes Tool ist eine einfache, testbare Python-Funktion – nichts hier hängt von kostenpflichtigen APIs ab, außer deinem eigenen optionalen Supabase-Projekt.


Related MCP server: MCP Server Toolkit

✨ Funktionen

Tool

Beschreibung

🌐 fetch_markdown(url)

Ruft eine Webseite ab, entfernt script/style/nav/footer und gibt sauberen Text zurück (begrenzt auf 8.000 Zeichen).

📄 read_log(file_path, lines)

Liest die letzten N Zeilen einer lokalen Datei – zeigt aktuelle Stack-Traces oder Fehlerausgaben an.

🔍 search_web(query, max_results)

Durchsucht das Live-Web über DuckDuckGo (ddgs, kein API-Schlüssel erforderlich) nach aktuellen Dokumentationen oder Lösungen.

🗄️ query_database(db_path_or_url, sql_query, limit)

Führt ein schreibgeschütztes SELECT gegen eine lokale SQLite-Datei oder eine Postgres/Supabase-Verbindungszeichenfolge aus, begrenzt auf limit Zeilen.


🏗️ Architektur

┌──────────────────────┐
│    MCP Client         │   (Claude Desktop / Claude Code / Cursor / etc.)
└──────────┬────────────┘
           │ MCP protocol (stdio)
┌──────────▼────────────┐
│  DevTools MCP Server   │   FastMCP("DevTools")   — server.py
│                        │
│  ┌──────────────────┐  │
│  │ fetch_markdown    │  │──▶ requests + BeautifulSoup ──▶ any URL
│  ├──────────────────┤  │
│  │ read_log          │  │──▶ local filesystem
│  ├──────────────────┤  │
│  │ search_web        │  │──▶ DDGS (DuckDuckGo, key-free)
│  ├──────────────────┤  │
│  │ query_database     │  │──▶ _is_safe_select()  (SQL safety gate)
│  │                    │  │      │
│  │                    │  │      ├──▶ _query_sqlite()   ──▶ local .db file
│  │                    │  │      └──▶ _query_postgres() ──▶ Postgres / Supabase
│  └──────────────────┘  │
└────────────────────────┘

Wie query_database entscheidet, wohin eine Abfrage gesendet wird

query_database(db_path_or_url, sql_query, limit)
        │
        ▼
  _is_safe_select(sql_query)?
        │
   ┌────┴────┐
   NO         YES
   │           │
 reject   does db_path_or_url start with
 query    "postgres://" or "postgresql://" ?
              │
        ┌─────┴─────┐
        YES           NO
        │             │
 _query_postgres()  _query_sqlite()

_is_safe_select ist eine strikte Hürde, die nur einzelne, einfache SELECT-Anweisungen zulässt – kein INSERT/UPDATE/DELETE/DROP/ALTER/usw. und keine gestapelten Abfragen, die mit ; verkettet sind. Das ist wichtig, weil der SQL-Text von einem LLM erzeugt wird und nicht von Hand getippt wird – die Hürde stellt sicher, dass eine halluzinierte oder manipulierte Abfrage deine Daten nicht verändern oder zerstören kann.

Stack:

  • fastmcp — MCP-Server-Framework; wandelt Python-Funktionen über @mcp.tool in MCP-Tools um

  • requests + beautifulsoup4 — Web-Scraping

  • ddgs — Live-Websuche ohne API-Schlüssel (ehemals duckduckgo-search)

  • sqlite3 — in Python eingebaut, für lokale Datenbankabfragen

  • psycopg2 — Postgres/Supabase-Client, wird nur bei Verwendung einer Postgres-URL lazy importiert

  • python-dotenv — lädt lokale .env-Variablen

  • pytest + pytest-mock — Testsuite


📂 Projektstruktur

.
├── venv/                # Local virtual environment (not committed)
├── .env                 # Local secrets — real keys/paths, never committed
├── .gitignore
├── README.md
├── requirements.txt      # Runtime + dev/test dependencies
├── server.py             # Main MCP server — all 4 tools live here
├── test_server.py        # Pytest suite covering all 4 tools
├── Dockerfile             # Optional — only needed for Glama's hosted deployment
├── glama.json             # Optional — repo attribution for Glama's listing
└── smithery.yaml         # Optional — only relevant if also listing on Smithery

🚀 Erste Schritte

1. Repository klonen

git clone https://github.com/YOUR_USERNAME/YOUR_REPO.git
cd YOUR_REPO

2. Virtuelle Umgebung erstellen & Abhängigkeiten installieren

python -m venv venv
source venv/bin/activate   # On Windows: venv\Scripts\activate

pip install -r requirements.txt

3. Umgebungsvariablen konfigurieren (optional)

server.py ruft beim Start load_dotenv() auf, sodass alle Variablen in einer lokalen .env-Datei automatisch übernommen werden. Keines der aktuellen Tools benötigt Umgebungsvariablen – query_database erhält seine Verbindungsinformationen als direkten Parameter – aber du möchtest vielleicht trotzdem eine .env für lokale Bequemlichkeit:

# Only needed if you want a default connection string handy locally.
# Real credentials should live here and nowhere else.
SUPABASE_DB_URL=postgresql://postgres:your-password@db.xxxxxxxx.supabase.co:5432/postgres

⚠️ Commite deine .env-Datei niemals. Sie ist bereits über .gitignore ausgeschlossen.

Hinweis: Das unterscheidet sich von den SUPABASE_URL / SUPABASE_KEY eines Supabase-Projekts (die vom REST/JS-Client verwendet werden). query_database spricht Postgres direkt über psycopg2 an, benötigt also die Postgres-Verbindungszeichenfolge aus deinem Supabase-Dashboard unter Einstellungen → Datenbank → Verbindungszeichenfolge, nicht das API-URL/Schlüssel-Paar.

4. Server lokal ausführen

python server.py

Dies startet den MCP-Server über stdio, bereit, mit einem beliebigen MCP-Client verbunden zu werden.


🔌 Verbindung mit Claude Desktop / Claude Code

Füge den Server zu deiner MCP-Client-Konfiguration hinzu (z. B. claude_desktop_config.json):

{
  "mcpServers": {
    "devtools": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}

Starte deinen Client neu – die vier Tools (fetch_markdown, read_log, search_web, query_database) erscheinen als Funktionen, die der Assistent aufrufen kann.


🧰 Tool-Referenz

fetch_markdown(url: str) -> str

Ruft eine Webseite ab, entfernt <script>-, <style>-, <nav>- und <footer>-Tags und gibt bereinigten Klartext zurück (begrenzt auf 8.000 Zeichen).

fetch_markdown("https://docs.python.org/3/library/asyncio.html")

read_log(file_path: str, lines: int = 50) -> str

Liest die letzten lines Zeilen einer lokalen Text-/Logdatei.

read_log("/var/log/app/error.log", lines=100)

search_web(query: str, max_results: int = 3) -> str

Durchsucht DuckDuckGo nach der angegebenen Abfrage und gibt für jedes Ergebnis Titel, Link und Textausschnitt zurück.

search_web("fastapi background tasks example")

query_database(db_path_or_url: str, sql_query: str, limit: int = 50) -> str

Führt ein schreibgeschütztes SELECT aus gegen:

  • eine lokale SQLite-Datei (übergib einen Dateipfad), oder

  • eine Postgres/Supabase-Datenbank (übergib eine Verbindungszeichenfolge, die mit postgres:// oder postgresql:// beginnt)

Die Ergebnisse werden als Liste von {column: value}-Wörterbüchern zurückgegeben, begrenzt auf limit Zeilen.

query_database("app.db", "SELECT * FROM users WHERE status = 'active'", limit=5)
query_database("postgresql://user:pass@host:5432/db", "SELECT id, email FROM users", limit=10)

Sicherheitsgarantien:

  • Nur Abfragen, die mit SELECT beginnen, sind erlaubt

  • Abfragen, die irgendwo INSERT, UPDATE, DELETE, DROP, ALTER, TRUNCATE, GRANT, REVOKE, CREATE oder ATTACH enthalten, werden abgelehnt

  • Gestapelte Abfragen (SELECT ...; DROP TABLE ...) werden abgelehnt

  • Bekannte Einschränkung: Die Prüfung ist ein Teilstring-Abgleich, kein vollständiger SQL-Parser – eine harmlose Abfrage wie SELECT * FROM updates_log wird ebenfalls abgelehnt, da sie den Teilstring update enthält. Das ist ein bewusster Trade-off: lieber Fehlalarme als übersehene gefährliche Abfragen.


🧪 Testing

Das Projekt enthält eine pytest-Suite mit 27 Tests, die alle vier Tools abdeckt und vollständig offline läuft – über gemockte Netzwerkaufrufe und Wegwerf-tmp_path-Fixtures. Nichts berührt eine echte Datei, Datenbank oder Website.

pip install -r requirements.txt
pytest test_server.py -v

Abgedeckt sind:

  • _is_safe_select — 10+ Fälle: gültige SELECTs, jedes verbotene Schlüsselwort, gestapelte Abfragen und bekanntes Fehlalarm-Verhalten

  • query_database (SQLite) — einfaches SELECT, limit, WHERE-Filterung, blockierte unsichere Abfragen, fehlende Datei, fehlende Tabelle, leere Ergebnismenge und Postgres-URL-Routing (gemockt)

  • read_log — Tail-Verhalten, fehlende Datei, Standard-Zeilenanzahl

  • fetch_markdown — HTML-Bereinigung und Fehlerbehandlung (Netzwerk gemockt)

  • search_web — Ergebnisformatierung, leere Ergebnisse, Fehlerbehandlung (Netzwerk gemockt)

_query_postgres selbst wird in dieser Suite nicht gegen eine Live-Datenbank getestet – nur die Routing-Logik, die entscheidet, ob sie aufgerufen wird. Ein Live-Test erfordert eine echte Postgres/Supabase-Verbindungszeichenfolge, die niemals in Testdateien hartcodiert oder ins Repository eingecheckt werden sollte.


🌐 Deployment

Option A — Glama (kostenloses Verzeichnislisting + Browser-Inspektor)

Reiche die GitHub-URL dieses Repos unter glama.ai/mcp ein – Glama indexiert deine Tools direkt aus dem Quellcode, ohne Build oder Manifest. Besucher erhalten einen In-Browser-Inspektor, um fetch_markdown, read_log, search_web und query_database auszuprobieren, ohne lokal etwas zu installieren.

Optional: Füge glama.json (bereits enthalten) hinzu, um das Listing deinem GitHub-Konto zuzuordnen/zuzuschreiben.

Option B — Glama-gehostetes Deployment (Glama betreibt es für dich, 24/7)

Verbinde die Glama GitHub App mit diesem Repo, und sie baut das enthaltene Dockerfile zu einer laufenden Instanz hinter Glamas Gateway (verwaltetes TLS, Authentifizierung, Logging). Prüfe glama.ai/mcp/hosting für aktuelle Plandetails, bevor du dich für diesen Weg entscheidest.

Option C — Smithery

⚠️ Seit Anfang 2026 akzeptiert Smithery keine neuen kostenlosen gehosteten Deployments mehr über GitHub – das erfordert jetzt einen kostenpflichtigen Plan. Der kostenlose Weg bei Smithery besteht darin, diesen Server als externen Server zu registrieren (d. h. du hostest ihn selbst – z. B. über die gehostete Option von Glama oben – und verweist Smitherys Listing einfach auf diese URL). smithery.yaml ist in diesem Repo weiterhin enthalten, falls du diesen Weg gehst; aktuelle Details findest du unter smithery.ai, da sich ihr Hosting-Modell aktiv ändert.


🔐 Umgebungsvariablen

Variable

Erforderlich

Verwendet von

SUPABASE_DB_URL (oder eine beliebige Postgres-URL)

❌ Optional

Wird nicht automatisch gelesen – query_database erhält die Verbindungszeichenfolge als direktes Argument. Nur als persönliche Referenz/Bequemlichkeit in .env nützlich.

query_database ist in Bezug auf Anmeldedaten bewusst zustandslos – innerhalb des Tools selbst wird nichts aus Umgebungsvariablen gelesen, sodass standardmäßig niemals Datenbank-Anmeldedaten serverseitig gespeichert werden.


🗺️ Roadmap

  • Einen echten Integrationstest gegen eine wegwerfbare Postgres/Supabase-Instanz hinzufügen (nur CI, Anmeldedaten werden nie eingecheckt)

  • Die substring-basierte SQL-Schlüsselwortprüfung durch einen echten SQL-Parser (z. B. sqlparse) ersetzen, um Fehlalarme zu eliminieren

  • Caching für search_web und fetch_markdown hinzufügen

  • Eine Authentifizierungsschicht für gehostete Smithery-Deployments hinzufügen


🤝 Mitwirken

Beiträge, Issues und Feature-Anfragen sind willkommen – eröffne gerne ein PR oder Issue.


📄 Lizenz

Dieses Projekt ist unter der MIT-Lizenz lizenziert.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers