Skip to main content
Glama
cenogram-mcp-server

cenogram-mcp-server

Official

search_by_polygon

Read-only

Search real estate deed transactions and prices within a custom GeoJSON polygon to analyze precise neighborhood or osiedle boundaries.

Instructions

Find transactions inside a GeoJSON Polygon - for precise neighborhood/osiedla boundaries; for a quick look start with search_by_area (its results can help estimate coordinates). Returns TRANSACTIONS (deeds and prices) with coordinates, despite the name; for the land plots inside a drawn shape pass the same polygon to list_parcels_in_area. Costs 5 API tokens. Permalink to a result: https://cenogram.pl/ceny-transakcyjne?src=mcpstdio#v=1&lat=&lng=&z=16&tx= ( from the "id:" line, / from "Location: °N, °E"; omit &tx= for the area only).

Input Schema

NameRequiredDescriptionDefault
pageNoPage 1-20 (50 rows).
floorNoUnit floor, multi-select: integers ('0' = parter, negatives = basement), 'Nplus' ('0plus' = ground and above), 'unknown' (none recorded). Not building storeys; rows with no floor drop out unless 'unknown' is listed.
limitNoMax results (1-3000); 50 shown.
roomsNoRooms (izby), residential units only; multi-select ('8plus' = 8 or more). Rows with no count drop out unless 'unknown' is listed.
dateToNoEnd date (YYYY-MM-DD)
streetNoStreet name filter (partial match)
landUseNoLand-use category, multi-select, case-sensitive (gruntyZabudowaneIZurbanizowane = built-up, gruntyRolne = agricultural, gruntyLesne = forest, terenyKomunikacyjne = transport); 'unknown' = none recorded (NULL), not 'no use'.
maxAreaNoMaximum area in m²
minAreaNoMinimum area in m²
polygonYesGeoJSON Polygon: [longitude, latitude] pairs, first and last point identical, max 500 vertices total.
dateFromNoStart date (YYYY-MM-DD)
districtNoDistrict name filter
maxPriceNoMaximum price in PLN
minPriceNoMinimum price in PLN
marketTypeNoprimary (developer) or secondary (resale); the ~55% of records with no market type drop out when this is set.
buildingTypeNoBuilding type (PKOB); 'unknown' = none recorded (NULL, ~39% of buildings), any other value excludes such rows.
propertyTypeNoProperty type filter
unitFunctionNoUnit function; 'unknown' = none recorded (NULL), any other value excludes such rows. Garages only via 'garage'.
ownershipTypeNoLegal-right type (rodzaj prawa), multi-select; perpetual_usufruct = użytkowanie wieczyste; 'unknown' = none recorded.
buildingStoreysNoAbove-ground storeys, multi-select: integers, 'Nplus' ('3plus' = 3+), 'unknown' (no count). Single-building deeds only, so 'unknown' also covers multi-building deeds. Not the unit floor; rows with no count drop out unless 'unknown' is listed.
mpzpDesignationNoMPZP zoning designation, exact token match; comma-separated = OR; 'unknown' = none recorded. Same codes as search_transactions mpzpDesignation.
transactionTypeNoMulti-select. For market analysis ALWAYS set it to exclude non-market deeds (subsidized, foreclosure, public_purpose); no-type rows (~2%) drop out unless 'unknown' is listed.
maxFootprintAreaNoMaximum building footprint in m², summed over the transaction's buildings; measured rows only (absence = 'not measured', not 'no building'). Not usable area.
minFootprintAreaNoMinimum building footprint in m², summed over the transaction's buildings; measured rows only (absence = 'not measured', not 'no building'). Not usable area.
excludeFractionalSharesNotrue = clean land prices: drops fractional ownership shares, whose price reflects the whole deed. Default false.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed16 schema fields changedv0.18.0
    • changedInput schema / properties / buildingStoreys / description
      Previous value: -"Number of above-ground storeys of the building. Multi-select buckets: exact non-negative integers (e.g. '1','2'), 'Nplus' e.g. '3plus' = 3 or more, 'unknown' = no storey count recorded (NULL). Recorded ONLY for single-building transactions, so 'unknown' covers BOTH a deed with several buildings (no single storey count exists) and a single building with missing data — never read it as 'a building with no storeys'. This is NOT the floor of a unit (see floor). Without 'unknown', rows with no storey count are excluded."New value: +"Above-ground storeys, multi-select: integers, 'Nplus' ('3plus' = 3+), 'unknown' (no count). Single-building deeds only, so 'unknown' also covers multi-building deeds. Not the unit floor; rows with no count drop out unless 'unknown' is listed."
    • changedInput schema / properties / buildingType / description
      Previous value: -"Building type filter (PKOB classification). 'unknown' = no type recorded (NULL); without it such rows are excluded (~39% of buildings have no type)."New value: +"Building type (PKOB); 'unknown' = none recorded (NULL, ~39% of buildings), any other value excludes such rows."
    • addedInput schema / properties / excludeFractionalShares
      Added value: +{
      +  "default": false,
      +  "description": "true = clean land prices: drops fractional ownership shares, whose price reflects the whole deed. Default false.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / floor / description
      Previous value: -"Floor of the unit (piętro lokalu, residential). Multi-select buckets: exact integers incl. '0' (parter) and negatives e.g. '-1' (basement), 'Nplus' e.g. '10plus' = 10 or more, '0plus' = ground and above, 'unknown' = no floor recorded (NULL). E.g. ['0','1','2'] for ground-to-2nd floor. Building storeys are a different attribute. Without 'unknown', rows with no floor are excluded."New value: +"Unit floor, multi-select: integers ('0' = parter, negatives = basement), 'Nplus' ('0plus' = ground and above), 'unknown' (none recorded). Not building storeys; rows with no floor drop out unless 'unknown' is listed."
    • changedInput schema / properties / landUse / description
      Previous value: -"Recorded land-use category of the transaction's land. Multi-select from: gruntyZabudowaneIZurbanizowane (built-up and urbanised), gruntyRolne (agricultural), gruntyLesne (forest), terenyKomunikacyjne (transport), inne (other). 'unknown' = no category recorded for the land (NULL) — a legitimate bucket, never a claim that the land has no use. Values are case-sensitive. E.g. ['gruntyRolne'] for farmland, or ['gruntyZabudowaneIZurbanizowane','gruntyRolne'] to compare developed vs farmland."New value: +"Land-use category, multi-select, case-sensitive (gruntyZabudowaneIZurbanizowane = built-up, gruntyRolne = agricultural, gruntyLesne = forest, terenyKomunikacyjne = transport); 'unknown' = none recorded (NULL), not 'no use'."
    • changedInput schema / properties / limit / description
      Previous value: -"Max results (1-3000, default 100). MCP displays up to 50 transactions."New value: +"Max results (1-3000); 50 shown."
    • changedInput schema / properties / marketType / description
      Previous value: -"Market type filter"New value: +"primary (developer) or secondary (resale); the ~55% of records with no market type drop out when this is set."
    • changedInput schema / properties / maxFootprintArea / description
      Previous value: -"Maximum building footprint (ground-plan) area in m², summed over all buildings of the transaction. Distinct from maxArea, which measures usable floor area (units) or land/parcel area. Set only where every linked building has footprint data, so this bound selects only measured rows — absence means 'not measured', not 'no building'."New value: +"Maximum building footprint in m², summed over the transaction's buildings; measured rows only (absence = 'not measured', not 'no building'). Not usable area."
    • changedInput schema / properties / minFootprintArea / description
      Previous value: -"Minimum building footprint (ground-plan) area in m², summed over all buildings of the transaction. Distinct from minArea, which measures usable floor area (units) or land/parcel area. Set only where every linked building has footprint data, so this bound selects only measured rows — absence means 'not measured', not 'no building'."New value: +"Minimum building footprint in m², summed over the transaction's buildings; measured rows only (absence = 'not measured', not 'no building'). Not usable area."
    • changedInput schema / properties / mpzpDesignation / description
      Previous value: -"MPZP zoning designation filter (exact match). Use 'unknown' for rows with no designation recorded (NULL); distinct from the registry code 'brakMPZPLubWZ'."New value: +"MPZP zoning designation, exact token match; comma-separated = OR; 'unknown' = none recorded. Same codes as search_transactions mpzpDesignation."
    • changedInput schema / properties / ownershipType / description
      Previous value: -"Ownership / legal-right type filter (rodzaj prawa do nieruchomości). land_ownership; perpetual_usufruct (użytkowanie wieczyste — covers both registry codes for this right); cooperative_ownership; unit_sale; ownership; unit_ownership_with_appurtenant_right; building_ownership_with_appurtenant_right. 'unknown' = no right recorded (NULL). Multi-select; e.g. ['land_ownership','perpetual_usufruct'] to compare ownership vs perpetual usufruct on undeveloped land."New value: +"Legal-right type (rodzaj prawa), multi-select; perpetual_usufruct = użytkowanie wieczyste; 'unknown' = none recorded."
    • addedInput schema / properties / page
      Added value: +{
      +  "description": "Page 1-20 (50 rows).",
      +  "maximum": 20,
      +  "minimum": 1,
      +  "type": "integer"
      +}
    • changedInput schema / properties / polygon / description
      Previous value: -"GeoJSON Polygon geometry. Coordinates: [longitude, latitude] pairs. First and last point must be identical. Max 500 vertices total."New value: +"GeoJSON Polygon: [longitude, latitude] pairs, first and last point identical, max 500 vertices total."
    • changedInput schema / properties / rooms / description
      Previous value: -"Number of rooms (izby) filter, residential units only. Multi-select; '8plus' means 8 or more, 'unknown' = no room count recorded (NULL). E.g. ['2','3'] for 2-3 izby flats. Without 'unknown', rows with no room count are excluded."New value: +"Rooms (izby), residential units only; multi-select ('8plus' = 8 or more). Rows with no count drop out unless 'unknown' is listed."
    • changedInput schema / properties / transactionType / description
      Previous value: -"Transaction type filter. For market analysis, ALWAYS specify to exclude non-market transactions."New value: +"Multi-select. For market analysis ALWAYS set it to exclude non-market deeds (subsidized, foreclosure, public_purpose); no-type rows (~2%) drop out unless 'unknown' is listed."
    • changedInput schema / properties / unitFunction / description
      Previous value: -"Unit/apartment function filter. 'unknown' = no function recorded (NULL); without it such rows are excluded. Garages appear only when 'garage' is selected, not via 'unknown'."New value: +"Unit function; 'unknown' = none recorded (NULL), any other value excludes such rows. Garages only via 'garage'."
  2. Changed4 schema fields changedv0.12.0
    • addedInput schema / properties / buildingStoreys
      Added value: +{
      +  "description": "Number of above-ground storeys of the building. Multi-select buckets: exact non-negative integers (e.g. '1','2'), 'Nplus' e.g. '3plus' = 3 or more, 'unknown' = no storey count recorded (NULL). Recorded ONLY for single-building transactions, so 'unknown' covers BOTH a deed with several buildings (no single storey count exists) and a single building with missing data — never read it as 'a building with no storeys'. This is NOT the floor of a unit (see floor). Without 'unknown', rows with no storey count are excluded.",
      +  "items": {
      +    "pattern": "^(\\d+|\\d+plus|unknown)$",
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / landUse
      Added value: +{
      +  "description": "Recorded land-use category of the transaction's land. Multi-select from: gruntyZabudowaneIZurbanizowane (built-up and urbanised), gruntyRolne (agricultural), gruntyLesne (forest), terenyKomunikacyjne (transport), inne (other). 'unknown' = no category recorded for the land (NULL) — a legitimate bucket, never a claim that the land has no use. Values are case-sensitive. E.g. ['gruntyRolne'] for farmland, or ['gruntyZabudowaneIZurbanizowane','gruntyRolne'] to compare developed vs farmland.",
      +  "items": {
      +    "enum": [
      +      "gruntyZabudowaneIZurbanizowane",
      +      "gruntyRolne",
      +      "gruntyLesne",
      +      "terenyKomunikacyjne",
      +      "inne",
      +      "unknown"
      +    ],
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / maxFootprintArea
      Added value: +{
      +  "description": "Maximum building footprint (ground-plan) area in m², summed over all buildings of the transaction. Distinct from maxArea, which measures usable floor area (units) or land/parcel area. Set only where every linked building has footprint data, so this bound selects only measured rows — absence means 'not measured', not 'no building'.",
      +  "type": "number"
      +}
    • addedInput schema / properties / minFootprintArea
      Added value: +{
      +  "description": "Minimum building footprint (ground-plan) area in m², summed over all buildings of the transaction. Distinct from minArea, which measures usable floor area (units) or land/parcel area. Set only where every linked building has footprint data, so this bound selects only measured rows — absence means 'not measured', not 'no building'.",
      +  "type": "number"
      +}
  3. Changed2 schema fields changedv0.6.0
    • changedInput schema / properties / limit / description
      Previous value: -"Max results (1-5000, default 100). MCP displays up to 50 transactions."New value: +"Max results (1-3000, default 100). MCP displays up to 50 transactions."
    • changedInput schema / properties / limit / maximum
      Previous value: -5000New value: +3000
  4. First observedv0.5.0

TDQS

A4.7/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, and the description adds meaningful context beyond that: it costs 5 API tokens, returns transactions with coordinates and prices, includes a permalink construction pattern, and clarifies the naming mismatch. This is useful behavioral information that helps the agent set expectations.

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 front-loaded with the core purpose and routing guidance, then adds cost and permalink details. Every sentence earns its place by helping the agent choose and use the tool correctly.

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 complex 25-parameter read-only tool with no output schema, the description covers purpose, alternatives, token cost, return content, and permalink format. Combined with the fully documented schema, this is complete enough for correct invocation.

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%, so all 25 parameters are already well documented in the schema. The description only references the polygon and does not add parameter-level semantics beyond what the schema provides, so the baseline of 3 is appropriate.

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 and resource: find transactions inside a GeoJSON Polygon. It explicitly distinguishes this from search_by_area for quick looks and list_parcels_in_area for land plots, and clarifies that it returns transactions despite the tool name.

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 routing guidance: use this for precise neighborhood/osiedla boundaries, start with search_by_area for a quick look, and use list_parcels_in_area for land plots inside the same shape. It also states the token cost, which helps the agent decide when to invoke it.

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