Skip to main content
Glama

Expat Living Italy

Get one province's profile

get_province
Read-onlyIdempotent

One Italian province (two-letter code such as AQ, or its slug — a comune's provinceCode): population, OMI prices, foreign residents by citizenship (citizenship, not birthplace), ALL ISTAT BES well-being indicators with polarity-aware percentiles among provinces (no composite score), every province- and region-grain map layer, seismicZones (how many of its comuni sit in each official seismic zone — a count of comuni, never an average, since a province has no zone of its own), and how much of the province meets each verified tax regime (places, not people). Sources use different province lists — Sardinia was reorganized in 2026 — so a section a source lacks is null with a reason and listed in missingSections: report it as missing, never substitute another province's figure.

Input Schema

NameRequiredDescriptionDefault
codeYesA province's two-letter code, e.g. "AQ", or its slug, e.g. "l-aquila". Find it in a comune's `provinceCode`.

Output Schema

NameRequiredDescriptionDefault
layersYesEvery province- and region-grain map layer for this province, each saying whose number it is.
pricesYes
provinceYes
wellbeingYes
populationYesSum of the province's comuni.
taxRegimesYesVerified regimes with at least one qualifying comune here: how much of the province meets the geographic criteria. Places, not people; a regime absent here is not a no.
attributionYes
seismicZonesYesHow this province's comuni are spread across the official seismic zones: a count per zone, never an average. A province has no zone of its own.
missingSectionsYesEvery part of this profile a source has no figure for, with why. Sources use different province lists (Sardinia was reorganized in 2026): a section a source lacks is listed here as missing, never filled in from another province.
placesNotPeopleYes
foreignResidentsByCitizenshipYesCitizenship, not birthplace — excludes foreign-born Italian citizens — and only the citizenships this site tracks, so a floor on foreign residents. Summed over the comuni ISTAT has a row for: `coverage` says how many that is, and a comune with no row adds nothing rather than a zero.
foreignResidentsAllCitizenshipsYesResidents holding any foreign citizenship: ISTAT's own total, not limited to the citizenships tracked in foreignResidentsByCitizenship. Citizenship, not birthplace. Summed over the comuni ISTAT has a total for: `coverage` says how many that is, and a comune with no total adds nothing rather than a zero.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • addedOutput schema / properties / attribution / properties / license
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "License of Expat Living Italy's own work only; upstream data keeps its own license, per dataset.",
      +  "properties": {
      +    "name": {
      +      "type": "string"
      +    },
      +    "url": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "name",
      +    "url"
      +  ],
      +  "type": "object"
      +}
    • changedOutput schema / properties / attribution / required
      Previous value: -[
      -  "publisher",
      -  "url",
      -  "citeAs",
      -  "request"
      -]New value: +[
      +  "publisher",
      +  "url",
      +  "citeAs",
      +  "request",
      +  "license"
      +]
  2. Changed2 schema fields changed
    • changedOutput schema / properties / layers / items / properties / grain / description
      Previous value: -"The level this value is measured at. Only \"comune\" is a measurement of this comune itself."New value: +"The level this value is measured at. Only \"comune\" is a measurement of this comune itself. \"autonomous_province\" is Bolzano or Trento, which the source scores on their own rather than as one Trentino-Alto Adige region: the figure belongs to that autonomous province, not to the region."
    • changedOutput schema / properties / layers / items / properties / grain / enum
      Previous value: -[
      -  "comune",
      -  "province",
      -  "region"
      -]New value: +[
      +  "comune",
      +  "province",
      +  "autonomous_province",
      +  "region"
      +]
  3. Changed3 schema fields changed
    • addedOutput schema / properties / layers / items / properties / officialZone
      Added value: +{
      +  "description": "Only on the seismic hazard layer: the comune's official zona sismica (1 = highest hazard, 4 = lowest). NOTE this runs the opposite way to `value`, which is a hazard class (5 minus the zone). Omitted for comuni that straddle zones.",
      +  "maximum": 4,
      +  "minimum": 1,
      +  "type": "integer"
      +}
    • addedOutput schema / properties / layers / items / properties / scaleNote
      Added value: +{
      +  "description": "Only on layers whose scale direction is easy to misread (the seismic hazard class): says which end is which.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / prices / properties / purchasePriceEurM2 / description
      Added value: +"OMI is Agenzia delle Entrate's official range of market values per m2, built from recorded sales and appraisals. Asking prices on listing sites are what sellers hope for, and usually run higher."
  4. Changed2 schema fields changed
    • addedOutput schema / properties / seismicZones
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "How this province's comuni are spread across the official seismic zones: a count per zone, never an average. A province has no zone of its own.",
      +  "properties": {
      +    "coverage": {
      +      "additionalProperties": false,
      +      "description": "How many of Italy's places this dataset covers at all, e.g. 7587 of 7894 comuni.",
      +      "properties": {
      +        "in": {
      +          "maximum": 9007199254740991,
      +          "minimum": -9007199254740991,
      +          "type": "integer"
      +        },
      +        "of": {
      +          "maximum": 9007199254740991,
      +          "minimum": -9007199254740991,
      +          "type": "integer"
      +        }
      +      },
      +      "required": [
      +        "in",
      +        "of"
      +      ],
      +      "type": "object"
      +    },
      +    "extractedOn": {
      +      "description": "ISO date this value was extracted from the source.",
      +      "type": "string"
      +    },
      +    "license": {
      +      "type": "string"
      +    },
      +    "method": {
      +      "description": "URL to the methodology page for this dataset.",
      +      "type": "string"
      +    },
      +    "reason": {
      +      "description": "Present only when value is null: why this place has no figure.",
      +      "type": "string"
      +    },
      +    "source": {
      +      "type": "string"
      +    },
      +    "unit": {
      +      "type": "string"
      +    },
      +    "value": {
      +      "anyOf": [
      +        {
      +          "additionalProperties": false,
      +          "properties": {
      +            "comuniByOfficialZone": {
      +              "additionalProperties": false,
      +              "description": "Comuni in each official zone (zone1 is the highest hazard). Split comuni are not counted here.",
      +              "properties": {
      +                "zone1": {
      +                  "maximum": 9007199254740991,
      +                  "minimum": -9007199254740991,
      +                  "type": "integer"
      +                },
      +                "zone2": {
      +                  "maximum": 9007199254740991,
      +                  "minimum": -9007199254740991,
      +                  "type": "integer"
      +                },
      +                "zone3": {
      +                  "maximum": 9007199254740991,
      +                  "minimum": -9007199254740991,
      +                  "type": "integer"
      +                },
      +                "zone4": {
      +                  "maximum": 9007199254740991,
      +                  "minimum": -9007199254740991,
      +                  "type": "integer"
      +                }
      +              },
      +              "required": [
      +                "zone1",
      +                "zone2",
      +                "zone3",
      +                "zone4"
      +              ],
      +              "type": "object"
      +            },
      +            "comuniWithoutClassification": {
      +              "maximum": 9007199254740991,
      +              "minimum": -9007199254740991,
      +              "type": "integer"
      +            },
      +            "reading": {
      +              "type": "string"
      +            },
      +            "straddlingZones": {
      +              "description": "Comuni that straddle zones and so have no single zone; named, not rounded to one.",
      +              "items": {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "label": {
      +                    "type": "string"
      +                  },
      +                  "name": {
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "name",
      +                  "label"
      +                ],
      +                "type": "object"
      +              },
      +              "type": "array"
      +            },
      +            "totalComuni": {
      +              "maximum": 9007199254740991,
      +              "minimum": -9007199254740991,
      +              "type": "integer"
      +            }
      +          },
      +          "required": [
      +            "comuniByOfficialZone",
      +            "straddlingZones",
      +            "comuniWithoutClassification",
      +            "totalComuni",
      +            "reading"
      +          ],
      +          "type": "object"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "vintage": {
      +      "description": "The period the value describes, e.g. \"2025H2\" or \"2025\" — not when it was fetched.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "value",
      +    "unit",
      +    "source",
      +    "vintage",
      +    "extractedOn",
      +    "method",
      +    "license"
      +  ],
      +  "type": "object"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "province",
      -  "population",
      -  "prices",
      -  "foreignResidentsByCitizenship",
      -  "foreignResidentsAllCitizenships",
      -  "wellbeing",
      -  "layers",
      -  "taxRegimes",
      -  "missingSections",
      -  "placesNotPeople",
      -  "attribution"
      -]New value: +[
      +  "province",
      +  "population",
      +  "prices",
      +  "foreignResidentsByCitizenship",
      +  "foreignResidentsAllCitizenships",
      +  "wellbeing",
      +  "seismicZones",
      +  "layers",
      +  "taxRegimes",
      +  "missingSections",
      +  "placesNotPeople",
      +  "attribution"
      +]
  5. Changed2 schema fields changed
    • changedOutput schema / properties / foreignResidentsAllCitizenships / description
      Previous value: -"Residents holding any foreign citizenship: ISTAT's own total, not limited to the 25 citizenships tracked in foreignResidentsByCitizenship. Citizenship, not birthplace. Summed over the comuni ISTAT has a total for: `coverage` says how many that is, and a comune with no total adds nothing rather than a zero."New value: +"Residents holding any foreign citizenship: ISTAT's own total, not limited to the citizenships tracked in foreignResidentsByCitizenship. Citizenship, not birthplace. Summed over the comuni ISTAT has a total for: `coverage` says how many that is, and a comune with no total adds nothing rather than a zero."
    • changedOutput schema / properties / foreignResidentsByCitizenship / properties / value / anyOf
      Previous value: -[
      -  {
      -    "items": {
      -      "additionalProperties": false,
      -      "properties": {
      -        "code": {
      -          "description": "ISO-2 citizenship code.",
      -          "type": "string"
      -        },
      -        "count": {
      -          "maximum": 9007199254740991,
      -          "minimum": -9007199254740991,
      -          "type": "integer"
      -        },
      -        "shareOfPopulation": {
      -          "type": "number"
      -        }
      -      },
      -      "required": [
      -        "code",
      -        "count",
      -        "shareOfPopulation"
      -      ],
      -      "type": "object"
      -    },
      -    "maxItems": 40,
      -    "type": "array"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "items": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "code": {
      +          "description": "ISO-2 citizenship code.",
      +          "type": "string"
      +        },
      +        "count": {
      +          "maximum": 9007199254740991,
      +          "minimum": -9007199254740991,
      +          "type": "integer"
      +        },
      +        "shareOfPopulation": {
      +          "type": "number"
      +        }
      +      },
      +      "required": [
      +        "code",
      +        "count",
      +        "shareOfPopulation"
      +      ],
      +      "type": "object"
      +    },
      +    "maxItems": 100,
      +    "type": "array"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
  6. Changed2 schema fields changed
    • addedOutput schema / properties / foreignResidentsAllCitizenships
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Residents holding any foreign citizenship: ISTAT's own total, not limited to the 25 citizenships tracked in foreignResidentsByCitizenship. Citizenship, not birthplace. Summed over the comuni ISTAT has a total for: `coverage` says how many that is, and a comune with no total adds nothing rather than a zero.",
      +  "properties": {
      +    "coverage": {
      +      "additionalProperties": false,
      +      "description": "How many of Italy's places this dataset covers at all, e.g. 7587 of 7894 comuni.",
      +      "properties": {
      +        "in": {
      +          "maximum": 9007199254740991,
      +          "minimum": -9007199254740991,
      +          "type": "integer"
      +        },
      +        "of": {
      +          "maximum": 9007199254740991,
      +          "minimum": -9007199254740991,
      +          "type": "integer"
      +        }
      +      },
      +      "required": [
      +        "in",
      +        "of"
      +      ],
      +      "type": "object"
      +    },
      +    "extractedOn": {
      +      "description": "ISO date this value was extracted from the source.",
      +      "type": "string"
      +    },
      +    "license": {
      +      "type": "string"
      +    },
      +    "method": {
      +      "description": "URL to the methodology page for this dataset.",
      +      "type": "string"
      +    },
      +    "reason": {
      +      "description": "Present only when value is null: why this place has no figure.",
      +      "type": "string"
      +    },
      +    "source": {
      +      "type": "string"
      +    },
      +    "unit": {
      +      "type": "string"
      +    },
      +    "value": {
      +      "anyOf": [
      +        {
      +          "maximum": 9007199254740991,
      +          "minimum": -9007199254740991,
      +          "type": "integer"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "vintage": {
      +      "description": "The period the value describes, e.g. \"2025H2\" or \"2025\" — not when it was fetched.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "value",
      +    "unit",
      +    "source",
      +    "vintage",
      +    "extractedOn",
      +    "method",
      +    "license"
      +  ],
      +  "type": "object"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "province",
      -  "population",
      -  "prices",
      -  "foreignResidentsByCitizenship",
      -  "wellbeing",
      -  "layers",
      -  "taxRegimes",
      -  "missingSections",
      -  "placesNotPeople",
      -  "attribution"
      -]New value: +[
      +  "province",
      +  "population",
      +  "prices",
      +  "foreignResidentsByCitizenship",
      +  "foreignResidentsAllCitizenships",
      +  "wellbeing",
      +  "layers",
      +  "taxRegimes",
      +  "missingSections",
      +  "placesNotPeople",
      +  "attribution"
      +]
  7. Added

TDQS

A3.6/5.0
Behavior5/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint=false, so the safety profile is settled; the description instead adds genuinely non-obvious behavioural context. It specifies null-with-reason semantics for sections a source lacks, names the `missingSections` field, warns that Sardinia's 2026 reorganization means source province lists diverge, and pins down unit semantics that are easy to get wrong (seismicZones is a count of comuni, never an average; tax regime coverage is places not people; citizenship is not birthplace). That is exactly the kind of caveat structured fields cannot carry.

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

Conciseness3/5

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

Almost every clause earns its place — the polarity caveat, the count-not-average rule and the places-not-people distinction all prevent real misinterpretation. However the whole thing is delivered as a single run-on sentence riddled with nested parentheses, so the most important operational rule (missingSections handling) lands at the very end where it is easy to skim past. It is information-dense but poorly structured.

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

Completeness4/5

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

With an output schema present the description need not document return shapes, yet it usefully pre-empts the interpretation traps an output schema cannot express. For a read-only, single-parameter lookup the coverage is close to sufficient; the residual gap is guidance on when a province call is the right call versus the sibling comune tools.

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

Parameters3/5

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

Schema description coverage is 100% for the single required `code` parameter, and the schema already supplies both the pattern and the 'AQ' / 'l-aquila' examples plus the `provinceCode` provenance. The description restates the same two formats without adding syntax, normalisation rules, or case handling beyond what the schema gives. Baseline 3 is appropriate when the schema does all the work.

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

Purpose4/5

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

The description names a specific resource at a specific grain — one Italian province, identified by two-letter code or slug — and enumerates the exact payload (population, OMI prices, foreign residents by citizenship, ISTAT BES indicators, map layers, seismic zones, tax regimes). That level of specificity separates it cleanly from get_comune, the neighbouring settlement-level profile tool. It only loses a point because the opening is a noun phrase rather than a verb+resource statement, so the action itself is implied by the title rather than the body.

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

Usage Guidelines2/5

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

There is no statement of when to reach for this tool versus get_comune, search_comuni, or find_comuni, and no prerequisite or exclusion is given. The only usage-shaped advice is about handling missing sections after the call ('report it as missing, never substitute another province's figure'), which governs output interpretation, not tool selection. An agent must infer the province-vs-comune routing from the data list alone.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources