Company Documents MCP Server
by niels-2005
README.md
# Company Documents MCP Server
Interner FastMCP-Server für die Suche in Unternehmensdokumenten. Der Server ist
für den Betrieb in einem privaten Unternehmensnetz vorgesehen und darf nicht
direkt aus dem Internet erreichbar sein.
## Voraussetzungen und Konfiguration
| Variable | Pflicht | Standard | Zweck |
| --- | --- | --- | --- |
| `MCP_AUTH_TOKEN` | ja | – | Gemeinsamer Bearer-Token für MCP-Clients |
| `OPENAI_API_KEY` | ja | – | API-Schlüssel für Embeddings |
| `MCP_HOST` | nein | `127.0.0.1` | Bind-Adresse des MCP-Servers |
| `MCP_PORT` | nein | `8000` | Port des MCP-Servers |
| `MCP_ALLOWED_HOSTS` | nein | `127.0.0.1,localhost` | Kommagetrennte erlaubte `Host`-Header für `/mcp` |
| `MCP_CHROMA_DIR` | nein | `.data/mcp-server/chroma` | Persistentes Chroma-Datenverzeichnis |
| `MCP_CACHE_DIR` | nein | `.cache/mcp-server` | Persistenter Antwort-Cache |
| `MCP_LOG_DIR` | nein | `logs` | Verzeichnis für Betriebs- und Qualitätslogs |
Secrets gehören ausschließlich in die Laufzeitumgebung bzw. eine nicht
versionierte `.env`-Datei.
## Betrieb
Der FastMCP-Lifespan öffnet beim Start das lokale Chroma-Datenverzeichnis. Ist
es nicht verfügbar, beendet sich der Prozess. Der Server stellt folgende
interne Health-Endpunkte bereit:
- `GET /healthz` – Prozess läuft.
- `GET /readyz` – Chroma antwortet aktuell; andernfalls `503`.
- `/mcp` – authentifizierter MCP-HTTP-Endpunkt.
Starten:
```bash
uv run mcp-server
```
Die VM-Firewall muss den MCP-Port auf das Unternehmensnetz bzw. VPN begrenzen.
HTTP ohne TLS ist nur unter dieser Bedingung zulässig. Bei externem Zugriff ist
ein HTTPS-Reverse-Proxy erforderlich.
Für direkten Zugriff von einem privaten Rechner auf eine VM muss der Server auf
allen VM-Schnittstellen lauschen und ihre IP als erlaubten Host kennen:
```bash
MCP_HOST=0.0.0.0
MCP_ALLOWED_HOSTS=127.0.0.1,localhost,VM_IP
```
Danach ist der authentifizierte MCP-Endpunkt unter
`http://VM_IP:8000/mcp` erreichbar. Ein Reverse Proxy, HTTPS und CORS sind
nicht erforderlich, solange die VM-Firewall den Port ausschließlich für das
private LAN oder VPN freigibt und kein Browser-JavaScript den Endpunkt direkt
anspricht.
## Caching und Ingest
Identische Aufrufe von `search_company_document` werden 24 Stunden im
Datei-Cache gespeichert. Das spart OpenAI-Embedding- und Chroma-Abfragen. Nach
einem erfolgreichen Ingest wird der gesamte Cache gelöscht, damit neue oder
geänderte Antworten sofort sichtbar sind:
```bash
uv run ingest-documents
```
Bei einem fehlgeschlagenen Ingest bleibt der bestehende Cache unverändert. Den
MCP-Service vor einem manuellen Ingest stoppen: Der eingebettete
`PersistentClient` verwendet denselben Datenpfad und wird als Einzelprozess
betrieben. Das mit `MCP_CHROMA_DIR` konfigurierte Verzeichnis ist der persistente
Chroma-Bestand und muss auf der VM zusammen mit den übrigen Betriebsdaten
gesichert werden (z. B. `/var/lib/mcp-server/chroma`).
## Beobachtbarkeit und Störungen
Der Server schreibt täglich rotierende JSONL-Dateien nach `logs/`:
- `server.jsonl` enthält Betriebsereignisse ohne Token, Suchanfragen oder
Antworten.
- `quality.jsonl` enthält für jeden Tool-Aufruf Zeit, Call-ID, Frage, Antwort
bzw. Fehlerstatus und Dauer. Diese Datei ist für Qualitätsauswertungen gedacht
und enthält interne Daten.
Audit- und Betriebslogs werden 30 Tage aufbewahrt. Das Logverzeichnis ist nur
für den Service-Benutzer lesbar. Temporäre OpenAI- und lokale I/O-Fehler
bei der Suche werden mit Exponential Backoff und Jitter innerhalb von 30
Sekunden erneut versucht; danach erhält der Client einen klaren temporären
Fehler.
Die Qualitätsdaten sind bewusst von den Betriebslogs getrennt. Ein späterer
Ausbau kann die Tagesdateien nach S3 übertragen.
Für Chroma wird kein Docker- oder Compose-Dienst benötigt.
## Docker
Das Produktionsimage enthält den bereits ingestierten Chroma-Bestand. Es ist
damit vertraulich zu behandeln und darf nur in einer freigegebenen internen
Registry gespeichert werden: Es enthält Dokumentinhalte und Embeddings.
Vor einem Build muss der lokale Chroma-Bestand aktuell sein. Nach einer
Dokumentänderung den Service stoppen, ingestieren und ein neues Image bauen:
```bash
uv run ingest-documents
docker build -t mcp-server:latest .
```
Der Container benötigt die Secrets ausschließlich zur Laufzeit. Die lokale
`.env`-Datei wird nicht in das Image kopiert. Für den Zugriff von einem zweiten
Rechner im privaten Netz die VM-IP bei den erlaubten Hosts eintragen und den
Port veröffentlichen:
```bash
docker run --detach --name mcp-server \
--env-file .env \
--env MCP_HOST=0.0.0.0 \
--env MCP_ALLOWED_HOSTS=127.0.0.1,localhost,VM_IP \
--publish 8000:8000 \
mcp-server:latest
```
Der MCP-Endpunkt ist dann `http://VM_IP:8000/mcp`. Die VM-Firewall muss Port
8000 auf das private Netz bzw. VPN begrenzen.
Chroma ist absichtlich im Image und wird nicht über ein Volume bereitgestellt:
Ein Datenupdate erfolgt durch einen neuen Ingest und Image-Build. Cache und
Logs werden im beschreibbaren Layer des Containers gespeichert. Sie bleiben bei
`docker stop` und `docker start` desselben Containers erhalten, werden aber bei
`docker rm` oder einem Container-Neuaufbau verworfen.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues