Skip to content

Latest commit

 

History

History
589 lines (440 loc) · 22.7 KB

File metadata and controls

589 lines (440 loc) · 22.7 KB

MCP mit Python: Kompaktkurs (60 Minuten)

Von null auf produktiv: MCP-Grundlagen, Python-Implementierung, Orchestrierung und Praxis-Projekte

Kursüberblick & Agenda (60 Min)

  • 0–5 Min: Ziele, Setup-Check, Kontext
  • 5–20 Min: Teil 1 – MCP-Grundlagen (Konzepte, Nachrichtenfluss)
  • 20–35 Min: Teil 2 – Server entwickeln (Minimal-Server + PDF-Tools)
  • 35–45 Min: Teil 3 – Client bauen (Single/Multi-Server, Fehlerbehandlung)
  • 45–55 Min: Teil 4 – LLM-Orchestrierung (Entscheidungs-Loop, Parser)
  • 55–60 Min: Teil 5 – Fallstricke, Capstone-Preview, Q&A

Lernziele

  • ✅ MCP-Konzepte verstehen und einordnen
  • ✅ MCP-Server mit Python entwickeln
  • ✅ MCP-Clients implementieren
  • ✅ LLM-gesteuerte Orchestrierung nutzen

Kontext: Vertrauliche, lokale Notenverwaltung

Wir nutzen ein praxisnahes Uni-Szenario: 5 Notenmeldungen verschiedener Kurse liegen als PDFs lokal vor und bleiben vertraulich. Das LLM (z. B. Ollama lokal) hat keinen direkten Zugriff auf diese Daten. Wenn ein Dozent oder Studierender eine Frage stellt (z. B. "Welche Studierenden haben Datenbanken bestanden?"), ruft das LLM dynamisch passende MCP-Tools auf (Discovery → Auswahl → Ausführung), um lokal Notendaten zu laden und die Antwort zu bilden. So zeigen wir Datenschutz, lokalen Bezug und schlanke Orchestrierung ohne überflüssige Implementierungsdetails.

  {{1-3}}

KI-Perspektive: Warum keine RAG Lösung? Wir würden außerhalb des LLM einen Vektorstore mit Embeddings der PDFs pflegen, eine Suchfunktion implementieren und bei Fragen relevante Passagen extrahieren. Das LLM würde dann nur diese Passagen sehen. MCP ermöglicht hingegen direkten, strukturierten Zugriff auf die Originaldokumente via Tools/Resources, ohne Vektorstore oder Retrieval-Logik.

  {{2-3}}

Softwareengeniering-Perspektive: Warum kann ich aus dem LLM nicht einfach irgendeine API nutzen? Die Bandbreite der APIs ist beliebig groß und damit nicht pauschal abdeckbar. MCP bietet eine einheitliche Schnittstelle mit klaren Contracts (Schemas), Tool-Discovery und strukturierter Kommunikation, die speziell für die Interaktion zwischen LLMs und externen Systemen entwickelt wurde.

Teil 1: MCP-Grundlagen (15 Min)

Das Model Context Protocol (MCP) ist ein offener Standard und Open-Source-Framework, das vom US-Unternehmen Anthropic entwickelt wurde, um die Integration und den Datenaustausch zwischen künstlicher Intelligenz (KI), insbesondere großen Sprachmodellen (LLMs), und externen Tools, Systemen sowie Datenquellen zu standardisieren.

MCP wurde offiziell am 25. November 2024 vorgestellt und als Open-Source-Projekt veröffentlicht.

https://www.anthropic.com/news/model-context-protocol

Seit ein paar Tagen (Dez. 2025) "gehört" MCP der neu gegründeten Agentic AI Foundation, als Teil der Linux Foundation Link

Warum also MCP?

  • Reproduzierbarkeit: Gleiche Eingaben → gleiche Tool-Aufrufe → determinierbare Outputs (JSON, Schemas).
  • Governance & Audit: Jeder Tool-Call ist nachvollziehbar (Name, Schema, Parameter). Ermöglicht Audit-Trails und Compliance bei vertraulichen Daten.
  • Kapselung & Wiederverwendung: Einmal implementierte Fähigkeiten (z. B. PDF-Extraktion) werden von mehreren Clients/LLMs genutzt, ohne Code-Duplikate.
  • Testbarkeit: Tools sind kleine, isolierte Einheiten mit klaren Contracts → Unit-/Integrationstests werden einfach.
  • Sicherheit: Eingaben werden gegen inputSchema validiert; Server kontrolliert Dateizugriffe/Whitelists, verhindert Rohdaten-Leaks.
  • Portabilität: Transport-agnostisch (stdio/HTTP/WebSocket); Server können lokal, on-prem, oder im Cluster laufen.
  • Kosten- & Latenzkontrolle: LLM-Aufrufe nur, wenn nötig; teure Schritte (LLM) von günstigen (Parsing, I/O) trennen.
  • Versionierung: Tool-APIs können versioniert werden (v1, v2) bei gleichzeitiger Koexistenz.
  • Capability-Discovery: LLMs entscheiden zur Laufzeit, welche Tools nötig sind; neue Tools werden automatisch sichtbar.
  • Orchestrierbarkeit: Ermöglicht Planen, Retries, Alternativen (Fallback-Tools), ohne monolithische Pipelines.
  • Monetarisierung: Tools/Resources können als eigenständige Services angeboten werden (ähnlich wie APIs).

https://mcpserverhub.com/

https://www.aibase.com/de/news/18202

Warum "Protokoll"?

MCP definiert, wie Client und Server kommunizieren:

  1. Standardisierte Nachrichten (JSON-RPC)
  2. Klare Schnittstellen (Tools, Resources, Prompts)
  3. Transport-unabhängig (stdio, HTTP, WebSocket)

MCP wird gern als USB- oder HTTP-Standard für LLMs bezeichnet, da es eine einheitliche Schnittstelle für die Kommunikation zwischen LLMs und externen Systemen bietet.

Frage: Welche Parallelen sehen Sie zu ROS2 und ROS1 in Bezug auf Protokolle und Nachrichtenformate?

Grundlagen

  • MCP Host: KI-Anwendung, die mehrere MCP-Clients verwaltet (z. B. IDE, Desktop-App).
  • MCP Client: 1:1-Verbindung zu genau einem Server; führt Listen-/Aufrufe aus.
  • MCP Server: Stellt Kontext und Fähigkeiten bereit (Tools, Resources, Prompts). Lokal (STDIO) oder remote (HTTP/SSE).
graph LR
    subgraph AI_Host["AI Host<br/>(Claude, ChatGPT, Cursor)"]
        AI[AI]
        MCP_Client[MCP Client]
        AI -->|uses| MCP_Client
    end
    
    subgraph MCP_Server["MCP Server<br/>(Adapter for Data Source)"]
        SERVER[SERVER]
    end
    
    subgraph Data_Source["Data Source<br/>(Files, Databases, APIs)"]
        DB[(Database)]
        FILE[📄 PDF<br/>File]
    end
    
    MCP_Client -->|Request via MCP<br/>'Give me file report.pdf'| SERVER
    SERVER -->|Response via MCP| MCP_Client
    SERVER -->|Fetch/Execute| Data_Source
    Data_Source -->|Return Data| SERVER
    
    classDef hostStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
    classDef serverStyle fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
    classDef dataStyle fill:#fff3e0,stroke:#f57c00,stroke-width:2px
    
    class AI_Host hostStyle
    class MCP_Server serverStyle
    class Data_Source dataStyle
Loading

Frage: Welche Varianten können Sie sich vorstellen, um den MCP-Client und -Server zu implementieren?

Ebenen (Layers) - Warum diese Trennung?

MCP trennt bewusst zwischen Was (Datenebene) und Wie (Transportebene).

Data Layer (Inhaltsebene) - "Was macht das Tool?"

  • Definiert die Bedeutung der Nachrichten: Welche Strukturen gibt es (Tools, Resources, Prompts)?
  • Regelt den Ablauf: Initialisierung, Capability Negotiation, Tool-Aufrufe, Benachrichtigungen.
  • Wichtig: Ist unabhängig davon, wie die Daten übertragen werden.

Praxis-Beispiel: Ein get_grades Tool bleibt identisch, egal ob per STDIO oder HTTP aufgerufen.

Transport Layer (Übertragungsebene) - "Wie erreiche ich den Server?"

  • Kümmert sich um die Mechanik der Kommunikation: Wie werden Nachrichten gesendet, empfangen, gesichert?
  • Regelt Authentifizierung, Verschlüsselung, Verbindungsaufbau, Fehlerbehandlung.

