Claude Code + Supabase: Datenbank-Integration für AI Agents

Wie Claude Code Agents sicher und direkt auf Supabase zugreifen — MCP-Konfiguration Schritt für Schritt, Row Level Security für Agents, pgvector für Agent-Memory, und 4 Anwendungsfälle die wir selbst in Produktion nutzen.

Warum Supabase ideal für Claude Code Agents ist

Wenn du AI Agents mit persistentem Zustand baust — also Agents, die sich Dinge merken, Nutzer-Status abfragen oder Metriken speichern müssen — brauchst du eine Datenbank. Die Frage ist nur: welche, und wie integrierst du sie sicher?

Wir nutzen Supabase seit Monaten in unserer Produktion. Unsere Agents verwalten darüber eine trial_users Tabelle, speichern täglich KPIs und führen semantische Suchen über pgvector-Embeddings aus. Hier ist, warum Supabase für diesen Zweck besser geeignet ist als ein selbst gehostetes Postgres oder eine klassische REST-API:

REST API — kein eigener DB-Server nötig

Supabase stellt für jede Tabelle automatisch eine REST API über PostgREST bereit. Das bedeutet: ein Claude Code Agent kann per einfachem HTTP-Request Daten lesen und schreiben — ohne Datenbankverbindung, ohne Connection Pooling, ohne eigene API-Schicht. Der MCP Server abstrahiert das nochmals, sodass der Agent direkt SQL-ähnliche Operationen ausführen kann, ohne je eine Verbindungszeichenkette sehen zu müssen.

Row Level Security — Agents kriegen nur was sie dürfen

Das ist der entscheidende Vorteil gegenüber einfachen REST-APIs: Supabase Row Level Security (RLS) erlaubt es, exakt zu definieren, welcher Agent welche Zeilen sehen darf. Ein Support-Agent darf nur Tickets lesen, kein anderer Nutzer. Ein Monitoring-Agent schreibt nur in Log-Tabellen, liest aber keine User-Passwörter. Diese Policies werden auf Datenbankebene erzwungen — kein Code-Bug im Agent kann sie umgehen.

Realtime Subscriptions — Agent reagiert auf DB-Events

Über Supabase Realtime kann ein Agent auf Datenbankänderungen reagieren, statt sie pollingbasiert abzufragen. Ein neuer Eintrag in support_tickets triggert sofort den zuständigen Agent. Das reduziert Latenz und vermeidet unnötige API-Aufrufe. Besonders nützlich für Event-Driven Agent-Architekturen.

Embeddings / pgvector — für semantische Suche in Agent-Memory

Supabase unterstützt die pgvector Extension direkt in PostgreSQL. Das bedeutet: du kannst Embeddings (Vektoren) direkt neben deinen strukturierten Daten speichern, Cosine-Similarity-Suchen ausführen und hybride Suchen kombinieren — strukturierte Filter plus semantische Nähe. Wir nutzen das für Agent-Memory: vergangene Entscheidungen werden als Embeddings gespeichert und bei neuen Aufgaben semantisch abgerufen.

Aus unserer Produktion: Wir verwalten trial_users, agent_kpis und yt_intelligence (Transkripte + Embeddings) in Supabase. Alle Claude Code Agents nutzen ausschließlich den ANON_KEY mit RLS — kein Agent hat je Zugriff auf den Service Role Key.

Setup: Supabase MCP in Claude Code konfigurieren

Claude Code unterstützt MCP (Model Context Protocol) Server, die dem Modell zusätzliche Fähigkeiten geben. Den Supabase MCP Server einzurichten dauert etwa 5 Minuten.

Schritt 1: Supabase URL und ANON_KEY holen

Gehe in deinem Supabase-Projekt zu Settings → API. Dort findest du:

Kopiere beide Werte. Den service_role Key brauchst du für Agent-Zugriff ausdrücklich nicht — dazu mehr im Sicherheitsabschnitt.

Schritt 2: MCP Server in .claude/settings.json eintragen

Im Projektverzeichnis (oder global unter ~/.claude/settings.json) fügst du den Supabase MCP Server ein. Das ist die minimale funktionierende Konfiguration:

{
  "mcpServers": {
    "supabase": {
      "command": "npx",
      "args": [
        "-y",
        "@supabase/mcp-server-supabase@latest",
        "--supabase-url", "https://DEIN-PROJEKT-ID.supabase.co",
        "--supabase-key", "DEIN_ANON_KEY"
      ]
    }
  }
}

Ersetze DEIN-PROJEKT-ID und DEIN_ANON_KEY mit deinen Werten aus Schritt 1. Für Produktionsprojekte empfehlen wir, die Werte als Umgebungsvariablen zu übergeben:

{
  "mcpServers": {
    "supabase": {
      "command": "npx",
      "args": [
        "-y",
        "@supabase/mcp-server-supabase@latest",
        "--supabase-url", "${SUPABASE_URL}",
        "--supabase-key", "${SUPABASE_ANON_KEY}"
      ]
    }
  }
}

Danach Claude Code neu starten. Mit /mcp kannst du prüfen, ob der Server verbunden ist. Du solltest supabase: connected sehen.

Tipp: Wenn du mehrere Projekte (Staging + Produktion) hast, trage zwei Einträge ein — z.B. supabase-prod und supabase-staging. So kannst du im Prompt explizit referenzieren, welche Umgebung der Agent nutzen soll.

4 praktische Anwendungsfälle aus der Produktion

Use Case 1

User-Daten lesen — Trial-User-Status prüfen

Unser Trial-Funnel schreibt neue Signups direkt in eine trial_users Tabelle in Supabase. Agents, die mit Trial-Usern interagieren, prüfen vor jeder Aktion den Status: Ist der Trial noch aktiv? Hat der User bereits onboardet? Welches Tier?

Produktions-Query: SELECT tier, trial_ends_at, onboarded FROM trial_users WHERE email = $1 AND trial_ends_at > now() — gibt direkt zurück ob der User noch berechtigt ist. RLS stellt sicher, dass kein Agent fremde User-Einträge sehen kann.
Use Case 2

Events loggen — Agent-Aktionen in DB schreiben

Jede signifikante Aktion unserer Agents wird in einer agent_events Tabelle protokolliert: welcher Agent, welche Aktion, Timestamp, ob erfolgreich. Das gibt uns Observability ohne externes Logging-System und ermöglicht es, Agent-Verhalten nachzuverfolgen und zu debuggen.

Schema: INSERT INTO agent_events (agent_id, action_type, payload, success, created_at) VALUES ($1, $2, $3, $4, now()) — schlankes Event-Log, querybar über Supabase Studio oder direkt via MCP.
Use Case 3

KPIs speichern — tägliche Metriken persistent halten

Unser Strategy-Agent berechnet täglich KPIs: Trial-Signups, aktive Sessions, Revenue-Pipeline. Diese landen in einer daily_kpis Tabelle mit date, metric_name und value. So kann der Agent beim nächsten Start direkt auf historische Daten zugreifen — ohne erneut alle Quellen abzufragen.

Vorteil: Ein Agent, der am Montag KPIs berechnet hat, muss sie nicht am Dienstag neu berechnen. SELECT value FROM daily_kpis WHERE metric_name = 'trial_signups' ORDER BY date DESC LIMIT 7 liefert die letzte Woche sofort.
Use Case 4

Semantische Suche — pgvector für Agent-Memory

Für unser YT-Intelligence-System speichern wir Video-Transkripte als Embeddings in Supabase. Wenn ein Agent eine Idee oder ein Konzept sucht, führt er eine Cosine-Similarity-Suche über alle gespeicherten Transkripte aus — und findet inhaltlich relevante Videos, auch wenn kein Keyword übereinstimmt.

Hybrid Search: Wir kombinieren pgvector <=> Cosine Distance mit einem Keyword-Filter via to_tsvector. Das gibt präzisere Ergebnisse als reine Vektorsuche — gerade bei fachspezifischen Begriffen.

Sicherheit: Was Agents NICHT dürfen

Das ist der kritischste Abschnitt. Ein falsch konfigurierter Agent mit zu viel Datenbankzugriff ist ein ernstes Sicherheitsproblem. Hier sind die Regeln, die wir nach mehreren Iterationen aufgestellt haben:

Service Role Key NIEMALS im Agent-Kontext

Der service_role Key bypassed alle Row Level Security Policies. Ein Agent mit diesem Key kann alles lesen, schreiben und löschen — uneingeschränkt. Dieser Key gehört ausschließlich in serverseitige Admin-Prozesse, niemals in Claude Code Agent Konfigurationen. Wenn er in einem Prompt oder einer Konfigurationsdatei auftaucht, behandle das als Security Incident.

NIEMALS: service_role Key in .claude/settings.json, Agent Prompts oder Umgebungsvariablen die Agents zugänglich sind. Immer nur anon Key für Agents — RLS schützt den Rest.

Row Level Security Policies definieren — Pflicht, nicht Option

Standardmäßig blockiert Supabase bei aktivierter RLS alle Zugriffe. Das ist gut — aber du musst explizite Policies definieren, was erlaubt ist. Für unsere agent_events Tabelle sieht das so aus:

-- Nur eigene Events lesen (über agent_id in JWT-Claims)
CREATE POLICY "agents_read_own_events"
ON agent_events FOR SELECT
USING (agent_id = current_setting('request.jwt.claims', true)::json->>'sub');

-- Schreiben erlaubt für alle authentifizierten Agents
CREATE POLICY "agents_insert_events"
ON agent_events FOR INSERT
WITH CHECK (true);

-- KEIN DELETE, KEIN UPDATE — Events sind immutable

Agents nur mit ANON_KEY — niemals Admin

Der anon Key ist so designed, dass er sicher in Client-Anwendungen genutzt werden kann — solange RLS korrekt konfiguriert ist. Agents sind konzeptuell Client-seitige Prozesse, selbst wenn sie auf Servern laufen. Die Kombination anon Key + RLS Policies gibt dir fine-grained Kontrolle ohne Admin-Risiko.

Minimale Berechtigungen pro Agent

Nicht jeder Agent braucht Zugriff auf alle Tabellen. Nutze Supabase Policies um Zugriff auf das absolute Minimum zu beschränken. Ein Content-Agent braucht keinen Zugriff auf trial_users. Ein Billing-Agent hat nichts in agent_memory zu suchen. Je kleiner der Blast Radius eines kompromittierten Agents, desto besser.

Häufige Fehler und wie du sie vermeidest

CORS-Fehler — Supabase URL falsch konfiguriert

Der häufigste Anfängerfehler: die Supabase URL ohne https:// oder mit abschließendem Slash eintragen. Die korrekte Form ist immer https://PROJEKT-ID.supabase.co ohne Slash am Ende. CORS-Fehler im MCP-Log bedeuten fast immer, dass die URL nicht stimmt oder das Projekt pausiert ist (Supabase pausiert inaktive Projekte im Free Tier nach 1 Woche).

RLS blockiert alle Queries — Policy fehlt

Wenn RLS aktiviert ist aber keine Policy definiert wurde, schlägt jede Query fehl — auch lesende. Das ist die sichere Default-Einstellung. Die Fehlermeldung lautet meist new row violates row-level security policy oder einfach leere Ergebnisse ohne Fehler. Lösung: zunächst mit dem Service Role Key testen (nur lokal, nie in Produktion), dann die fehlende Policy ergänzen.

-- Debug: Alle Policies einer Tabelle anzeigen
SELECT schemaname, tablename, policyname, cmd, qual
FROM pg_policies
WHERE tablename = 'deine_tabelle';

Timeout bei großen Queries — Paginierung nötig

Supabase hat einen Default-Timeout von 10 Sekunden für Queries. Bei großen Tabellen (oder teuren Vektor-Suchen) wird der überschritten. Lösung: immer paginieren. Nutze LIMIT und OFFSET, oder noch besser Cursor-basierte Paginierung mit WHERE id > $last_id LIMIT 100. Für Vektor-Suchen: Index anlegen (CREATE INDEX ON tabelle USING ivfflat (embedding vector_cosine_ops)).

Agent schreibt Duplikate

Agents, die bei jedem Start die gleichen Events oder KPIs schreiben, erzeugen schnell Duplikate. Nutze INSERT ... ON CONFLICT DO NOTHING oder UPSERT mit einer eindeutigen Constraint-Spalte. Für KPIs zum Beispiel:

-- UPSERT: update wenn vorhanden, insert wenn neu
INSERT INTO daily_kpis (date, metric_name, value)
VALUES (CURRENT_DATE, 'trial_signups', 42)
ON CONFLICT (date, metric_name)
DO UPDATE SET value = EXCLUDED.value, updated_at = now();

Code-Beispiel: Agent der Trial-User-Status prüft

Hier ist ein vollständiges Beispiel: ein Python-Skript das einen Claude Code Agent simuliert, der über den Supabase MCP Server den Trial-Status eines Users prüft und entsprechend handelt. Du kannst dieses Muster direkt in eigene Agent-Prompts übernehmen.

import os
import anthropic

client = anthropic.Anthropic()

def check_trial_status(email: str) -> dict:
    """
    Nutzt Claude Code Agent mit Supabase MCP
    um Trial-User-Status zu prüfen.
    """

    system_prompt = """Du bist ein Agent mit Zugriff auf unsere Supabase Datenbank.
    Nutze das Supabase MCP Tool um Datenbankabfragen auszuführen.
    Antworte immer mit strukturierten JSON-Daten.
    WICHTIG: Nur SELECT-Queries, niemals INSERT/UPDATE/DELETE für User-Daten."""

    user_prompt = f"""Prüfe den Trial-Status für Email: {email}

    Führe folgende Query aus:
    SELECT
        email,
        tier,
        trial_ends_at,
        onboarded,
        CASE
            WHEN trial_ends_at > now() THEN 'active'
            ELSE 'expired'
        END as status
    FROM trial_users
    WHERE email = '{email}'
    LIMIT 1;

    Gib das Ergebnis als JSON zurück mit den Feldern:
    found (bool), status (active/expired/not_found), tier, days_remaining (int)
    """

    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=1024,
        system=system_prompt,
        messages=[{"role": "user", "content": user_prompt}]
        # MCP Server wird über .claude/settings.json geladen
    )

    return response.content[0].text

# Verwendung:
# result = check_trial_status("user@example.com")
# print(result)
# Ausgabe: {"found": true, "status": "active", "tier": "starter", "days_remaining": 8}

In der Praxis ist der MCP Server bereits konfiguriert wenn der Agent startet — er muss nur wissen, welche Tabellen er abfragen darf (das regeln die RLS Policies) und wie die Abfragen aussehen sollen (das steht im System-Prompt).

Eigene AI Agents mit Datenbankanbindung bauen?

Wir helfen dir beim Setup — von Supabase-Konfiguration über RLS-Policies bis hin zu kompletten Agent-Architekturen. 14 Tage kostenlos testen.

Kostenlos starten →

Fazit

Supabase ist aktuell die beste Wahl wenn du Claude Code Agents mit persistentem Datenbankzugriff ausstatten willst. Die Kombination aus automatischer REST API, Row Level Security und pgvector macht es möglich, Agents sicher und granular anzubinden — ohne eigene Backend-Schicht.

Die wichtigsten Punkte zusammengefasst:

Wenn du die MCP-Grundlagen noch nicht kennst, empfehle ich dir zuerst unseren Überblick über alle MCP Server. Danach macht dieser Artikel nochmals mehr Sinn.