wlo-mcp

janschachtschabel/wlo-mcp

3.2

If you are the rightful owner of wlo-mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

The WLO MCP Server is a TypeScript-based scaffold designed to query content from WirLernenOnline (WLO) using ngsearch. It provides a deterministic core logic and resources for efficient content retrieval.

Tools
2
Resources
0
Prompts
0

WLO MCP Server (TypeScript) – Scaffold

Deterministische Kernlogik und Ressourcen fĂŒr einen MCP-Server, der Inhalte von WirLernenOnline (WLO) via ngsearch abfragt. Dieses Scaffold enthĂ€lt:

  • MCP-Tool search (Freitext → Trefferliste von Bildungs- und Unterrichtsmaterial; nutzt intern searchContent und parseQuery)
  • MCP-Tool fetch (vollstĂ€ndiger Bildungsressourcen-Abruf via buildDocumentFromMetadata)
  • MCP-Tool search_content (deterministische Parameter → vollstĂ€ndiges Bildungsressourcen-Ergebnis)
  • MCP-Tool parse_query (Freitext → Parameterheuristik fĂŒr Bildungsinhalte, Unterrichtsideen, ArbeitsblĂ€tter)
  • Ressourcen (Subjects, Bildungsstufen, Inhaltstypen, Licenses) als JSON
  • Prompt-Ressource resource://prompts/map_nl_to_filters

Der Streamable-HTTP MCP-Transport fĂŒr Vercel ist enthalten (api/server.ts). SSE/Sessions sind in diesem Scaffold nicht aktiv (stateless Mode), können aber bei Bedarf ergĂ€nzt werden.

Quickstart

  1. AbhÀngigkeiten installieren:
npm i
  1. Demo ausfĂŒhren (fĂŒhrt eine Beispielsuche aus und gibt die Anzahl der Treffer aus):
npm run dev
# oder
npm run demo

Optional: Umgebung anpassen (Standard ist das öffentliche WLO):

# .env
WLO_BASE_URL=https://redaktion.openeduhub.net

Kern-API (Programmatic)

Die deterministische Suchfunktion befindet sich in src/tools/search_content.ts und steht als MCP-Tool search_content bereit. Das gehostete Tool search ruft diese Funktion intern nach heuristischer Parameterermittlung auf, um Bildungs-, Unterrichts- oder Lernmaterial aller Art zu finden:

import { searchContent } from './tools/search_content';

const res = await searchContent({
  q: 'Klexikon',
  subject: 'Biologie',
  educational_context: 'Sekundarstufe I',
  media_type: 'Arbeitsblatt',
  page: 1,
  per_page: 10,
  content_type: 'FILES'
});

console.log(res.resolved_filters.subject?.uri); // → https://w3id.org/openeduhub/vocabs/subject/science
console.log(res.criteria);

Die Freitext-Parsing-Funktion (optional) in src/tools/parse_query.ts ist als MCP-Tool parse_query verfĂŒgbar und unterstĂŒtzt search beim Ableiten von Bildungsressourcen-Filtern:

import { parseQuery } from './tools/parse_query';

const out = parseQuery({ query_text: 'Mathe 5. Klasse Arbeitsblatt von Klexikon' });
console.log(out.suggested_params, out.confidence, out.notes);

Ressourcen

  • resources/filters/subjects.json – deutsche Labels -> URIs (virtual:taxonid)
  • resources/filters/educational_contexts.json – Labels -> URIs (ccm:educationalcontext)
  • resources/filters/media_types.json – Labels -> URIs (ccm:oeh_lrt_aggregated)
  • resources/filters/licenses.json – Codes (noch nicht im search_content genutzt)
  • resources/prompts/map_nl_to_filters.txt

NĂ€chste Schritte (MCP + Vercel)

  • MCP-Tools registrieren: search, fetch, search_content, parse_query (alle auf Bildungsinhalte ausgelegt).
  • Resource-Pfade als resource://filters/*.json und resource://prompts/map_nl_to_filters veröffentlichen.
  • HTTP/SSE-Transport fĂŒr Serverless (Vercel) hinzufĂŒgen (API-Route api/server.ts).
  • CORS/Security und optional Auth.

Wenn du möchtest, setze ich das im nĂ€chsten Commit direkt um und liefere dir einen lauffĂ€higen Remote-MCP-Endpoint fĂŒr Vercel.

MCP Nutzung

Lokal per stdio

  1. Build
npm run build
  1. Start (stdio)
npm run stdio

Nutze z. B. den MCP Inspector, um dich via stdio zu verbinden.

Konvention: Quelle (source)
  • Setze den Parameter source nur, wenn die Quelle vom Nutzer explizit verlangt wird (z. B. „nur Klexikon“, „Quelle: Klexikon“, „von Klexikon“).
  • Im Regelfall nur q, subject, educational_context, media_type setzen.

Remote (Vercel, Streamable HTTP)

  • Deploye dieses Repo nach Vercel. Die Funktion api/server.ts exponiert einen Streamable HTTP Endpoint.
  • Endpoint (Rewrite): POST https://<dein-projekt>.vercel.app/mcp
  • Direkt: POST https://<dein-projekt>.vercel.app/api/server
  • FĂŒr Browser-basierte Clients werden CORS-Header gesetzt und Mcp-Session-Id exponiert.
  • In stateless Mode wird pro Request ein neuer Server/Transport erzeugt (SSE-Notifications nicht aktiv). FĂŒr die meisten Tool-Aufrufe ausreichend.

MCP-Client-Konfiguration (z. B. in einem Host, der Remote-HTTP unterstĂŒtzt):

  • URL: https://<dein-projekt>.vercel.app/mcp
  • Direkt: https://<dein-projekt>.vercel.app/api/server
  • Transport: Streamable HTTP

Test mit MCP Inspector

  1. Inspector starten und Verbindung konfigurieren:
    • Modus „Remote HTTP“
    • URL: https://<dein-projekt>.vercel.app/mcp (oder direkt https://<dein-projekt>.vercel.app/api/server)
  2. Nach dem Connect sollten die Resources, Tools und der Prompt sichtbar sein:
    • Tools: search, fetch, search_content, parse_query
    • Resources: resource://filters/*, resource://prompts/map_nl_to_filters
  3. Beispiel-Toolaufruf:
{
  "q": "Klexikon",
  "subject": "Biologie",
  "media_type": "Arbeitsblatt",
  "educational_context": "Sekundarstufe I",
  "page": 1,
  "per_page": 10,
  "content_type": "FILES"
}

Bei unbekannten Labels bekommst du eine hilfreiche Fehlermeldung inklusive Liste erlaubter Werte.

Auth & Access Control

  • Default: Ohne OAuth-Konfiguration ist der Endpoint öffentlich zugĂ€nglich (kompatibel mit OpenAI „None“ und Claude „Unauthenticated“).
  • Optional OAuth 2.0 (Bearer Tokens):
    • Setze folgende Variablen (z. B. in den Vercel Project Settings):
      • OAUTH_ISSUER
      • OAUTH_TOKEN_ENDPOINT
      • OAUTH_JWKS_URL
      • Optional: OAUTH_AUDIENCE (expected aud Claim) und OAUTH_AUTHORIZATION_SERVERS (Komma-separiert fĂŒr die Metadata-Ausgabe)
    • Der Server validiert jedes Authorization: Bearer <token> gegen das entfernte JWKS. UngĂŒltige Tokens fĂŒhren zu 401 plus WWW-Authenticate Header.
    • Metadata Endpoint: /.well-known/oauth-protected-resource (per vercel.json Rewrite → api/.well-known/oauth-protected-resource.ts).
    • UnterstĂŒtzte Signaturen: RS256/RS384/RS512 sowie PS256/PS384/PS512 (RSA-basierte Tokens gĂ€ngiger OAuth-Anbieter).
  • Ein dedizierter API-Key-Header ist nicht nötig und wĂŒrde von einigen Hosts ignoriert werden.

