No description
  • Python 99.4%
  • Shell 0.5%
  • Dockerfile 0.1%
Find a file
2026-07-20 16:34:20 +02:00
domains Add changes from Nicolas 2026-07-20 16:34:20 +02:00
examples Add changes from Nicolas 2026-07-20 16:34:20 +02:00
.gitignore EPRTR 2026-05-25 15:59:53 +02:00
build.sh Refactor 2026-05-23 16:30:25 +02:00
CLAUDE.md Add changes from Nicolas 2026-07-20 16:34:20 +02:00
deploy.sh EEA Air Quality MCP server 2026-07-17 15:53:54 +02:00
Dockerfile Refactor 2026-05-23 16:30:25 +02:00
LICENSE Add AGPLv3 license 2026-05-23 16:36:49 +02:00
README.md Add changes from Nicolas 2026-07-20 16:34:20 +02:00
requirements.txt EEA Air Quality MCP server 2026-07-17 15:53:54 +02:00
server.py Add changes from Nicolas 2026-07-20 16:34:20 +02:00
superset.py Fix Superset CSRF 2026-06-19 12:22:14 +02:00

mcp-peacedata — Server MCP per PeaceData

Server MCP FastMCP per PeaceData, l'istanza Apache Superset di PeaceLink su data.peacelink.it. Espone dataset strutturati come strumenti MCP per l'agente AI.

Ogni dominio è una sub-app FastMCP montata su un percorso separato — la webapp carica solo gli strumenti del dominio pertinente all'intent corrente.

Accesso al server MCP

Il server è disponibile pubblicamente su mcp-peacedata.peacelink.it. L'accesso è riservato agli utenti autorizzati da PeaceLink.

Come ottenere l'accesso

  1. Registrati su login.peacelink.it
  2. Invia una richiesta di accesso tramite il modulo di richiesta

L'accesso viene abilitato manualmente dall'amministratore.

Durata della sessione

I token hanno durata breve (default realm: 5 minuti) ma il client MCP li rinnova automaticamente tramite il refresh token (durata: 30 minuti). In condizioni normali il login non è mai richiesto nuovamente. Se la sessione rimane inattiva per più di 30 minuti, il client chiederà di autenticarsi di nuovo.

Per un'integrazione permanente senza re-login, il client MCP può richiedere lo scope offline_access durante il login iniziale. Keycloak rilascia un token offline che non scade per inattività e viene rinnovato automaticamente.

Configurare il client MCP

Una volta autorizzato, aggiungi il server nel tuo client MCP. Al primo utilizzo il client aprirà il browser per completare il login su Keycloak — non è necessario gestire token manualmente.

Endpoint disponibili:

Dominio URL
Trasferimenti armi (SIPRI) https://mcp-peacedata.peacelink.it/sipri
Campagne nonviolente (NAVCO) https://mcp-peacedata.peacelink.it/navco
Sistemi d'arma nucleari https://mcp-peacedata.peacelink.it/nuclear-weapons-dataset
Infrastrutture militari in Europa https://mcp-peacedata.peacelink.it/military-infra
Emissioni industriali EPRTR (Italia) https://mcp-peacedata.peacelink.it/eprtr
Spese militari globali 18162019 https://mcp-peacedata.peacelink.it/military-spending
Accordi di pace PA-X 19902025 https://mcp-peacedata.peacelink.it/peace-agreements
Conflitti armati ACLED 1996oggi https://mcp-peacedata.peacelink.it/acled
Qualità dell'aria ARPA Puglia — rete ADI Taranto https://mcp-peacedata.peacelink.it/arpa-taranto
Qualità dell'aria EEA — storico orario, stazioni pubbliche https://mcp-peacedata.peacelink.it/eea-air-quality
Qualità dell'aria ISPRA — ultime ore, stazioni pubbliche https://mcp-peacedata.peacelink.it/ispra-air-quality

Esempi di integrazione

La directory examples/ contiene due script Python autonomi per integrare PeaceData MCP nella tua applicazione o per esplorare i dati da riga di comando.

Dipendenze

pip install httpx mcp

1. Autenticazione (examples/authenticate.py)

Esegui questo script una volta sola per ottenere e memorizzare il token Keycloak. Il token viene salvato in ~/.config/peacedata/tokens.json (permessi 600) e rinnovato automaticamente da client.py.

