- Python 99.4%
- Shell 0.5%
- Dockerfile 0.1%
| domains | ||
| examples | ||
| .gitignore | ||
| build.sh | ||
| CLAUDE.md | ||
| deploy.sh | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
| requirements.txt | ||
| server.py | ||
| superset.py | ||
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
- Registrati su login.peacelink.it
- 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 1816–2019 | https://mcp-peacedata.peacelink.it/military-spending |
| Accordi di pace PA-X 1990–2025 | https://mcp-peacedata.peacelink.it/peace-agreements |
| Conflitti armati ACLED 1996–oggi | 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 (1950–presente) |
| CAMPAGNE | /navco |
Campagne nonviolente NAVCO |
| NUCLEARE | /nuclear-weapons-dataset |
Sistemi d'arma nucleari CSR — P5, 1945–presente |
| INFRASTRUTTURE | /military-infra |
Infrastrutture militari in Europa |
| INQUINAMENTO | /eprtr |
Emissioni industriali EPRTR — Italia |
| SPESE MILITARI | /military-spending |
Spese militari globali 1816–2019 |
| ACCORDI DI PACE | /peace-agreements |
Accordi di pace PA-X 1990–2025 |
| CONFLITTI | /acled |
Conflitti armati ACLED 1996–oggi |
| 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:*ehttp://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 automaticamenterealm_access.rolesnel token — nessun mapper aggiuntivo necessario - Authentication flow
mcp-peacedata-browser(duplicato dabrowser):- Sub-flow
Role check(Generic, Conditional):Condition - User Role(Required): aliasrequire-mcp-peacedata-access, rolemcp-peacedata-access, Negate: ONDeny 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
- Sub-flow
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 aunuseddirettamente 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
- L'utente si registra autonomamente su
login.peacelink.it - 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:
- Creare
peacedata/domains/<nome>.pycon una sub-app FastMCP - Montare il dominio in
peacedata/server.py - Registrare il nuovo intent e profilo nel DB del repo
assistant(webapp UI opostgres/10-intents.sql) - Aggiungere la variabile d'ambiente a
.env.example