Praxis-Beispiel: Der gleiche Server kann lokal (STDIO) für Entwicklung oder remote (HTTP) für Produktion laufen.

Analogie zu ROS: Ähnlich wie ROS-Messages (sensor_msgs) über DDS, TCP oder WebSocket übertragen werden können, funktionieren MCP-Tools über verschiedene Transporte.

Praktischer Nutzen:

# Server-Code (bleibt gleich):
@app.call_tool()
async def call_tool(name, args):
    return get_grades(args["course_id"])

# Transport wechseln (nur 1 Zeile):
stdio_server()      # Lokal für Tests
# oder
sse_server()        # Remote für Produktion

Primitive der Datenebene

Wir unterschieden drei Haupttypen von MCP-Primitiven:

  • Tools
  • Resources
  • Prompts

Im folgenden werden diese Primitiven im Detail erklärt.

Tools

Tools sind Funktionen, die spezifische Aufgaben ausführen. Jedes Tool hat:

  • Discovery: tools/list
  • Aufruf: tools/call mit name und arguments (validiert gegen das JSON Schema inputSchema).
{
    "name": "extract_pdf_text",
    "description": "Extrahiert Text aus PDF",
    "inputSchema": {
        "type": "object",
        "properties": {
            "file_path": {"type": "string"}
        }
    }
}
  1. Validierung: Server prüft Eingaben, bevor Code ausgeführt wird
  2. Dokumentation: LLM weiß, welche Parameter möglich sind
  3. Sicherheit: Verhindert ungültige/gefährliche Eingaben
  4. Typsicherheit: String, Number, Boolean, Object, Array
  5. UI-Generierung: Tools können automatisch Formulare erzeugen
Tool(
    name="get_grades",
    description="Ruft Notenliste eines Kurses ab",
    inputSchema={
        "type": "object",
        "properties": {
            "course_id": {
                "type": "string",
                "description": "ID des Kurses (z.B. 'datenbanken_ws2024')",
                "pattern": "^[a-z_0-9]+$"  # Nur Kleinbuchstaben, Unterstriche, Zahlen
            }
        },
        "required": ["course_id"]  # Pflichtparameter
    }
)

Was passiert bei Tool-Aufruf?

sequenceDiagram
    participant C as Client
    participant S as Server

    C->>S: tools/call("get_grades", {"course_id": "datenbanken_ws2024"})
    Note over S: 1. Validiere gegen inputSchema
    Note over S: ✓ course_id ist string
    Note over S: ✓ course_id ist required
    Note over S: ✓ Pattern matched
    Note over S: 2. Führe Tool aus
    S-->>C: {success: true, data: [...]}

    C->>S: tools/call("get_grades", {"course": 123})
    Note over S: 1. Validiere gegen inputSchema
    Note over S: ✗ "course" existiert nicht
    Note over S: ✗ "course_id" fehlt (required)
    S-->>C: {error: "Missing required parameter: course_id"}
Loading

Best Practices:

  • ✅ Beschreibungen für alle Properties (LLM-Verständnis)
  • ✅ Patterns für Strings (Sicherheit)
  • ✅ Min/Max für Numbers (Plausibilitätsprüfung)
  • ✅ Enums statt Freitext (weniger Fehler)
  • ✅ Required vs. Optional klar trennen
  • ❌ Keine komplexen Verschachtelungen (LLM-Verwirrrung)
  • ❌ Keine zu restriktiven Patterns (Flexibilität)

Resources

Resources sind lesbare Datenquellen, die LLMs als Kontext nutzen können. Im Gegensatz zu Tools (Aktionen) sind Resources passive Datenprovider.

Unterschied: Tools vs. Resources

Aspekt Tools (Aktionen) Resources (Daten)
Zweck Aktion ausführen Daten bereitstellen
Beispiel calculate_gpa() courses://list
Zustand Kann ändern Read-only
Caching Nein Ja
Komplexität Logik ausführen Daten liefern

Wann Resources statt Tools?

Resource verwenden wenn:

  • Statische/semi-statische Daten (z.B. Kursliste, Schema)
  • Kontext für LLM-Entscheidungen (z.B. verfügbare Optionen)
  • Wiederholter Zugriff auf gleiche Daten (Caching!)
  • Read-only Zugriff ausreichend