# Login standard (token di breve durata, rinnovato automaticamente)
python examples/authenticate.py

# Token offline (non scade per inattività — consigliato per script non interattivi)
python examples/authenticate.py --offline

Il browser si apre automaticamente per il login su Keycloak. Al termine, lo script stampa l'access token corrente.

2. Client MCP (examples/client.py)

# Elenca i server disponibili
python examples/client.py servers

# Elenca gli strumenti di un server (con descrizione e parametri)
python examples/client.py tools sipri
python examples/client.py tools acled

# Chiama uno strumento con argomenti JSON
python examples/client.py call sipri get_arms_transfers \
    --args '{"supplier": "Italy"}'

python examples/client.py call sipri get_top_suppliers \
    --args '{"year_from": 2010, "year_to": 2024, "top_n": 10}'

# Usa un token esplicito invece della cache locale
python examples/client.py --token <token> tools navco

Il token viene rinnovato automaticamente se scaduto (purché il refresh token sia ancora valido). Se la sessione è scaduta, esegui nuovamente authenticate.py.


Struttura

_shared/
  superset.py        Client Superset async riutilizzabile (auth JWT, auto-refresh)
peacedata/
  server.py          App Starlette — monta tutte le sub-app dei domini
  domains/
    sipri.py             Trasferimenti armi SIPRI → /sipri
    navco.py             Campagne nonviolente NAVCO → /navco
    nuclear.py           Dataset sistemi d'arma nucleari CSR → /nuclear-weapons-dataset
    military_infra.py    Infrastrutture militari → /military-infra
    eprtr.py             Emissioni industriali EPRTR → /eprtr
    military_spending.py Spese militari globali → /military-spending
    peace_agreements.py  Accordi di pace PA-X → /peace-agreements
    acled.py             Conflitti ACLED → /acled
    arpa_taranto.py      Qualità dell'aria ARPA Puglia — rete ADI → /arpa-taranto
  Dockerfile
  requirements.txt

Domini esposti

Dominio Percorso Dati
ARMI /sipri Trasferimenti di armi SIPRI (1950presente)
CAMPAGNE /navco Campagne nonviolente NAVCO
NUCLEARE /nuclear-weapons-dataset Sistemi d'arma nucleari CSR — P5, 1945presente
INFRASTRUTTURE /military-infra Infrastrutture militari in Europa
INQUINAMENTO /eprtr Emissioni industriali EPRTR — Italia
SPESE MILITARI /military-spending Spese militari globali 18162019
ACCORDI DI PACE /peace-agreements Accordi di pace PA-X 19902025
CONFLITTI /acled Conflitti armati ACLED 1996oggi
ARIA TARANTO /arpa-taranto Qualità dell'aria ARPA Puglia — rete ADI Taranto (dati live)
ARIA EEA /eea-air-quality Qualità dell'aria EEA — storico orario, stazioni pubbliche, 38 paesi
ARIA ISPRA /ispra-air-quality Qualità dell'aria ISPRA InfoARIA — ultime ore, finestra mobile ~8 giorni

Avvio locale

cd peacedata
pip install -r requirements.txt

export SUPERSET_URL=https://data.peacelink.it
export SUPERSET_USER=...
export SUPERSET_PASSWORD=...
export SIPRI_DATABASE_ID=...
export NAVCO_DATABASE_ID=...
export NUCLEAR_DATABASE_ID=...

python server.py
# Server su :8001
# Health check: GET http://localhost:8001/health

Variabili d'ambiente

