Skip to main content
Glama

normattiva-mcp

CLI e server MCP per leggere, verificare e citare norme italiane da Normattiva.it, pensati per essere usati anche da modelli LLM economici (es. DeepSeek 4 flash). Il testo di un articolo viene sempre dall'API di Normattiva, mai dal permalink del portale (2.000 volte più pesante per lo stesso contenuto — vedi ARCHITETTURA.md).

Cosa fa

Da terminale (norm --help):

  • norm leggi <fonte> <articolo> — legge il testo verificato di un articolo (norm leggi "codice civile" 2043)

  • norm link <fonte> <articolo> — costruisce la citazione Markdown, verificandola per difetto

  • norm urn <urn> — legge un URN già in mano (es. un rinvio trovato in un testo)

  • norm fonti [testo] — elenca le fonti verificate, o ne cerca una

  • norm doctor — controlla se l'endpoint del testo risponde

  • norm stato — mostra localmente cache, quote, cooldown e ultimo incidente

  • norm skill — installa e aggiorna la skill Agent Skills per gli assistenti

  • norm verifica --tutte — mostra prima il costo stimato; esegue solo con --esegui, dopo avere prenotato tutto il budget necessario

Come server MCP (norm-mcp), cinque strumenti:

  • normattiva_leggi_articolo — stessa lettura di norm leggi

  • normattiva_link — stessa citazione di norm link

  • normattiva_trova_fonte — cerca una fonte nella tabella, nessuna rete

  • normattiva_leggi_urn — stessa lettura di norm urn

  • normattiva_stato_rete — stato locale della protezione, senza rete

Una futura ricerca full-text non è ancora esposta: se verrà aggiunta, dovrà usare solo un canale Open Data ufficiale adatto al volume richiesto.

Related MCP server: Dutch-law-mcp

Installazione

Richiede uv e Python 3.12-3.14.

uv tool install --editable .

Installa entrambi i comandi (norm, norm-mcp) in ~/.local/bin, restando sincronizzati col sorgente (utile durante lo sviluppo; per un uso normale basta uv tool install normattiva-mcp una volta pubblicato su PyPI).

Collegare il server MCP a un assistente

Esempio per Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "normattiva": {
      "command": "/Users/tuonome/.local/bin/norm-mcp",
      "args": []
    }
  }
}

Riavvia l'app dopo aver modificato il file. Il server parla solo su stdio, nessuna porta di rete aperta.

Installare la skill Agent Skills

La skill portabile normattiva-mcp segue lo standard aperto Agent Skills e non contiene estensioni specifiche di un singolo modello. È inclusa anche nel pacchetto Python, così la CLI può installarla dopo un'installazione da PyPI, uv tool o pipx.

norm skill list
norm skill install opencode
norm skill install claude-code
norm skill install codex
norm skill install pi
norm skill install all

install all installa soltanto nei client rilevati tramite il loro binario o la directory di configurazione e indica quelli saltati. Indicando un client preciso, l'installazione viene invece eseguita anche se il relativo binario non è sul PATH.

Il livello predefinito è personale. Per installarla solo nel progetto corrente:

norm skill install opencode --level project

Le destinazioni sono quelle native dei client: ~/.claude/skills, ~/.agents/skills, ~/.config/opencode/skills e ~/.pi/agent/skills; a livello progetto diventano rispettivamente .claude/skills, .agents/skills, .opencode/skills e .pi/skills. norm skill update aggiorna le copie già installate, norm skill show mostra la sorgente e norm skill uninstall <client> la rimuove dal client indicato.

Per collaudare un modello, il protocollo incluso parte da operazioni locali, usa al massimo un canary reale e richiede che la ripetizione identica sia servita dalla cache. Gli errori e l'arresto su critico/bloccato vanno provati solo con mock o server locale.

Uso prudente della rete

Avvertenza: osservazioni empiriche indicano che, dopo un numero elevato di richieste, Normattiva.it può smettere di rispondere in modo persistente da uno specifico indirizzo IP pur restando raggiungibile da altre reti. Non vi è una conferma ufficiale che si tratti di un ban, e sintomi analoghi possono dipendere anche da filtri o problemi di instradamento. Considerare comunque concreto il rischio: usare l'MCP con parsimonia, evitare raffiche e parallelismo e fermarsi al primo errore o cooldown senza tentare di proseguire tramite altre reti.

Il programma usa soltanto l'endpoint Open Data documentato POST .../atto/dettaglio-atto-urn, mai scraping HTML, browser automation, proxy o cambio di IP/VPN. Il permalink è generato come link, ma non viene scaricato.

Un database SQLite condiviso coordina CLI, MCP e processi concorrenti: una sola richiesta reale alla volta, almeno 5 secondi fra richieste e cache condivisa. Il testo vigente resta in cache 7 giorni, quello storico 30; gli errori deterministici 400/404 un'ora. NORMATTIVA_OFFLINE=1 usa solo la cache; se il database protettivo non è disponibile, non viene inviata nessuna richiesta.

I limiti seguenti sono cautele locali del progetto, non limiti comunicati da Normattiva: 30 consultazioni e 2 diagnosi per 24 ore mobili, con un massimo assoluto di 60. Si possono solo ridurre con le variabili d'ambiente; non aumentare da flag CLI o tool MCP. Ogni tentativo HTTP, anche fallito, consuma quota e non esistono retry automatici.

Configurazione facoltativa: NORMATTIVA_STATO_DB sceglie il file SQLite; NORMATTIVA_OFFLINE=1 disabilita la rete; NORMATTIVA_LIMITE_CONSULTAZIONI, NORMATTIVA_LIMITE_DIAGNOSI e NORMATTIVA_LIMITE_ASSOLUTO possono soltanto ridurre le rispettive soglie. NORMATTIVA_CONTATTO_USER_AGENT aggiunge un contatto volontario al User-Agent stabile del progetto.

Un 429 comporta il rispetto di Retry-After e comunque almeno 6 ore di pausa; 401/403/409 24 ore; 5xx o risposta malformata 15 minuti. Timeout, reset e TLS sono eventi indeterminati, non prova di ban, e avviano un cooldown crescente. Durante il cooldown, avvisa l'utente e non ritentare: non cambiare IP, VPN o proxy per proseguire.

Ogni risposta MCP che può usare la rete include protezione_rete; la CLI scrive il consumo reale su stderr (per esempio consultazione 7/30 — totale 9/60). A 50%, 80% e 90% il livello diventa rispettivamente attenzione o critico. Quando è critico o bloccato, il modello deve fermare il workflow e avvertire l'utente. Prima di un'attività con più consultazioni, usa norm stato o normattiva_stato_rete.

norm doctor non esegue rete durante un cooldown e fa al massimo una richiesta. La verifica completa è limitata a una ogni 7 giorni e parte solo se il budget intero è prenotabile. Prima di aumentare i volumi o offrire il servizio a terzi, chiedere al gestore indicazioni scritte su limiti, canale bulk e modalità d'uso preferite. Future operazioni massive devono usare solo eventuali canali ufficiali asincroni/bulk, mai un fan-out articolo per articolo.

Documentazione

Licenza

Il codice di questo repository è distribuito con licenza MIT (vedi LICENSE).

I dati restituiti dagli strumenti (testi normativi, metadati degli atti) provengono da Normattiva.it, Istituto Poligrafico e Zecca dello Stato, e sono distribuiti con licenza Creative Commons Attribuzione 4.0 Internazionale (CC BY 4.0). Ogni risposta degli strumenti include l'attribuzione richiesta dalla licenza.

Available Tools

5 tools
normattiva_leggi_articoloLeggi il testo verificato di un articoloA
Read-onlyIdempotent

Legge un articolo dato nome o alias della fonte (es. codice civile, l.fall.) e numero, anche con estensione ("21novies"). Per i codici storici è la via affidabile: usa prima normattiva_trova_fonte se l'alias non è certo. Controlla sempre esito: preambolo non è l'articolo; abrogato è informazione; vigenza_storica indica testo non vigente. vigenza (YYYY-MM-DD) chiede una data storica.

ParametersJSON Schema
NameRequiredDescriptionDefault
fonteYes
vigenzaNo
articoloYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
urnYes
esitoYes
testoNo
avvisiNo
headingNo
incipitNo
caratteriNo
messaggioNo
permalinkYes
attribuzioneYes
aggiornamentiNo
protezione_reteYes
vigenza_storicaNo
data_abrogazioneNo

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds meaningful behavioral detail beyond the readOnly/idempotent annotations: it documents the `esito` field, warns that `preambolo` is not the article, clarifies that `abrogato` is informational, and explains `vigenza_storica` as non-current text. This is exactly the kind of output-behavior context an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place: first the core function, then the routing guidance, then the critical output caveats, then the historical-date parameter. The use of semicolon-separated `esito` values keeps it compact without losing clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only lookup tool with an output schema already present, the description provides enough context to select and invoke it correctly. It covers input semantics, uncertainty handling, special output states, and historical-date behavior, so no critical operational gap remains.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description compensates well: `fonte` is explained as name/alias with examples, `articolo` is explained as number with extension, and `vigenza` is explained as a YYYY-MM-DD historical date. All three parameters receive meaningful semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action: reading an article by source name/alias and article number, including extension forms like "21novies". It also positions the tool against siblings by naming normattiva_trova_fonte as the pre-step for uncertain aliases and implying article lookup by name rather than by URN.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly tells the agent to use normattiva_trova_fonte first when the alias is uncertain, and labels this tool as the reliable path for historical codes. It also gives clear operational guidance around checking `esito` and providing a `vigenza` date for historical text.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

normattiva_leggi_urnLeggi un URN Normattiva già disponibileA
Read-onlyIdempotent

Legge un URN completo ottenuto altrove. Verifica esito: anche una risposta 200 può essere un preambolo; abrogato e vigenza_storica non sono diritto vigente. Per fonte più articolo usa normattiva_leggi_articolo, che passa dalla tabella verificata.

ParametersJSON Schema
NameRequiredDescriptionDefault
urnYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
urnYes
esitoYes
testoNo
avvisiNo
headingNo
incipitNo
caratteriNo
messaggioNo
permalinkYes
attribuzioneYes
aggiornamentiNo
protezione_reteYes
vigenza_storicaNo
data_abrogazioneNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/idempotent annotations, the description adds critical runtime caveats: the agent must check `esito`, a 200 response may still be only a preamble, and abrogated or historical-validity results are not current law. These are exactly the kind of behavioral warnings that prevent incorrect interpretation of results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three concise sentences with no filler. The first sentence states the core operation, the second adds essential result-interpretation guidance, and the third routes to an alternative tool. Every sentence earns its place and the most important information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that this tool has one simple parameter, rich annotations covering read-only/idempotent/non-destructive behavior, and an output schema, the description covers the key operational nuance and sibling routing. It tells the agent what to verify in the response and warns about false positives. Nothing critical is missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides no description for the single `urn` parameter (0% coverage), so the description must compensate. It adds meaningful context by calling the URN 'completo' and specifying that it was 'ottenuto altrove', which differentiates it from source/article inputs. It does not include a URN format example, but for a single simple parameter this is adequate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action, 'Legge un URN completo ottenuto altrove', clearly defining the tool as reading a complete Normattiva URN obtained elsewhere. It also distinguishes itself from the sibling normattiva_leggi_articolo by clarifying that source-plus-article requests belong to that tool. The purpose is unambiguous and well differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when this tool is appropriate: when a complete URN is already available. It also gives a concrete alternative, instructing the agent to use normattiva_leggi_articolo for source-plus-article queries because that tool uses the verified table. This is clear direction with a named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

normattiva_stato_reteMostra stato locale di quota, cache e cooldownA
Read-onlyIdempotent

