• v2.4.0 576df2cddd

    v2.4.0
    CI / verify (push) Successful in 52s
    Release / release (push) Successful in 37s
    Stable

    torben released this 2026-09-02 05:22:23 +00:00 | 98 commits to main since this release

    2.4.0 - 2026-09-02 - MCP-Leseserver: zweiter Konsument auf demselben Kern

    Author: Torben Nehmer

    Letzter Schritt der Sequenz aus #36, inhaltlich Issue #19. chemenu bekommt einen zweiten
    Konsumenten: search, types, describe_type, lint und status über MCP. Kein CLI mit
    angeschraubter Netzwerkschnittstelle — CLI und Server sind zwei Adapter auf dem Kern, den 2.3.0
    freigelegt hat.

    tools/chemenu/mcp/, im Repo statt als eigenes Artefakt. Der Golden-Test, der die
    Serverantworten gegen die --json-Formen der CLI hält, läuft nur mit beiden Seiten in einer
    Testsuite; getrennt würde aus einem Contract eine Versionsabsprache. Der Test ruft wikitool als
    Subprozess gegen denselben Baum auf, über CHEMENU_ROOT — womit er nebenbei die Root-Auflösung
    von außen mitprüft.

    Zwei Transports. stdio zum Entwickeln und Testen ohne Netz, streamable-http für die
    Auslieferung — der einzige, vor den sich die Authentifizierungs-Middleware überhaupt setzen kann,
    weil sie ein HTTP-Reverse-Proxy ist. sse ist über das SDK erreichbar und wird bewusst nicht
    angeboten: der abgelöste Remote-Transport, jetzt darauf zu bauen verschiebt den Wechsel nur.
    --host/--port gibt es, weil der Default auf Loopback bindet und ein Container hinter einem
    Proxy eine Adresse braucht, die der Proxy erreicht — eine Eigenschaft der Software, nicht einer
    Installation. Beide Transports sind gegen den echten Korpus gegengeprüft.

    Kein Schreibpfad, strukturell. Weder der Server noch chemenu.api importiert irgendetwas
    unter chemenu.commands, also existieren new, touch, xref, cite, publish, migrate
    und version bump in dieser Reichweite gar nicht, statt aus einer Liste gefiltert zu werden. Ein
    Test importiert das Servermodul in einem frischen Interpreter und sieht in sys.modules nach;
    ein zweiter ruft alle fünf Tools auf und vergleicht den Dateibaum, HEAD und
    git status --porcelain vorher/nachher.

    Jede Antwort trägt ihren Commit. commit und as_of in jedem Payload; null heißt, der
    bediente Baum hat uncommittete Änderungen und die Antwort entspricht keiner Revision. Der Stempel
    ist die Revision, aus der die Seiten tatsächlich gelesen wurden — zwischen Laden und Stempeln
    kann der Baum sich bewegen, deshalb reicht der Ladepfad seine Revision durch, statt noch einmal
    zu fragen. Das war beim ersten Durchlauf falsch: types/lint/status lasen die zuletzt
    gecachte Revision und stempelten null, obwohl der Baum sauber war.

    Telemetrie in den bedienten Baum wird beim Start verweigert, nicht stillschweigend
    umgeleitet. Tracing ist per Default an und schreibt nach reports/telemetry/ im Repo — genau das
    Verzeichnis, das der Sync per git reset --hard wegräumen darf. WIKI_TRACE=0 oder
    WIKI_TRACE_DIR außerhalb des Korpus. Heute schreibt auf diesem Pfad nichts (der Emitter hängt an
    cli.main() und den Gates), die Sperre ist gegen später.

    Fehler an der Protokollgrenze. Ein ChemenuError wird zum ToolError des SDK — eine
    absichtliche Ablehnung, deren Text den Aufrufer erreicht. Alles andere bleibt ein Absturz, dessen
    Text auf dem Server bleibt. Ein kaputtes Prädikat ist das Argument des Aufrufers, also muss die
    Zeile mitreisen, die sagt, was stattdessen zu schreiben ist.

    Bewusst nicht enthalten: Authentifizierung und Rate Limiting (Middleware vor dem Prozess),
    Deployment (private Infrastruktur), der Iteration Budget Gate — er begrenzt eine Agenten-Session
    und nicht einen Nutzer, weshalb Retrieval von ihm befreit ist; ihn hier als Rate Limiter zu
    benutzen würde ihn dazu verwässern.

    Die Abhängigkeit ist optional (tools/requirements-mcp.txt): eine Instanz, die nur die CLI
    benutzt, soll dafür nicht pydantic, starlette, uvicorn und cryptography installieren müssen. CI
    installiert sie, denn ein übersprungener Golden-Test ist genau der Weg, auf dem Server und CLI
    unbemerkt auseinanderlaufen.

    Betrieb und Sync-Mechanismus: instructions/mcp-read-server.md.
    Polling (git fetch && git reset --hard) statt Webhook — kein eingehender Endpunkt, keine
    Signaturprüfung. reset --hard ist dort tragend und keine Bequemlichkeit: ein abgedrifteter Baum
    antwortet zwar richtig, parst aber bei jeder Anfrage neu und stempelt jede Antwort mit null.

    Dateien: chemenu/mcp/ (neu: server.py, __main__.py), chemenu/api.py,
    tools/requirements-mcp.txt (neu), instructions/mcp-read-server.md (neu), tools/CONTRACT.md,
    tools/README.md, .gitea/workflows/ci.yml, tests/test_mcp_server.py (neu).

    Downloads