Backup automatico script del 2026-08-23 12:04

This commit is contained in:
daniele committed 2026-08-23 12:04:16 +02:00
1 parent 11823447a2
commit 795a15a7b6
66 files changed
+8546

No files matched your search

+297
View File
@@ -0,0 +1,297 @@
# Loogle MCP Hub — Architettura e parametri
Documento di riferimento per la piattaforma MCP domestica LOOGLE.IT.
Ultimo aggiornamento: 2026-08-22
---
## Scopo
**Loogle MCP Hub** espone agli assistenti AI (Claude, ChatGPT, Gemini, Cursor) due capacità principali:
1. **Archivio contesto** — memoria persistente per progetti e task, isolata per utente
2. **Knowledge base RAG** — ricerca semantica su documenti Paperless e sui contesti salvati
Tutti i dati restano in LAN/NAS; laccesso esterno avviene solo via HTTPS + OAuth.
---
## Architettura logica
```
┌─────────────────────────────────────────────────────────────┐
│ Client AI (ChatGPT / Claude / Gemini / Cursor) │
└───────────────────────────┬─────────────────────────────────┘
│ HTTPS + OAuth Bearer
┌─────────────────────────────────────────────────────────────┐
│ NPM VIP 192.168.128.85 → mcp.loogle.it:443 │
└───────────────────────────┬─────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Pi-1 :8700 loogle-mcp (FastAPI) │
│ ├── /mcp JSON-RPC MCP │
│ ├── /oauth/* OAuth 2.1 PKCE │
│ └── /dashboard UI famiglia │
│ Pi-1 :8700 loogle-mcp-indexer (worker Paperless→vector) │
└───────┬─────────────────────────────┬───────────────────────┘
│ │
▼ ▼
┌───────────────┐ ┌─────────────────────┐
│ SQLite │ │ Vector store │
│ /data/*.db │ │ Qdrant DS920 :6333 │
│ utenti OAuth │ │ o fallback SQLite │
└───────────────┘ └─────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ NFS /mnt/ha-apps/mcp/context/{utente}/projects/... │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Paperless docs.loogle.it (sorgente documenti + OCR) │
└─────────────────────────────────────────────────────────────┘
```
---
## Componenti e percorsi
| Componente | Host | Porta | Percorso / container |
|------------|------|-------|----------------------|
| MCP Gateway | Pi-1 | 8700 | `loogle-mcp` |
| Indexer | Pi-1 | — | `loogle-mcp-indexer` |
| Qdrant (primario) | DS920 | 6333 | opzionale, compose extrema |
| Vector fallback | Pi-1 | — | `/data/vector_fallback.db` |
| Context NFS | NAS | — | `/mnt/ha-apps/mcp/context/` |
| DB SQLite | Pi-1 | — | `/home/daniely/docker/loogle-mcp/data/loogle_mcp.db` |
| Compose locale | Pi-1 | — | `/home/daniely/docker/loogle-mcp/` |
| Compose failover | Pi-1/Pi-2 | — | `/home/daniely/rete/compose/failover/loogle-mcp-compose.yml` |
| Runbook | — | — | `/home/daniely/rete/ha/RUNBOOK-mcp.md` |
---
## URL e endpoint
| Servizio | URL |
|----------|-----|
| MCP (client AI) | `https://mcp.loogle.it/mcp` |
| Dashboard web | `https://mcp.loogle.it/dashboard` |
| Health | `https://mcp.loogle.it/health` |
| OAuth authorize | `https://mcp.loogle.it/oauth/authorize` |
| OAuth token | `https://mcp.loogle.it/oauth/token` |
| Metadata OAuth | `https://mcp.loogle.it/.well-known/oauth-authorization-server` |
| Metadata risorsa MCP | `https://mcp.loogle.it/.well-known/oauth-protected-resource` |
---
## DNS
| Record | Tipo | Valore | Dove configurato |
|--------|------|--------|------------------|
| `mcp.loogle.it` | A | `192.168.128.85` (VIP NPM) | Pi-hole `/etc/pihole/pihole.toml` → hosts |
| Risoluzione LAN | — | Pi-hole → Unbound → split-horizon | Come `docs.loogle.it`, `pass.loogle.it` |
**Script setup:** `/home/daniely/rete/scripts/setup-mcp-dns-npm.sh`
**Verifica:**
```bash
dig +short mcp.loogle.it @127.0.0.1 # → 192.168.128.85
curl -sf https://mcp.loogle.it/health
```
---
## NPM (reverse proxy)
| Parametro | Valore |
|-----------|--------|
| Proxy host ID | 30 |
| Dominio | `mcp.loogle.it` |
| Upstream normale | `192.168.128.80:8700` |
| Certificato TLS | `npm-65` (Let's Encrypt) |
| Failover route | `rete/ha/npm-routes.conf` riga `30\|mcp.loogle.it\|8700\|...` |
| Websocket | ON |
| Force SSL | ON |
**Failover:** `npm-failover-route.sh` aggiorna upstream su Pi-2 / DS920 in base allo scenario HA.
---
## Variabili d'ambiente (`.env`)
File: `/home/daniely/docker/loogle-mcp/.env`
| Variabile | Descrizione | Esempio |
|-----------|-------------|---------|
| `MCP_BASE_URL` | URL pubblico (issuer JWT) | `https://mcp.loogle.it` |
| `MCP_JWT_SECRET` | Segreto firma token OAuth | *(stringa lunga casuale)* |
| `MCP_OAUTH_CLIENT_ID` | Client OAuth pre-registrato | `loogle-mcp-public` |
| `PAPERLESS_URL` | API documenti | `https://docs.loogle.it` |
| `PAPERLESS_API_TOKEN` | Token API admin (fallback) | vedi [PAPERLESS-TOKEN.md](PAPERLESS-TOKEN.md) |
| `PAPERLESS_API_TOKEN_{USER}` | Token API per utente | `DANIELE`, `LUCIA`, `DAVIDE`, `LUCA` |
| `QDRANT_URL` | Vector DB remoto | `http://192.168.128.100:6333` |
| `OLLAMA_URL` | Embedding locale | `http://192.168.128.100:11434` |
| `OLLAMA_EMBED_MODEL` | Modello embedding | `nomic-embed-text` |
| `OPENAI_API_KEY` | Fallback embedding cloud | *(opzionale)* |
| `INDEXER_INTERVAL_MINUTES` | Intervallo sync Paperless | `30` |
| `THERMAL_TEMP_HARD_C` | Pausa embedding se CPU DS920 ≥ °C | `70` |
| `THERMAL_TEMP_SOFT_C` | Rallenta embedding sopra °C | `58` |
| `THERMAL_CPU_TARGET_PCT` | Cap load1 (nproc × %) | `40` |
| `OLLAMA_NUM_THREAD` | Thread CPU per richiesta embed | `1` |
| `OLLAMA_EMBED_DELAY_S` | Pausa tra embed (duty-cycle lento) | `10` |
| `DS920_THERMAL_URL` | Probe temp/load DS920 | `http://192.168.128.100:9191/thermal` |
---
## Utenti e isolamento
| Persona | Username | Ruolo | Password iniziale |
|---------|----------|-------|-------------------|
| Daniele | `daniele` | admin | `daniele` *(cambiarla)* |
| Lucia | `lucia` | user | `lucia` |
| Davide | `davide` | user | `davide` |
| Luca | `luca` | user | `luca` |
- Ogni utente vede **solo** i propri progetti in `/mnt/ha-apps/mcp/context/{username}/`
- I token OAuth JWT contengono `sub` = username; ogni tool filtra per utente
- Ladmin può `reindex_document`, vedere audit completo, revocare refresh token
**Scope OAuth:** `context:read`, `context:write`, `knowledge:read`, `knowledge:write`, `gitea:read`, `gitea:write`, `home:read`, `irrigation:read`, `turni:read`, `admin` (solo daniele)
---
## Tool MCP esposti
| Tool | Scope minimo | Funzione |
|------|--------------|----------|
| `ping` | — | Test connettività |
| `whoami` | — | Utente e scope attivi |
| `list_projects` | context:read | Elenco progetti |
| `create_project` | context:write | Nuovo progetto |
| `get_project_context` | context:read | Legge memoria progetto |
| `save_context` | context:write | Salva/appende memoria |
| `archive_project` | context:write | Archivia progetto |
| `search_context` | context:read | Ricerca semantica contesti |
| `search_knowledge` | knowledge:read | RAG Paperless + contesti + Gitea + app |
| `search_gitea_knowledge` | knowledge:read | RAG solo Gitea |
| `search_apps_knowledge` | knowledge:read | RAG Irrigazione + Turni |
| `list_apps_indexed` | knowledge:read | Stato indicizzazione app |
| `reindex_apps` | admin | Re-sync RAG app |
| `get_document` | knowledge:read | Testo documento Paperless |
| `list_recent_documents` | knowledge:read | Ultimi doc indicizzati |
| `reindex_document` | admin | Re-indicizza documento |
| `get_home_dashboard` | home:read | Dashboard Loogle Casa |
| `get_home_weather` | home:read | Meteo casa |
| `get_network_overview` | home:read | Panoramica rete LAN |
| `get_network_failover_status` | home:read | Stato failover cluster |
| `get_ha_entity` | home:read | Entità Home Assistant |
| `list_ha_entities` | home:read | Elenco entità HA |
| `search_ha_entities` | home:read | Cerca entità HA |
| `get_irrigation_status` | irrigation:read | Stato irrigazione |
| `get_irrigation_zones` | irrigation:read | Zone irrigazione |
| `get_irrigation_history` | irrigation:read | Storico irrigazioni |
| `get_turni_status` | — | Stato servizio Turni |
| `get_my_shifts` | turni:read | Turni utente corrente |
| `list_turni_doctors` | turni:read | Medici Turni-Live |
Vedi anche tool Gitea in `docs/GITEA-TOKEN.md` e app homelab in `docs/APPS-INTEGRATION.md`.
---
## Storage contesto (per progetto)
```
/mnt/ha-apps/mcp/context/{username}/projects/{project-id}/
meta.json # titolo, tag, date, stato, gitea_repo (opz.)
context.md # memoria persistente
sessions/ # snapshot conversazioni
artifacts/ # file generati dagli agenti
```
---
## Vector store / RAG
| Collection Qdrant | Contenuto |
|-------------------|-----------|
| `kb_shared_family` | Documenti famiglia (tag non personali) |
| `kb_personal_{user}` | Documenti personali |
| `ctx_{user}` | Embedding dei contesti agente |
| `gitea_shared_family` | File testo da repo Gitea non privati |
| `gitea_personal_{user}` | File testo da repo Gitea privati dell'owner |
| `apps_shared_family` | Export Irrigazione + Turni (P7) |
**Nota Pi 5:** Qdrant locale su ARM (page size 16K) non è supportato. Default: Qdrant su DS920 o fallback SQLite in `/data/vector_fallback.db`.
**Pipeline indexer:** ogni 30 min:
1. Paperless → chunk → embedding (Ollama DS920) → upsert `kb_*`
2. Gitea (repo configurati in `GITEA_INDEX_REPOS_*`) → file `.md`/`.py`/`.sh` → chunk → upsert `gitea_*`
3. Irrigazione + Turni → snapshot/storico → upsert `apps_shared_family` (vedi `docs/APPS-INTEGRATION.md`)
---
## Sicurezza
- TLS terminato su NPM (Let's Encrypt)
- OAuth 2.1 Authorization Code + PKCE
- JWT access token 1h + refresh token 30 giorni (revocabili)
- Audit log: `{timestamp, user, tool, resource_id}` in SQLite
- CrowdSec attivo su NPM
- Nessun accesso cross-user ai dati
---
## Operazioni comuni
```bash
# Stato servizi
cd /home/daniely/docker/loogle-mcp && docker compose ps
# Log
docker logs -f loogle-mcp
docker logs -f loogle-mcp-indexer
# Redeploy
./scripts/deploy.sh
# DNS + NPM (se reinstall)
sudo /home/daniely/rete/scripts/setup-mcp-dns-npm.sh
# Failover route
/home/daniely/rete/scripts/npm-failover-route.sh normal
# Backup dati MCP
/home/daniely/rete/infra-monitor/mcp-restic-backup.sh
```
---
## Failover (tier-b)
| Scenario | Comportamento |
|----------|---------------|
| Pi-1 down, Pi-2 up | Stack MCP su Pi-2, NPM upstream → `.81:8700` |
| Extrema DS920 | NPM3 + upstream DS920 |
| Monitoraggio | Probe `mcp_ok` in `failover-status.sh` |
---
## Da completare (post-install)
1. **`PAPERLESS_API_TOKEN_*`** in `.env` — vedi [PAPERLESS-TOKEN.md](PAPERLESS-TOKEN.md)
2. **Ollama su DS920** con `nomic-embed-text` per embedding locali
3. **Qdrant su DS920** (opzionale): `rete/compose/extrema-ds920/loogle-mcp-compose.yml`
4. **Cambio password** per tutti gli utenti dal dashboard
5. **`MCP_JWT_SECRET`** — impostare valore robusto in produzione
---
## Riferimenti
- [Guida utenti famiglia](docs/GUIDA-UTENTI.md)
- [Onboarding tecnico client AI](docs/ONBOARDING.md)
- [Runbook operativo](/home/daniely/rete/ha/RUNBOOK-mcp.md)
- [README progetto](README.md)