#!/usr/bin/env python3
"""
Mission Control — Memory MCP Server

Stdio-MCP-Server fuer persistentes Gedaechtnis.
Laeuft als Subprocess von Cline / Claude Code / OpenCode auf dem Client-Rechner.
Ruft die /api/memory-Endpunkte von Mission Control via HTTP auf.

Konfiguration via Env-Vars:
  MC_URL    Mission Control URL (default: http://192.168.178.151:9000)
  MC_TOKEN  Auth-Token (default: leer)

Einmalig installieren (auf dem Rechner wo das KI-Tool laeuft):
  pip install mcp httpx
"""

import os
import httpx
from mcp.server.fastmcp import FastMCP

MC_URL = os.environ.get("MC_URL", "http://192.168.178.151:9000").rstrip("/")
MC_TOKEN = os.environ.get("MC_TOKEN", "")

mcp = FastMCP("mission-control-memory")


def _headers() -> dict:
    return {"X-MC-Token": MC_TOKEN} if MC_TOKEN else {}


def _get(path: str, **params) -> list | dict:
    r = httpx.get(f"{MC_URL}{path}", headers=_headers(), params=params, timeout=10)
    r.raise_for_status()
    return r.json()


def _post(path: str, data: dict) -> dict:
    r = httpx.post(f"{MC_URL}{path}", headers=_headers(), json=data, timeout=10)
    r.raise_for_status()
    return r.json()


def _put(path: str, data: dict) -> dict:
    r = httpx.put(f"{MC_URL}{path}", headers=_headers(), json=data, timeout=10)
    r.raise_for_status()
    return r.json()


def _delete(path: str) -> dict:
    r = httpx.delete(f"{MC_URL}{path}", headers=_headers(), timeout=10)
    r.raise_for_status()
    return r.json()


@mcp.tool()
def get_memories(category: str = "") -> str:
    """Laedt gespeicherte Fakten und Entscheidungen. category: stable | versioned | ephemeral | (leer = alle)"""
    params = {"category": category} if category else {}
    items = _get("/api/memory", **params)
    if not items:
        return "Keine Memories gespeichert."
    cat_icon = {"stable": "🔵", "versioned": "🟡", "ephemeral": "⏱"}
    return "\n".join(
        f"{cat_icon.get(m['category'], '·')} [{m['category']}] {m['content']}"
        f"  (Quelle: {m['source']}, ID: {m['id'][:8]})"
        for m in items
    )


@mcp.tool()
def add_memory(content: str, category: str = "stable", source: str = "agent") -> str:
    """Speichert einen Fakt oder eine Entscheidung.
    category: stable=Projektfakten (selten aendern), versioned=Tech-Versionen (bei Updates ueberschreiben), ephemeral=temporaerer Kontext (nach 7 Tagen geloescht).
    """
    m = _post("/api/memory", {"content": content, "category": category, "source": source})
    return f"Gespeichert (ID: {m['id'][:8]}): {content}"


@mcp.tool()
def search_memories(q: str) -> str:
    """Sucht per Stichwort in allen gespeicherten Fakten."""
    items = _get("/api/memory", q=q)
    if not items:
        return f"Keine Treffer fuer '{q}'."
    return "\n".join(
        f"[{m['category']}] {m['content']}  (ID: {m['id'][:8]})"
        for m in items
    )


@mcp.tool()
def update_memory(memory_id: str, content: str = "", category: str = "") -> str:
    """Aktualisiert einen bestehenden Eintrag (z.B. nach Tech-Update). Nur gesetzte Felder werden geaendert."""
    data: dict = {}
    if content:
        data["content"] = content
    if category:
        data["category"] = category
    if not data:
        return "Nichts zu aktualisieren (content und category sind leer)."
    m = _put(f"/api/memory/{memory_id}", data)
    return f"Aktualisiert: {m['content']}"


@mcp.tool()
def delete_memory(memory_id: str) -> str:
    """Loescht einen veralteten oder falschen Eintrag anhand seiner ID."""
    _delete(f"/api/memory/{memory_id}")
    return f"Eintrag {memory_id[:8]} geloescht."


if __name__ == "__main__":
    mcp.run()
