# 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