- Save cover email body as DMS document with new 'email' context type - Show email body separately from attachments in email detail view - Add per-category DMS document assignment in quarterly confirmation (Studiennachweis, Einkommenssituation, Vermögenssituation) - Add VERSION file and context processor for automatic version display - Add MCP server, agent system, import/export, and new migrations - Update compose files and production environment template Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
152 lines
6.8 KiB
Python
152 lines
6.8 KiB
Python
"""
|
||
MCP Server für die Stiftungsverwaltung.
|
||
|
||
Startmodus:
|
||
python -m mcp_server.server
|
||
|
||
Konfiguration über Umgebungsvariablen:
|
||
MCP_AUTH_TOKEN – Aktiver Zugriffstoken (vom MCP-Client gesetzt)
|
||
MCP_TOKEN_READONLY – Token für readonly-Rolle
|
||
MCP_TOKEN_EDITOR – Token für editor-Rolle
|
||
MCP_TOKEN_ADMIN – Token für admin-Rolle
|
||
|
||
DJANGO_SETTINGS_MODULE – Django-Settings (Standard: core.settings)
|
||
DB_HOST, DB_PORT, POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD – DB-Verbindung
|
||
"""
|
||
|
||
import logging
|
||
import os
|
||
import sys
|
||
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
# Django Standalone-Setup (ORM ohne HTTP-Server)
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
|
||
# Pfad zum app/-Verzeichnis in sys.path aufnehmen (damit Imports funktionieren)
|
||
_app_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
if _app_dir not in sys.path:
|
||
sys.path.insert(0, _app_dir)
|
||
|
||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings")
|
||
|
||
import django # noqa: E402
|
||
|
||
django.setup()
|
||
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
# Logging
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
|
||
logging.basicConfig(
|
||
level=logging.WARNING,
|
||
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
||
stream=sys.stderr,
|
||
)
|
||
logger = logging.getLogger("mcp_server")
|
||
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
# Auth-Check vor Server-Start
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
|
||
from mcp_server.auth import get_current_role, require_role # noqa: E402
|
||
|
||
_current_role = get_current_role()
|
||
try:
|
||
require_role(_current_role)
|
||
except ValueError as exc:
|
||
logger.error("MCP Auth-Fehler: %s", exc)
|
||
sys.exit(1)
|
||
|
||
logger.info("MCP Server startet mit Rolle: %s", _current_role)
|
||
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
# MCP Server Initialisierung
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
|
||
from mcp.server.fastmcp import FastMCP # noqa: E402
|
||
|
||
mcp = FastMCP(
|
||
"Stiftungsverwaltung",
|
||
instructions=(
|
||
"MCP-Server der gemeinnützigen Familienstiftung. "
|
||
f"Aktive Rolle: {_current_role}. "
|
||
"Lese-Zugriff auf alle Stiftungsdaten. "
|
||
+ ("Schreib-Zugriff aktiv. " if _current_role in ("editor", "admin") else "")
|
||
+ "PII-Felder werden bei readonly/editor maskiert."
|
||
),
|
||
)
|
||
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
# Lese-Tools registrieren (alle Rollen)
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
|
||
from mcp_server.tools.lesen import ( # noqa: E402
|
||
dashboard,
|
||
destinataer_details,
|
||
destinataer_suchen,
|
||
dokument_details,
|
||
dokument_suchen,
|
||
globale_suche,
|
||
konten_uebersicht,
|
||
land_details,
|
||
land_suchen,
|
||
paechter_suchen,
|
||
statistiken,
|
||
termine_anzeigen,
|
||
transaktionen_suchen,
|
||
verwaltungskosten,
|
||
)
|
||
|
||
mcp.tool()(destinataer_suchen)
|
||
mcp.tool()(destinataer_details)
|
||
mcp.tool()(land_suchen)
|
||
mcp.tool()(land_details)
|
||
mcp.tool()(paechter_suchen)
|
||
mcp.tool()(konten_uebersicht)
|
||
mcp.tool()(verwaltungskosten)
|
||
mcp.tool()(transaktionen_suchen)
|
||
mcp.tool()(dokument_suchen)
|
||
mcp.tool()(dokument_details)
|
||
mcp.tool()(termine_anzeigen)
|
||
mcp.tool()(globale_suche)
|
||
mcp.tool()(dashboard)
|
||
mcp.tool()(statistiken)
|
||
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
# Schreib-Tools registrieren (nur editor/admin)
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
|
||
from mcp_server.auth import can_write # noqa: E402
|
||
|
||
if can_write(_current_role):
|
||
from mcp_server.tools.schreiben import ( # noqa: E402
|
||
destinataer_aktualisieren,
|
||
destinataer_anlegen,
|
||
dokument_verknuepfen,
|
||
foerderung_anlegen,
|
||
land_anlegen,
|
||
paechter_anlegen,
|
||
termin_anlegen,
|
||
unterstuetzung_anlegen,
|
||
verpachtung_anlegen,
|
||
verwaltungskosten_erfassen,
|
||
)
|
||
|
||
mcp.tool()(destinataer_anlegen)
|
||
mcp.tool()(destinataer_aktualisieren)
|
||
mcp.tool()(foerderung_anlegen)
|
||
mcp.tool()(unterstuetzung_anlegen)
|
||
mcp.tool()(land_anlegen)
|
||
mcp.tool()(verpachtung_anlegen)
|
||
mcp.tool()(paechter_anlegen)
|
||
mcp.tool()(verwaltungskosten_erfassen)
|
||
mcp.tool()(termin_anlegen)
|
||
mcp.tool()(dokument_verknuepfen)
|
||
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
# Server starten
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
|
||
if __name__ == "__main__":
|
||
mcp.run(transport="stdio")
|