MCP vs RAG vs AI Agent: detaillierte Erklärung mit Beispielen

Zu diesem Artikel gibt es ein kurzes Video:YouTubeTikTok

1. Überblick

Die Namen MCP, RAG und AI Agent tauchen überall auf, wenn es um LLM-Anwendungen geht, und es ist leicht, sie als „drei konkurrierende Optionen” zu verwechseln. In Wirklichkeit lösen sie aber drei verschiedene Probleme: RAG hilft LLMs, auf Basis eigener Daten richtig zu antworten, AI Agent hilft LLMs, selbst Pläne zu erstellen und Aktionen auszuführen, während MCP ein Kommunikationsstandard ist, damit LLM-Apps einheitlich mit Tools/Daten verbunden werden können. Nach diesem Artikel kannst du die drei Konzepte klar unterscheiden, weißt, wann man welches einsetzt, und hast ein paar funktionsfähige Java/Spring-AI-Code-Beispiele, um die Praxis zu verstehen.

2. Was ist RAG?

RAG (Retrieval-Augmented Generation) ist eine Technik, bei der externe Daten „eingebettet” werden, bevor ein LLM aufgerufen wird, sodass das Modell auf echte Daten antwortet statt nur auf sein Trainingswissen.

2.1. Der Workflow von RAG

  1. Konvertieren Sie Quelltext (Richtlinien, Dokumente, FAQs) in Embeddings (Zahlen-Vektoren) und speichern Sie diese in einer Vektor-Datenbank.
  2. Wenn der Nutzer eine Frage stellt, konvertieren Sie diese in ein Embedding und finden Sie die ähnlichsten Textstellen (Similarity Search).
  3. Fügen Sie die gefundenen Abschnitte in den Prompt ein und senden Sie ihn dann an das LLM, um eine Antwort zu generieren.

Beispiel: Der OrderService muss die Frage „Was ist die Richtlinie für Online-Rücksendungen?” auf Basis von Unternehmensrichtlinien-Dokumenten beantworten, nicht auf Basis von allgemeinem Modellwissen.

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-vector-store-pgvector</artifactId>
</dependency>

2.2. Einfaches RAG-Code-Beispiel

@Service
public class ReturnPolicyAssistant {

    private final VectorStore vectorStore;
    private final ChatClient chatClient;

    public ReturnPolicyAssistant(VectorStore vectorStore, ChatClient.Builder builder) {
        this.vectorStore = vectorStore;
        this.chatClient = builder.build();
    }

    public String answer(String question) {
        List<Document> relevant = vectorStore.similaritySearch(
                SearchRequest.query(question).withTopK(3));

        String context = relevant.stream()
                .map(Document::getContent)
                .collect(Collectors.joining("\n---\n"));

        String prompt = """
                Beantworten Sie die Kundenfrage basierend auf der folgenden Richtlinien-Dokumentation.
                Wenn es keine Informationen gibt, sagen Sie "Ich bin nicht sicher".

                Dokumentation:
                %s

                Frage: %s
                """.formatted(context, question);

        return chatClient.prompt(prompt).call().content();
    }
}
  • vectorStore.similaritySearch gibt 3 Textabschnitte zurück, die der Frage am ähnlichsten sind.
  • Der Prompt wird durch den aus dem Vector Store abgerufenen Context „augmentiert”, bevor er an das LLM gesendet wird.
  • Wenn die Dokumentation keine relevanten Informationen enthält, wird das Modell angewiesen, „Ich bin nicht sicher” zu antworten, statt zu halluzinieren (Halluzination).
Eingabe:  "Ich habe vor 5 Tagen online ein Hemd gekauft, kann ich es umtauschen?"
Ausgabe: "Nach unserer Richtlinie können Sie innerhalb von 7 Tagen nach Erhalt umtauschen, 
         solange das Produkt noch das Etikett hat. Ihr Hemd ist noch innerhalb der Frist."

Hinweis: RAG hilft dem Modell nur, „mehr Daten zu kennen”. Es hilft nicht, dass das Modell von selbst handelt (APIs aufruft, Datenbanken aktualisiert). Wenn Sie brauchen, dass das Modell etwas tut statt nur zu antworten, brauchen Sie einen Agent.

3. Was ist AI Agent?

Ein AI Agent ist ein System, das ein LLM als „Gehirn” nutzt, um Pläne zu erstellen, passende Tools auszuwählen, Tools aufzurufen, Ergebnisse zu beobachten und dies zu wiederholen, bis das Ziel erreicht ist – anders als RAG, das nur bei der Beantwortung einer Frage stehen bleibt.

3.1. Der Schleifen-Zyklus reason → act → observe

Das häufigste Modell ist ReAct: Das Modell denkt (Reasoning), wählt ein Tool aus, das aufgerufen wird (Action), erhält das Ergebnis (Observation) und denkt dann weiter basierend auf diesem Ergebnis.

public interface AgentTool {
    String name();
    String description();
    String execute(String input);
}

@Component
public class CheckOrderStatusTool implements AgentTool {
    private final OrderRepository orderRepository;

    public CheckOrderStatusTool(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    public String name() { return "checkOrderStatus"; }
    public String description() { return "Bestellstatus nach orderId prüfen"; }

    public String execute(String orderId) {
        return orderRepository.findById(orderId)
                .map(o -> "Bestellung %s ist %s".formatted(orderId, o.getStatus()))
                .orElse("Bestellung %s nicht gefunden".formatted(orderId));
    }
}

3.2. Agent wählt und ruft Tools auf

@Service
public class SupportAgent {

    private final ChatClient chatClient;
    private final List<AgentTool> tools;

    public SupportAgent(ChatClient.Builder builder, List<AgentTool> tools) {
        this.chatClient = builder.build();
        this.tools = tools;
    }

    public String handle(String userMessage) {
        return chatClient.prompt()
                .user(userMessage)
                .tools(tools.toArray()) // Spring AI mappt automatisch die execute()-Methode zu Function Calls
                .call()
                .content();
    }
}
  • tools(tools.toArray()) teilt dem Modell mit, dass es diese Tools aufrufen kann; Spring AI generiert automatisch das Schema für Function-Calling.
  • Das Modell entscheidet selbst: Wenn die Frage den Bestellstatus betrifft, ruft es checkOrderStatus mit der aus der Frage ermittelten orderId auf, erhält das Ergebnis und interpretiert es dann in natürlicher Sprache.
Nutzer: "Wie geht es meiner Bestellung ORD-2024-891?"
Agent: (ruft Tool checkOrderStatus("ORD-2024-891") auf)
       → "Bestellung ORD-2024-891 wird gerade geliefert und soll in 2 Tagen ankommen."

3.3. Tool-Auswahl-Verhalten testen

@Test
void shouldCallCheckOrderStatusWhenAskingAboutOrder() {
    AgentTool tool = new CheckOrderStatusTool(orderRepository);
    when(orderRepository.findById("ORD-1")).thenReturn(Optional.of(shippedOrder));

    String result = tool.execute("ORD-1");

    assertThat(result)
        .contains("ORD-1")
        .contains("SHIPPED");
}

Dieser Test ruft kein echtes LLM auf, sondern bestätigt nur, dass die Tool-Logik funktioniert – das Verhalten „Modell wählt welches Tool” sollte mit einem Eval Set getestet werden, nicht mit starrem Unit Testing, da die LLM-Ausgabe nicht deterministisch ist.

Hinweis: Agents sind mächtig, aber riskanter als RAG – wenn Tools Schreibzugriff haben (Rückerstattung, Update), kann eine falsche Überlegung des Modells echte Folgen haben. Fügen Sie immer einen Bestätigungsschritt hinzu oder beschränken Sie die Berechtigungen für sensible Tools.

4. Was ist MCP?

MCP (Model Context Protocol) ist ein offener Standard, der definiert, wie eine LLM-Anwendung (genannt Host) sich über ein einheitliches Protokoll mit externen Datenquellen und Tools (genannt Server) verbindet, statt dass jede Integration seinen eigenen Code schreiben muss.

4.1. Die Probleme, die MCP löst

Vor MCP: Wenn Sie 5 LLM-Apps haben und jede 10 Datenquellen/Tools (Datenbank, CRM, Dateisystem…) nutzen soll, müssen Sie bis zu 50 separate Integrationen schreiben – das bekannte N×M-Problem. MCP macht daraus N+M: Jeder Server wird einmal geschrieben, und jeder Host, der dem MCP-Standard folgt, kann ihn aufrufen.

4.2. MCP-Architektur

  • Host: Die Anwendung, die das LLM enthält (Chatbot, IDE-Assistent…).
  • Client: Eine Komponente im Host, die eine 1-zu-1-Verbindung zu einem MCP Server aufrechterhält.
  • Server: Ein Prozess, der 3 Arten von „Fähigkeiten” bereitstellt:
    • Resources: lesbare Daten (ähnlich einem GET-Endpunkt).
    • Tools: aufrufbare Aktionen (ähnlich POST/Action).
    • Prompts: wiederverwendbare Prompt-Vorlagen.

4.3. Beispiel: Schreiben eines MCP Server in Java

<dependency>
    <groupId>io.modelcontextprotocol.sdk</groupId>
    <artifactId>mcp</artifactId>
    <version>0.8.0</version>
</dependency>
public class OrderMcpServer {

    public static void main(String[] args) {
        McpSyncServer server = McpServer.sync(StdioServerTransport.builder().build())
                .serverInfo("order-service", "1.0.0")
                .tool(orderLookupTool())
                .build();

        server.start();
    }

    private static McpServerFeatures.SyncToolSpecification orderLookupTool() {
        var schema = """
                {
                  "type": "object",
                  "properties": { "orderId": { "type": "string" } },
                  "required": ["orderId"]
                }
                """;

        return new McpServerFeatures.SyncToolSpecification(
                new Tool("getOrderById", "Bestellung nach orderId nachschlagen", schema),
                (exchange, args) -> {
                    String orderId = (String) args.get("orderId");
                    String status = OrderLookup.findStatus(orderId);
                    return new CallToolResult(List.of(new TextContent(status)), false);
                });
    }
}
  • McpServer.sync(...) erstellt den Server mit stdio-Transport (der Host führt den Server als Subprocess aus und kommuniziert über stdin/stdout).
  • tool(orderLookupTool()) registriert ein Tool getOrderById mit JSON-Schema, das die Eingabe beschreibt, damit jeder Host nach MCP-Standard „sehen kann, welche Felder dieses Tool braucht”.
  • Wenn ein Client getOrderById aufruft, gibt der Server ein CallToolResult mit dem Text-Inhalt zurück.

4.4. MCP Server von Spring AI Client aufrufen

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
spring:
  ai:
    mcp:
      client:
        stdio:
          connections:
            order-service:
              command: java
              args: ["-jar", "order-mcp-server.jar"]
@Service
public class McpAgentBridge {

    private final SyncMcpToolCallbackProvider toolCallbackProvider;
    private final ChatClient chatClient;

    public McpAgentBridge(SyncMcpToolCallbackProvider toolCallbackProvider,
                           ChatClient.Builder builder) {
        this.toolCallbackProvider = toolCallbackProvider;
        this.chatClient = builder.build();
    }

    public String ask(String question) {
        return chatClient.prompt()
                .user(question)
                .tools(toolCallbackProvider.getToolCallbacks())
                .call()
                .content();
    }
}
  • Spring AI startet den MCP Server (order-mcp-server.jar) automatisch als Subprocess und behält die Verbindung über stdin/stdout.
  • toolCallbackProvider.getToolCallbacks() ruft alle Tools auf, die der Server bereitstellt (hier: getOrderById) und fügt sie als Function Calls ins Modell ein, genau wie bei der manuellen Registrierung von AgentTool in Abschnitt 3 – nur dass dieses Tool von einem unabhängigen Prozess nach einem gemeinsamen Standard bereitgestellt wird.

Hinweis: MCP ersetzt Function Calling des LLMs nicht. Es ist eine Transport- und Standardisierungsschicht unter Function Calling, die es Tools ermöglicht, einmal geschrieben und auf vielen Hosts (Claude Desktop, IDE, Ihre App) wiederverwendet zu werden, ohne den Integrationscode jedes Mal zu ändern.

5. Vergleich von MCP, RAG und AI Agent

Kriterium RAG AI Agent MCP
Was sollen sie lösen Modell fehlen private/neue Daten Modell kann nicht selbst handeln oder mehrstufige Pläne erstellen Tool/Daten haben redundanten Integration-Code, sind nicht standardisiert
Operative Einheit Abrufen + Prompt Augmenting Reason-Act-Observe-Schleife Verbindungsprotokoll Host ↔ Server
Ruft es Tools/Aktionen auf? Nein (nur Lesezugriff) Ja Ja (stellt Tools für Agent-Aufrufe bereit)
Risiko-Level Niedrig (nur falsche Antworten bei schlechtem Abruf) Hoch (könnte falsche Aktionen ausführen) Hängt von Tools darunter ab; das Protokoll selbst ist neutral
Beziehungen untereinander Ist eine „Datenquelle”, die der Agent nutzen kann Kann RAG als Tool nutzen, MCP nutzen um standardisierte Tools aufzurufen Ist eine „Pipeline” für den Agent zum Aufrufen von RAG/Tools auf einheitliche Weise

Kurz: RAG gibt dem Modell Wissen, Agent gibt dem Modell die Fähigkeit zu handeln, MCP ist der Kommunikationsstandard, damit diese Aktionen/Abrufe nicht jedes Mal neu geschrieben werden müssen, wenn man den Host oder das Tool wechselt.

6. Alle drei in einem realen System kombinieren

Reale große Projekte wählen nicht eine aus drei Optionen, sondern stapeln sie aufeinander:

Nutzer → AI Agent (Planung, ReAct-Schleife)
          ├─ ruft MCP Client → MCP Server "knowledge-base" → gibt RAG-Similarity-Such-Ergebnisse zurück
          ├─ ruft MCP Client → MCP Server "order-service"  → Tool getOrderById auf
          └─ ruft MCP Client → MCP Server "payment-service" → Tool refundPayment auf (braucht Bestätigung)

In dieser Architektur:

  • RAG sitzt in einem separaten MCP Server (z.B. Server „knowledge-base” stellt Ressourcen mit Similarity-Such-Ergebnissen bereit).
  • Agent ist das Orchestrator, das die Reasoning-Schleife ausführt, interessiert sich nicht dafür, wie Tools geschrieben sind, sondern nur dass sie MCP einhalten.
  • MCP ist die vereinheitlichte Kommunikationsschicht zwischen Agent und allen Servern, mit der Sie neue Server hinzufügen können (z.B. „shipping-service”), ohne Agent-Code zu ändern.

7. Häufige Fehler

  • RAG verwenden, wenn Aktionen nötig sind: Daten in den Prompt eingeben, aber erwarten, dass das Modell die Datenbank selbst aktualisiert – RAG kann das nicht, Sie brauchen Agent + Tools mit Schreibberechtigung.
  • Agent ohne Tool-Berechtigungsbeschränkung: Agent kann direkt Tools wie deleteOrder oder refundPayment aufrufen, ohne menschliche Bestätigung, was Schaden verursacht, wenn das Modell falsch denkt.
  • MCP mit einem »AI Framework« verwechseln: MCP ist nur ein Verbindungsprotokoll, nicht selbst denkend oder abrufend. Wenn Ihr Server keine nützlichen Tools/Ressourcen bereitstellt, macht MCP das Modell nicht intelligenter.
  • Top-k zu klein oder zu groß in RAG: Top-k klein (1–2) führt zu fehlenden Kontext, Top-k groß (10+) macht den Prompt lang, verbraucht Token und verwässert wichtige Signale. Beginnen Sie mit 3–5 und bewerten Sie neu mit echten Eval Sets.
  • MCP-Tool-Schema nicht versionieren: Wenn Sie das Input-Schema des Tools ändern, ohne die Version zu erhöhen, werden andere Hosts, die den alten Server verwenden, mit falschen Parametern aufrufen.

8. Fazit

RAG, AI Agent und MCP konkurrieren nicht – sie liegen auf drei verschiedenen Ebenen eines LLM-Systems: RAG bietet Daten, Agent gibt Entscheidungs- und Handlungsfähigkeit, MCP bietet den Verbindungsstandard, damit das nicht jedes Mal neu geschrieben werden muss, wenn man Tool oder Host wechselt. Bei der Gestaltung eines realen AI-Systems sollten Sie mit der Frage beginnen, „was muss das Modell zusätzlich wissen” (RAG), „was muss das Modell tun” (Agent), und erst dann „wie können wir Tools/Daten an vielen Orten wiederverwenden” (MCP) – diese Reihenfolge hilft, von Anfang an über-Engineering zu vermeiden.

mcpragai-agentspring-aillm