Skip to main content
Glama
benethos-hub

Unofficial Lexware Office MCP Server

by benethos-hub

Inoffizieller Lexware Office MCP Server

CI PyPI Python Coverage License

Haftungsausschluss

  • Dieses Projekt ist nicht mit Lexware oder Haufe-Lexware GmbH & Co. KG verbunden, wird von ihnen nicht unterstützt und nicht gesponsert. „Lexware“ und „Lexware Office“ sind Marken der jeweiligen Inhaber.

  • Es verwendet die dokumentierte öffentliche API mit einem API-Schlüssel, den Sie selbst erzeugen und widerrufen können. Die Nutzung dieser API unterliegt den eigenen Bedingungen von Lexware, die Sie unabhängig von diesem Projekt akzeptieren. Die API kann sich jederzeit ändern, und Anfragen können gedrosselt oder blockiert werden.

  • Es greift auf echte Buchhaltungsdaten zu. Schreibzugriff ist standardmäßig deaktiviert. Wenn Sie ihn aktivieren, ist alles, was über die API erstellt wird, ein echter und rechtlich relevanter Datensatz – ein finalisiertes Dokument kann über die API nicht zurückgezogen werden.

  • Daten können unvollständig oder veraltet sein. Nichts hier ist Steuer-, Buchhaltungs- oder Rechtsberatung. Verlassen Sie sich nicht darauf für Meldungen, Prüfungen oder Ihre Buchführungspflichten.

  • Bereitgestellt „wie besehen“, ohne Gewähr. Für den persönlichen und beruflichen Gebrauch auf eigenes Risiko. Siehe LICENSE.

  • Für die kommerzielle Nutzung prüfen Sie die API-Bedingungen von Lexware sowie Ihre eigenen Aufbewahrungs- und Dokumentationspflichten.

Ein MCP-Server, der einen MCP-Client wie Claude Desktop mit einem Lexware Office-Konto über die offizielle öffentliche REST-API verbindet. Stellen Sie Fragen zu Rechnungen, Kontakten, Artikeln und Belegen in natürlicher Sprache, und der Client holt sie für Sie.

Status: 0.2.2. Der Server verarbeitet Kontakte, Belege und Dokumente: finden, lesen, erstellen, ändern, sehen, was noch offen ist, PDF herunterladen und Beleg hochladen. get_profile beantwortet, welches Konto verbunden ist. Jedes Werkzeug in der folgenden Tabelle ist gebaut und wurde gegen ein Live-Konto getestet. Es spricht stdio mit einem Client, der es startet, und streamable HTTP hinter einem Bearer-Token, wenn etwas anderes es erreichen muss – als veröffentlichtes Container-Image, mit einer Compose-Datei für beide. Siehe SPECS.md für die vollständige technische Spezifikation und die Roadmap.

Warum es das gibt

Lexware Office hält die tägliche Buchhaltung eines kleinen Unternehmens. Die meisten Fragen dazu sind Lesefragen – was ist noch offen, was hat dieser Kunde bestellt, welcher Beleg gehört zu dieser Ausgabe – und genau solche Fragen beantwortet ein Assistent gut, sobald er die Daten sehen kann. Dieser Server macht das möglich, ohne etwas zu exportieren, mit einem API-Schlüssel, den der Kontoinhaber erzeugt und widerrufen kann.

Related MCP server: lexware-mcp-server

Sicherheit zuerst

Der Server zeigt auf ein echtes Buchhaltungssystem, daher sind die Standardwerte vorsichtig.

Führen Sie ihn schreibgeschützt aus, wenn Sie keinen Grund dagegen haben. Dieser Server kann echte Buchhaltungsdaten ändern – einen Kontakt anlegen, einen Beleg erfassen, eine Rechnung ausstellen, einen Beleg anhängen – und es ist der Assistent, der entscheidet, wann er ein solches Werkzeug aufruft, nicht Sie. --tools read-only gibt ihm alles, was er braucht, um Fragen zu den Büchern zu beantworten, was die meisten wollen: suchen, lesen und herunterladen. Nichts in dieser Menge schreibt.

Aktivieren Sie ein Schreibwerkzeug, wenn Sie eine Aufgabe dafür haben, und wissen Sie, was es hinterlässt. Diese API kann einen Buchungsbeleg überhaupt nicht löschen, daher wird ein falscher in der Web-App korrigiert und nicht hier zurückgezogen, und eine finalisierte Rechnung ist ein echtes Dokument mit einer Nummer, die verwendet wurde. Wenn Sie nicht sicher sind, welche Werkzeuge Sie brauchen, ist schreibgeschützt der ehrliche Ausgangspunkt – die Berechtigungsseite fügt später mit einem Klick eines hinzu, und ein Client, der notifications/tools/list_changed beachtet, wie Claude Desktop es tut, übernimmt es ohne Neustart.

  • Nichts ist aktiviert, bis Sie es sagen. Eine frische Installation hat keine Policy-Datei, und ein Server ohne eine bietet überhaupt keine Werkzeuge an. Was dieser Server tun darf, ist eine Entscheidung, die jemand getroffen hat, nie ein Standard, der passiert ist.

  • Ein Flag pro Werkzeug, in einer JSON-Datei, die Sie mit --tools schreiben, durch setup klicken oder von Hand bearbeiten. Keine Stufe, keine Gruppe: create_contact an und upload_file aus ist ein normaler Wunsch, und es gibt keine Kombination, die die Datei nicht ausdrücken kann.

  • Was ein Werkzeug Sie kostet, ist sichtbar, während Sie entscheiden. Jedes aktivierte Werkzeug wird bei jeder Anfrage an den Assistenten gesendet, und die Berechtigungsseite setzt diese Zahl in jede Zeile.

  • Die Datei wird zweimal geprüft, einmal beim Erstellen der Werkzeugliste und noch einmal, wenn ein Aufruf eintrifft, sodass eine veraltete Werkzeugliste auf dem Client nicht durchrutschen kann.

  • Der API-Schlüssel wird nie protokolliert, nie in einem Werkzeugergebnis zurückgegeben und in Fehlermeldungen geschwärzt. Er gehört in die .env und sonst nirgendwo hin – nicht in die Konfigurationsdatei Ihres Clients, die ein anderes Programm besitzt und neu schreibt, und die die Leute screenshotten, wenn sie um Hilfe bitten. Auch kein Pfad von Ihrem Rechner erreicht den Assistenten.

