# leadtech-bmad-mcp — MCP central exposé au tailnet via sidecar Tailscale.
#
# Architecture (cf. docs/design_nuc_tailscale.md) :
#
#   tailnet ──https──► [tailscale sidecar] ──http (réseau interne)──► [mcp:8080]
#
# - Le serveur MCP n'écoute QUE sur le réseau Docker interne (aucun port publié
#   sur l'hôte → aucune exposition LAN/WAN).
# - Le sidecar rejoint le tailnet sous le hostname `leadtech-mcp` et termine TLS
#   via `tailscale serve` (cert MagicDNS automatique).
# - URL client finale : https://leadtech-mcp.wyvern-snapper.ts.net/mcp
#
# Prérequis : copier .env.example en .env et y mettre LEADTECH_TS_AUTHKEY
# (auth key Tailscale Reusable, NON-Ephemeral — voir README / design doc).

name: leadtech-mcp

services:
  mcp:
    build:
      context: .
      dockerfile: Dockerfile
    image: leadtech-bmad-mcp:local
    container_name: leadtech-bmad-mcp
    restart: unless-stopped
    # Tourne en max:max (uid 1000) pour écrire l'index + 95_a_capitaliser.md
    # dans le bind-mont sans casser les permissions du repo Git hôte.
    user: "1000:1000"
    environment:
      LEADTECH_ROOT: /leadtech
      LEADTECH_MCP_TRANSPORT: streamable-http
      LEADTECH_MCP_HOST: 0.0.0.0
      LEADTECH_MCP_PORT: "8080"
      # Le sidecar termine TLS et forwarde le Host tailnet ; sans whitelist,
      # la protection anti-DNS-rebinding renvoie 421. Inclut le hostname interne
      # (mcp:8080) au cas où le proxy préserve l'autorité d'origine.
      LEADTECH_MCP_ALLOWED_HOSTS: "leadtech-mcp.wyvern-snapper.ts.net,leadtech-mcp.wyvern-snapper.ts.net:443,mcp:8080,mcp"
      # Instance centrale = seule à écrire (capitalisation centralisée).
      LEADTECH_MCP_ALLOW_WRITE: "1"
    volumes:
      # Source de vérité : le clone Git Lead_tech (lecture + écriture buffer/index).
      - /srv/helpers/_Assistant_Lead_Tech:/leadtech
      # Les projets cibles de route_to_project_memory (mêmes chemins que sur l'hôte).
      - /srv/projects:/srv/projects
    networks:
      - internal
    # PAS de `ports:` — jamais exposé hors du réseau Docker interne.

  tailscale:
    image: tailscale/tailscale:v1.98.3
    container_name: leadtech-mcp-ts
    restart: unless-stopped
    # ⚠ PAS de `hostname:` ici (collision DNS Docker service vs hostname,
    #   cf. knowledge/infra/risques/docker.md). TS_HOSTNAME suffit côté tailnet.
    depends_on:
      - mcp
    environment:
      TS_AUTHKEY: ${LEADTECH_TS_AUTHKEY:?LEADTECH_TS_AUTHKEY manquant — voir .env.example}
      TS_HOSTNAME: leadtech-mcp
      TS_STATE_DIR: /var/lib/tailscale
      TS_SERVE_CONFIG: /config/serve.json
      TS_USERSPACE: "false"
      TS_EXTRA_ARGS: --accept-dns=false
    volumes:
      - /srv/docker-data/leadtech-mcp/tailscale/state:/var/lib/tailscale
      - ./tailscale/serve.json:/config/serve.json:ro
      - /dev/net/tun:/dev/net/tun
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    networks:
      - internal
    labels:
      - "homepage.group=Infra"
      - "homepage.name=Lead_tech MCP"
      - "homepage.href=https://leadtech-mcp.wyvern-snapper.ts.net/mcp"

networks:
  internal:
    name: leadtech-mcp-internal
    driver: bridge
