| name | italian-parliament-cli |
| description | Query Italian Parliament open data from the command line (italianparliament CLI). Use when the user wants to run shell pipelines, export CSV/JSONL, or script analysis over deputies, senators, bills, votes, speeches, and groups. |
| compatibility | Requires the @aborruso/italianparliament-mcp npm package installed globally (provides the `italianparliament` command) |
| metadata | {"author":"aborruso","version":"1.4"} |
Italian Parliament CLI Skill
Use the italianparliament CLI to query Camera dei Deputati and Senato della Repubblica open data from the shell.
Installation
npm install -g @aborruso/italianparliament-mcp
Discovery (orchestration)
italianparliament guide
italianparliament which "testo ddl"
italianparliament <command> --help
General syntax
italianparliament <resource> <action> [--option value ...]
Default output: CSV (for spreadsheets, duckdb, mlr). Add --format jsonl for jq/streaming.
Default legislature
Current legislature is 19. Most commands default to 19 when --legislature is omitted.
Command reference
See full command reference.
Common patterns
Count deputies in a legislature
italianparliament deputies list --legislature 19 --format csv | wc -l
Export all bills as CSV
italianparliament bills list --legislature 19 --format csv > bills-19.csv
Find an MP by name
italianparliament search find --name meloni
Top 20 MPs by interrogations (AIC)
italianparliament rank list --rank-by aic-primo-firmatario --legislature 19 --limit 20
Who voted against in a vote
italianparliament vote-detail show --vote-uri <vote-uri> --format jsonl | \
jq 'select(.vote=="Contrario")'
Dissidenti, e altri obiettivi giornalistici derivabili senza tool dedicato
Vedi obiettivi giornalistici: ricette pronte (es. i "ribelli" che votano contro la linea di gruppo) combinando i tool esistenti.
A person's full career (legislatures + government)
italianparliament person-career show --uri http://dati.camera.it/ocd/deputato.rdf/d302103_19
Government members filtered by name
italianparliament gov-members list --name draghi
Group ranking by AIC, also per member
italianparliament group-rank list --rank-by aic --legislature 19
Nota: members in group-rank è il numero di iscritti attuali al gruppo (iscrizioni senza data di fine), stesso valore qualunque sia --rank-by. Non è il totale storico di chi è mai passato dal gruppo in quella legislatura (che include anche chi l'ha lasciato) — per quello serve group-members senza filtrare su end_date. Su un gruppo sciolto prima della fine della legislatura può risultare vuoto: nessuna sua iscrizione è rimasta "aperta", quindi il dato non è calcolabile e non viene forzato a zero.
Iter completo di una legge (Camera → Senato → pubblicazione)
Non generare la timeline a memoria: costruiscila dai tool, passo per passo. bill-progress è la spina dorsale.
italianparliament bills list --keyword "salario giusto" --legislature 19
italianparliament bill-progress list --uri http://dati.camera.it/ocd/attocamera.rdf/ac19_2911
italianparliament bill-progress list --number 1933 --branch S --legislature 19
italianparliament senato-votes list --ddl-uri http://dati.senato.it/ddl/60201
italianparliament bill-text links --uri http://dati.camera.it/ocd/attocamera.rdf/ac19_2911
italianparliament bill-text fetch --did 60201 --out testo.md
Voti Camera di un provvedimento: parti da votes list --bill-code <numero atto>, non da --keyword né dalle date. Prende il voto finale, la fiducia, gli ordini del giorno e i voti sugli emendamenti che il grafo collega all'atto — cose che la ricerca per parola chiave manca sistematicamente, perché la descrizione di una votazione spesso è solo un codice (EM 1.1077).
Tre cose da sapere:
- È il numero dell'atto Camera, non quello del decreto-legge né della legge: il DL 100/2026 è il C.3053, e
--bill-code 100 dà (correttamente) zero righe. Risali prima all'atto con bills list --keyword …. Il numero base include le varianti: 2790 copre anche il 2790-bis.
- Un vuoto non significa "non si è votato": la CLI lo spiega su stderr. Quasi sempre è il numero sbagliato.
- Un risultato pieno non è per forza completo. Restano fuori i voti a codice secco (
EM 1.1077, SUBEM 0.1.1077.4) delle sedute in cui la fonte non ha popolato il riferimento all'atto: capita a sedute intere, e capita sui provvedimenti più contesi. Caso reale: la prima lettura della legge elettorale (C.2822), dove --bill-code 2822 dà 28 votazioni ma le 12 della seduta del 14/7/2026 — compreso l'emendamento preferenze passato 188-187 — non ci sono. Quando l'atto ha avuto un esame in Aula lungo, incrocia sempre con votes list --date-from … --date-to … sulle date che leggi in bill-progress: lì la colonna bill_number è comunque valorizzata, perché l'atto viene ereditato dalla seduta monotematica. Poi il dettaglio con vote-detail, mai il conteggio dedotto.
Ricerca testuale (--keyword)
--keyword (su bills, aic, committee-sessions, ecc.) è un match letterale sul titolo formale dell'atto, non una ricerca semantica: cerca la stringa così com'è nel testo ufficiale. Il lessico giornalistico spesso non coincide con quello normativo, quindi un risultato vuoto è quasi sempre un mismatch di parole, non un dato assente.
Regole d'oro:
- Usa il termine normativo, non quello giornalistico. Es.
elezione (non elettorale), disabilità/portatori di handicap, sostegno (non fuorisede/fuori sede). In dubbio, prova entrambi.
- Conversioni di decreto-legge: cerca col numero del decreto. Il titolo formale inizia sempre con «Conversione in legge del decreto-legge , n. …», quindi il numero (es.
--keyword "127", meglio con un intervallo di date attorno alla presentazione) è un aggancio più affidabile di qualunque sinonimo tematico: il nome giornalistico del provvedimento ("riforma della Maturità", "DL Semplificazioni") nel titolo spesso non compare.
- Prova più sinonimi e radici di parola prima di concludere. Preferisci la radice breve che copre più forme:
elett → elettorale/elettori, elez → elezione/elezioni (occhio: elezioni al plurale non matcha un titolo con elezione al singolare — la radice sì); ambient → ambiente/ambientale. Se il tool matcha a confini di parola (es. aic --keyword), usa più keyword separate.
- Vuoto ≠ assente. Se non trovi nulla, riformula con un sinonimo o una radice prima di dire all'utente che il dato non c'è. Solo dopo 2-3 varianti fallite l'assenza è credibile.
- Per dati di una commissione, prima risolvi il nome ufficiale.
--committee-name (su audizioni, committee-sessions) è un match letterale sul label ufficiale dell'organo, e il nome giornalistico spesso non coincide: la "commissione Covid" nel LOD è «…SARS-CoV-2», la stringa "covid" non compare mai. L'elenco è piccolo (~85 organi per la Camera in leg. 19), quindi la ricetta è: committees list --chamber camera --legislature 19 --format csv | grep -i <radice> (es. sars, cov, inchiesta), poi passa il nome esatto o l'URI a audizioni/committee-sessions/committee-members.
- Sindacato ispettivo (Senato): non ricercabile per argomento con
sindacato-ispettivo, ma ricercabile con aic. sindacato-ispettivo --keyword non filtra sull'oggetto perché il LOD Senato non espone l'oggetto/testo dell'atto (solo tipo, numero, data, firmatari): su quel tool non promettere ricerche tematiche. La via c'è però ed è , perché il dataset della Camera pubblica ~160.000 atti di sindacato ispettivo del Senato : risponde a «cosa hanno chiesto i senatori su X». Non dire più "non si può cercare per argomento al Senato". Limite: un'assenza in non prova che l'atto Senato non esista (i due insiemi non coincidono perfettamente).
Grounding (non inventare)
Quando ricostruisci iter, voti o schede, il rischio è la confabulazione su scheletro reale: partire da un dato giusto e riempire i buchi con valori plausibili ma falsi (voti, date, firmatari, contenuti). Regole:
- Riporta solo ciò che un comando ha restituito. Se un voto, un firmatario, una data o un contenuto non è nell'output, scrivi "non disponibile" — non completare con numeri o nomi verosimili.
- Aggancia gli atti per identificatore, ma non trasportare il numero da un ramo all'altro. Il numero non si conserva nel passaggio Camera→Senato (
C.2669 → S.1924). Usa bill-progress --number <n> --branch S: se al Senato non esiste quel numero, il comando risale da sé alla fase C.<n> e restituisce tutte le fasi del DDL nei due rami (nota su stderr). Non concludere mai "il Senato non ha ancora l'atto" da quel vuoto. E se un S.<n> esiste, verifica il titolo: può essere un atto completamente diverso (S.1511 ≠ fase Senato di C.1511).
- Una navetta finisce su un altro atto: non chiamare "stato attuale" l'ultimo stato di quello di partenza. Se un testo torna modificato dall'altro ramo, alla Camera la lettura successiva è un atto variante con suffisso (
C.703 → C.703-B). La timeline di C.703 si chiude con Approvato, segue Navette nel febbraio 2024, mentre la legge è stata approvata definitivamente nel novembre 2025 su C.703-B. bill-progress sul ramo Camera sonda le varianti e le annuncia con un NOTA: su stderr: finché quella nota compare, l'iter non è concluso — rilancia con l'URI indicato prima di scrivere che un provvedimento è fermo. Non confondere -B/-C/-D (letture successive) con -A (testo della commissione).
- Un vuoto con filtro di date ti dice se è latenza o no: leggilo su stderr. Sui comandi Camera (
aic, votes), quando il risultato è vuoto e c'era un intervallo di date, la CLI dice fino a quando quell'area di dati è stata caricata. Due esiti opposti: "la finestra non è ancora coperta da un caricamento" → può essere dato non ancora pubblicato, verifica alla fonte e non dire che non è avvenuto nulla; "la finestra è coperta" → il ritardo è escluso, la causa sta nei filtri o è un'assenza strutturale. Le aree hanno freschezze diverse (fine luglio 2026: atti e interrogazioni al 28/07, votazioni al 24/07, sedute e interventi d'Aula fermi al 18/06), quindi lo stesso giorno può essere coperto per un comando e non per un altro. Il Senato non espone questo segnale.
Tips
- Pipe CSV into
duckdb -c "SELECT ... FROM read_csv_auto('/dev/stdin')" for SQL analysis
- Use
--limit to cap results during exploration
- Un'opzione con nome sbagliato è un errore, non un filtro ignorato. La CLI rifiuta i flag non dichiarati e suggerisce il nome vicino (
--committee-uri → "forse intendevi --committee-name?"), quindi un output che arriva è un output con i filtri davvero applicati. Le grafie --date-from e --dateFrom sono equivalenti.
- Un elenco che riempie
--limit è tagliato, e il taglio ha una direzione. Gli elenchi sono ordinati per data decrescente: se filtri per intervallo e il risultato satura il limite, a mancare sono i giorni più vecchi dell'intervallo, non righe sparse. La CLI lo dice su stderr (AVVISO: risultato troncato…) — leggilo, non redirigerlo via. Regola: quando l'avviso compare, non concludere mai che in quei giorni non sia successo nulla; chiedi il totale reale con --count-only e poi decidi se alzare --limit (max 1000), paginare con --offset o restringere le date. Su intervalli lunghi 1000 righe possono coprire un solo mese: es. aic list --legislature 19 --date-from 2025-01-01 --date-to 2025-12-31 sono 11.649 righe reali.
- URIs from
list commands can be passed to show commands
- Senato confidence votes have empty
ddl_uri at the source, but senato-votes list --ddl-uri <uri> now returns the fiducia anyway (it resolves the DDL's seduta dates and re-links the confidence vote of that day). Still check ddl_uri on any "final" vote found by date: it may belong to a different act (unified text). --ddl-uri derives the legislature from the DDL, so a historical DDL (e.g. leg.18 http://dati.senato.it/ddl/52988) works without passing --legislature.
- Non passare
--legislature quando un altro input la determina. Tre tool la deducono da soli e sbagliarla è il modo tipico di ottenere un vuoto che sembra assenza di dato: audizioni dalla data (marzo 2020 → leg. 18), senato-attendance dalle legislature in cui quel senatore ha voti (un senatore non più in carica dà il suo ultimo mandato invece di "nessun voto"), dalle sedute dell'intervallo. no: lì non c'è nulla da cui dedurre, quindi per una legislatura passata va indicata.