Werkzeuge

Jedes Werkzeug unten ist gebaut und wurde gegen ein Live-Konto getestet. Keines ist aktiviert, bis die Policy-Datei es nennt.

Lesewerkzeuge:

Werkzeug

Was es tut

get_profile

Firmenprofil und Verbindungsprüfung

search_contacts

Kunden und Lieferanten nach Name, E-Mail, Nummer oder Rolle finden

get_contact

Ein Kontakt mit Adressen, Rollen und Version

search_articles

Artikel auflisten, gefiltert nach Nummer, Barcode oder Art. Die API bietet keine Suche nach Titel

get_article

Ein Artikel mit seinem Preisblock und Version

search_vouchers

Die zentrale Abfrage – Belegliste filtern nach Typ, Status, Kontakt, Datumsbereich und was noch offen ist

get_sales_document

Eine Rechnung, ein Angebot, eine Gutschrift, eine Auftragsbestätigung, ein Lieferschein, eine Mahnung oder eine Anzahlungsrechnung vollständig lesen

get_voucher

Einen Buchungsbeleg lesen, per ID oder per Belegnummer

get_payments

Zahlungsstatus und offener Betrag eines Belegs

get_recurring_templates

Vorlagen, die Rechnungen nach Zeitplan ausstellen, eine oder eine Seite davon

get_master_data

Länder, Zahlungsbedingungen, Buchungskategorien und Drucklayouts, mit einer Suche zum Eingrenzen

download_document

Das gerenderte PDF oder XML eines Verkaufsdokuments speichern

download_file

Eine gespeicherte Datei speichern, z. B. einen hochgeladenen Beleg

read_download

Eine heruntergeladene Datei in die Antwort einfügen, für Clients, die einem Ressourcenlink nicht folgen können

get_deeplink

Einen Permalink zu einem Verkaufsdokument, Kontakt oder Beleg in der Web-App erstellen, ohne API-Aufruf

Schreibwerkzeuge. Diese ändern echte Buchhaltungsdaten, also aktivieren Sie sie einzeln und gegen ein Konto, das Sie bereit sind, ändern zu lassen:

Werkzeug

Was es tut

create_contact

Einen Kunden oder Lieferanten anlegen

update_contact

Einen ändern, ohne das anzufassen, was Sie nicht genannt haben

create_article

Einen Artikel zum Katalog hinzufügen

update_article

Einen ändern, ohne das anzufassen, was Sie nicht genannt haben

create_voucher

Einen Buchungsbeleg erfassen

update_voucher

Einen bereits erfassten ändern

create_sales_document

Eine Rechnung, ein Angebot, eine Gutschrift, eine Auftragsbestätigung, ein Lieferschein oder eine Mahnung erstellen – ein Entwurf, es sei denn, Sie bitten um Ausstellung, was der Assistent nur auf Ihre ausdrückliche Anweisung tun darf

upload_file

Einen Beleg hochladen, der auch seinen Beleg erstellt

attach_file_to_voucher

Eine Datei an einen bereits vorhandenen Beleg hängen

update_contact und update_voucher kosten zwei API-Aufrufe statt einem. Die API ersetzt einen Datensatz, statt ihn zu patchen, daher wird der aktuelle zuerst gelesen und die Änderung daraufgelegt. Ohne das würde das Ändern nur einer E-Mail-Adresse die Adressen, die Notiz und alles andere leeren. Beide benötigen auch die version, die Sie zuletzt gelesen haben: Wenn sich der Datensatz dazwischen geändert hat, wird die Aktualisierung verweigert und nichts geschrieben.

Ein Werkzeug löscht, und es ist das einzige:

Werkzeug

Was es tut

delete_article

Einen Artikel entfernen. Die API kann ihn nicht zurückbringen. Erfordert confirm: true und sendet nichts ohne es

Es ist bisher das einzige Mitglied des Schritts --tools irreversible, daher ist dieser Schritt der einzige Weg, es zu aktivieren. Ein Artikel ist auch das einzige, was diese API löschen lässt, was die andere Hälfte des Punktes ist:

--tools write ist nicht dasselbe wie rückgängig machbar. Nichts, was diese Voreinstellung aktiviert, löscht einen Datensatz, aber zwei ihrer Tools erzeugen einen, der danach nicht mehr entfernt werden kann.

Ein Buchungsbeleg kann nicht über die API gelöscht werden. Es gibt keinen Endpunkt dafür, daher muss ein falsches create_voucher in der Lexware-Office-Web-App korrigiert werden, und er wird in dem Moment gebucht, in dem er erstellt wird – die API akzeptiert keinen Status auf dem Weg hinein. Dasselbe gilt für upload_file: Das Hochladen eines Belegs erstellt auch den dazugehörigen Beleg, sodass es einen Datensatz hinterlässt, obwohl sein Name nur die Datei erwähnt.

Downloads werden in das Download-Verzeichnis auf dem Rechner geschrieben, auf dem der Server läuft, und auf zwei Arten gemeldet: ein Pfad, der das ist, was man möchte, wenn Client und Server denselben Rechner nutzen, und eine Ressourcen-URI, die der Client lesen kann, um die Bytes zu erhalten, egal wo der Server ist. Die Datei selbst reist nie im Tool-Ergebnis mit, weil base64 etwa das 1,37-fache der Dateigröße an Kontext kostet und kein Modell ein PDF ohnehin lesen kann. Eine vorhandene Datei wird nie ersetzt: Ein zweiter Download wird neben dem ersten mit einem Zähler im Namen gespeichert.

Die Ressourcenliste wird beim Start des Servers aus dem Download-Verzeichnis gefüllt, sodass eine URI nach einem Neustart lesbar bleibt. Was der Server nicht kann, ist einen neuen Download anzukündigen: Das MCP-SDK gibt ihm keine Möglichkeit, eine Listenänderungs-Benachrichtigung zu senden, sodass ein Client, der beim Start einmal auflistet, nichts sieht, was später in der Sitzung abgerufen wird.

Zwischen dem und der Tatsache, dass Claude Desktop Ressourcenlinks überhaupt nicht verfolgt, ist read_download der Weg, der immer funktioniert. Es nimmt dieselbe URI und legt den Inhalt in die Antwort. Was ankommt, hängt von der Datei ab:

Datei

Kommt an als

XML

Text, sodass eine XRechnung tatsächlich gelesen werden kann

PDF

Bilder seiner Seiten, standardmäßig die ersten 10

Bild

das Bild

Alles andere

ein eingebettetes Binärformat, das der Client verarbeiten soll

Ein PDF wird gerendert und nicht durchgereicht, weil Claude Desktop ein eingebettetes Binärformat in einen Bildblock verwandelt, wenn es die API aufruft, und application/pdf dort kein zulässiger Bildtyp ist, sodass die gesamte Anfrage abgelehnt wird. Das Rendern kostet auch keinen API-Aufruf, da die Datei bereits auf dem Server liegt.

Ein Link in die Web-App ist ein separates Tool. get_deeplink verwandelt eine ID in eine URL für einen Browser, kostet keinen API-Aufruf und ist der Weg, der immer noch funktioniert, wenn der Client weder die Datei noch einen Ressourcenlink anzeigen kann: Jemand öffnet sie selbst. Ein Download trägt keinen – er beantwortet, wo die Bytes sind, was eine andere Frage ist, und die beiden wurden einmal lange genug zusammengeführt, sodass ein defekter Link mit einem funktionierenden Download mitreiste.

upload_file akzeptiert PDF, JPEG, PNG und XML, höchstens 5 MiB pro Datei, was die API akzeptiert. Eine XML-Datei wird als XRechnung behandelt und abgelehnt, wenn sie keine ist.

Anforderungen

  • uv, das sein eigenes Python und den uvx-Befehl mitbringt, den jedes folgende Beispiel verwendet

  • Python 3.11 oder neuer, falls man lieber sein eigenes mitbringt. Die Installation zieht das MCP-SDK, httpx, platformdirs und pypdfium2 nach sich, letzteres zum Rendern von PDF-Seiten

  • Ein Lexware-Office-Konto mit aktiviertem Public-API-Add-on

  • Ein API-Schlüssel von https://app.lexware.de/addons/public-api

Einen API-Schlüssel erhalten

  1. Melden Sie sich als Kontoinhaber bei Lexware Office an.

  2. Öffnen Sie das Public-API-Add-on unter https://app.lexware.de/addons/public-api.

  3. Erstellen Sie einen Schlüssel und kopieren Sie ihn einmal – er wird nur ein einziges Mal angezeigt.

  4. Halten Sie ihn aus jeder Datei heraus, die in die Versionskontrolle geht. Legen Sie ihn in config/.env ab, das gitignored ist, oder übergeben Sie ihn als Umgebungsvariable. Ein Schlüssel in config/.env wird gefunden, egal aus welchem Verzeichnis der Server gestartet wird, sodass ein Client wie Claude Desktop keinen eigenen Schlüssel in seiner Konfigurationsdatei benötigt.

Ein Schlüssel kann jederzeit auf derselben Seite widerrufen werden, was der schnellste Weg ist, den Zugriff zu unterbrechen, wenn etwas verdächtig aussieht.

Installation

Der einfachste Weg, den Server auszuführen – kein Klon, keine manuelle virtuelle Umgebung, kein git. uvx holt und führt ihn bei Bedarf von PyPI aus (veröffentlicht als benethos-lexware-office-mcp). Um ihn stattdessen in einem Container auszuführen, siehe In einem Container.

1. Installieren Sie uv, falls Sie es noch nicht haben – die uv-Installationsseite deckt jede Plattform ab. Es bringt uvx mit, und das ist das Einzige, was hier benötigt wird.

2. Konfigurieren Sie den Server. Dafür muss nichts installiert werden: uvx holt das Paket und führt es aus.

uvx benethos-lexware-office-mcp setup

Das öffnet die unter Konfiguration im Browser beschriebene Oberfläche: Schlüssel, Einstellungen und ein Kontrollkästchen pro Tool. Alles, was sie tut, kann auch von Hand erledigt werden – starten Sie eine Einstellungsdatei mit uvx benethos-lexware-office-mcp --settings-sample > config/.env, setzen Sie den Schlüssel hinein und verwenden Sie --tools wie unten beschrieben.

Überprüfen Sie, dass es funktioniert:

uvx benethos-lexware-office-mcp --help

3. Weisen Sie Claude Desktop darauf hin in claude_desktop_config.json:

{
  "mcpServers": {
    "benethos-lexware-office-mcp": {
      "command": "uvx",
      "args": ["benethos-lexware-office-mcp"]
    }
  }
}

Dort erscheint kein Pfad von Ihrem Rechner, und das ist der Punkt: uvx sucht das Paket nach Namen. Zwei Dinge, die über diesen Eintrag wissenswert sind:

  • Pinnen Sie eine Version für Stabilität: "args": ["benethos-lexware-office-mcp==0.2.2"]. Ohne Pin nimmt uvx die neueste Version, die es auflösen kann, und ein Neustart des Clients reicht aus, um zu ändern, was es ausführt.

  • uvx muss auf dem PATH liegen, den der Client verwendet, was nicht immer der ist, den Ihr Terminal hat – einige GUI-Clients übergeben eine reduzierte Umgebung. Wenn der Server nicht startet, setzen Sie den absoluten Pfad zu uvx in command und starten Sie den Client vollständig neu, anstatt ihn neu zu laden.

Hätten Sie lieber einen eigenen Befehl? uv tool install benethos-lexware-office-mcp gibt Ihnen benethos-lexware-office-mcp ohne das uvx davor, was sich lohnt, wenn Sie häufig Berechtigungen über die Befehlszeile ändern. Es bringt sonst nichts: Die gleiche Version kann auf beide Arten gepinnt werden, und ein Warmstart unterscheidet sich um zig Millisekunden. Ein Hinweis – uv installiert es in sein eigenes Tool-Verzeichnis, das bei einer frischen Installation nicht auf dem PATH liegt. Das sagt es, wenn es fertig ist. Führen Sie uv tool update-shell aus und öffnen Sie ein neues Terminal.

Stattdessen aus den Quellen, um zu entwickeln oder etwas Unveröffentlichtes auszuführen:

git clone https://github.com/benethos-hub/lexware-office-mcp
cd lexware-office-mcp
uv sync
uv run benethos-lexware-office-mcp setup

Ein Client benötigt dann den Interpreter der virtuellen Umgebung dieses Checkouts, command zeigt auf .venv/Scripts/python.exe unter Windows oder .venv/bin/python anderswo, mit args von ["-m", "benethos_lexware_office_mcp"].

Kein Schlüssel dort, absichtlich. Der Server findet ihn in der .env. Eine Konfigurationsdatei eines Clients ist der falsche Ort für eine Anmeldedaten: Sie gehört nicht Ihnen – ein anderes Programm besitzt sie, entscheidet, wo sie lebt und wann es sie neu schreibt. Es ist die Datei, die Leute screenshotten, wenn sie Hilfe bei einem MCP-Setup suchen, sie ist in der eigenen Einstellungsansicht des Clients lesbar und reist mit dem Rest der Client-Konfiguration auf den nächsten Rechner. Die .env ist zumindest eine Datei, die dieses Projekt dokumentiert, die nichts in Ihrem Namen synchronisiert und die die Konfigurationsoberfläche schreibt, ohne Ihnen den Schlüssel jemals zurückzuzeigen.

Diese .env ist bereits der Teil, mit dem man vorsichtig sein sollte. Sie enthält eine Anmeldedaten für ein echtes Buchhaltungssystem, also halten Sie sie aus der Versionskontrolle, aus freigegebenen Ordnern und aus Backups heraus, die andere lesen können. Wenn Sie den Server nicht mehr verwenden, löschen Sie sie und widerrufen Sie den Schlüssel unter Erweiterungen, Public API – das Widerrufen ist der einzige Schritt, der den Zugriff tatsächlich beendet.

4. Starten Sie Claude Desktop vollständig neu – beenden Sie es über das Tray, anstatt das Fenster zu schließen. Das gilt für die Konfigurationsdatei, die Sie gerade bearbeitet haben, die ein Client beim Start einmal liest, und es ist auch das, was eine geänderte Einstellung in der .env benötigt – der Server liest diese ebenfalls beim Start. Es ist nicht für Berechtigungen nötig: Ändern Sie diese später, und der laufende Client wird informiert, siehe Einzelne Tools deaktivieren.

Konfiguration im Browser

uvx benethos-lexware-office-mcp setup

Drei Seiten auf 127.0.0.1, geschlossen mit Strg+C. Sie schreiben dieselben Dateien wie die Befehlszeile, sodass Sie entweder oder beide verwenden können. Die Bildschirme sind auf Deutsch, weil Lexware Office nur für deutsche Unternehmen verkauft wird, und jede ist unten nach dem benannt, was sie mit ihrem Label in Klammern tut.

Übersicht (Übersicht) – welche .env und welche tools.json tatsächlich gelten, worauf sich jede Einstellung auflöst und woher dieser Wert stammt, ob jede Datei bereits existiert, wie viele Tools aktiv sind und was sie kosten. Ein Verbindungstest über den Button, niemals beim Laden der Seite.

Zugangsdaten (Zugangsdaten) – der API-Schlüssel, der vor dem Speichern gegen die API geprüft wird, sofern Sie nichts anderes angeben, und die Einstellungen, die nicht geheim sind. Der Schlüssel wird Ihnen nie zurückgezeigt, nie protokolliert und nie exportiert. Wenn eine Umgebungsvariable ihn setzt, sagt die Seite das, weil das überschreiben würde, was Sie speichern.

Rechte (Rechte) – ein Kontrollkästchen pro Tool, gruppiert, mit den Voreinstellungen als Schaltflächen. Bei einer frischen Installation ohne Richtliniendatei sind die Lesetools als Ausgangspunkt vorab angekreuzt – ein Vorschlag in einem Formular, keine Berechtigung: Es gibt noch keine Datei und daher noch kein Tool, bis Sie Speichern drücken, und die Seite sagt das. Jede Zeile trägt, was dieses Tool den Assistenten an Kontext kostet, und die Summe folgt Ihren Häkchen: Jedes aktivierte Tool wird bei jeder Anfrage an das Modell gesendet, sodass das Einschalten eines eine Budgetentscheidung und eine Berechtigungsentscheidung ist. Schreibende Tools sind markiert, und die, deren Ergebnis die API nicht zurücknehmen kann, sind separat markiert: nur App für einen Kontakt, den Lexware Office ohne Aufhebens löscht, und nur App · Buchhaltung für einen Datensatz, der in die Bücher eingeht. Keines bedeutet, dass es feststeckt – nichts ist festgeschrieben, wenn es erstellt wird, und eine Legende auf der Seite nennt die vier Dinge, die einen Datensatz später binden.

Profile leben auch hier. Speichern Sie die aktuelle Auswahl unter einem Namen, laden Sie sie später. Laden füllt nur die Felder: Nichts erreicht tools.json, bis Sie Speichern drücken. Ein Name, der bereits vergeben ist, wird abgelehnt, anstatt stillschweigend zu ersetzen, was da ist – Groß-/Kleinschreibung und Leerzeichen ergeben kein zweites Profil – und das Ersetzen ist eine eigene Schaltfläche neben der Liste. Sie werden in tool_profiles.json neben der Richtliniendatei gespeichert.

