Skip to main content
Glama

Cenogram - Polish Real Estate Data

get_permits_in_area

Read-only

List the building permits and works notifications registered since 2016 within a radius of a point — issued decisions only, matched through the parcel geometry we hold, which is near-complete but not the whole cadastre — to see what is being built nearby. Returns a deduplicated list of cases, newest first and NOT nearest first (one entry per permit or notification; a permit and a notification for the same investment are two cases), plus an aggregate by year and statutory object category that counts ALL matched cases in the circle, not only the listed ones, with the permit/notification split and the building volume where it is recorded. Each case carries its kind, intent and works type, object category with a short label, decision or intake date, deciding authority, investment address with the building number, volume, and its distance from the centre of the circle (to the parcel covered by the case, not to the building; rounded to 10 m). A volume marked suspect — a single-family case far above one house, usually several buildings filed as one case — is shown as recorded and stays in the sums. truncated means more cases matched than the limit: pass the returned cursor back as cursor with the same filters for the next page. The aggregate covers all pages, so do not add it up across them. Filters: dateFrom (default two years back, never earlier than 2016-01-01) and dateTo (inclusive; pass dateFrom too when dateTo is older than two years); categories / excludeCategories: statutory object categories I–XXX, arrays (excludeCategories keeps cases that have no category); intent: shorthand for multi_family (= categories [XIII]), single_family (= [I], which includes semi-detached and terraced houses) or all (default), not combinable with categories; worksType: new_construction (default) or all (adds extensions, demolitions and other works). radiusKm is 0.1–2 (default 2); for a wider area make several calls for neighbouring centre points. Category examples: apartment blocks → categories=[XIII]; buildings without the utility-network noise → excludeCategories=[XXVI] (utility networks, XXVI, can make up most of a list); utility works as a sign that land is being serviced for development → categories=[XXVI]. For "how many / how much" questions pass aggregateOnly=true: you get the aggregate without the list, at the same price. What is closest: the list is ordered by date, so a page can be full of cases far from the point. To see what is next to it, use a smaller radiusKm (for example 0.3) rather than paging through a large circle. How to read it: a case is listed when any of its parcels intersects the circle. Permits are held once a decision has been issued; the outcome of that decision, granted or refused, is not part of the data held here, and notifications are held only where they were accepted without objection. Cases still pending are not held at all. Matching uses the parcel's current identifier and geometry, so cases filed before a parcel split or merge may be invisible, some cases whose parcel number carries a sheet segment may be matched less exactly or be missing, and parcels without geometry are not searched. The answer states how many parcels we hold in the circle: 0 means no data for the area, not that nothing is being built. A short or empty list is never a statement that nothing is being built. Coordinates: for a parcel take them from resolve_parcel (or search_parcels); for a street use list_parcels_in_area(location, street) and take the centre point of a returned row; otherwise they come from the user — never guess them. The data is loaded periodically, not live; the answer gives the date of the last refresh. A query that outruns its time limit answers with an error asking for a smaller radius. Cost: 5 API tokens per call, charged also when the list is empty (a collection is not refunded); each page is a separate call. This feature can be switched off for maintenance; when it is, the call returns a plain "temporarily unavailable" message rather than data.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
latYesLatitude of the circle's centre (WGS84, Poland). From a resolve_parcel / list_parcels_in_area result or the user; never guessed.
lngYesLongitude of the circle's centre (WGS84, Poland). From a resolve_parcel / list_parcels_in_area result or the user; never guessed.
limitNoCases in the list, 1–200 (default 50). The aggregate always counts all matched cases.
cursorNoOpaque cursor from the previous answer, to get the next page. Pass it back unchanged with the same filters (limit may differ); it is not available with aggregateOnly.
dateToNoWindow end, YYYY-MM-DD, inclusive; not earlier than dateFrom. When it is older than two years, pass dateFrom as well (the default start is two years back).
intentNoShorthand: multi_family = categories [XIII], single_family = categories [I] (includes semi-detached and terraced houses), all = no filter (default). Cannot be combined with categories.
dateFromNoWindow start, YYYY-MM-DD, on the decision date (intake date for notifications). Default: two years back; earlier than 2016-01-01 is treated as 2016-01-01.
radiusKmNoRadius in km, 0.1–2 (default 2). For a wider area, call again for neighbouring centre points; for what is closest to the point, use a smaller radius.
worksTypeNonew_construction (default) or all (adds extensions, demolitions and other works).
categoriesNoKeep only these statutory object categories (Roman numerals I–XXX), e.g. ["XIII"] for apartment blocks or ["XXVI"] for utility networks. Not combinable with intent other than all, and must not overlap with excludeCategories.
aggregateOnlyNotrue = return only the aggregate (year × category counts, permit/notification split, volumes) without the case list, for 'how many' questions. Same price; cannot be combined with cursor.
excludeCategoriesNoRemove these statutory object categories (cases without a category stay), e.g. ["XXVI"] to drop utility networks. Must not overlap with categories.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed9 schema fields changed
    • addedInput schema / properties / aggregateOnly
      Added value: +{
      +  "description": "true = return only the aggregate (year × category counts, permit/notification split, volumes) without the case list, for 'how many' questions. Same price; cannot be combined with cursor.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / categories
      Added value: +{
      +  "description": "Keep only these statutory object categories (Roman numerals I–XXX), e.g. [\"XIII\"] for apartment blocks or [\"XXVI\"] for utility networks. Not combinable with intent other than all, and must not overlap with excludeCategories.",
      +  "items": {
      +    "enum": [
      +      "I",
      +      "II",
      +      "III",
      +      "IV",
      +      "V",
      +      "VI",
      +      "VII",
      +      "VIII",
      +      "IX",
      +      "X",
      +      "XI",
      +      "XII",
      +      "XIII",
      +      "XIV",
      +      "XV",
      +      "XVI",
      +      "XVII",
      +      "XVIII",
      +      "XIX",
      +      "XX",
      +      "XXI",
      +      "XXII",
      +      "XXIII",
      +      "XXIV",
      +      "XXV",
      +      "XXVI",
      +      "XXVII",
      +      "XXVIII",
      +      "XXIX",
      +      "XXX"
      +    ],
      +    "type": "string"
      +  },
      +  "maxItems": 30,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • addedInput schema / properties / cursor
      Added value: +{
      +  "description": "Opaque cursor from the previous answer, to get the next page. Pass it back unchanged with the same filters (limit may differ); it is not available with aggregateOnly.",
      +  "maxLength": 300,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / dateTo
      Added value: +{
      +  "description": "Window end, YYYY-MM-DD, inclusive; not earlier than dateFrom. When it is older than two years, pass dateFrom as well (the default start is two years back).",
      +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +  "type": "string"
      +}
    • addedInput schema / properties / excludeCategories
      Added value: +{
      +  "description": "Remove these statutory object categories (cases without a category stay), e.g. [\"XXVI\"] to drop utility networks. Must not overlap with categories.",
      +  "items": {
      +    "enum": [
      +      "I",
      +      "II",
      +      "III",
      +      "IV",
      +      "V",
      +      "VI",
      +      "VII",
      +      "VIII",
      +      "IX",
      +      "X",
      +      "XI",
      +      "XII",
      +      "XIII",
      +      "XIV",
      +      "XV",
      +      "XVI",
      +      "XVII",
      +      "XVIII",
      +      "XIX",
      +      "XX",
      +      "XXI",
      +      "XXII",
      +      "XXIII",
      +      "XXIV",
      +      "XXV",
      +      "XXVI",
      +      "XXVII",
      +      "XXVIII",
      +      "XXIX",
      +      "XXX"
      +    ],
      +    "type": "string"
      +  },
      +  "maxItems": 30,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • changedInput schema / properties / intent / description
      Previous value: -"multi_family = category XIII, single_family = category I (includes semi-detached and terraced houses), all = no filter (default)."New value: +"Shorthand: multi_family = categories [XIII], single_family = categories [I] (includes semi-detached and terraced houses), all = no filter (default). Cannot be combined with categories."
    • changedInput schema / properties / lat / description
      Previous value: -"Latitude of the circle's centre (WGS84, Poland). From a resolve_parcel / search_parcels result or the user; never guessed."New value: +"Latitude of the circle's centre (WGS84, Poland). From a resolve_parcel / list_parcels_in_area result or the user; never guessed."
    • changedInput schema / properties / lng / description
      Previous value: -"Longitude of the circle's centre (WGS84, Poland). From a resolve_parcel / search_parcels result or the user; never guessed."New value: +"Longitude of the circle's centre (WGS84, Poland). From a resolve_parcel / list_parcels_in_area result or the user; never guessed."
    • changedInput schema / properties / radiusKm / description
      Previous value: -"Radius in km, 0.1–2 (default 2). For a wider area, call again for neighbouring centre points."New value: +"Radius in km, 0.1–2 (default 2). For a wider area, call again for neighbouring centre points; for what is closest to the point, use a smaller radius."
  2. Added

TDQS

A4.4/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, yet the description adds far more: 5-token cost charged even on empty results, per-page billing, periodic (not live) data with a refresh date, maintenance outages returning 'temporarily unavailable', cursor/truncation semantics, aggregate spanning all pages, pending/refused cases absent, and parcel-geometry matching gaps. This is unusually rich disclosure for a read-only tool.

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?

It is front-loaded with purpose but then becomes a very long block, and several points are restated: the smaller-radius advice appears twice, cursor/truncated paging is explained in the description and again in the schema, and cost/pagination are revisited under 'Cost'. Much of the length is justified by tool complexity, but redundancy costs it.

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?

There is no output schema, so the description carries the full return-value burden — and it does: deduplicated list, newest-first (not nearest-first) ordering, per-case fields, the year×category aggregate with permit/notification split and volumes, the truncated flag, and error-on-timeout behavior. An agent has everything needed to call and interpret it.

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 100%, so the baseline is 3, and the description largely mirrors the schema (intent shorthand, worksType, category examples). It does add semantic value the schema does not carry cleanly: the rationale for the two-year default floor at 2016-01-01, the radius-vs-paging strategy, and the category examples tied to real question shapes.

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 opening states a precise verb+resource+scope: 'List the building permits and works notifications ... within a radius of a point — issued decisions only'. It is immediately distinguishable from generic transaction tools by its spatial framing, but it never explicitly addresses the potentially confusable sibling get_transaction_permits, so sibling differentiation is left implicit.

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 gives explicit when-to-use-each-option guidance: aggregateOnly=true for 'how many/how much' questions, a smaller radiusKm rather than paging for 'what is closest', categories/excludeCategories examples for specific question shapes, and routing for coordinates via resolve_parcel / list_parcels_in_area / user, with 'never guess them'. Alternatives and trade-offs are spelled out rather than implied.

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