# -*- coding: utf-8 -*-
"""AI-Host4me Skills — MCP-server.

Ontsluit de bibliotheek van ai-host4me.nl (3.200+ Claude Skills, 2.600+ MCP-
servers, code libraries) als MCP-tools, zodat je ze rechtstreeks in Claude Code
of een andere MCP-client kunt zoeken en downloaden.

Tools:
  - search_library(query, kind?, limit?)  -> matchende items (metadata)
  - get_item(slug)                         -> één item + readme + sha256
  - download_item(slug, dest?)             -> ZIP naar schijf (met checksum-check)
  - list_categories()                      -> geldige categorie-keys

Config (env):
  AIH_API_KEY   verplicht — read-sleutel (leden maken die zelf aan in de
                bibliotheek ▸ API-sleutels; zie https://ai-host4me.nl/developers.html)
  AIH_BASE_URL  optioneel — default https://ai-host4me.nl (of pre.ai-host4me.nl)

Draaien:
  pip install "mcp[cli]" httpx
  AIH_API_KEY=aih_... python server.py           # stdio (Claude Code)

Registreren in .mcp.json:
  {"mcpServers": {"ai-host4me": {"command": "python",
     "args": ["pad/naar/server.py"], "env": {"AIH_API_KEY": "aih_..."}}}}
"""
import hashlib
import os
import pathlib

import httpx
from mcp.server.fastmcp import FastMCP

BASE = os.environ.get("AIH_BASE_URL", "https://ai-host4me.nl").rstrip("/")
API_KEY = os.environ.get("AIH_API_KEY", "")

mcp = FastMCP("ai-host4me")


def _client() -> httpx.Client:
    if not API_KEY:
        raise RuntimeError("AIH_API_KEY ontbreekt — maak een read-sleutel aan in de bibliotheek (API-sleutels).")
    return httpx.Client(base_url=BASE, headers={"X-Api-Key": API_KEY}, timeout=60)


@mcp.tool()
def search_library(query: str, kind: str = "", limit: int = 15) -> list[dict]:
    """Zoek in de AI-Host4me-bibliotheek op trefwoord (titel/beschrijving/slug).

    query: zoekterm. kind: optioneel filter 'skill' | 'plugin' | 'library'.
    limit: max aantal resultaten (1-50). Geeft compacte metadata terug
    (slug, title, description, kind, category, license, downloads)."""
    q = (query or "").strip().lower()
    limit = max(1, min(50, limit))
    with _client() as c:
        params = {"action": "list"}
        if kind in ("skill", "plugin", "library"):
            params["kind"] = kind
        data = c.get("/api.php", params=params).json()
    items = data.get("skills", []) if data.get("ok") else []
    hits = []
    for it in items:
        hay = " ".join(str(it.get(k, "")) for k in ("slug", "title", "description", "title_nl", "description_nl")).lower()
        if not q or q in hay:
            hits.append({k: it.get(k) for k in ("slug", "title", "description", "kind", "category", "license", "downloads")})
        if len(hits) >= limit:
            break
    return hits


@mcp.tool()
def get_item(slug: str) -> dict:
    """Haal één item op: volledige metadata, readme (EN/NL), versiegeschiedenis
    en de SHA-256 van de ZIP. slug moet exact matchen (zie search_library)."""
    with _client() as c:
        data = c.get("/api.php", params={"action": "get", "slug": slug}).json()
    if not data.get("ok"):
        return {"error": data.get("error", "not_found"), "slug": slug}
    return data.get("skill", {})


@mcp.tool()
def download_item(slug: str, dest: str = ".") -> dict:
    """Download de ZIP van een item naar map `dest` en verifieer de SHA-256
    tegen de door de API opgegeven checksum. Geeft het pad en de verificatie-
    status terug. Handig om een skill meteen lokaal te installeren."""
    with _client() as c:
        meta = c.get("/api.php", params={"action": "get", "slug": slug}).json()
        expected = (meta.get("skill") or {}).get("sha256", "") if meta.get("ok") else ""
        r = c.get("/api.php", params={"action": "zip", "slug": slug})
        if r.status_code != 200:
            return {"error": f"download mislukt (HTTP {r.status_code})", "slug": slug}
        content = r.content
    out = pathlib.Path(dest).expanduser() / f"{slug}.zip"
    out.parent.mkdir(parents=True, exist_ok=True)
    out.write_bytes(content)
    got = hashlib.sha256(content).hexdigest()
    return {"slug": slug, "path": str(out), "bytes": len(content),
            "sha256": got, "verified": bool(expected) and got == expected,
            "checksum_source": "api" if expected else "unavailable"}


@mcp.tool()
def list_categories() -> list[str]:
    """De geldige categorie-keys van de bibliotheek (voor filteren/zoeken)."""
    with _client() as c:
        data = c.get("/api.php", params={"action": "list", "limit": 1}).json()
    return data.get("categories", []) if data.get("ok") else []


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