diff --git a/infra/connection-hosts.md b/infra/connection-hosts.md new file mode 100644 index 0000000..4fab2e2 --- /dev/null +++ b/infra/connection-hosts.md @@ -0,0 +1,348 @@ +# Connection Hosts — nuclide.systems + +Maintained reference for every host, LAN address, port, and public URL. +**Last verified: 2026-05-23.** + +> Source of truth: [`ct-inventory.md`](../ct-inventory.md) (guests) · [`portmap.md`](portmap.md) (Docker ports) · [`homelab-architecture.md`](../services/homelab-architecture.md) (topology). + +--- + +## Network infrastructure + +| Device | LAN IP | Admin UI | Notes | +|---|---|---|---| +| **UDM Home** (UCG Fiber, UniFi OS 5.0.16) | `192.168.1.1` | `https://192.168.1.1` (SSO + MFA) | Gateway, DNS forwarder → AdGuard; port-forwards 80/443 → Zoraxy (`.4`), 15001 TCP/UDP → CT 104 | +| **D-Link DGS-1210-28P** | `192.168.1.10` | `http://192.168.1.10` (HTTP-only, pw: `tapirnase`) | 28-port PoE switch — physical core. UDM on port 26, CT 104 cluster on port 10, APs on ports 3 & 16. SNTP fixed 2026-05-19. | +| **UNAS Pro** (NFS server) | `192.168.1.31` | `http://192.168.1.31` | NFSv3 export: `192.168.1.31:/var/nfs/shared/storage` (→ `/mnt/pve/unas`). ~19 T bulk storage. | +| **UniFi U7 APs** | `.50` `.51` `.52` `.53` | via UDM | Hallway, In-wall, Bedroom (Schlafzimmer), Dining (Esszimmer). SSID: `nuclide`, WPA2/WPA3. | +| **TP-Link RE700X** | `192.168.1.187` | `http://192.168.1.187` | WiFi extender — NATs devices behind it (3D printer `.189` invisible to UniFi). | + +--- + +## Proxmox VE host — `nuc` + +| | Value | +|---|---| +| **IP** | `192.168.1.20` | +| **Admin UI** | `https://192.168.1.20:8006` (OIDC via Pocket-ID client `38469e7e`) | +| **SSH** | `ssh root@192.168.1.20` (key auth) | +| **Hardware** | Intel Core Ultra 7 155H · 22 threads · 64 GiB RAM · PVE 9.1.11 | +| **Storage** | `local-zfs` ~1.9 T (NVMe), `local` (dir), `unas` (NFS ~19 T) | +| **API token** | `root@pam!mcp` (PVEAuditor role, read-only) | + +--- + +## LXC / VM guests + +### VM 100 — `haos` (Home Assistant OS) + +| | Value | +|---|---| +| **IP** | `192.168.1.60` (DHCP, stable) | +| **HA UI** | `https://ha.nuclide.systems` → `192.168.1.60:8123` | +| **SSH** | `ssh root@192.168.1.60` (key installed manually in HA terminal) | +| **OCPP** | `https://ocpp.nuclide.systems` → `192.168.1.60:8887` | +| **HA-MCP add-on** | `http://192.168.1.60:9583/private_ehnWeRl2G3De6NnbcN7teQ` (gateway upstream, no TLS) | +| **Specs** | 4c / 16 GiB (balloon 4 GiB) / 32 GiB; USB Zigbee dongle passed through | + +### CT 101 — `shepard` + +| | Value | +|---|---| +| **IP** | `192.168.1.49` | +| **SSH** | `ssh root@192.168.1.49` | +| **Public** | `https://shepard.nuclide.systems` (Caddy → `:80`) · `https://shepard-api.nuclide.systems` (→ `:8080`) | +| **MCP** | `https://shepard.nuclide.systems/v2/mcp` (Bearer `${SHEPARD_API_KEY}`) | +| **Specs** | 12c / 32 GiB / 500 GiB + NFS; Intel iGPU (card+render) | +| **Stack** | Caddy, Shepard frontend/backend, Keycloak, Mongo, Neo4j, TimescaleDB | + +### CT 102 — `dns` (AdGuard Home) + +| | Value | +|---|---| +| **IP** | `192.168.1.2` | +| **SSH** | `ssh root@192.168.1.2` | +| **Admin UI** | `http://192.168.1.2` (port 80) | +| **DNS** | `192.168.1.2:53` — LAN resolver (UDM forwards all DNS here) | +| **Specs** | 2c / 1 GiB / 4 GiB | + +### CT 103 — `backrest` + +| | Value | +|---|---| +| **IP** | `192.168.1.3` | +| **SSH** | `ssh root@192.168.1.3` | +| **UI** | `http://192.168.1.3:9898` (LAN-only, no auth) | +| **Specs** | 1c / 512 MiB / 8 GiB + NFS (`/mnt/pve/unas`) | +| **Notes** | JottaCloud offsite via rclone; repos `services-repo` + `media-repo` | + +### CT 104 — `docker` (main Docker host) + +| | Value | +|---|---| +| **IP** | `192.168.1.40` | +| **SSH** | `ssh root@192.168.1.40` | +| **Specs** | 16c / 48 GiB / 200 GiB + NFS; Intel Arc iGPU (card+render) | +| **Role** | ~65 containers across ~23 compose stacks in `/opt/stacks/` | + +See [Docker services table](#docker-services--ct-104) below for all ports. + +### CT 105 — `nextcloud` + +| | Value | +|---|---| +| **IP** | `192.168.1.41` | +| **SSH** | `ssh root@192.168.1.41` | +| **Public** | `https://nc.nuclide.systems` → `192.168.1.41:11000` | +| **Specs** | 4c / 8 GiB / 100 GiB + NFS (migrated to NFSv3 2026-05-22) | +| **Auth** | Pocket-ID OIDC (client `a14b8076`) | + +### CT 108 — `zoraxy` (reverse proxy) + +| | Value | +|---|---| +| **IP** | `192.168.1.4` | +| **SSH** | `ssh root@192.168.1.4` | +| **Admin UI** | `http://192.168.1.4:8000` (LAN only) | +| **Specs** | 2c / 2 GiB / 6 GiB | +| **Cert** | Wildcard `*.nuclide.systems` (ACME via Let's Encrypt) | +| **Config** | `proxy/zoraxy/routes.json` → `scripts/zoraxy_sync.py --apply` | + +### CT 110 — `id` (Pocket-ID OIDC) + +| | Value | +|---|---| +| **IP** | `192.168.1.5` | +| **SSH** | `ssh root@192.168.1.5` | +| **Public** | `https://id.nuclide.systems` → `192.168.1.5:11000` | +| **Specs** | 1c / 1 GiB / 4 GiB | +| **OIDC endpoints** | Authorization: `https://id.nuclide.systems/authorize` · Token: `https://id.nuclide.systems/api/oidc/token` · Userinfo: `https://id.nuclide.systems/api/oidc/userinfo` · Discovery: `https://id.nuclide.systems/.well-known/openid-configuration` | + +### CT 111 — `dev` (Coder + Gitea) + +| | Value | +|---|---| +| **IP** | `192.168.1.42` | +| **SSH** | `ssh root@192.168.1.42` | +| **Specs** | 12c / 32 GiB / 60 GiB + NFS; Intel Arc iGPU (render) | + +| Port | Service | Public URL | +|---|---|---| +| 7080 | Coder | `https://dev.nuclide.systems` | +| 3000 | Gitea | `https://git.nuclide.systems` | +| 222 | Gitea SSH | `ssh -p 222 git@git.nuclide.systems` | +| 13080 | docs site | `http://192.168.1.42:13080` (LAN; mkdocs Material, auto-rebuild every 5 min) | +| internal | act-runner | — (`ct111-runner` Gitea Actions) | + +### CT 112 — `secrets` (Infisical) + +| | Value | +|---|---| +| **IP** | `192.168.1.7` | +| **SSH** | `ssh root@192.168.1.7` | +| **UI + API** | `http://192.168.1.7:8200` **(LAN-only — no Zoraxy route; must not be internet-exposed)** | +| **Specs** | 2c / 4 GiB / 20 GiB | +| **Stack** | `/opt/stacks/infisical/` — Infisical + Postgres 16 + Redis 7 (all internal, no external ports) | + +### CT 113 — `db` (shared Postgres) + +| | Value | +|---|---| +| **IP** | `192.168.1.6` | +| **SSH** | `ssh root@192.168.1.6` | +| **Specs** | 2c / 4 GiB / 40 GiB | + +| Port | Service | Access | +|---|---|---| +| 5432 | Postgres 17 | LAN: `192.168.1.6:5432` — tenants: LiteLLM, paperless, memos, n8n (reverted), Vaultwarden | +| 5050 | pgAdmin 4 | `http://192.168.1.6:5050` (LAN only, no Zoraxy route) | + +--- + +## Docker services — CT 104 + +All on `192.168.1.40` unless noted. Zoraxy (`192.168.1.4`) terminates TLS for public URLs. + +### Infrastructure (10000–10999) + +| Port | Container | Public URL | Notes | +|---|---|---|---| +| 10000 | `homepage` | — | Dashboard (LAN only) | +| 10001 | `dozzle` | `https://dozzle.nuclide.systems` | Log viewer | +| 10002 | `arcane` | `https://arcane.nuclide.systems` | Web IDE (OIDC `81cf4ed0`) | +| 10003 | `gotify` | `https://gotify.nuclide.systems` | Push notifications | +| 10004 | `garage` | `https://s3.nuclide.systems` | S3 API (Garage); internal: `http://garage:3900` | +| 10005 (localhost) | `garage` admin | — | Localhost only | + +### Security & Auth (11000–11999) + +| Port | Container | Public URL | Notes | +|---|---|---|---| +| 11001 | `vaultwarden` | `https://vault.nuclide.systems` | Password manager (OIDC client created, SSO not yet wired) | + +### Media — Immich (12000–12999) + +| Port | Container | Public URL | Notes | +|---|---|---|---| +| 12000 | `immich_server` | `https://immich.nuclide.systems` | Photos/videos (OIDC `9c91c18b`) | +| internal | `immich_power_tools` | `https://immich-tools.nuclide.systems` | Container-internal :3000, Zoraxy proxy | + +### Media — Downloads / Arr (13000–13999) + +All behind `vpn_gluetun` container network. + +| Port | Container | Public URL | Notes | +|---|---|---|---| +| 13001 | `rdtclient` | — | LAN only | +| 13002 | `prowlarr` | — | LAN only | +| 13003 | `audiobookshelf` | `https://abs.nuclide.systems` | OIDC `cbbf20d5` | +| 13004 | `shelfarr` | — | LAN only (OIDC `d8733fcc`) | +| 13005 | `flaresolverr` | — | Internal only | +| 30000 | `vpn_gluetun` | — | VPN HTTP control API | + +### AI Stack (14000–14999, 8080, 18xxx) + +| Port | Container | Public URL | Notes | +|---|---|---|---| +| 14000 | `litellm` | `https://ai.nuclide.systems` | LLM proxy; internal: `http://litellm:4000`; master key: `sk-tapirnase` | +| 14001 | `lobehub` | `https://chat.nuclide.systems` | Chat UI (OIDC `26f3c26b`) | +| 14002 | `qdrant_scientific` | — | Vector DB (LAN/internal only) | +| 8080 | `mcp-gateway` | `https://mcp.nuclide.systems` | MCP gateway (OIDC `e73bb7b9`); API key: `JxxCqKw32XoN4LOHunDikS6u1RpS7R5ythzaqADPuIA` | +| 18002 | `comfyui` | — | Image gen (Intel Arc); LAN only | +| 18003 | `comfyui-mcp` | via gateway `/comfyui/mcp` | FastMCP | +| 18005 | `docling-mcp` | via gateway `/docling/mcp` | PDF→Markdown | +| 18007 | `kroki-mcp` | via gateway `/kroki/mcp` | Diagram rendering | +| 18009 | `speaches` | — | TTS/STT; LAN only | +| 18011 | `upload-artifact-mcp` | via gateway `/upload-artifact/mcp` | S3 artifact upload | +| internal | `searxng` | — | `shared_backend`; used by LobeChat | + +### Documents (15000–15999) + +| Port | Container | Public URL | Notes | +|---|---|---|---| +| 15000 | `traccar` | `https://traccar.nuclide.systems` | GPS tracking UI | +| 15001 | `traccar` | — | TCP+UDP watch protocol (forwarded at UDM level) | +| 15002 | `paperless-ai` | `https://paperless-ai.nuclide.systems` | Internal-only Zoraxy policy | +| 15003 | `paperless-ngx-webserver-1` | `https://paperless.nuclide.systems` | Internal-only Zoraxy policy | + +### Automation (16000–16999) + +| Port | Container | Public URL | Notes | +|---|---|---|---| +| 16000 | `n8n` | `https://n8n.nuclide.systems` | Workflow automation (OIDC `33135ad4`); SQLite local disk | + +### Notes & Bookmarks (17000–17999) + +| Port | Container | Public URL | Notes | +|---|---|---|---| +| 17000 | `memos` | `https://memos.nuclide.systems` | Notes (OIDC `62bf4e0d`) | +| 17001 | `karakeep` | `https://hoarder.nuclide.systems` | Bookmarks (OIDC `d92f82b0`) | + +### Storage Admin (20000–20999) + +| Port | Container | Notes | +|---|---|---| +| 20010 (localhost) | `pgadmin` | shared-db pgAdmin, localhost only on CT 104 | + +--- + +## External hardware + +### QNAP UNAS Pro — NFS/SMB server + +| | Value | +|---|---| +| **IP** | `192.168.1.31` | +| **Admin UI** | `http://192.168.1.31` | +| **NFS export** | `192.168.1.31:/var/nfs/shared/storage` (NFSv3 only; v4 not available) | +| **CIFS** | `//192.168.1.31/storage` (used by Nextcloud CT 105 only) | + +### QNAP TS-251D — Klipper 3D printer host + +| | Value | +|---|---| +| **IP** | `192.168.1.189` (behind TP-Link RE700X at `.187`) | +| **Mainsail** | `http://192.168.1.189:80` | +| **Moonraker** | `http://192.168.1.189:7125` | +| **Notes** | Klipper config backed up daily to `git.nuclide.systems/fkrebs/klipper-config` via cron | + +--- + +## OIDC clients — Pocket-ID (`id.nuclide.systems`) + +| Client ID | Service | Redirect URI | +|---|---|---| +| `e73bb7b9` | litellm / mcp-gateway | (empty — accepts all) | +| `26f3c26b` | lobehub | `https://chat.nuclide.systems/api/auth/callback/generic-oidc` | +| `81cf4ed0` | arcane | `https://arcane.nuclide.systems/auth/oidc/callback` | +| `33135ad4` | n8n | `https://n8n.nuclide.systems/auth/oidc/callback` | +| `9c91c18b` | immich | `https://immich.nuclide.systems/auth/login` + mobile | +| `62bf4e0d` | memos | `https://memos.nuclide.systems/auth/callback` | +| `d92f82b0` | karakeep | `https://hoarder.nuclide.systems/api/auth/callback/custom` | +| `a14b8076` | nextcloud | `https://nc.nuclide.systems/apps/user_oidc/code` | +| `0aee4280` | Coder | `https://dev.nuclide.systems/api/v2/users/oidc/callback` | +| `9444609e` | Gitea | `https://git.nuclide.systems/user/oauth2/pocket-id/callback` | +| `38469e7e` | Proxmox VE | `https://192.168.1.20:8006` | +| `cbbf20d5` | Audiobookshelf | `https://abs.nuclide.systems/…` + `*` | +| `d8733fcc` | shelfarr | `*` | +| `78c78998` | Claude MCP | `https://claude.ai/api/mcp/auth_callback` + `https://mcp.nuclide.systems/mcp/auth/callback` | +| `82ca2d53` | nuc-ai (MCP spawned servers) | (empty) | +| `7fe1a14b` | zoraxy | (empty) | +| (new) | vaultwarden | `https://vault.nuclide.systems/auth/callback` — SSO not yet wired | +| ~~798a367f~~ | ~~daytona~~ | **DECOMMISSIONED — remove from Pocket-ID** | + +--- + +## Quick-reference — all public URLs + +| URL | Backend | Service | +|---|---|---| +| `https://ai.nuclide.systems` | `192.168.1.40:14000` | LiteLLM (LLM proxy) | +| `https://chat.nuclide.systems` | `192.168.1.40:14001` | LobeChat | +| `https://mcp.nuclide.systems` | `192.168.1.40:8080` | MCP gateway | +| `https://id.nuclide.systems` | `192.168.1.5:11000` | Pocket-ID (OIDC) | +| `https://nc.nuclide.systems` | `192.168.1.41:11000` | Nextcloud | +| `https://ha.nuclide.systems` | `192.168.1.60:8123` | Home Assistant | +| `https://ocpp.nuclide.systems` | `192.168.1.60:8887` | EV charger OCPP | +| `https://shepard.nuclide.systems` | `192.168.1.49:80` | Shepard | +| `https://shepard-api.nuclide.systems` | `192.168.1.49:8080` | Shepard API | +| `https://dev.nuclide.systems` | `192.168.1.42:7080` | Coder | +| `https://git.nuclide.systems` | `192.168.1.42:3000` | Gitea | +| `https://arcane.nuclide.systems` | `192.168.1.40:10002` | Arcane | +| `https://dozzle.nuclide.systems` | `192.168.1.40:10001` | Dozzle (logs) | +| `https://gotify.nuclide.systems` | `192.168.1.40:10003` | Gotify | +| `https://s3.nuclide.systems` | `192.168.1.40:10004` | Garage S3 | +| `https://vault.nuclide.systems` | `192.168.1.40:11001` | Vaultwarden | +| `https://immich.nuclide.systems` | `192.168.1.40:12000` | Immich | +| `https://immich-tools.nuclide.systems` | `192.168.1.40` (internal) | Immich Power Tools | +| `https://abs.nuclide.systems` | `192.168.1.40:13003` | Audiobookshelf | +| `https://n8n.nuclide.systems` | `192.168.1.40:16000` | n8n | +| `https://memos.nuclide.systems` | `192.168.1.40:17000` | Memos | +| `https://hoarder.nuclide.systems` | `192.168.1.40:17001` | Karakeep | +| `https://traccar.nuclide.systems` | `192.168.1.40:15000` | Traccar | +| `https://paperless.nuclide.systems` | `192.168.1.40:15003` | Paperless-ngx (internal-only policy) | +| `https://paperless-ai.nuclide.systems` | `192.168.1.40:15002` | Paperless AI (internal-only policy) | + +**Not publicly proxied** (LAN/localhost only): pgAdmin, ComfyUI, Qdrant, RDTClient, Prowlarr, ShelfArr, Flaresolverr, Speaches, AdGuard admin, Backrest UI, Infisical. + +--- + +## SSH cheat-sheet + +```bash +ssh root@192.168.1.20 # PVE host (nuc) +ssh root@192.168.1.40 # CT 104 docker +ssh root@192.168.1.41 # CT 105 nextcloud +ssh root@192.168.1.42 # CT 111 dev +ssh root@192.168.1.49 # CT 101 shepard +ssh root@192.168.1.2 # CT 102 dns (AdGuard) +ssh root@192.168.1.3 # CT 103 backrest +ssh root@192.168.1.4 # CT 108 zoraxy +ssh root@192.168.1.5 # CT 110 id (Pocket-ID) +ssh root@192.168.1.6 # CT 113 db (Postgres) +ssh root@192.168.1.7 # CT 112 secrets (Infisical) +ssh root@192.168.1.60 # VM 100 haos (Home Assistant — key must be installed manually) +ssh -p 222 git@git.nuclide.systems # Gitea SSH +``` + +All LXCs reachable from `nuc` host via root key. Use `pct exec -- bash` for console access without SSH. diff --git a/services/mcp-servers.md b/services/mcp-servers.md new file mode 100644 index 0000000..7d0710f --- /dev/null +++ b/services/mcp-servers.md @@ -0,0 +1,533 @@ +# MCP Servers — nuclide.systems + +Complete reference for all 27 MCP servers managed by the gateway at `https://mcp.nuclide.systems`. +**Last verified: 2026-05-23.** + +> Architecture doc: [`mcp-gateway.md`](mcp-gateway.md) · Config file: `/opt/stacks/ai/mcp-gateway/config.json` on CT 104 · Secrets: `/opt/stacks/ai/.env` + +--- + +## Overview + +| # | Server | Group | Kind | Gateway URL | Status | +|---|---|---|---|---|---| +| 1 | `context7` | dev | catalog | `https://mcp.nuclide.systems/context7/mcp` | ✓ | +| 2 | `fetch` | dev | spawn | `https://mcp.nuclide.systems/fetch/mcp` | ✓ | +| 3 | `git` | dev | catalog | `https://mcp.nuclide.systems/git/mcp` | ✓ | +| 4 | `gitlab` | dev | catalog | `https://mcp.nuclide.systems/gitlab/mcp` | ✓ | +| 5 | `kroki` | dev | static | `https://mcp.nuclide.systems/kroki/mcp` | ✓ | +| 6 | `markitdown` | dev | catalog | `https://mcp.nuclide.systems/markitdown/mcp` | ✓ | +| 7 | `sequential-thinking` | dev | catalog | `https://mcp.nuclide.systems/sequential-thinking/mcp` | ✓ | +| 8 | `time` | dev | spawn | `https://mcp.nuclide.systems/time/mcp` | ✓ | +| 9 | `docling` | dev | static | `https://mcp.nuclide.systems/docling/mcp` | ✓ | +| 10 | `coder` | dev | static | `https://mcp.nuclide.systems/coder/mcp` | ✓ | +| 11 | `shepard` | dev | static | `https://mcp.nuclide.systems/shepard/mcp` | ✓ | +| 12 | `crawl4ai` | research | spawn | `https://mcp.nuclide.systems/crawl4ai/mcp` | ✓ | +| 13 | `paper-search` | research | catalog | `https://mcp.nuclide.systems/paper-search/mcp` | ✓ | +| 14 | `searxng` | research | spawn | `https://mcp.nuclide.systems/searxng/mcp` | ✓ | +| 15 | `wikipedia-mcp` | research | catalog | `https://mcp.nuclide.systems/wikipedia-mcp/mcp` | ✓ | +| 16 | `youtube-transcript` | research | catalog | `https://mcp.nuclide.systems/youtube-transcript/mcp` | ✓ | +| 17 | `bluesky` | personal | static | `https://mcp.nuclide.systems/bluesky/mcp` | ✓ | +| 18 | `obsidian` | personal | spawn | `https://mcp.nuclide.systems/obsidian/mcp` | ✓ | +| 19 | `gotify` | personal | spawn | `https://mcp.nuclide.systems/gotify/mcp` | ✓ | +| 20 | `home-assistant` | personal | static | `https://mcp.nuclide.systems/home-assistant/mcp` | ✓ | +| 21 | `immich` | personal | spawn | `https://mcp.nuclide.systems/immich/mcp` | ✓ | +| 22 | `memos` | personal | spawn | `https://mcp.nuclide.systems/memos/mcp` | ✓ | +| 23 | `n8n` | personal | static | `https://mcp.nuclide.systems/n8n/mcp` | ✓ | +| 24 | `nextcloud` | personal | spawn | `https://mcp.nuclide.systems/nextcloud/mcp` | ✓ | +| 25 | `unifi` | personal | spawn | `https://mcp.nuclide.systems/unifi/mcp` | ✓ | +| 26 | `comfyui` | image | static | `https://mcp.nuclide.systems/comfyui/mcp` | ✓ | +| 27 | `upload-artifact` | storage | static | `https://mcp.nuclide.systems/upload-artifact/mcp` | ✓ | + +**Auth**: all gateway URLs require `Authorization: Bearer `. Get a config bundle at `https://mcp.nuclide.systems/mcp-config?format=claude`. + +**Gateway API key** (for `/api/*` management calls): `JxxCqKw32XoN4LOHunDikS6u1RpS7R5ythzaqADPuIA` + +--- + +## Group: `dev` + +### `context7` — Library documentation + +| | Value | +|---|---| +| **Kind** | catalog (`mcp/context7`) | +| **Internal upstream** | `http://mcp-context7:8000` | +| **Image** | `mcp-catalog-bridge` → Docker MCP Catalog `mcp/context7` | +| **Transport** | streamable-HTTP | +| **Resources** | 256 MiB mem limit | +| **Cache TTL** | 300 s | +| **Credentials** | none | +| **Notes** | Fetches live documentation for libraries/frameworks. No env vars. | + +--- + +### `fetch` — HTTP fetch + +| | Value | +|---|---| +| **Kind** | spawn | +| **Internal upstream** | `http://mcp-fetch:8000` | +| **Image** | `ghcr.io/astral-sh/uv:python3.12-trixie-slim` | +| **Command** | `uvx --with mcp-server-fetch mcp-proxy --stateless --host 0.0.0.0 --port 8000 -- python -m mcp_server_fetch` | +| **Transport** | streamable-HTTP | +| **Cache TTL** | 120 s | +| **Credentials** | none | + +--- + +### `git` — Git operations + +| | Value | +|---|---| +| **Kind** | catalog (`mcp/git`) | +| **Internal upstream** | `http://mcp-git:8000` | +| **Image** | `mcp-catalog-bridge` → Docker MCP Catalog `mcp/git` | +| **Transport** | streamable-HTTP | +| **Resources** | 256 MiB mem limit | +| **Credentials** | none | +| **Notes** | DinD child runs in `ai-internal` network. | + +--- + +### `gitlab` — GitLab (DLR) + +| | Value | +|---|---| +| **Kind** | catalog (`mcp/gitlab`) | +| **Internal upstream** | `http://mcp-gitlab:8000` | +| **Image** | `mcp-catalog-bridge` → Docker MCP Catalog `mcp/gitlab` | +| **Transport** | streamable-HTTP | +| **Resources** | 256 MiB mem limit | +| **Credentials** | | +| `GITLAB_PERSONAL_ACCESS_TOKEN` | `C8OXPT0J_oY-ha6KAzcn0286MQp1OjEyaAk.01.0z0jn01p4` | +| `GITLAB_API_URL` | `https://gitlab.dlr.de/api/v4` | +| **Notes** | Uses `--pass-environment` in bridge cmd so Docker CLI resolves `-e KEY` passthrough. Targets DLR GitLab, not gitlab.com. | + +--- + +### `kroki` — Diagram rendering + +| | Value | +|---|---| +| **Kind** | static | +| **Internal upstream** | `http://kroki-mcp:8000` (own stack, `:18007` on host) | +| **Transport** | streamable-HTTP | +| **Health check** | every 300 s | +| **Credentials** | none | +| **Notes** | Supports Mermaid, Excalidraw, and all Kroki-supported formats. | + +--- + +### `markitdown` — Markdown conversion + +| | Value | +|---|---| +| **Kind** | catalog (`mcp/markitdown`) | +| **Internal upstream** | `http://mcp-markitdown:8000` | +| **Image** | `mcp-catalog-bridge` → Docker MCP Catalog `mcp/markitdown` | +| **Transport** | streamable-HTTP | +| **Resources** | 256 MiB mem limit | +| **Credentials** | none | + +--- + +### `sequential-thinking` — Chain-of-thought reasoning + +| | Value | +|---|---| +| **Kind** | catalog (`mcp/sequentialthinking`) | +| **Internal upstream** | `http://mcp-sequential-thinking:8000` | +| **Image** | `mcp-catalog-bridge` → Docker MCP Catalog `mcp/sequentialthinking` | +| **Transport** | streamable-HTTP | +| **Resources** | 256 MiB mem limit | +| **Credentials** | none | + +--- + +### `time` — Time & timezone + +| | Value | +|---|---| +| **Kind** | spawn | +| **Internal upstream** | `http://mcp-time:8000` | +| **Image** | `ghcr.io/astral-sh/uv:python3.12-trixie-slim` | +| **Command** | `uvx --with mcp-server-time mcp-proxy --stateless --host 0.0.0.0 --port 8000 -- python -m mcp_server_time --local-timezone Europe/Berlin` | +| **Transport** | streamable-HTTP | +| **Credentials** | none | + +--- + +### `docling` — PDF → Markdown (SAIA) + +| | Value | +|---|---| +| **Kind** | static | +| **Internal upstream** | `http://docling-mcp:8000` (own stack, `:18005` on host) | +| **Transport** | streamable-HTTP | +| **Health check** | every 300 s | +| **Credentials** | none | +| **Notes** | SAIA-powered Docling; handles PDF, DOCX, images → Markdown. | + +--- + +### `coder` — Coder workspace management + +| | Value | +|---|---| +| **Kind** | static | +| **Internal upstream** | `http://coder-mcp:8000` (own stack on `ai-internal`) | +| **Transport** | streamable-HTTP | +| **Health check** | every 300 s | +| **Credentials** | Coder token baked into `coder-mcp` container env (see `/opt/stacks/ai/coder-mcp/`) | +| **Notes** | Replaced daytona 2026-05-20. Can create/start/stop Coder workspaces on CT 111. | + +--- + +### `shepard` — Shepard product platform + +| | Value | +|---|---| +| **Kind** | static (exact upstream) | +| **Upstream** | `https://shepard.nuclide.systems/v2/mcp` | +| **Transport** | streamable-HTTP | +| **Health check** | disabled | +| **Auth header** | `Authorization: Bearer ${SHEPARD_API_KEY}` | +| `SHEPARD_API_KEY` | `eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI3ZWVhZDk0Mi02M2E1LTRjZmMtYWVhOS1iMWQwZjBhMjkxZWEiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvIiwibmJmIjoxNzc5MzcyODQyLCJpYXQiOjE3NzkzNzI4NDIsImp0aSI6ImY5YzAyYjc3LTNkZGYtNGZjZS1hYzJlLTBlYmM5N2FlYjJhZiJ9.Z9LY9vwLm2l0TmORQ2GriCnkLPzZnSC9q2sE62Ab8Gpi_374Gd5MffDkute0xF2ZwbhH3aRSCpEd93HmFDs-1F3IwoFQpBGiLedTL0N3gC_6J-PFv_i54FHFImEiH_h0yJilzrfgR4Prn_hFZMniE080Kf3Ll-uvYnNK-U-AkPjqb8KfP1BA6dt3HjiOjpicdSh2URpzAKxyVwddGeve3Ha9LboPu-dOb8nmiwiW6E75eakNGGR2mwPxITDxVaqxuSipBwBiDIHzfU4iT7T7b8aipvGd1upfGlx7RcbHdGg9gVNR4jH_--5qLb5124MQxZ486dlH6i7w6AMqtdkzGA` | +| **Notes** | Native MCP endpoint on CT 101 Shepard stack (Keycloak + backend). | + +--- + +## Group: `research` + +### `crawl4ai` — Web crawling / scraping + +| | Value | +|---|---| +| **Kind** | spawn | +| **Internal upstream** | `http://mcp-crawl4ai:11235` | +| **Image** | `unclecode/crawl4ai:latest` | +| **Transport** | SSE (`/sse`) | +| **Resources** | 2 GiB mem limit; OOM score adj 300 | +| **Cache TTL** | 120 s | +| **Credentials** | none | + +--- + +### `paper-search` — Academic paper search + +| | Value | +|---|---| +| **Kind** | catalog (`mcp/paper-search`) | +| **Internal upstream** | `http://mcp-paper-search:8000` | +| **Image** | `mcp-catalog-bridge` → Docker MCP Catalog `mcp/paper-search` | +| **Transport** | streamable-HTTP | +| **Resources** | 256 MiB mem limit | +| **Cache TTL** | 300 s | +| **Credentials** | | +| `UNPAYWALL_EMAIL` | `fkrebs@nucli.de` | +| **Notes** | `--pass-environment` passthrough. Optional: `CORE_API_KEY`, `DOAJ_API_KEY` (not currently set). | + +--- + +### `searxng` — Web search (self-hosted) + +| | Value | +|---|---| +| **Kind** | spawn | +| **Internal upstream** | `http://mcp-searxng:8000` | +| **Image** | `isokoliuk/mcp-searxng:latest` | +| **Transport** | streamable-HTTP | +| **Credentials** | | +| `SEARXNG_URL` | `http://searxng:8080` (internal `shared_backend` network) | +| **Notes** | Routes to the self-hosted SearXNG instance. No external API keys needed. | + +--- + +### `wikipedia-mcp` — Wikipedia search + +| | Value | +|---|---| +| **Kind** | catalog (`mcp/wikipedia-mcp`) | +| **Internal upstream** | `http://mcp-wikipedia-mcp:8000` | +| **Image** | `mcp-catalog-bridge` → Docker MCP Catalog `mcp/wikipedia-mcp` | +| **Transport** | streamable-HTTP | +| **Resources** | 256 MiB mem limit | +| **Cache TTL** | 300 s | +| **Credentials** | none | + +--- + +### `youtube-transcript` — YouTube transcripts + +| | Value | +|---|---| +| **Kind** | catalog (`mcp/youtube-transcript`) | +| **Internal upstream** | `http://mcp-youtube-transcript:8000` | +| **Image** | `mcp-catalog-bridge` → Docker MCP Catalog `mcp/youtube-transcript` | +| **Transport** | streamable-HTTP | +| **Resources** | 256 MiB mem limit | +| **Cache TTL** | 300 s | +| **Credentials** | none | + +--- + +## Group: `personal` + +### `bluesky` — Bluesky / AT Protocol + +| | Value | +|---|---| +| **Kind** | static | +| **Internal upstream** | `http://ariel-mcp:8000` (own container on `ai-internal`) | +| **Transport** | streamable-HTTP | +| **Health check** | every 300 s | +| **Credentials** (baked into `ariel-mcp` env) | | +| `ATPROTO_IDENTIFIER` | `nucli.de` | +| `ATPROTO_PASSWORD` | `blxw-datl-l7zo-qwwq` | +| `BLUESKY_IDENTIFIER` | `nucli.de` | +| `BLUESKY_APP_PASSWORD` | `4mrm-go4j-avzg-2yo7` | +| **Notes** | Uses Brian Ellin's `ariel-mcp` image. Rate-limit handling pending. | + +--- + +### `obsidian` — Obsidian vault (Nextcloud-backed) + +| | Value | +|---|---| +| **Kind** | spawn | +| **Image** | `mcp-obsidian-bridge` + mcpvault | +| **Internal upstream** | `http://mcp-obsidian:8000` | +| **Transport** | streamable-HTTP | +| **Cache TTL** | 30 s | +| **Vault path** | Nextcloud `fkrebs@nucli.de/files/Notizen` (UNAS mount) | +| **Credentials** | inherits Nextcloud credentials from gateway env | +| **Notes** | Vault read/write against the Nextcloud-mounted Obsidian vault. | + +--- + +### `gotify` — Push notifications + +| | Value | +|---|---| +| **Kind** | spawn | +| **Internal upstream** | `http://mcp-gotify:8000` | +| **Image** | `kcofoni/gotify-mcp` | +| **Transport** | HTTP (`GOTIFY_MCP_TRANSPORT=http`) | +| **Cache TTL** | 0 (real-time) | +| **Credentials** | | +| `GOTIFY_URL` | `http://192.168.1.40:10003` | +| `GOTIFY_CLIENT_TOKEN` | `CwaslnnN-MTNRoC` | +| `GOTIFY_APP_TOKEN` | `AO84CFvU4XmoPBJ` | +| **Notes** | Can send and receive push notifications. App token = send; client token = receive. | + +--- + +### `home-assistant` — Home Assistant + +| | Value | +|---|---| +| **Kind** | static (exact upstream) | +| **Upstream** | `http://192.168.1.60:9583/private_ehnWeRl2G3De6NnbcN7teQ` | +| **Transport** | streamable-HTTP | +| **Health check** | disabled | +| **Cache TTL** | 15 s | +| **Credentials** | Token embedded in path (`/private_ehnWeRl2G3De6NnbcN7teQ`) — HA MCP add-on authentication | +| **Notes** | Direct to HA add-on on VM 100. ~2492 entities. `exact_upstream: true` so the path is forwarded verbatim. | + +--- + +### `immich` — Immich photo library + +| | Value | +|---|---| +| **Kind** | spawn | +| **Internal upstream** | `http://mcp-immich:8000` | +| **Image** | `ghcr.io/astral-sh/uv:python3.12-trixie-slim` | +| **Command** | `uvx --with immich-mcp` → uvicorn streamable-HTTP app | +| **Transport** | streamable-HTTP | +| **Credentials** | | +| `IMMICH_BASE_URL` | `http://192.168.1.40:12000` | +| `IMMICH_API_KEY` | `jhtAOjyCU1cXxBoj6gZGLfCjpv8TmcwaXqiex6f5po` | +| **Notes** | DNS rebinding protection disabled (TransportSecuritySettings). | + +--- + +### `memos` — Memos notes + +| | Value | +|---|---| +| **Kind** | spawn | +| **Internal upstream** | `http://mcp-memos:8000` | +| **Image** | `ghcr.io/astral-sh/uv:python3.12-trixie-slim` | +| **Command** | `uvx --with mcp-server-memos mcp-proxy --stateless ... -- mcp-server-memos --host 192.168.1.40 --port 17000 --token "$MEMOS_TOKEN"` | +| **Transport** | streamable-HTTP | +| **Cache TTL** | 0 (real-time) | +| **Credentials** | | +| `MEMOS_TOKEN` | `memos_pat_sOnvLytuaaVdEiqUSWubgfLut6AnoWb0` | +| **Health probe** | `search_memo` with keyword `__healthcheck__` | + +--- + +### `n8n` — n8n workflow automation + +| | Value | +|---|---| +| **Kind** | static (exact upstream) | +| **Upstream** | `https://n8n.nuclide.systems/mcp-server/http` | +| **Transport** | streamable-HTTP | +| **Health check** | disabled | +| **TLS** | `insecure_tls: true` (self-signed cert workaround) | +| **Auth header** | `Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI4YWY1YzgxMy1mODljLTRiODMtYmNmOC01ZDU5ODY0YTAzOGEiLCJpc3MiOiJuOG4iLCJhdWQiOiJtY3Atc2VydmVyLWFwaSIsImp0aSI6IjBmNjA1NDBmLTBmZmQtNGEwNS1iNjZlLTA2ZjU2YzZlNjY2MCIsImlhdCI6MTc3OTQ1NjAzN30.hf_Vg45R_hOJSY11H4GVAuvqWv39SitvtIXBXnorlXQ` | +| **Notes** | n8n MCP server; exposes configured workflows as tools. JWT `iat: 1779456037`. | + +--- + +### `nextcloud` — Nextcloud files & calendar + +| | Value | +|---|---| +| **Kind** | spawn | +| **Internal upstream** | `http://mcp-nextcloud:8000` | +| **Image** | `ghcr.io/cbcoutinho/nextcloud-mcp-server:latest` | +| **Transport** | streamable-HTTP | +| **Mode** | `MCP_DEPLOYMENT_MODE=single_user_basic` | +| **Health check** | disabled | +| **Credentials** | | +| `NEXTCLOUD_HOST` | `https://nc.nuclide.systems` | +| `NEXTCLOUD_USERNAME` | `fkrebs@nucli.de` | +| `NEXTCLOUD_PASSWORD` | `iRn4ECFf2dS24B9sFP3fkPosjrPVKZdaJBuwRpP9sVBnL6A7qN6lXNk2iK4yYblksc2ewzkb` | +| `NEXTCLOUD_VERIFY_SSL` | `false` | +| **Notes** | App-password generated via `occ` for `fkrebs@nucli.de` 2026-05-22. Re-enabled after fix. | + +--- + +### `unifi` — UniFi Network + +| | Value | +|---|---| +| **Kind** | spawn | +| **Internal upstream** | `http://mcp-unifi:8000` | +| **Image** | `ghcr.io/enuno/unifi-mcp-server:latest` | +| **Transport** | HTTP (`MCP_SERVER_TRANSPORT=http`) | +| **Cache TTL** | 15 s | +| **Credentials** | | +| `UNIFI_API_KEY` | `yeBrsK8l6h5LSBc8ocsdLeSkGnc9bsKY` | +| `UNIFI_API_TYPE` | `local` | +| `UNIFI_LOCAL_HOST` | `192.168.1.1` | +| `UNIFI_LOCAL_PORT` | `443` | +| `UNIFI_LOCAL_VERIFY_SSL` | `false` | +| **Notes** | 197 tools. Network App API key (local API). Site Manager/cloud tools need `UNIFI_SITE_MANAGER_ENABLED`. | + +--- + +## Group: `image` + +### `comfyui` — ComfyUI image generation + +| | Value | +|---|---| +| **Kind** | static | +| **Internal upstream** | `http://comfyui-mcp:8000` (own stack, `:18003` on host) | +| **Transport** | streamable-HTTP | +| **Health check** | every 300 s | +| **Credentials** | none (auth via gateway Bearer) | +| **Notes** | Intel Arc iGPU; FLUX.1-schnell GGUF. LobeChat can also connect directly to `http://comfyui-mcp:8000/mcp` on `ai-internal`. See [`comfyui.md`](comfyui.md). | + +--- + +## Group: `storage` + +### `upload-artifact` — S3 artifact upload + +| | Value | +|---|---| +| **Kind** | static | +| **Internal upstream** | `http://upload-artifact-mcp:8000` (own stack, `:18011` on host) | +| **Transport** | streamable-HTTP | +| **Health check** | every 300 s | +| **Credentials** | Garage S3 credentials baked into `upload-artifact-mcp` container env | +| **Notes** | Uploads chat artifacts (images, files) to Garage S3 at `s3.nuclide.systems`. | + +--- + +## Client configuration + +### Auto (recommended) + +``` +GET https://mcp.nuclide.systems/mcp-config?format=claude # Claude Code / Claude Desktop +GET https://mcp.nuclide.systems/mcp-config?format=cursor # Cursor +GET https://mcp.nuclide.systems/mcp-config?format=raw # raw token + URLs +``` + +Requires Pocket-ID session. Downloads a pre-built config with fresh long-lived token. Merge `mcpServers` block into `~/.claude/settings.json`. + +### Manual (Claude Code) + +```json +{ + "mcpServers": { + "": { + "type": "http", + "url": "https://mcp.nuclide.systems//mcp", + "headers": { + "Authorization": "Bearer JxxCqKw32XoN4LOHunDikS6u1RpS7R5ythzaqADPuIA" + } + } + } +} +``` + +--- + +## Gateway management API + +All calls require `Authorization: Bearer JxxCqKw32XoN4LOHunDikS6u1RpS7R5ythzaqADPuIA`. + +```bash +BASE=https://mcp.nuclide.systems +TOKEN=JxxCqKw32XoN4LOHunDikS6u1RpS7R5ythzaqADPuIA +H="Authorization: Bearer $TOKEN" + +# List all servers + status +curl -H "$H" $BASE/api/servers + +# Start / stop a server +curl -X POST -H "$H" $BASE/api/servers/memos/start +curl -X POST -H "$H" $BASE/api/servers/memos/stop + +# Create new server (persists to config.json) +curl -X POST -H "$H" -H "Content-Type: application/json" \ + -d '{"name":"myserver","static":true,"upstream":"http://host:port","group":"custom"}' \ + $BASE/api/servers + +# Delete server (stops container + removes from config.json) +curl -X DELETE -H "$H" $BASE/api/servers/myserver + +# Patch server config +curl -X PATCH -H "$H" -H "Content-Type: application/json" \ + -d '{"enabled":false}' \ + $BASE/api/servers/myserver + +# Health check +curl $BASE/health +``` + +--- + +## Other credentials in gateway `.env` + +These are available to spawned containers via `${VAR}` substitution in `config.json`: + +| Variable | Value | Used by | +|---|---|---| +| `GATEWAY_API_KEYS` | `JxxCqKw32XoN4LOHunDikS6u1RpS7R5ythzaqADPuIA` | All API/proxy calls to gateway | +| `LITELLM_MASTER_KEY` | `sk-tapirnase` | LiteLLM proxy (shared pw — rotate pending) | +| `LITELLM_API_KEY` | `sk-tapirnase` | same | +| `GITEA_TOKEN` | `c15e3348bf725054131633061002d677685cd4f4` | Gitea API access | +| `NEXTCLOUD_MCP_OAUTH_CLIENT_ID` | `82ca2d53-6df4-4671-875c-fee85b54b76f` | Pocket-ID client for MCP spawned servers | +| `NEXTCLOUD_MCP_OAUTH_CLIENT_SECRET` | `zOfHItEeKVa6Tf40RpnhihFmgnCDkkfz` | same | +| `SHEPARD_BASE_URL` | `https://shepard-api.nuclide.systems/shepard/api` | Shepard API | +| `GOTIFY_TOKEN_ALERTS` | `AtjFdduWArgAe7q` | Gotify — alert app token (gateway internal) | +| `GOTIFY_TOKEN_AGENTS` | `AB3dzfj5TUPCfYf` | Gotify — agent app token (gateway internal) |