Tool verwenden wenn:

  • Komplexe Berechnungen nötig (z.B. GPA berechnen)
  • Zustand ändert sich (z.B. Note hinzufügen)
  • Parametrisierte Abfragen (z.B. Noten filtern nach Kurs)
  • Externe API-Aufrufe

Praxisbeispiel aus mcp_grades:

# Resource: Kursliste (statisch, cacheable)
Resource(
    uri="courses://all",
    name="Verfügbare Kurse",
    description="Liste aller Kurse im System",
    mimeType="application/json"
)
# LLM fragt: "Welche Kurse gibt es?"
# → Direkter Zugriff ohne Tool-Call!

# vs. Tool: Noten abrufen (dynamisch, parametrisiert)
Tool(
    name="get_grades",
    description="Ruft Noten eines spezifischen Kurses ab",
    inputSchema={
        "properties": {"course_id": {"type": "string"}}
    }
)
# LLM fragt: "Zeige Noten von Datenbanken"
# → Muss Tool aufrufen mit Parameter

Discovery und Zugriff:

  • Discovery: resources/list
  • Lesen: resources/read(uri)

Prompts

WICHTIG: MCP-Prompts sind NICHT die Prompts, die Sie an ein LLM schicken! Es sind wiederverwendbare Prompt-Templates, die der Server bereitstellt.

Was sind MCP-Prompts?

MCP-Prompts sind vordefinierte Interaktionsmuster, die Clients vom Server abrufen können. Sie funktionieren wie Makros oder Vorlagen für häufige Aufgaben.

Kernidee: Prompts sind Orchestrierungs-Pattern, die Tools und Resources zusammenführen:

Resources (Daten) + Tools (Aktionen) + Prompts (Workflow) = Komplette Lösung

Analogie: Kochen

  • Resources = Zutaten (Daten wie Kurslisten, Notendaten)
  • Tools = Küchengeräte (Funktionen wie calculate_gpa, get_grades)
  • Prompts = Rezept (Schritt-für-Schritt Anleitung, die Zutaten + Geräte kombiniert)

Ein Prompt sagt dem LLM: "Hole diese Daten (Resource), verarbeite sie mit diesem Tool, kombiniere die Ergebnisse so-und-so."

Unterschied zu LLM-Prompts:

Aspekt LLM-Prompt (gewöhnlich) MCP-Prompt (Template)
Was ist das? Text, den Sie an LLM senden Wiederverwendbare Vorlage vom Server
Wo definiert? Client-Code oder User-Input Server als MCP-Primitive
Zweck Instruktion für LLM Standardisierte Interaktionsmuster
Beispiel "Analysiere dieses Dokument" Template: "Analysiere {doc_type} mit Fokus auf {aspect}"

Wann MCP-Prompts verwenden?

Sinnvoll für:

  • Wiederkehrende Analyseaufgaben mit Variationen
  • Standardisierte Workflows (z.B. "Code Review", "Bug Report")
  • Vorlagen für verschiedene Dokumenttypen
  • Best-Practice-Patterns für bestimmte Domänen

Nicht sinnvoll für:

  • Einmalige, freie Konversationen
  • Dynamisch generierte Prompts
  • Einfache Tool-Aufrufe

Praxisbeispiel aus Notenverwaltung:

# MCP-Prompt (Template vom Server):
Prompt(
    name="course_analysis",
    description="Analysiert einen Kurs nach verschiedenen Kriterien",
    arguments=[
        {"name": "course_id", "description": "ID des Kurses", "required": True},
        {"name": "focus", "description": "Analysefokus", "required": False}
    ],
    template="""Analysiere den Kurs {course_id}.

Fokus: {focus}

Führe folgende Schritte aus:
1. Rufe Notendaten mit get_grades(course_id="{course_id}") ab
2. Berechne Statistiken (Durchschnitt, Median, Bestehensquote)
3. Identifiziere Ausreißer (sehr gute/schlechte Noten)
4. Erstelle Zusammenfassung mit Empfehlungen

Ausgabeformat: Strukturierter Report als Markdown."""
)

# Client fragt: "Analysiere Datenbanken"
# → MCP Host ruft Prompt ab und ersetzt Variablen:
#    course_id="datenbanken_ws2024", focus="Bestehensquote"
# → Sendet gefülltes Template an LLM
# → LLM folgt den Schritten im Template

Discovery und Nutzung:

# Discovery
prompts = await session.list_prompts()
# → [{"name": "course_analysis", "description": "...", "arguments": [...]}]

# Abrufen mit Argumenten
prompt = await session.get_prompt(
    name="course_analysis",
    arguments={
        "course_id": "datenbanken_ws2024",
        "focus": "Bestehensquote"
    }
)
# → Gibt gefülltes Template zurück

# An LLM senden
response = llm.chat(messages=[
    {"role": "system", "content": prompt.messages[0].content}
])

Workflow-Beispiel:

sequenceDiagram
    participant U as User
    participant C as Client
    participant S as Server
    participant L as LLM

    U->>C: "Analysiere Kurs Datenbanken"
    C->>S: prompts/get("course_analysis", {course_id: "datenbanken"})
    S-->>C: Template mit gefüllten Variablen
    C->>L: Template als System-Prompt senden
    Note over L: LLM folgt Schritten im Template
    L->>C: Tools aufrufen (get_grades, calculate_stats)
    C->>S: tools/call(...)
    S-->>C: Notendaten
    C->>L: Ergebnisse zurück an LLM
    L-->>C: Strukturierter Report
    C-->>U: Analyse-Ergebnis
Loading

Best Practices:

Gute MCP-Prompts:

  • Klare Schrittfolgen
  • Parametrisierbar (Variablen)
  • Domänen-spezifisch
  • Wiederverwendbar

Schlechte MCP-Prompts:

  • Zu allgemein ("Analysiere etwas")
  • Keine Variablen (nicht parametrisierbar)
  • Zu komplex (über 1000 Zeichen)
  • Einmalige Nutzung

Wann Prompts NICHT verwenden:

In vielen Fällen sind Tools direkter und besser:

# ❌ Kompliziert: Prompt + LLM + Tool
Prompt("analyze_course", template="...")
→ LLM interpretiertRuft Tools auf

# ✅ Einfacher: Direkt Tool mit klarem Zweck
Tool("analyze_course", inputSchema={...})
→ Direkte Ausführung

Lebenszyklus einer Verbindung

Dieser Ablauf fasst den MCP‑Verbindungslebenszyklus zusammen:

  • Handshake: initialize verhandelt Protokollversion und Fähigkeiten (capabilities), inkl. Identität (clientInfo, serverInfo).
  • Discovery: tools/list liefert verfügbare Funktionen und Metadaten für dynamische Tool‑Auswahl.
  • Execution: tools/call mit schema‑validierten arguments erzeugt strukturierte content‑Antworten.
  • Notifications: Server teilt Änderungen mit (z. B. notifications/tools/list_changed), Client aktualisiert per erneutem tools/list.
  • Termination: Sauberes Schließen verhindert offene Sessions und inkonsistente Zustände.
sequenceDiagram
    actor U as Nutzer/LLM-App
    participant C as MCP Client
    participant S as MCP Server

    U->>C: Verbinde zu Server
    Note over C,S: Handshake
    C->>S: initialize(protocolVersion, capabilities, clientInfo)
    S-->>C: initialize result(serverInfo, capabilities)
    C-->>S: notifications/initialized

    Note over C,S: Discovery
    C->>S: tools/list
    S-->>C: tools = [name, description, inputSchema]

    Note over C,S: Execution
    C->>S: tools/call(name, arguments)
    Note over S: Validierung gegen inputSchema
    S-->>C: content = [{type: "text", text: JSON}]

    Note over C,S: Notifications
    S-->>C: notifications/tools/list_changed
    C->>S: tools/list (Refresh)

    Note over C,S: Termination
    U->>C: Sitzung beenden
    C-->>S: Termination/Close Connection
Loading

Praxisbeispiele: Nutzerfragen mit und ohne MCP

  • Ohne MCP: Der Nutzer fragt direkt das LLM.

    • Frage: "Welche Farbe hat der Himmel?"
    • Verhalten: Das LLM beantwortet aus allgemeinem Weltwissen, kein Tool‑Aufruf nötig.
  • Mit MCP: Der Nutzer stellt eine universitätsspezifische Frage, die lokale Notendaten braucht.

    • Frage: "Welche Studierenden haben im Kurs Datenbanken eine 1.0 erreicht?"
    • Verhalten: Das LLM erkennt fehlendes Wissen und nutzt MCP‑Tools, um lokal Notendaten zu laden und zu analysieren.