Die Richtliniendatei selbst kann von derselben Seite heruntergeladen und wieder eingelesen werden – die Datei wie sie ist, sodass sie auf einer anderen Installation mit oder ohne diese Oberfläche funktioniert, und eine tools.json, die von --tools geschrieben wurde, liest hier. Das Einlesen kreuzt nur die Felder an, und das Speichern ist weiterhin ein separater Druck. Ein Tool, das die Datei nicht erwähnt, bleibt aus, und die Seite sagt, wie viele das sind, was --tools sync in der Befehlszeile tut.

Zwei Dinge sind wissenswert. Es bindet 127.0.0.1 und nichts anderes – die Seiten haben kein Passwort, was nur vertretbar ist, solange sie von einem anderen Rechner aus nicht erreichbar sind, daher gibt es keine Option, das zu ändern. Und es ist ein separater Befehl: Der MCP-Server bedient nie HTTP, und ein Client wie Claude Desktop startet diesen, nicht diesen.

--port N verschiebt es, --no-browser druckt nur die Adresse, und --env-file und --tools-file sagen, welche Dateien es bearbeitet. Anders als überall sonst müssen diese Dateien noch nicht existieren.

Wenn Ihr Client den Server mit --tools-file startet, geben Sie setup dasselbe Argument – sonst bearbeitet es eine andere Datei und meldet Erfolg. Beide Prozesse fixieren ihre Dateien beim Start und ändern sie danach nie, und keiner kann sehen, wie der andere gestartet wurde. Die Übersicht druckt die "args"-Zeile, die Ihren Client mit den Dateien abgleicht, die die Oberfläche hält, was die einfachere Richtung ist.

Einzelne Tools deaktivieren

Eine JSON-Datei entscheidet, was dieser Server anbietet, und nichts anderes. Entweder kreuzen Sie die Felder unter setup oben an oder starten Sie die Datei mit

uvx benethos-lexware-office-mcp --tools read-only

das jedes Tool in tools.json schreibt, die einen auf „an“ und den Rest auf „aus“ setzt, und ausgibt, was es getan hat. Drei Voreinstellungen, die jeweils die letzte enthalten:

aktiviert

--tools read-only

nur Abfragen

--tools write

und Erstellen und Aktualisieren

--tools irreversible

und Löschen eines Artikels

--tools sync

ändert kein Flag, fügt nur die Tools hinzu, von denen die Datei noch nichts gehört hat

--tools show berichtet nur. --tools-file PATH gibt an, wohin geschrieben wird, und funktioniert mit allen — --tools write --tools-file ./tools.json erstellt die Datei dort.

Eine Voreinstellung überschreibt die gesamte Datei, daher gehen manuelle Änderungen verloren. Verwenden Sie eine, um eine Datei zu starten, nicht um eine zu aktualisieren. Wenn ein Upgrade neue Tools bringt, führen Sie --tools sync aus: Es schreibt sie als „aus“ ein, lässt jedes von Ihnen gesetzte Flag unangetastet und schaltet nie etwas ein. Genau das ist der Grund, warum es das einzige dieser Tools ist, das sicher aus einem Skript ausgeführt werden kann.

Der dritte Schritt ist ein eigener, weil es eine eigene Entscheidung ist: Was gelöscht wird, ist weg, daher sollte es durch Benennung gewählt werden, nicht durch Auswahl der größten Option. Genau ein Tool hat eine solche Wirkung, delete_article, und das ist kein vorübergehender Zustand — ein Artikel ist das Einzige, was diese API löschen kann, und es gibt auch keine Möglichkeit, danach etwas zu buchen, abzuschließen oder zu stornieren.

Ohne --tools-file wird die Datei genau wie die .env gesucht, zuerst mit niedrigster Priorität:

  1. das Konfigurationsverzeichnis pro Benutzer

  2. config/ eines Checkouts, wenn Sie aus den Quellen laufen

  3. config/ und dann das Wurzelverzeichnis des Arbeitsverzeichnisses

Die zuletzt gefundene gewinnt, und eine Datei, die noch niemand erstellt hat, löst zur ersten auf. Danach bearbeiten Sie sie:

{
 "create_contact": false,
 "search_contacts": true,
 "upload_file": false
}

Ein Tool, das auf false gesetzt ist, wird nicht aufgelistet und kann nicht aufgerufen werden. Ein Tool, das die Datei nicht erwähnt, ist ebenfalls aus — Schweigen ist eine Ablehnung, also wartet ein Tool, das mit einem Upgrade kommt, auf Sie, anstatt von selbst zu erscheinen. Keine Datei bedeutet überhaupt keine Tools, weshalb --tools Teil der Einrichtung des Servers ist.

Die Datei wird beim Aufbau der Tool-Liste und bei jedem Aufruf erneut gelesen, sodass eine Änderung sofort in beide Richtungen wirkt — kein Neustart. Der Server teilt dem Client auch mit, wenn sich die Menge der aktivierten Tools ändert, sodass dieser die Liste selbst erneut abruft: Claude Desktop nimmt eine Änderung während des Betriebs auf. Nichts hängt davon ab, da ein Tool, das ausgeschaltet wurde, nicht aufgerufen werden kann, egal welche Liste der Client noch anzeigt. Wenn Ihres es nicht bemerkt, starten Sie es neu — Claude Desktop, indem Sie es aus dem Tray beenden.

Jedes Tool deklariert auch, was es ist — lesend oder schreibend, zu welcher Gruppe es gehört und ob das, was es schreibt, wieder entfernt werden kann. Diese Klassifizierung ist es, die --tools read-only auswählt und nach der die Browser-Oberfläche gruppiert und markiert. Sie entscheidet nie über einen Aufruf: nur die Datei.

Konfiguration

Woher ein Wert kommt und welcher gewinnt

Es gilt eine .env, nie mehrere. Dies sind die Orte, an denen sie gesucht wird, zuerst die niedrigste, und die höchste, die existiert, ist die Datei — die anderen werden nicht gelesen:

  1. .env im Konfigurationsverzeichnis pro Benutzer

  2. config/.env des Checkouts, aus dem der Server läuft, falls er aus einem läuft

  3. config/.env und dann .env im Arbeitsverzeichnis

--env-file benennt sie stattdessen, und dann findet überhaupt keine Suche statt. Das ist dieselbe Regel, die --tools-file für die Richtliniendatei befolgt, also bedeuten beide Flags dasselbe: diese Datei und sonst nichts.

