Metadata-Version: 2.4
Name: lexitanon
Version: 0.2.0
Summary: Python client for the REST API of LexITanon: pseudonymize and redact legal documents on your own server
Author: be next GmbH
License: MIT License
        
        Copyright (c) 2026 be next GmbH
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
        This licence covers this client library and its examples only. LexITanon itself (the program and its
        AI model) is proprietary software of be next GmbH and needs a licence: https://lexitanon.com
        
Project-URL: Homepage, https://lexitanon.com
Project-URL: Documentation, https://lexitanon.com/handbuch/
Keywords: pseudonymization,redaction,anonymization,legal,GDPR,DSGVO,LexITanon,MCP,Model Context Protocol
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Natural Language :: German
Classifier: Topic :: Text Processing
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# LexITanon - Python-Client und Beispiele

[LexITanon](https://lexitanon.com) pseudonymisiert und schwärzt juristische Dokumente - Urteile, Beschlüsse,
Schriftsätze - **vollständig auf Ihrem eigenen Server**, ohne Cloud. Dieses Projekt enthält eine
Python-Bibliothek für die REST-Schnittstelle von LexITanon sowie Beispiele für typische Aufgaben in der
Kanzlei-IT: einzelne Texte und PDFs, ganze Ordner, Eingangsordner für ein Dokumentenmanagementsystem und
die Überwachung des Servers.

- nur die Python-Standardbibliothek (keine weiteren Pakete), Python 3.9 oder neuer, Windows, Linux, macOS
- die Bibliothek verbindet sich ausschließlich mit Ihrem LexITanon-Server - Ihre Dokumente gehen nirgendwo
  anders hin
- die REST-Schnittstelle gehört zur **Server-Ausgabe** von LexITanon
  ([Ausgaben und Preise](https://lexitanon.com/preise/))
- mit `lexitanon-mcp` können KI-Assistenten Dokumente über Ihren LexITanon-Server pseudonymisieren; das
  pseudonymisierte Ergebnis geht dann an den KI-Dienst, mit dem der Assistent arbeitet - siehe
  [KI-Assistenten anbinden (MCP)](#ki-assistenten-anbinden-mcp)

## Installation

```
pip install lexitanon
```

oder direkt aus diesem Projekt: `pip install "git+https://gitlab.com/beaexpert/lexitanon.git"`

## Schnellstart

```python
from lexitanon import Client

lx = Client("http://lexitanon-server:8471")      # oder die Umgebungsvariable LEXITANON_URL

r = lx.redact_text("Herr Max Mustermann, geboren am 3. Mai 1980, wohnt Hauptstraße 5, 10115 Berlin.")
print(r.redacted)   # Herr [NAME], geboren am [DATUM], wohnt [ANSCHRIFT], [ORT].
for f in r.findings:
    print(f.group, f.original, "->", f.replacement)

# eine PDF-Datei: einreichen, warten, Ergebnis speichern, Auftrag auf dem Server löschen
r = lx.redact_file("Urteil.pdf", "Urteil_pseudonymisiert.pdf")
print(len(r.findings), "Angaben ersetzt", r.count_by_group())

# Schwärzung (Balken) statt Platzhaltern, nur bestimmte Arten von Angaben
lx.redact_file("Urteil.pdf", "Urteil_geschwaerzt.pdf", replacement="block", groups=["personen", "orte"])
```

## Die Bibliothek im Überblick

| Aufruf | Zweck |
|---|---|
| `Client(url, timeout=120, retries=5)` | ein LexITanon-Server; `url` z. B. `http://lexitanon-server:8471` |
| `info()`, `ready()` | Version, KI-Modell, Regeln, Lizenz, Grenzen, Warteschlange; `ready()`: erreichbar und lizenziert |
| `groups()` | die Arten von Angaben: `personen`, `organisationen`, `orte`, `datum`, `aktenzeichen`, `kontakt`, `bank`, `steuerid`, `kennnummern`, `gesundheit` |
| `redact_text(text, groups=None, replacement="label", numbering=False, dates=None)` | kurzen Text sofort bearbeiten → `Result` |
| `redact_file(datei, ausgabe=None, format="pdf", …)` | Datei (PDF oder Text) bearbeiten, Ergebnis speichern → `Result` |
| `submit(datei)` → `Job` | Datei als Auftrag einreichen (kehrt sofort zurück) |
| `Job.wait()`, `status()`, `result(format)`, `save(pfad, format)`, `delete()` | Auftrag abwarten, Ergebnis als `pdf`, `txt` oder `json` abholen, löschen; als `with`-Block wird der Auftrag am Ende gelöscht |

`replacement="label"` ist die **Pseudonymisierung** (Platzhalter wie `[NAME]`), `replacement="block"` die
**Schwärzung** (schwarze Balken). Ein `Result` enthält den bearbeiteten Text (`redacted`), den gelesenen Text
(`text`) und die Fundstellen (`findings`: Art, Position, Original, Ersatz).

Ab LexITanon 0.5 (auch für `submit` und `redact_file`): `numbering=True` nummeriert die Platzhalter (`[NAME_1]`,
`[NAME_2]`; nicht mit der Schwärzung); `dates` bestimmt die Datumsangaben: `"replace"` (`[DATUM]`, Standard),
`"keep"` (unverändert), `"month"` (nur Monat und Jahr) oder `"shift"` (alle um dieselbe Zahl von Tagen
verschoben, `date_shift_days=` oder zufällig; der verwendete Wert steht in `Result.date_shift_days`).

Ist die Warteschlange des Servers voll (HTTP 503), wartet der Client von selbst so lange, wie der Server
angibt, und versucht es erneut.

## Fehler

Alle Fehler sind Unterklassen von `LexITanonError` mit `status` (HTTP), `code` und `message` (deutsch):

| Klasse | Bedeutung |
|---|---|
| `ConnectionFailed` | Server nicht erreichbar (Adresse, Port, Firewall) |
| `BadRequest` | z. B. unbekannte Art in `groups`, leerer Text |
| `LicenceRequired` | keine gültige Lizenz |
| `SessionOnly` | eine Desktop-Ausgabe: sie hat keine REST-Schnittstelle |
| `Forbidden` | Zugriff von einem anderen Rechner, obwohl LexITanon nur lokal freigegeben ist (`--bind`) |
| `FileTooLarge`, `UnsupportedFile`, `NoTextLayer` | Datei zu groß, kein PDF/Text, gescanntes PDF ohne Textebene |
| `Busy` | ausgelastet (nach allen Wiederholungen) |
| `NotFound`, `NotReady`, `JobFailed`, `Timeout` | Auftrag unbekannt/gelöscht, noch nicht fertig, fehlgeschlagen, zu lange |

## Kommandozeile

```
lexitanon-client --url http://lexitanon-server:8471 info
lexitanon-client text "Max Mustermann wohnt in Berlin."
lexitanon-client file Urteil.pdf -o Urteil_pseudonymisiert.pdf
lexitanon-client file Urteil.pdf --block --groups personen,orte
lexitanon-client folder eingang/ ausgang/ --workers 4
```

## KI-Assistenten anbinden (MCP)

<!-- mcp-name: com.lexitanon/lexitanon-mcp -->

`lexitanon-mcp` ist ein MCP-Server (Model Context Protocol) für KI-Assistenten - Claude Desktop, andere
MCP-fähige Programme oder eigene Agenten der Kanzlei. Der Assistent kann damit Dokumente über **Ihren**
LexITanon-Server pseudonymisieren oder schwärzen und arbeitet danach nur mit dem Ergebnis: Statt
„Max Mustermann“ sieht das KI-Modell `[NAME_1]`.

So läuft es ab:

1. Sie bitten den Assistenten, z. B. `D:\Akten\Urteil.pdf` zu pseudonymisieren und dann zusammenzufassen.
2. Der Assistent ruft das Werkzeug `datei_pseudonymisieren` mit diesem Pfad auf. `lexitanon-mcp` liest die Datei auf
   Ihrem Rechner und gibt sie an Ihren LexITanon-Server (`LEXITANON_URL`); LexITanon pseudonymisiert sie dort und
   das Ergebnis wird als neue Datei gespeichert (`Urteil_pseudonymisiert.pdf`).
3. An den Assistenten zurück gehen nur der Pfad der Ergebnisdatei, eine Zusammenfassung (Anzahl je Art von
   Angaben, Hinweise) und auf Wunsch der pseudonymisierte Text.
4. Der Assistent gibt diesen pseudonymisierten Text an den KI-Dienst weiter, mit dem er arbeitet - oft eine
   Cloud-KI.

### Datenschutz - bitte lesen

- **Was lokal bleibt:** LexITanon pseudonymisiert auf Ihrem eigenen Rechner bzw. Server; `lexitanon-mcp`
  verbindet sich ausschließlich mit Ihrem LexITanon-Server (`LEXITANON_URL`). Das pseudonymisierte Ergebnis geben
  Sie über den Assistenten an den KI-Dienst Ihrer Wahl weiter - häufig eine Cloud-KI. Für diesen Dienst gelten
  dessen Bedingungen.
- **Was der KI-Assistent erhält:** nur den pseudonymisierten Text, die Arten der ersetzten Angaben, ihre Anzahl,
  die Platzhalter und deren Position im Ergebnis. Kein Werkzeug gibt Originalwerte zurück, und eine Rückführung
  (Platzhalter → Original) bietet `lexitanon-mcp` nicht an.
- **Ergebnisse prüfen:** Die Qualität hängt davon ab, was LexITanon erkennt, und keine automatische Erkennung
  ist vollständig. Prüfen Sie das Ergebnis, bevor Sie sensible Dokumente an einen KI-Dienst geben: Lassen Sie den
  Assistenten zuerst nur die Ergebnisdatei erstellen (ohne `text_zurueckgeben`), prüfen Sie diese Datei und geben
  Sie sie erst dann frei. Viele MCP-Programme fragen außerdem vor jedem Werkzeugaufruf nach Ihrer Zustimmung.
- **Originale nicht in den Chat:** Was Sie selbst in den Chat kopieren, erhält das KI-Modell im Original. Nennen Sie
  dem Assistenten stattdessen den Pfad der Datei. Aus demselben Grund ist `pseudonymisieren_text` nur begrenzt
  nützlich: Den Text übergibt das KI-Modell selbst, es kennt ihn also bereits. Sinnvoll ist das Werkzeug für eigene
  Agenten, die es aus ihrem Programm heraus aufrufen, bevor ein KI-Modell den Text sieht.
- **Verschobene Datumsangaben:** Mit `dates: "shift"` und zufälliger Verschiebung erfährt das KI-Modell nicht, um
  wie viele Tage verschoben wurde - der Wert steht nur im Protokoll des MCP-Clients (stderr). Geben Sie
  `date_shift_days` selbst vor (z. B. für weitere Dokumente desselben Falls), kennt der Aufrufer den Wert ohnehin;
  daraus lassen sich die echten Daten zurückrechnen. Sollen Daten verborgen bleiben, verwenden Sie `replace` oder
  `month`.
- **Netzwerk:** Läuft der LexITanon-Server auf einem anderen Rechner, geht die REST-Schnittstelle über HTTP ohne
  TLS und ohne Anmeldung. Nutzen Sie sie nur in einem vertrauenswürdigen Netz - oder über einen TLS-Reverse-Proxy
  oder einen SSH-Tunnel, z. B. `ssh -N -L 8471:127.0.0.1:8471 lexitanon-server` und
  `LEXITANON_URL=http://127.0.0.1:8471`.
- **Dateien:** nur lokale PDF- und Textdateien (`.pdf`, `.txt`); die Eingabedatei wird nie überschrieben, eine
  vorhandene Ergebnisdatei nur mit `ueberschreiben: true`. Mit `LEXITANON_MCP_ORDNER` beschränken Sie den Zugriff
  auf bestimmte Ordner.

### Einrichtung

Voraussetzungen: die Bibliothek (siehe [Installation](#installation)), Python 3.9 oder neuer und ein
LexITanon-Server (Server-Ausgabe; `numbering` und `dates` ab LexITanon 0.5). Den vollständigen Pfad des Befehls
zeigt `which lexitanon-mcp` (macOS, Linux) bzw. `where lexitanon-mcp` (Windows).

| Umgebungsvariable | Bedeutung |
|---|---|
| `LEXITANON_URL` | Ihr LexITanon-Server, Standard `http://127.0.0.1:8471` - die einzige Adresse, mit der sich `lexitanon-mcp` verbindet |
| `LEXITANON_MCP_ORDNER` | optional: nur in diesen Ordnern lesen und schreiben; mehrere mit `;` (Windows) bzw. `:` (macOS, Linux) getrennt |
| `LEXITANON_MCP_LOG` | Protokoll auf stderr: `debug`, `info`, `warning` (Standard) oder `error`; es enthält nie Dokumenttext |

Eine Anmeldung (Token) braucht es nicht: LexITanon fragt derzeit keine ab.

**Claude Desktop:** Einstellungen → Entwickler → Konfiguration bearbeiten öffnet `claude_desktop_config.json`
(macOS: `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\Claude\`). Eintragen und Claude Desktop neu
starten:

```json
{
  "mcpServers": {
    "lexitanon": {
      "command": "/usr/local/bin/lexitanon-mcp",
      "env": {
        "LEXITANON_URL": "http://127.0.0.1:8471",
        "LEXITANON_MCP_ORDNER": "/Users/kanzlei/Akten"
      }
    }
  }
}
```

Mit [uv](https://docs.astral.sh/uv/) ohne vorherige Installation (`uvx` lädt das Paket `lexitanon` von PyPI):

```json
{
  "mcpServers": {
    "lexitanon": {
      "command": "uvx",
      "args": ["lexitanon"],
      "env": {
        "LEXITANON_URL": "http://127.0.0.1:8471"
      }
    }
  }
}
```

Unter Windows, mit Python statt des Befehls:

```json
{
  "mcpServers": {
    "lexitanon": {
      "command": "C:\\Program Files\\Python312\\python.exe",
      "args": ["-m", "lexitanon.mcp"],
      "env": {
        "LEXITANON_URL": "http://lexitanon-server:8471",
        "LEXITANON_MCP_ORDNER": "D:\\Akten"
      }
    }
  }
}
```

**Andere MCP-Programme und eigene Agenten:** Transport `stdio`, Befehl `lexitanon-mcp` (gleichwertig: `lexitanon`,
`uvx lexitanon` oder `python -m lexitanon.mcp`), die Umgebungsvariablen wie oben. Viele Programme übernehmen den Block `mcpServers` von oben
unverändert. Wer das Protokoll selbst spricht: JSON-RPC 2.0, eine Nachricht je Zeile (UTF-8), Protokollversionen
2024-11-05 bis 2025-11-25, z. B.

```
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"kanzlei-agent","version":"1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"datei_pseudonymisieren","arguments":{"datei":"/akten/Urteil.pdf","numbering":true}}}
```

### Werkzeuge

| Werkzeug | Zweck | Angaben |
|---|---|---|
| `datei_pseudonymisieren` | eine lokale PDF- oder Textdatei bearbeiten und das Ergebnis als neue Datei speichern (Standard: neben der Eingabe mit `_pseudonymisiert` bzw. `_geschwaerzt`); gibt Pfad und Zusammenfassung zurück | `datei` (Pflicht), `ausgabe`, `format` (`pdf`, `txt`), `ueberschreiben`, `text_zurueckgeben` und die Optionen |
| `pseudonymisieren_text` | einen Text bearbeiten; gibt den Text und eine Zusammenfassung zurück | `text` (Pflicht), `fundstellen` (Art, Platzhalter und Position im Ergebnis) und die Optionen |
| `kategorien` | die Arten von Angaben (Kennung für `groups`, Name, Beispiele) und die Arten der Ersetzung | - |
| `server_info` | Version, Ausgabe, KI-Modell, Regeln und Lizenzstatus des Servers (ohne Lizenzschlüssel und Kennungen) | - |

Optionen: `replacement` (`label` = Pseudonymisierung, `block` = Schwärzung), `groups` (z. B.
`["personen", "orte"]`), `numbering` (`[NAME_1]`, `[NAME_2]` - empfohlen, damit das KI-Modell Personen
auseinanderhalten kann), `dates` (`replace`, `keep`, `month`, `shift`) und `date_shift_days`.

## Beispiele

| Datei | Inhalt |
|---|---|
| [examples/01_text.py](examples/01_text.py) | einen Text pseudonymisieren, Fundstellen anzeigen, Arten auswählen |
| [examples/02_pdf.py](examples/02_pdf.py) | eine PDF-Datei pseudonymisieren und schwärzen, Schritt für Schritt |
| [examples/03_ordner.py](examples/03_ordner.py) | einen ganzen Ordner bearbeiten, mehrere Dateien gleichzeitig, Bericht als CSV (Excel) |
| [examples/04_eingangsordner.py](examples/04_eingangsordner.py) | einen Eingangsordner überwachen (DMS, Scanner-Export) |
| [examples/05_server_pruefen.py](examples/05_server_pruefen.py) | den Server überwachen (Rückgabewerte wie bei Nagios/Icinga/Checkmk) |

`examples/Musterurteil.pdf` und `examples/beispiel.txt` sind frei erfunden.

```
export LEXITANON_URL=http://lexitanon-server:8471      # Windows: set LEXITANON_URL=...
python examples/02_pdf.py examples/Musterurteil.pdf
```

## Hinweise

- **Jedes Ergebnis prüfen:** LexITanon ist ein Hilfsmittel. Wie jedes automatische Verfahren kann es Angaben
  übersehen oder zu viel ersetzen - siehe [Benutzerhandbuch](https://lexitanon.com/handbuch/), Kapitel „Grenzen
  und Hinweise“.
- **Netzwerk:** LexITanon fragt derzeit keine Anmeldung ab und überträgt im Netzwerk unverschlüsselt (HTTP).
  Geben Sie es nur in einem vertrauenswürdigen internen Netz frei.
- **Ergebnisse** liegen nur im Arbeitsspeicher des Servers und werden gelöscht, sobald der Auftrag gelöscht
  wird (`redact_file` und `with`-Blöcke tun das), spätestens nach `--result-ttl` (Standard 15 Minuten).
- Die vollständige Beschreibung der Schnittstelle liefert der Server selbst: `GET /api/v1/openapi.json`.

## Tests

```
python -m unittest discover -s tests                                   # ohne Server (Nachbildung)
LEXITANON_URL=http://lexitanon-server:8471 python -m unittest discover -s tests   # zusätzlich gegen einen echten Server
```

## Lizenz und Kontakt

Diese Bibliothek und die Beispiele: siehe [LICENSE](LICENSE). LexITanon selbst ist eine lizenzpflichtige
Software der be next GmbH. Fragen: [lexitanon.com/kontakt](https://lexitanon.com/kontakt/)