Non usa la rete. Mostra rapporto di protezione e aggregati giornalieri (richieste reali, cache hit, errori, densità e cooldown). Usalo prima di un'attività con più consultazioni.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
rapportoYes
aggregati_giornalieriYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses a key behavioral trait not captured by annotations: it does not use the network and operates on local state ('Non usa la rete', 'stato locale'). It also explains what the report contains (real requests, cache hits, errors, density, cooldown), which is useful context beyond the readOnly/idempotent/non-destructive annotations. There is no contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, with the most important fact (no network, local state) front-loaded and the usage guidance placed second. There is no filler, repetition, or irrelevant detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only status tool with an output schema present, the description is complete: it says what the tool does, that it is local, what metrics it shows, and when to invoke it. No return-format explanation is needed because the output schema already covers that.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the description has nothing to explain. Per the baseline for parameterless tools, a score of 4 is appropriate; the description does not attempt to invent unnecessary parameter detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Mostra' / shows) and a clear resource: local state of quota, cache, and cooldown, along with daily aggregates. It also distinguishes itself from the sibling lookup tools by explicitly saying it does not use the network ('Non usa la rete'), making its role as a status/health tool unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit timing guidance: use it before an activity with multiple consultations ('Usalo prima di un'attività con più consultazioni'). It does not name alternatives or exclusions, but this is clear, actionable context for an agent choosing between this status tool and the sibling legal-research tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

normattiva_trova_fonteCerca una fonte nella tabella verificataA
Read-onlyIdempotent

Cerca nome o alias nella tabella locale: tipo, data, numero, allegato e stato, senza rete. Usalo prima di un codice storico: un allegato indovinato può puntare a un atto diverso. Una fonte assente qui non è assente dall'ordinamento.