Zwei Dinge liegen außerhalb dieser Datei, eines darunter und eines darüber:

  • die eingebaute Standardeinstellung für eine Einstellung, die keine Datei erwähnt

  • eine echte Umgebungsvariable, die schlägt, was auch immer die Datei sagt

Die letzte ist die, die Menschen überrascht. Eine Einstellung, die in Ihrer Shell exportiert, in einen env-Block eines Clients gesetzt oder in einer Compose-Datei festgelegt wurde, kann nicht durch Bearbeiten einer .env geändert werden — weder von Hand noch über setup. Der Wert wird geschrieben, die Datei ist korrekt, und nichts passiert.

Die Konfigurationsoberfläche sagt das, anstatt Sie es herausfinden zu lassen: Jede Einstellung trägt ein Abzeichen, das ihre Quelle benennt, und eine, die eine Umgebungsvariable hält, ist als solche markiert. Wenn etwas, das Sie gespeichert haben, ignoriert zu werden scheint, ist dieses Abzeichen die Antwort.

In einem Container ist das kein Randfall. compose.yaml legt den Transport, die Bind-Adresse, den Port und die erlaubten Hosts als echte Umgebungsvariablen fest, weil diese zum Container gehören und nicht zur Installation darin. Alles andere — der API-Schlüssel, das HTTP-Token, die Limits — bleibt dem Konfigurationsvolumen überlassen, was die Konfigurationsoberfläche in die Lage versetzt, es zu ändern.

Die gleiche Reihenfolge gilt für die Richtliniendatei, und LXO_MCP_TOOL_POLICY und --tools-file benennen eine direkt. Die Oberfläche fixiert die Datei, die sie beim Start gefunden hat, sodass die Seite ihr eigenes Subjekt nicht unter Ihnen austauschen kann.

Benennen der Dateien

--env-file PATH benennt eine Einstellungsdatei anstelle der Suche und paart sich mit --tools-file, sodass ein Eintrag in der Konfiguration eines Clients sein eigenes Konto und seine eigenen Berechtigungen trägt:

"args": ["--env-file", "/path/to/test.env",
         "--tools-file", "/path/to/test-tools.json"]

Ein Pfad, der nicht existiert, wird abgelehnt, anstatt stillschweigend auf die Suche zurückzufallen — außer unter setup, das teilweise existiert, um einen zu erstellen.

setup schreibt diese Datei für Sie.

Die Einstellungen

Variable

Bedeutung

Standard

LXO_MCP_API_KEY

Ihr Lexware-Office-API-Schlüssel. Erforderlich.

—

LXO_MCP_TOOL_POLICY

Pro-Tool-An/Aus-Datei, siehe unten

tools.json im Konfigurationsverzeichnis

LXO_MCP_BASE_URL

API-Basis-URL

https://api.lexware.io

LXO_MCP_APP_BASE_URL

Web-App-Basis für Deeplinks

https://app.lexware.de

LXO_MCP_DOWNLOAD_DIR

Wo heruntergeladene Dokumente landen

Benutzer-Cache-Verzeichnis

LXO_MCP_TIMEOUT

HTTP-Timeout in Sekunden

30

LXO_MCP_RATE

Anfragen pro Sekunde, global über alle Endpunkte

1.5

LXO_MCP_BURST

Token-Bucket-Kapazität. Der eigene Bucket des Kontos fasst 4

2

LXO_MCP_PAGE_SIZE

Zeilen pro Seite, die eine Suche anfordert und zurückgibt

25

LXO_MCP_PDF_PAGES

Seiten eines PDFs, die read_download standardmäßig rendert

10

LXO_MCP_LOG_LEVEL

Protokollstufe auf stderr

INFO

LXO_MCP_TRANSPORT

stdio, streamable-http oder sse

stdio

LXO_MCP_BEARER_TOKEN

Gemeinsames Geheimnis, das jede HTTP-Anfrage tragen muss. Erforderlich für einen HTTP-Transport

—

LXO_MCP_HTTP_HOST

Adresse, an die für einen HTTP-Transport gebunden wird

127.0.0.1

LXO_MCP_HTTP_PORT

Zu bindender Port

8770

LXO_MCP_HTTP_PATH

URL-Pfad, auf dem der Transport bedient

/mcp

LXO_MCP_ALLOWED_HOSTS

Host-Werte, die außer Loopback akzeptiert werden, durch Komma getrennt

—

LXO_MCP_GENERATE_BEARER_TOKEN

Erstellt beim Start ein Token, wenn keines gesetzt ist, und schreibt es in die Einstellungsdatei

aus

LXO_MCP_EXIT_ON_CONFIG_CHANGE

Beendet den Prozess, wenn sich die Einstellungsdatei ändert, für etwas, das ihn neu startet

aus

Jede obige Einstellung ist in Gebrauch. LXO_MCP_PAGE_SIZE ist auf 250 begrenzt, was die niedrigste Seitengröße ist, die ein Endpunkt akzeptiert, und ein größerer Wert wird beim Start abgelehnt, anstatt später in einen API-Fehler zu münden.

Transport

stdio ist die Standardeinstellung und das, was Claude Desktop und vergleichbare lokale Clients verwenden: Der Client startet den Server als eigenen Kindprozess, und nichts anderes kann mit ihm sprechen.

streamable-HTTP und SSE bedienen dieselben Tools auf einem Port, für einen Container oder eine eigene Maschine:

uvx benethos-lexware-office-mcp --transport streamable-http --port 8770

Zwei Dinge stehen vor diesem Port, und keines ist optional. Ein Bearer-Token, das jede Anfrage als Authorization: Bearer <token> tragen muss — ohne LXO_MCP_BEARER_TOKEN weigert sich der Server, überhaupt einen HTTP-Transport zu starten, weil sonst jeder, der den Port erreichen kann, Ihre Lexware-Anmeldedaten ausgeben könnte. Und der DNS-Rebinding-Schutz des SDK, der Host und Origin gegen eine Zulassungsliste der Loopback-Namen prüft, erweitert durch --allowed-hosts, wo ein Container oder ein Proxy einen anderen Namen davor setzt.