sequenceDiagram
        actor U as Nutzer
        participant H as MCP Host (KI‑App)
        participant C as MCP Client
        participant S as MCP Server

        rect rgb(240,240,240)
        Note over U,H: Beispiel 1 – Ohne MCP
        U->>H: "Welche Farbe hat der Himmel?"
        H-->>U: "Blau" (direktes LLM‑Wissen)
        end

        rect rgb(230,245,255)
        U->>H: "Welche Studierenden haben Datenbanken mit 1.0 bestanden?"
        H->>C: Starte Client / Verbindung
        C->>S: initialize()
        S-->>C: capabilities

        H->>C: Discovery anstoßen
        C->>S: tools/list
        S-->>C: [list_courses, get_grades, get_student_transcript, calculate_gpa]
        C-->>H: Tools registrieren (Name, Beschreibung, Schema)

        H->>C: Tool‑Aufruf vorbereiten
        C->>S: tools/call("get_grades", {course_id: "datenbanken_ws2024"})
        Note over S: Noten aus PDF extrahieren
        S-->>C: {success: true, students: [{matrikel: "12345", name: "Max Mustermann", grade: 1.0}, …]}
        C-->>H: Ergebnis an Host/LLM weiterreichen

        H->>C: Folgeaktion (Filterung)
        Note over H: LLM filtert Studierende mit Note 1.0
        C-->>H: Kontext aktualisieren und Antwort formulieren
        H-->>U: "Folgende Studierende haben eine 1.0: Max Mustermann (12345)"
        end
Loading

Lessons Learned (aus Praxis)

  • Strukturierte Outputs: Immer valides JSON liefern; reine Textantworten erschweren Parsing. Best Practice: Output-Schema in Tool-Description dokumentieren (siehe get_grades in mcp_grades als Beispiel). JSON ermöglicht: Maschinenlesbarkeit, Typsicherheit, Erweiterbarkeit, automatische Validierung.
  • Klare inputSchema: Fehlende/optionale Felder sauber definieren, Defaults dokumentieren.
  • Tool-Discovery testen: list_tools muss konsistent sein, sonst scheitert die Orchestrierung.
  • Lokale Pfade: Absolute vs. relative Pfade konsistent halten; Zugriff auf vertrauliche Daten absichern.
  • LLM-Grenzen: Prompt-Länge begrenzen; bei Unsicherheit dynamisch MCP verwenden
  • Fehlerbehandlung: Eindeutige Fehlermeldungen und success: false mit Ursache liefern.
  • Trennung von Kurs vs. Code: Didaktik im Kurs, ausführbare Beispiele in examples/.

Teil 2: MCP-Anwendung entwickeln

Anthropic und die Community stellt eine Sammlung von MCP-Servern bereit, die als Referenzimplementierungen dienen:

Repository: github.com/modelcontextprotocol/servers

Wichtige Server:

  • filesystem: Sicherer Dateizugriff mit Whitelisting
  • github: GitHub API Integration (Repos, Issues, PRs)
  • gitlab: GitLab API Integration
  • google-drive: Google Drive Zugriff
  • slack: Slack-Integration (Nachrichten, Kanäle)
  • postgres: PostgreSQL Datenbank-Queries
  • sqlite: SQLite Datenbank-Zugriff
  • brave-search: Web-Suche via Brave API
  • fetch: HTTP-Requests (Web-Scraping, APIs)
  • puppeteer: Browser-Automation

Achtung: Für produktive Systeme bestehen, wie in guten Softwareprojekten üblich, Anforderungen an Sicherheit, Skalierbarkeit und Wartbarkeit. Passen Sie Ihre Server Implementierung entsprechend an.

Minimalbeispiel: Simple Calculator

Minimalbeispiel: Ein MCP-Server mit einem einfachen Tool add, das zwei Zahlen addiert. Ein Client ruft dieses Tool auf und zeigt das Ergebnis an.

Beispiel Claude Desktop

Leider nur unter Windows und MacOS verfügbar.

!?

Notenverwaltung MCP Server

Notenverwaltung: Ein MCP-Server mit Tools für Notenverwaltung (list_courses, get_grades, get_student_transcript, calculate_gpa). Die Tools extrahieren Daten aus lokalen PDF-Dateien und bieten strukturierten Zugriff auf Notendaten.