ParametersJSON Schema
NameRequiredDescriptionDefault
testoYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
notaNo
tipoNo
aliasNo
statoNo
numeroNo
trovataYes
allegatoNo
nota_statoNo
disponibileNo
nome_canonicoNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive. The description adds valuable behavioral context beyond annotations: the tool searches only a local table without network access, and it cautions that the local table is not a complete representation of the legal order. This helps the agent calibrate expectations about result completeness.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, each earning its place: first defines the action and scope, second gives usage guidance with rationale, third states a critical limitation. It is front-loaded with the core purpose and contains no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter tool with an output schema and annotations covering safety, the description is complete. It covers what the tool does, its offline/local scope, when to use it, what caveats apply to the result, and the meaning of the sole parameter. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description carries the burden. It compensates by indicating that the 'testo' parameter is the 'nome o alias' to search for in the local table. While it does not provide format examples or edge cases, it gives the essential semantic meaning for the single parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Cerca') and resource ('tabella locale'), and lists the searchable attributes: 'tipo, data, numero, allegato e stato'. It distinguishes the tool from network-based siblings by explicitly noting it works 'senza rete', making its offline nature clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit usage context: 'Usalo prima di un codice storico' and warns that 'un allegato indovinato può puntare a un atto diverso'. It also provides a clear limitation ('Una fonte assente qui non è assente dall'ordinamento') which functions as when-not-to-conclude absence. It does not name sibling alternatives, but the context is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.2.0
    • Changednormattiva_leggi_articolo4 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "ProtezioneReteOutput": {
        +    "description": "Stato corrente e operazioni distinte, incluso un recupero storico.",
        +    "properties": {
        +      "acquisita_il": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Acquisita Il"
        +      },
        +      "attivita": {
        +        "title": "Attivita",
        +        "type": "string"
        +      },
        +      "avviso": {
        +        "title": "Avviso",
        +        "type": "string"
        +      },
        +      "consumo_attivita": {
        +        "title": "Consumo Attivita",
        +        "type": "string"
        +      },
        +      "consumo_globale": {
        +        "title": "Consumo Globale",
        +        "type": "string"
        +      },
        +      "cooldown_fino": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Cooldown Fino"
        +      },
        +      "livello": {
        +        "title": "Livello",
        +        "type": "string"
        +      },
        +      "origine": {
        +        "title": "Origine",
        +        "type": "string"
        +      },
        +      "rapporti": {
        +        "items": {
        +          "$ref": "#/$defs/RapportoReteOutput"
        +        },
        +        "title": "Rapporti",
        +        "type": "array"
        +      },
        +      "richieste_residue": {
        +        "title": "Richieste Residue",
        +        "type": "integer"
        +      },
        +      "ultimo_incidente": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Ultimo Incidente"
        +      }
        +    },
        +    "required": [
        +      "origine",
        +      "attivita",
        +      "consumo_attivita",
        +      "consumo_globale",
        +      "richieste_residue",
        +      "livello",
        +      "avviso"
        +    ],
        +    "title": "ProtezioneReteOutput",
        +    "type": "object"
        +  },
        +  "RapportoReteOutput": {
        +    "description": "Parte serializzabile del rapporto SQLite, senza dati di ricerca.",
        +    "properties": {
        +      "acquisita_il": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Acquisita Il"
        +      },
        +      "attivita": {
        +        "title": "Attivita",
        +        "type": "string"
        +      },
        +      "avviso": {
        +        "title": "Avviso",
        +        "type": "string"
        +      },
        +      "consumo_attivita": {
        +        "title": "Consumo Attivita",
        +        "type": "string"
        +      },
        +      "consumo_globale": {
        +        "title": "Consumo Globale",
        +        "type": "string"
        +      },
        +      "cooldown_fino": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Cooldown Fino"
        +      },
        +      "livello": {
        +        "title": "Livello",
        +        "type": "string"
        +      },
        +      "origine": {
        +        "title": "Origine",
        +        "type": "string"
        +      },
        +      "richieste_residue": {
        +        "title": "Richieste Residue",
        +        "type": "integer"
        +      },
        +      "ultimo_incidente": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Ultimo Incidente"
        +      }
        +    },
        +    "required": [
        +      "origine",
        +      "attivita",
        +      "consumo_attivita",
        +      "consumo_globale",
        +      "richieste_residue",
        +      "livello",
        +      "avviso"
        +    ],
        +    "title": "RapportoReteOutput",
        +    "type": "object"
        +  }
        +}
      • changedOutput schema / description
        Previous value: -"Un solo schema per i tre esiti possibili (`esito` discrimina), così i\ndue strumenti che leggono un articolo condividono un'unica forma di\nuscita — nessuna copia divergente fra loro."New value: +"Schema comune per articolo, abrogato e preambolo."
      • addedOutput schema / properties / protezione_rete
        Added value: +{
        +  "$ref": "#/$defs/ProtezioneReteOutput"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "esito",
        -  "urn",
        -  "permalink",
        -  "attribuzione"
        -]New value: +[
        +  "esito",
        +  "urn",
        +  "permalink",
        +  "attribuzione",
        +  "protezione_rete"
        +]
    • Changednormattiva_leggi_urn4 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "ProtezioneReteOutput": {
        +    "description": "Stato corrente e operazioni distinte, incluso un recupero storico.",
        +    "properties": {
        +      "acquisita_il": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Acquisita Il"
        +      },
        +      "attivita": {
        +        "title": "Attivita",
        +        "type": "string"
        +      },
        +      "avviso": {
        +        "title": "Avviso",
        +        "type": "string"
        +      },
        +      "consumo_attivita": {
        +        "title": "Consumo Attivita",
        +        "type": "string"
        +      },
        +      "consumo_globale": {
        +        "title": "Consumo Globale",
        +        "type": "string"
        +      },
        +      "cooldown_fino": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Cooldown Fino"
        +      },
        +      "livello": {
        +        "title": "Livello",
        +        "type": "string"
        +      },
        +      "origine": {
        +        "title": "Origine",
        +        "type": "string"
        +      },
        +      "rapporti": {
        +        "items": {
        +          "$ref": "#/$defs/RapportoReteOutput"
        +        },
        +        "title": "Rapporti",
        +        "type": "array"
        +      },
        +      "richieste_residue": {
        +        "title": "Richieste Residue",
        +        "type": "integer"
        +      },
        +      "ultimo_incidente": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Ultimo Incidente"
        +      }
        +    },
        +    "required": [
        +      "origine",
        +      "attivita",
        +      "consumo_attivita",
        +      "consumo_globale",
        +      "richieste_residue",
        +      "livello",
        +      "avviso"
        +    ],
        +    "title": "ProtezioneReteOutput",
        +    "type": "object"
        +  },
        +  "RapportoReteOutput": {
        +    "description": "Parte serializzabile del rapporto SQLite, senza dati di ricerca.",
        +    "properties": {
        +      "acquisita_il": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Acquisita Il"
        +      },
        +      "attivita": {
        +        "title": "Attivita",
        +        "type": "string"
        +      },
        +      "avviso": {
        +        "title": "Avviso",
        +        "type": "string"
        +      },
        +      "consumo_attivita": {
        +        "title": "Consumo Attivita",
        +        "type": "string"
        +      },
        +      "consumo_globale": {
        +        "title": "Consumo Globale",
        +        "type": "string"
        +      },
        +      "cooldown_fino": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Cooldown Fino"
        +      },
        +      "livello": {
        +        "title": "Livello",
        +        "type": "string"
        +      },
        +      "origine": {
        +        "title": "Origine",
        +        "type": "string"
        +      },
        +      "richieste_residue": {
        +        "title": "Richieste Residue",
        +        "type": "integer"
        +      },
        +      "ultimo_incidente": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Ultimo Incidente"
        +      }
        +    },
        +    "required": [
        +      "origine",
        +      "attivita",
        +      "consumo_attivita",
        +      "consumo_globale",
        +      "richieste_residue",
        +      "livello",
        +      "avviso"
        +    ],
        +    "title": "RapportoReteOutput",
        +    "type": "object"
        +  }
        +}
      • changedOutput schema / description
        Previous value: -"Un solo schema per i tre esiti possibili (`esito` discrimina), così i\ndue strumenti che leggono un articolo condividono un'unica forma di\nuscita — nessuna copia divergente fra loro."New value: +"Schema comune per articolo, abrogato e preambolo."
      • addedOutput schema / properties / protezione_rete
        Added value: +{
        +  "$ref": "#/$defs/ProtezioneReteOutput"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "esito",
        -  "urn",
        -  "permalink",
        -  "attribuzione"
        -]New value: +[
        +  "esito",
        +  "urn",
        +  "permalink",
        +  "attribuzione",
        +  "protezione_rete"
        +]
    • Changednormattiva_link4 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "ProtezioneReteOutput": {
        +    "description": "Stato corrente e operazioni distinte, incluso un recupero storico.",
        +    "properties": {
        +      "acquisita_il": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Acquisita Il"
        +      },
        +      "attivita": {
        +        "title": "Attivita",
        +        "type": "string"
        +      },
        +      "avviso": {
        +        "title": "Avviso",
        +        "type": "string"
        +      },
        +      "consumo_attivita": {
        +        "title": "Consumo Attivita",
        +        "type": "string"
        +      },
        +      "consumo_globale": {
        +        "title": "Consumo Globale",
        +        "type": "string"
        +      },
        +      "cooldown_fino": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Cooldown Fino"
        +      },
        +      "livello": {
        +        "title": "Livello",
        +        "type": "string"
        +      },
        +      "origine": {
        +        "title": "Origine",
        +        "type": "string"
        +      },
        +      "rapporti": {
        +        "items": {
        +          "$ref": "#/$defs/RapportoReteOutput"
        +        },
        +        "title": "Rapporti",
        +        "type": "array"
        +      },
        +      "richieste_residue": {
        +        "title": "Richieste Residue",
        +        "type": "integer"
        +      },
        +      "ultimo_incidente": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Ultimo Incidente"
        +      }
        +    },
        +    "required": [
        +      "origine",
        +      "attivita",
        +      "consumo_attivita",
        +      "consumo_globale",
        +      "richieste_residue",
        +      "livello",
        +      "avviso"
        +    ],
        +    "title": "ProtezioneReteOutput",
        +    "type": "object"
        +  },
        +  "RapportoReteOutput": {
        +    "description": "Parte serializzabile del rapporto SQLite, senza dati di ricerca.",
        +    "properties": {
        +      "acquisita_il": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Acquisita Il"
        +      },
        +      "attivita": {
        +        "title": "Attivita",
        +        "type": "string"
        +      },
        +      "avviso": {
        +        "title": "Avviso",
        +        "type": "string"
        +      },
        +      "consumo_attivita": {
        +        "title": "Consumo Attivita",
        +        "type": "string"
        +      },
        +      "consumo_globale": {
        +        "title": "Consumo Globale",
        +        "type": "string"
        +      },
        +      "cooldown_fino": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Cooldown Fino"
        +      },
        +      "livello": {
        +        "title": "Livello",
        +        "type": "string"
        +      },
        +      "origine": {
        +        "title": "Origine",
        +        "type": "string"
        +      },
        +      "richieste_residue": {
        +        "title": "Richieste Residue",
        +        "type": "integer"
        +      },
        +      "ultimo_incidente": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Ultimo Incidente"
        +      }
        +    },
        +    "required": [
        +      "origine",
        +      "attivita",
        +      "consumo_attivita",
        +      "consumo_globale",
        +      "richieste_residue",
        +      "livello",
        +      "avviso"
        +    ],
        +    "title": "RapportoReteOutput",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / properties / avvisi
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "title": "Avvisi",
        +  "type": "array"
        +}
      • addedOutput schema / properties / protezione_rete
        Added value: +{
        +  "$ref": "#/$defs/ProtezioneReteOutput"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "markdown",
        -  "verificato"
        -]New value: +[
        +  "markdown",
        +  "verificato",
        +  "protezione_rete"
        +]
    • Addednormattiva_stato_rete
    • Changednormattiva_trova_fonte3 fields changed
      • addedOutput schema / properties / disponibile / anyOf
        Added value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / disponibile / default
        Previous value: -trueNew value: +null
      • removedOutput schema / properties / disponibile / type
        Removed value: -"boolean"
  2. 4 tool updatesv0.1.1
    • First observednormattiva_leggi_articolo
    • First observednormattiva_leggi_urn
    • First observednormattiva_link
    • First observednormattiva_trova_fonte