Keines macht den Port sicher für die Veröffentlichung in einem Netzwerk. Sie machen ihn überlebensfähig auf einer Maschine, die mit anderen Prozessen geteilt wird. --host bindet an einen anderen Ort als Loopback, was ein Container tun muss — siehe In einem Container für den Grund, warum das nicht die Lockerung ist, die es aussieht.

In einem Container

Das Image ist für linux/amd64 und linux/arm64 veröffentlicht, sodass nichts aus diesem Repository benötigt wird, um eines auszuführen:

docker pull ghcr.io/benethos-hub/lexware-office-mcp:latest

Pinnen Sie eine Version für alles, von dem Sie abhängen - :0.2.2 für eine exakte Veröffentlichung, :0.2 um deren Patch-Veröffentlichungen zu folgen. :latest bewegt sich mit jeder Veröffentlichung, und :edge wird bei Bedarf aus dem gebaut, was main enthält, und ist überhaupt keine Veröffentlichung.

Mit Compose

docker compose up -d                      # the server, on 127.0.0.1:8770
docker compose --profile setup up -d      # add the configuration interface
docker compose rm -f -s setup             # take the interface away again

Nicht docker compose --profile setup down. Das ist das gesamte Projekt: Es nimmt den Server mit herunter. rm -f -s setup stoppt und entfernt den einen Dienst und lässt den Server laufen. docker compose stop setup funktioniert auch und behält den gestoppten Container für das nächste Mal.

Wie ausgeliefert, baut compose.yaml aus diesem Checkout. Zwei auskommentierte Zeilen in jedem seiner beiden Dienste wechseln auf das veröffentlichte Image, und diese Datei ist dann das Einzige, was Sie von hier benötigen.

Als einzelne Container

docker run -d --name lexware-office-mcp \
  --restart unless-stopped \
  -p 127.0.0.1:8770:8770 \
  -v lxo-config:/config -v lxo-downloads:/downloads \
  ghcr.io/benethos-hub/lexware-office-mcp:latest

Das Token, das es für sich selbst generiert hat, befindet sich im Konfigurationsvolumen, von wo Sie es lesen:

docker exec lexware-office-mcp grep LXO_MCP_BEARER_TOKEN /config/.env

Diese eine Zeile statt der gesamten Datei: Sobald ein Schlüssel eingegeben wurde, sitzt der API-Schlüssel auch dort, und er hat nichts in einem Terminal zu suchen, das Sie möglicherweise screenshotten.

Die Konfigurationsoberfläche ist dasselbe Image mit seinem anderen Befehl, das auf dasselbe Volumen zeigt:

docker run --rm -d --name lexware-office-mcp-setup \
  -p 127.0.0.1:8771:8771 \
  -v lxo-config:/config -v lxo-downloads:/downloads \
  ghcr.io/benethos-hub/lexware-office-mcp:latest \
  setup --no-browser --host 0.0.0.0 --port 8771 \
        --env-file /config/.env --tools-file /config/tools.json

Es wurde mit --rm gestartet, also ist das Stoppen auch sein Ende:

docker stop lexware-office-mcp-setup

--restart unless-stopped ist hier keine Dekoration. Der Container beendet seinen Prozess, wenn sich die Einstellungsdatei ändert, was eine gespeicherte Einstellung in einen laufenden Server bringt. Ohne Neustartrichtlinie endet er und bleibt beendet.

Schalten Sie die Oberfläche aus, wenn Sie fertig sind

Öffnen Sie http://127.0.0.1:8771/, geben Sie den Schlüssel ein, aktivieren Sie die Tools — und stoppen Sie es dann. Nichts stoppt es für Sie. Es hat kein Login, es akzeptiert einen API-Schlüssel, und es wird diese Seite fröhlich weiter bedienen, solange die Maschine läuft.

docker compose rm -f -s setup             # Compose
docker stop lexware-office-mcp-setup      # a single container
docker ps --filter name=setup             # nothing listed means it is off

Der Server soll laufen. Die Oberfläche soll für die Minuten laufen, die du darin konfigurierst, weshalb ein einfaches docker compose up sie weglässt und weshalb sie keine Neustart-Richtlinie hat: Einmal gestoppt, bleibt sie gestoppt, bis du sie erneut anforderst.

Es muss nichts vorbereitet werden. Beim ersten Start erzeugt der Server ein Bearer-Token, schreibt es in das Konfigurations-Volume und teilt dies mit — die Oberfläche zeigt es an, und das ist der Wert, den ein Client benötigt. Es ist nicht in das Image eingebacken, wo jede Kopie es teilen würde.

Der Container bindet 0.0.0.0, und das ist keine Lockerung. Ein Prozess auf dem eigenen Loopback des Containers kann über einen veröffentlichten Port überhaupt nicht erreicht werden. Die Isolation ist der Netzwerk-Namespace, und wer den Port erreichen darf, entscheidet die Veröffentlichung, die nur 127.0.0.1 abbildet.

Eine im Browser gespeicherte Einstellung erreicht den laufenden Server. Einstellungen werden beim Start nur einmal gelesen, daher wird der Container angewiesen, zu enden, wenn sich seine Einstellungsdatei ändert, und Compose startet ihn eine Sekunde später neu. Was Compose als echte Umgebungsvariablen festlegt — den Transport, die Bind-Adresse, den Port, die erlaubten Hosts — gehört zum Container und kann nicht über das Volume geändert werden, siehe Konfiguration.

Beispiel-Prompts

Sobald der Server verbunden ist, sind Prompts wie diese die beabsichtigte Verwendung:

  • „Welche Rechnungen sind noch offen, und welche davon sind überfällig?"

  • „Zeig mir alles, was wir Kunde Muster GmbH in diesem Quartal in Rechnung gestellt haben."

  • „Was enthält Rechnung RE-2024-0142, und wurde sie bezahlt?"

  • „Finde den Artikel mit der Nummer A-1007 und nenne mir seinen aktuellen Preis."

  • „Lade das PDF der letzten Gutschrift herunter, die wir ausgestellt haben."

  • „Gib mir einen Link, um Beleg X in Lexware Office zu öffnen."

Ratenbegrenzungen

Die Lexware-API erlaubt zwei Anfragen pro Sekunde, durchgesetzt mit einem Token-Bucket. Dieses Budget ist global — es deckt alle Endpunkte der API gleichzeitig ab, sodass das Lesen eines Kontakts und das Lesen einer Rechnung aus derselben Zulassung schöpfen.

Der Server spiegelt dies mit einem einzigen Token-Bucket wider, der von jeder Anfrage im Prozess geteilt wird und standardmäßig knapp unter der dokumentierten Rate nachgefüllt wird. Lexware merkt an, dass die exakte Durchsetzung des Limits ohne Puffer ohnehin tendenziell 429er erzeugt, sobald Netzwerk-Jitter die Ankunftszeiten verschiebt, daher lässt der Standardwert Spielraum. Anfragen werden durch diesen Bucket serialisiert statt parallel abgefeuert, was bedeutet, dass eine breite Frage, die viele Dokumente berührt, langsamer wird statt blockiert.

Zwei Dinge sind wissenswert:

  • Das Budget gehört zu deinem Konto, nicht zu diesem Prozess. Eine zweite Instanz des Servers, eine andere Integration oder ein Skript, das du selbst ausführst, verbrauchen alle aus denselben zwei pro Sekunde.

  • Lexware warnt, dass ein Client, der nach einem 429 weiterhin hämmert, dauerhaft blockiert bleiben kann. Der Server weicht daher exponentiell zurück und gibt nach einigen Versuchen auf, statt es härter zu versuchen.

Der Bucket des Kontos wurde am 2026-08-21 gemessen und fasst vier: fünf gleichzeitig abgefeuerte Anfragen brachten vier durch und eine wurde abgelehnt. Der Standardwert von 2 lässt die Hälfte davon für alles andere, das auf dasselbe Konto zugreift — die Web-App, eine andere Integration, eine zweite Instanz dieses Servers. Erhöhe ihn auf 4 nur, wenn du weißt, dass dieser Server der einzige Verbraucher ist.

Beide Limiter-Werte sind über LXO_MCP_RATE und LXO_MCP_BURST konfigurierbar, falls sich dein Konto anders verhält.

Entwicklung

uv sync --extra dev
uv run pytest -q
uv run ruff check .
uv run ruff format --check .
uv run mypy

Die Testsuite ist vollständig offline. Sie mockt die HTTP-Ebene und benötigt keinen API-Schlüssel, läuft also überall. Zwei Arten von Tests verlassen den Prozess, ohne die Maschine zu verlassen: Drei starten den Server als echten Subprozess und sprechen MCP über stdio mit ihm, was auch beweist, dass beim Startpfad nichts auf stdout geschrieben wird, und die Konfigurationsoberfläche wird über einen echten Loopback-HTTP-Server mit einem echten Cookie-Jar gesteuert, weil ihre CSRF-Schutzmechanismen nur so getestet werden können, wie ein Browser ihnen begegnet.

Mit diesem Repository wird kein API-Schlüssel ausgeliefert und keiner gehört in CI, daher kann ein Checkout von sich aus nie mit Lexware sprechen. Die Überprüfung des Servers gegen die echte API ist daher immer ein bewusster lokaler Lauf mit einem von dir bereitgestellten Schlüssel, getrennt von der obigen Suite und nie Teil davon:

uv run python tests/smoke.py
uv run python tests/smoke.py --env-file path/to/.env

Er liest dein Konto und schreibt nichts darauf. Der Server, den er baut, erhält die Voreinstellung read-only, sodass die Schreibwerkzeuge gar nicht erst aufrufbar sind. Er gibt aus, was er geprüft hat, wofür das Konto nichts hatte und was fehlgeschlagen ist, und er maskiert Datensatz-IDs, damit der Bericht irgendwo eingefügt werden kann. pytest führt ihn nie aus. Siehe SPECS.md Abschnitt 14.1, warum eine Live-Prüfung kein Gate ist.

Beiträge und Issues sind willkommen. SPECS.md ist der Ort, an dem Designentscheidungen mit der Begründung und den Messungen dahinter festgehalten werden.

Lizenz

MIT. Siehe LICENSE.

Marken und Zugehörigkeit

Dieses Projekt ist nicht mit Lexware, Haufe-Lexware GmbH & Co. KG oder deren Tochtergesellschaften verbunden, von ihnen unterstützt oder gesponsert. „Lexware" und „Lexware Office" sind Marken ihrer jeweiligen Inhaber und werden hier nur verwendet, um die API zu benennen, mit der diese Software integriert, in beschreibendem Sinne.

Die Software spricht ausschließlich mit der dokumentierten öffentlichen API unter Verwendung von Anmeldedaten, die der Kontoinhaber bereitstellt und widerrufen kann. Die Nutzung dieser API unterliegt Lexwares eigenen Bedingungen, die du unabhängig von diesem Projekt akzeptierst.

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    MCP server for DACH accounting automation. Connect AI assistants to sevDesk and Lexoffice — create invoices, manage contacts, handle bookings and vouchers for German-speaking businesses.
    15
    43 npm
    -
  • A
    license
    B
    quality
    A
    maintenance
    MCP server for the Lexware Office API that enables management of invoices, contacts, articles, vouchers, and more through the Model Context Protocol.
    66
    460 npm
    6
    Functional Source , Version 1.1, MIT Future
  • A
    license
    A
    quality
    B
    maintenance
    Enables MCP-capable assistants to query and manage Lexware Office contacts, sales documents, vouchers, files, payments, webhooks, and reference data via the Lexware Office public API. Adds bank reconciliation tools for matching bank statement CSVs against Lexware vouchers or scanned receipt PDFs.
    4
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP server for Lexware Office that enables querying and managing contacts, sales documents, vouchers, files, payments, and webhooks through a sandboxed two-tool interface (search/execute) with read-only-by-default write safety.
    2
    MIT