sql-specialist-mcp
sql-specialist-mcp
Ein kleines, feinabgestimmtes Open-Weight-Modell, das natürliche Sprachfragen zu einer SQLite-Datenbank beantwortet und als MCP-Tool bereitgestellt wird, das jeder MCP-Client (Claude Desktop, Claude Code, benutzerdefinierte Agenten) direkt aufrufen kann – unterstützt durch eine ausführungsgenaue Eval-Harness, die den Spezialisten gegen das Prompting eines Frontier-Modells auf Genauigkeit, Latenz und Kosten benchmarkt.
Der Sinn dieses Projekts ist nicht „eine Text-zu-SQL-Demo bauen“ – es geht darum, die Teile des LLM-Engineerings zu zeigen, die unterhalb des Promptings liegen: ein kleines Modell nehmen, es über LoRA an eine Aufgabe anpassen, es effizient servieren und mit einer echten, ausführungsbasierten Eval beweisen, dass ein günstiger Spezialist für diese enge Aufgabe mit dem Prompting eines Frontier-Modells konkurrieren kann (oder besser ist).
Interaktive Demo ausprobieren – alle 28 echten Eval-Fragen durchklicken und das tatsächlich generierte SQL, die Latenz und die Ergebniszeilen des Spezialisten neben der Frontier-Baseline sehen. Keine Installation erforderlich.
Warum es das gibt
Die meisten „AI-Portfolio“-Text-zu-SQL-Projekte sind LangChain-Schnellstarts. Zwei Dinge hier sollen anders sein:
Die Eval ist rigoros, nicht Bauchgefühl. Jede Gold-Abfrage wird beim Erstellen des Datensatzes gegen die Datenbank ausgeführt (139/139 validiert), und die Bewertung vergleicht Ergebnismengen, nicht den Abfragetext – eine semantisch korrekte Abfrage mit anderer Spaltenreihenfolge wird trotzdem als korrekt bewertet. Ein Prädiktor, der nur das Gold-SQL wiedergibt, erzielt 100 %; ein Prädiktor, der immer eine trivial falsche Abfrage zurückgibt, erzielt 0 %. Beides ist als Sanity-Test eingecheckt (
tests/test_harness_oracle.py), damit die Korrektheit der Harness selbst nicht vorausgesetzt wird.Es wird als etwas Nutzbares ausgeliefert, nicht nur als Demo-Repo. Das feinabgestimmte Modell wird als echtes MCP-Tool (
nl_to_sql) bereitgestellt – Claude Desktop oder Claude Code aufmcp_server/server.pyzeigen und es kann die Datenbank tatsächlich als Teil einer Konversation abfragen.
Related MCP server: mcp-sqlite-chat
Ergebnisse
Die vollständige Pipeline wurde auf echter Hardware Ende-zu-Ende ausgeführt,
beide Seiten: echtes LoRA-Feintuning, echtes Merge, echte GGUF-Quantisierung,
echtes Ollama-Serving, echte Eval – und eine echte Frontier-Baseline gegen die
Live-Claude-API. Basismodell: Qwen/Qwen2.5-Coder-0.5B-Instruct (gewählt für
eine schnelle Iterationsschleife auf einem Laptop; siehe Feintuning unten
für den 1.5B-Pfad).
Prädiktor | Genauigkeit | n | p50-Latenz | p95-Latenz | Kosten / 1k Aufrufe |
Frontier: Claude Haiku 4.5 (gepromptet) | 53,6 % | 28 | 1055 ms | 1884 ms | 1,06 $ |
sql-specialist (feinabgestimmt, quantisiert, lokal) | 92,9 % | 28 | 207 ms | 371 ms | 0,00 $ |
Lies das mit der Einschränkung, nicht nur mit der Schlagzeile. Ich habe
jede der 13 gemessenen „Fehlschläge“ von Claude Haiku gegen diesen Eval-Satz
manuell geprüft: Null davon waren SQL-Logikfehler. Alle 13 waren
Spaltenauswahl- oder Zeilenreihenfolge-Konventionsabweichungen – z. B. die
Rückgabe von (name, email), wenn die Gold-Antwort nur (name) war, oder
korrekte Zeilen in einer anderen Reihenfolge als ein ORDER BY, das die
ursprüngliche Frage nie spezifiziert hatte. Die strenge
Ausführungsgenauigkeitsmetrik (eval/execution.py vergleicht Ergebniszeilen
Spalte für Spalte) bewertet diese identisch zu einer wirklich falschen
Abfrage, was der feinabgestimmte Spezialist nie produziert, weil er die
genauen Konventionen dieses Datensatzes aus 111 Trainingsbeispielen
auswendig gelernt hat – etwas, das ein Frontier-Modell, das zero-shot
gepromptet wird, nicht wissen kann. Vollständige Fehler-für-Fehler-Taxonomie
in COMPARISON.md.
Also: Die Genauigkeitslücke ist real, aber teilweise ein Artefakt dessen, was die Eval belohnt, nicht rein eine Denklücke. Die Latenz- und Kostenlücke ist kein Artefakt – 207 ms/lokal/kostenlos vs. 1055 ms/1,06 $ pro 1k Aufrufe ist das tatsächliche, ungeschönte Ergebnis, ein quantisiertes 0.5B-Modell lokal auszuführen, statt eine API aufzurufen, und es ist der Vergleich, auf dem die Prämisse dieses Projekts tatsächlich beruht.
Die eigenen 2 Fehler des Spezialisten (von 28) waren echte Logikfehler, keine
Formatierungsabweichungen – eine plausible orders.total-Spalte halluziniert,
die in diesem Schema nicht existiert, und ein Tabellenqualifizierer in einem
Multi-Tabellen-SELECT weggelassen. Das Training konvergierte sauber über 3
Epochen (Eval-Loss 0,060 → 0,048 → 0,008), und das quantisierte Modell
(988 MB f16 → 373 MB q4_k_m) wird über Ollama in ~200 ms bedient.
Was hier echt ist
Ehrlich zu sein, ist wichtiger, als es aussieht – es ist der Unterschied zwischen einem Projekt, dem ein Recruiter vertrauen kann, und einem, das sich wie Marketing liest.
Die synthetische Datenbank und der Datensatz sind nachweislich korrekt.
shopsphere.dbwird deterministisch geseedet (seed=42); jedes der 139 Gold-Paare (Frage, SQL) indata/*.jsonlwird aus parametrisierten Vorlagen generiert und zur Build-Zeit gegen die echte Datenbank ausgeführt – eine Vorlage, die ungültiges SQL produziert, lässt den Build fehlschlagen, sie liefert nicht stillschweigend ein schlechtes Label.Die Korrektheit der Eval-Harness ist selbst getestet, nicht vorausgesetzt –
tests/test_harness_oracle.pystellt sicher, dass ein Orakel-Prädiktor (gibt Gold-SQL wörtlich zurück) genau 100 % erzielt und ein absichtlich falscher Prädiktor ~0 %, bevor die Zahl eines echten Prädiktors vertraut wird.Ausführungsgenauigkeit, nicht String-Match.
eval/execution.pyvergleicht Ergebnismengen (reihenfolgeunabhängig, es sei denn, die Gold-Abfrage hatORDER BY), sodass eine anders geschriebene, aber semantisch äquivalente Abfrage trotzdem als korrekt bewertet wird.Das Feintuning ist echt, auf dieser Maschine, verifiziert konvergierend. LoRA (8,8 M trainierbare Parameter, 1,75 % des Modells) über 3 Epochen, Eval-Loss sinkt monoton in jeder Epoche. Siehe Engineering-Notizen unten für zwei echte Bugs, die dabei gefunden und behoben wurden.
SQL-Ausführung ist wirklich sandboxed, nicht nur dazu gepromptt, sich zu verhalten: Leseabfragen werden gegen eine Regex-Allowlist validiert und gegen eine echte schreibgeschützte SQLite-Verbindung ausgeführt (
mode=roauf OS-Ebene) – ein Bug im Regex-Guard kann trotzdem nicht zu einem Schreibzugriff führen. Das ist über die Eval-Harness hinaus wichtig, weil derselbe Guard im MCP-Server läuft, wo das SQL von einem Modell stammt, das auf eine Agentenfrage antwortet, nicht aus einem kuratierten Eval-Satz.Der MCP-Server ist ein echtes, aufrufbares Tool, das das echte feinabgestimmte Modell bedient, Ende-zu-Ende verifiziert:
nl_to_sql("Which employees have no manager assigned?")→ generiert SQL über das quantisierte Modell über Ollama → führt es schreibgeschützt aus → gibt echte Zeilen zurück → protokolliert Latenz/Kosten in die Observability.Observability ist selbstgebaut und ohne Abhängigkeiten –
observability/logger.pyprotokolliert jeden Aufruf (Latenz, Tokens, geschätzte Kosten, Erfolg/Fehler) in eine lokale SQLite-Datei, kein externes Konto nötig, gleiches Muster wiepr-review-agent.Die Frontier-Baseline ist auch echt –
eval/baseline_frontier.pylief gegen die Live-Claude-API (Claude Haiku 4.5), nicht nur sauber importiert. Ihre „Fehler“ entpuppten sich als echter Eval-Methodik-Befund – siehe Ergebnisse oben undCOMPARISON.mdfür die vollständige manuelle Fehlerprüfung.
Engineering-Notizen: zwei echte Bugs, die beim echten Ausführen gefunden wurden
Das tatsächliche Ausführen des Feintunings (statt es als „sollte in der Theorie funktionieren“ zu belassen) brachte zwei echte PyTorch-Speicherbugs ans Licht, beide im aktuellen Code behoben:
MPS-Caching-Allocator-Ausreißer. Das Training auf dem MPS-Backend von Apple Silicon über
transformers.Trainerließ den Prozess auf 23 GB RSS anwachsen und hängen, bei dynamischem Pro-Batch-Padding – jede unterschiedliche (Batch, seq_len)-Form bekommt ihren eigenen Speicherpool im MPS-Allocator von PyTorch, der freigegebenen Speicher nicht an das OS zurückgibt. Fix:--device cpu-Override infinetune.py, und grundsätzlicher: festes Padding (unten), damit diese Bug-Klasse auf keinem Backend wieder auftreten kann.Trainer/DataLoader-Overhead, nicht das Modell. Ein direkter Forward+Backward-Pass wurde mit 1,6 s/Beispiel gemessen; dieselbe Berechnung übertransformers.Trainerließ den Prozess Minuten zwischen protokollierten Schritten ohne entsprechende Rechenleistung im Leerlauf. Root-Cause durch Isolieren des tatsächlichen Modell+LoRA-Forward/Backward mit manuellem Timing, bevor angenommen wurde, der Bug sei im Modellcode. Fix:Trainerdurch eine ~40-zeilige manuelle Trainingsschleife ersetzt (training/finetune.py) – gleiches LoRA-Setup, direkte Kontrolle über die Batch-Schleife, kein unerklärlicher Overhead. Außerdem die Batch-Kollation von dynamisch-pro-Batch auf feste Länge umgestellt (jeder Batch identisch geformt), was unabhängig das Allocator-Fragmentierungsmuster aus Bug #1 behob.
Keiner der Fixes ist ein Workaround, der obendrauf gepackt ist – beide sind
in training/finetune.py als die einzige Implementierung sichtbar, nicht als
alternativer Pfad.
Architektur
data/build_dataset.py ──▶ data/{train,eval}.jsonl (139 examples, template-generated,
every gold SQL executed at build time)
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
training/finetune.py eval/baseline_frontier.py tests/test_harness_oracle.py
(LoRA on a small (prompt Claude Haiku/ (sanity-checks the harness
open model) Sonnet as the baseline) itself before trusting scores)
│ │
▼ │
training/merge_and_quantize.py
│ │
▼ ▼
serving/ollama_predictor.py ──┴──▶ eval/harness.py ──▶ eval/report.py ──▶ COMPARISON.md
│ (execution-accuracy scoring,
│ same logic for every predictor)
▼
mcp_server/server.py (nl_to_sql tool -- installable in Claude Desktop/Code)
│
▼
observability/logger.py (latency, tokens, cost -- local SQLite, no external account)Projektstruktur
schema/ synthetic "ShopSphere" e-commerce DB (7 tables) + seeded generator
data/ templated gold (question, SQL) dataset -- every query build-time validated
eval/ execution-accuracy harness, frontier baseline, comparison report
training/ LoRA fine-tuning pipeline + LoRA-merge/quantize script
serving/ Ollama-backed and in-process HF predictors, Ollama Modelfile template
mcp_server/ the installable MCP tool (nl_to_sql)
observability/ self-built call logging (latency/tokens/cost), no external account
tests/ harness sanity checks (oracle predictor must score 100%)Einrichtung
python3.11 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt # base: anthropic, mcp, requests
python schema/generate_data.py # build the seeded database
python data/build_dataset.py # build + validate the gold dataset
python tests/test_harness_oracle.py # confirm the eval harness itself is soundrequirements-train.txt fügt torch/transformers/peft/trl für den
Feintuning-Pfad hinzu – schwerer, separat gehalten, damit der
Eval/Serving/MCP-Pfad schnell installiert.
Die vollständige Pipeline ausführen
1. Frontier-Baseline (benötigt ANTHROPIC_API_KEY):
export ANTHROPIC_API_KEY="..."
python -m eval.baseline_frontier --model claude-haiku-4-5
# writes eval/results_claude-haiku-4-5.json2. Den Spezialisten feinabstimmen (das ist, was tatsächlich ausgeführt wurde, um die obigen Ergebnisse zu erzeugen – dauert ~15 Minuten aktive Rechenzeit auf einer Laptop-CPU, obwohl die Wanduhrzeit stark mit der Systemlast variiert; eine GPU ist viel schneller, siehe unten):
pip install -r requirements-train.txt
python -m training.finetune --base-model Qwen/Qwen2.5-Coder-0.5B-Instruct --device cpu
python -m training.merge_and_quantize --base-model Qwen/Qwen2.5-Coder-0.5B-Instruct
# then follow the printed llama.cpp + ollama create instructions3. Den Spezialisten auf dieselbe Weise bewerten wie die Baseline:
python -c "
from eval.harness import run_eval, report_to_dict
from serving.ollama_predictor import OllamaPredictor
import json
report = run_eval(OllamaPredictor())
json.dump(report_to_dict(report), open('eval/results_specialist.json', 'w'), indent=2)
"4. Den Vergleichsbericht generieren:
python -m eval.report eval/results_claude-haiku-4-5.json eval/results_specialist.jsonFeintuning: Skalierung
Die obigen Ergebnisse verwenden Qwen2.5-Coder-0.5B-Instruct auf der CPU,
für eine schnelle lokale Iterationsschleife. training/finetune.py --base-model akzeptiert jedes HF-Causal-LM-Repo (oder ein lokales
Verzeichnis) – Qwen2.5-Coder-1.5B-Instruct ist ein einfacher Tausch für
bessere Qualität, und eine einzelne Cloud-GPU (eine T4 reicht für diese
Datensatzgröße) trainiert beide Größen in ein paar Minuten statt ~15:
pip install -r requirements-train.txt
python -m training.finetune \
--base-model Qwen/Qwen2.5-Coder-1.5B-Instruct \
--epochs 3--device {cuda,mps,cpu} überschreibt die Auto-Erkennung. MPS wird auf
Apple Silicon automatisch erkannt, aber für diese Aufgabe noch nicht
empfohlen – siehe Engineering-Notizen oben.
MCP-Server
# Backend defaults to a locally-served model via Ollama:
python -m mcp_server.server
# Or run against a prompted frontier model instead (no fine-tune needed --
# useful for trying the tool before training anything):
SQL_SPECIALIST_BACKEND=frontier SQL_SPECIALIST_MODEL=claude-haiku-4-5 \
ANTHROPIC_API_KEY=... python -m mcp_server.serverZur MCP-Konfiguration von Claude Desktop hinzufügen
(claude_desktop_config.json):
{
"mcpServers": {
"sql-specialist": {
"command": "/absolute/path/to/sql-specialist-mcp/.venv/bin/python",
"args": ["-m", "mcp_server.server"],
"cwd": "/absolute/path/to/sql-specialist-mcp"
}
}
}Dann Claude etwas fragen wie „Mit dem sql-specialist-Tool, welche Kunden
haben noch nie eine Bestellung aufgegeben?“ – es ruft nl_to_sql auf,
bekommt echte Zeilen aus der Datenbank zurück und antwortet, gestützt auf
die tatsächlichen Daten.
Sicherheitshinweise
SQL-Ausführung ist auf zwei unabhängigen Ebenen schreibgeschützt: ein Regex-Guard, der alles außer
SELECT/WITHablehnt, und eine echte OS-Level-schreibgeschützte SQLite-Verbindung (file:...?mode=ro) als Backstop.Der MCP-Server führt nie etwas aus, das der Guard ablehnt, unabhängig davon, was das Modell oder der aufrufende Agent verlangt hat.
Keine Geheimnisse sind in diesem Repo gespeichert.
ANTHROPIC_API_KEYwird nur aus der Umgebung gelesen.
Was ich als Nächstes bauen würde
Die Eval für Spalten-Obermengen normalisieren – eine Vorhersage als korrekt bewerten, wenn die Werte der von der Gold-Abfrage angeforderten Spalten vorhanden sind, statt eine exakte Spalte-für-Spalte-Übereinstimmung zu verlangen. Das ist der Fix, der aus der Fehler-Taxonomie in
COMPARISON.mdimpliziert wird; er würde sehr wahrscheinlich den größten Teil der gemessenen 53,6 %→92,9 %-Lücke schließen und einen Vergleich erzeugen, der tatsächliche Denkfähigkeit von Konventionsabgleich isoliert.eval/baseline_frontier.pyauch gegen Claude Sonnet ausführen, für einen Vergleichspunkt mit stärkerem Modell (Haiku ist die günstige/schnelle Stufe; Sonnet ist die Frage „wie viel schließt Modellstärke allein die Lücke“).Qwen2.5-Coder-1.5B-Instructauf einer GPU feintunen und die Genauigkeit mit dem 0.5B-Ergebnis (92,9 %) vergleichen, um den Größe/Qualitäts-Kompromiss direkt zu quantifizieren.DPO, das auf die beiden bekannten Fehlermodi des Spezialisten abzielt (halluzinierte Spalten, weggelassene Tabellenqualifizierer bei Multi-Joins), jetzt, wo echte Fehlerdaten existieren.
vLLM-Serving-Pfad für einen Durchsatzvergleich gegen den Ollama/GGUF-Pfad.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables natural language database queries by combining Ollama's language models with SQLite database access through an MCP server.
- FlicenseNot gradedqualityCmaintenanceEnables querying and managing a SQLite database using natural language, with an MCP server and Groq LLM.
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to query a SQLite database using natural language through the Model Context Protocol (MCP). Includes security guardrails that block destructive SQL operations.
- AlicenseNot gradedqualityDmaintenanceMCP tool server providing SQLite database access for AI agents.MIT
Related MCP Connectors
GibsonAI MCP server: manage your databases with natural language
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Free OpenAI-compatible inference with signed provenance receipts and 3 focused MCP tools.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Eshanya1/sql-specialist-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server