Variabile Note
SUPERSET_URL URL base Superset (default: https://data.peacelink.it)
SUPERSET_USER Username Superset
SUPERSET_PASSWORD Password Superset
SIPRI_DATABASE_ID ID database Superset per i dati SIPRI
NAVCO_DATABASE_ID ID database Superset per i dati NAVCO
NUCLEAR_DATABASE_ID ID database Superset per i dati nucleari

Gli ID si trovano in Superset → Settings → Databases.

Accesso pubblico (Keycloak)

Il server è esposto pubblicamente su mcp-peacedata.peacelink.it con autenticazione Bearer token via Keycloak. L'accesso interno dalla webapp (pck-ai-mcp-peacedata-svc via DNS cluster) rimane invariato e senza autenticazione.

Internet → Traefik ingress → ForwardAuth (oauth2-proxy) → pck-ai-mcp-peacedata-svc
Webapp   → pck-ai-mcp-peacedata-svc (DNS interno, nessun ingress)   ← invariato

Configurazione Keycloak

Realm peacelink su login.peacelink.it:

  • Registrazione self-service: Realm Settings → Login → User registration: ON
  • Realm role: mcp-peacedata-access — assegnato manualmente dall'admin agli utenti autorizzati
  • Client mcp-peacedata:
    • Client authentication: OFF (client pubblico — i client MCP sono app desktop/CLI che non possono custodire un secret)
    • Standard Flow: ON, Direct Access Grants: OFF, Service accounts: OFF
    • PKCE: Advanced → Proof Key for Code Exchange → S256 (obbligatorio)
    • Valid redirect URIs: http://localhost:* e http://127.0.0.1:* (i client MCP aprono un server HTTP locale su porta casuale per ricevere il callback)
  • Client scope mcp-peacedata-dedicated → mapper Audience: Included client audience = mcp-peacedata
  • Scope roles (default): include automaticamente realm_access.roles nel token — nessun mapper aggiuntivo necessario
  • Authentication flow mcp-peacedata-browser (duplicato da browser):
    • Sub-flow Role check (Generic, Conditional):
      • Condition - User Role (Required): alias require-mcp-peacedata-access, role mcp-peacedata-access, Negate: ON
      • Deny Access (Required)
    • Associato al client: Advanced → Authentication flow overrides → Browser Flow → mcp-peacedata-browser
    • Gli utenti senza il ruolo ricevono un errore al login e non ottengono mai un token
    • Il flow è associato solo a questo client — tutti gli altri client usano il browser flow di default

Nota: il role check agisce solo sul browser flow (PKCE). Il Direct Access Grants è disabilitato proprio perché bypasserebbe questo controllo.

Manifesti Kubernetes

In pck3s/ai/mcp-servers/peacedata/:

File Contenuto
mcp-auth-deployment.yaml Deployment oauth2-proxy (ForwardAuth) + Service
mcp-auth-middleware.yaml Middleware Traefik ForwardAuth
public-ingress.yaml Ingress pubblico mcp-peacedata.peacelink.it

Secret richiesto (una tantum):

kubectl create secret generic pck-ai-mcp-peacedata -n ai \
  --from-literal=cookie-secret=$(openssl rand -hex 16)

OAUTH2_PROXY_CLIENT_SECRET è impostato a unused direttamente nel deployment — oauth2-proxy lo richiede per avviarsi ma Keycloak lo ignora per i client pubblici.

Flusso di autenticazione

Utente si registra su login.peacelink.it
       ↓
Admin assegna il ruolo `mcp-peacedata-access` nella console Keycloak
       ↓
Utente apre il proprio client MCP (Claude Desktop, ecc.)
       ↓
Client → Keycloak: Authorization Code + PKCE login
Keycloak verifica il ruolo → emette access token di breve durata (~5 min)
       ↓
Client invia: Authorization: Bearer <token>
       ↓
Traefik → ForwardAuth → oauth2-proxy valida JWT (firma, issuer, audience, scadenza)
       ↓
200 OK → Traefik inoltra a pck-ai-mcp-peacedata-svc

Aggiungere un nuovo utente

  1. L'utente si registra autonomamente su login.peacelink.it
  2. Admin: Users → seleziona utente → Role mapping → Assign role → mcp-peacedata-access

L'utente può ora autenticarsi tramite il proprio client MCP (Authorization Code + PKCE).

Revocare l'accesso

Rimuovere il ruolo mcp-peacedata-access dall'utente in Keycloak. Il token corrente resta valido fino alla scadenza (~5 min). Per revoca immediata: Sessions → seleziona sessione → Logout nella console Keycloak.


Aggiungere un nuovo dominio

Vedere CLAUDE.md per la guida completa allo sviluppo.

In sintesi:

  1. Creare peacedata/domains/<nome>.py con una sub-app FastMCP
  2. Montare il dominio in peacedata/server.py
  3. Registrare il nuovo intent e profilo nel DB del repo assistant (webapp UI o postgres/10-intents.sql)
  4. Aggiungere la variabile d'ambiente a .env.example