TDQS

A4.5/5.0

Scored across 5 tools

Disambiguation4/5

Each tool has a distinct job: source lookup, article read, URN read, permalink construction, and network status. The only mild overlap is between normattiva_leggi_articolo and normattiva_leggi_urn, but the descriptions clearly separate them by input type.

Naming Consistency4/5

All tool names share the normattiva_ prefix and use snake_case, with several following an action-first pattern like normattiva_leggi_articolo and normattiva_trova_fonte. normattiva_link and normattiva_stato_rete deviate slightly from the verb_noun style, but the overall pattern is still recognizable and predictable.

Tool Count5/5

Five tools is a tight, well-scoped count for a Normattiva citation and retrieval server. Each tool contributes a distinct capability and none feels redundant or missing from the core workflow.

Completeness4/5

The set covers the main workflow: finding a source, reading an article, resolving a URN, generating a permalink, and checking network status. A full-text search or article-list endpoint would be a useful addition, but the current surface is functional for citation-oriented tasks with no hard dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    F
    maintenance
    Enables querying over 3,200 Dutch statutes (AVG, Wetboek van Strafrecht, Burgerlijk Wetboek, etc.) with verbatim, citation-grounded text from official sources, directly from MCP-compatible AI assistants.
    18
    48 npm
    13
    Apache 2.0
  • A
    license
    Not graded
    quality
    F
    maintenance
    MCP server for Italian law – indexes statutes from Normattiva such as Codice Civile, Codice Penale, and more, with EU implementation mapping.
    61 npm
    1
    Apache 2.0
  • A
    license
    A
    quality
    A
    maintenance
    An MCP server for Italian law, enabling live access to legislation via Normattiva and case law from the Constitutional Court, Supreme Court, and administrative courts, with citation verification.
    14
    Apache 2.0