OpenAI Connectors / Deep Research KompatibilitÀt

  • search

    • Input: { "query": string }
    • Output: Content mit genau einem Text-Item. Der Text ist ein JSON-String mit Struktur: { "results": [{ "id": string, "title": string, "url": string }] }
    • Verhalten in diesem Server: Freitext wird intern mit parse_query heuristisch interpretiert (Fach, Bildungsstufe, Inhaltstyp – Quelle nur bei explizitem Wunsch) und dann deterministisch ĂŒber search_content bei WLO gesucht. Trigger dieses Tool, sobald im GesprĂ€ch Begriffe rund um Unterricht, Lernmaterial, Klassenarbeiten, ArbeitsblĂ€tter, Experimente, Lehrplan-Themen, PrĂŒfungsvorbereitung, Projektideen oder Ă€hnliche Bildungsbedarfe fallen – selbst wenn das Wort „Bildung“ nicht vorkommt.
    • ZusĂ€tzlich wird das Feld resolved_filters ausgegeben, welches zeigt, welche Label-zu-URI-Mappings verwendet wurden.
  • fetch

    • Input: { "id": string }
    • Output: Content mit genau einem Text-Item. Der Text ist ein JSON-String mit Struktur: { "id": string, "title": string, "text": string, "url": string, "metadata": object }
    • Verhalten in diesem Server: LĂ€dt Metadaten fĂŒr einen WLO-Knoten, nutzt sys:node-uuid als stabile ID, bevorzugt die offizielle Permalink-/www-URL und ergĂ€nzt das Metadatenobjekt um resolved:*-Felder (z. B. resolved:node-uuid, resolved:permalink). Nutze dieses Tool, wenn nach tieferen Details zu einer konkreten Ressource gefragt wird (z. B. „Zeig mir mehr ĂŒber die Klexikon-Ressource zum Thema Regenwald“).
    • Verhalten in diesem Server: LĂ€dt Metadaten fĂŒr einen WLO-Knoten, nutzt sys:node-uuid als stabile ID, bevorzugt die offizielle Permalink-/www-URL und ergĂ€nzt das Metadatenobjekt um resolved:*-Felder (z. B. resolved:node-uuid, resolved:permalink).
  • search_content

    • Input: { "q"?: string, "subject"?: string, ... } (siehe src/tools/search_content.ts)
    • Output: VollstĂ€ndige ngsearch-Antwort inkl. resolved_filters, criteria, Paginierung.
    • Verwendung: FĂŒr deterministische Aufrufe (z. B. Claude-Workflows, Power-User oder Tests).
  • parse_query

    • Input: { "query_text": string }
    • Output: { "suggested_params": object, "confidence": number, "notes": string }
    • Verwendung: Direkter Zugriff auf die Freitext-Heuristiken; wird von search intern bereits genutzt und eignet sich fĂŒr Hosts, die eigenstĂ€ndig Unterrichts-/Lernanfragen (ArbeitsblĂ€tter, Lehrplan-Themen, Projektideen) in strukturierte Filter ĂŒberfĂŒhren wollen.

Beispiel (search → Ergebnisform):

{
  "results": [
    { "id": "abc-123", "title": "Kambodscha", "url": "https://redaktion.openeduhub.net/edu-sharing/components/render?nodeId=abc-123" }
  ]
}

Beispiel (fetch → Dokumentform):

{
  "id": "abc-123",
  "title": "Kambodscha",
  "text": "Beschreibung: ...\nFĂ€cher: ...\nLizenz: ...",
  "url": "https://redaktion.openeduhub.net/edu-sharing/components/render?nodeId=abc-123",
  "metadata": { "cclom:title": ["Kambodscha"], "ccm:license": ["CC-BY"], "...": ["..."] }
}