Skip to main content
Glama
cenogram

cenogram-mcp-server

Official

Cenogram MCP Server

npm version Node.js License: MIT

Polish Real Estate Transaction & Parcel Data for AI

MCP server for Polish real estate data. Access 8M+ real estate transactions from the national Registry of Prices and Values (Rejestr Cen Nieruchomosci, RCN) - prices from notarial deeds, not listings - directly from Claude, Cursor, ChatGPT, Grok, or any MCP-compatible AI assistant. Beyond transaction prices, the server resolves cadastral parcels and adds per-parcel context: zoning, flood and landslide risk, heritage register, building permits and construction activity, public transport access, agricultural land classification, surrounding land use, nature - nearby forest and overlapping protected areas - what lies underground (mining terrains and major groundwater reservoirs), the land-use and soil-quality classification, and road access.

Data source: Polish national RCN registry (Rejestr Cen Nieruchomosci) | Platform: cenogram.pl

Get your API key

  1. Go to cenogram.pl/api

  2. Enter your email

  3. You'll receive your cngrm_... API key by email

Manage your keys at cenogram.pl/ustawienia.

Free tier

New accounts start with 1,000 tokens and a 14-day trial of the Standard plan. After that the key keeps working on 50 tokens a week - the balance is restored to 50 every 7 days rather than accumulating - with no expiry date and no card.

A call costs 1 token for statistics, reference data, parcel identity and municipal context; 2 for a transaction search, a price histogram or a list of the parcels in an area; 4 for one context layer of a parcel or transaction; 5 for spatial search, parcel outlines, valuation and a multi-district comparison; 45 for get_parcel_report, which returns every layer at once. Location catalogues are free. Paid plans raise the allowance - see cenogram.pl/api.

Related MCP server: rcs-mcp

Installation

Pick your client. All options below use the hosted server - no local install needed (except npx/stdio).

One command - zero config files:

claude mcp add cenogram https://mcp.cenogram.pl/mcp \
  -t http -H "Authorization: Bearer YOUR_API_KEY"

Add to .cursor/mcp.json in your project:

{
  "mcpServers": {
    "cenogram": {
      "type": "http",
      "url": "https://mcp.cenogram.pl/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Add to your config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

npx (stdio):

{
  "mcpServers": {
    "cenogram": {
      "command": "npx",
      "args": ["-y", "@cenogram/mcp-server@latest"],
      "env": {
        "CENOGRAM_API_KEY": "YOUR_API_KEY"
      }
    }
  }
}

Add to .vscode/mcp.json in your workspace:

{
  "servers": {
    "cenogram": {
      "type": "http",
      "url": "https://mcp.cenogram.pl/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Add to ~/.codeium/windsurf/mcp_config.json:

HTTP remote:

{
  "mcpServers": {
    "cenogram": {
      "type": "http",
      "url": "https://mcp.cenogram.pl/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

If HTTP doesn't work, use the npx (stdio) option below instead.

In VS Code: Settings > Cline > MCP Servers. Add:

{
  "cenogram": {
    "type": "http",
    "url": "https://mcp.cenogram.pl/mcp",
    "headers": {
      "Authorization": "Bearer YOUR_API_KEY"
    }
  }
}

Requires Node.js >= 18. Use this if you want to run the server locally instead of connecting to the hosted one.

{
  "mcpServers": {
    "cenogram": {
      "command": "npx",
      "args": ["-y", "@cenogram/mcp-server@latest"],
      "env": {
        "CENOGRAM_API_KEY": "YOUR_API_KEY"
      }
    }
  }
}

Client

Config file

Cursor

.cursor/mcp.json

Claude Code

.mcp.json in your project

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json

Windsurf

~/.codeium/windsurf/mcp_config.json

Cline

VS Code settings > Cline > MCP Servers

Configuration

Env Variable

Required

Default

Description

CENOGRAM_API_KEY

Yes (stdio)

-

API key from cenogram.pl/api

CENOGRAM_API_URL

No

https://cenogram.pl

API base URL

MCP_TRANSPORT

No

stdio

Set to http for Streamable HTTP mode

MCP_PORT

No

3002

HTTP server port (HTTP mode only)

CENOGRAM_CLIENT_ID

No

auto-generated

Persistent client identifier

You can also use the --http CLI flag instead of MCP_TRANSPORT=http.

Tips

  • Model selection: For best results, use Claude Opus 4.7. It makes more sequential tool calls and produces richer analysis. You can switch the model in the dropdown at the bottom of the chat window.

Example Prompts

Polish:

  • "Jaka jest mediana cen mieszkan w Krakowie w 2025?"

  • "Pokaz transakcje z ulicy Pulawskiej 15 na Mokotowie"

  • "Znajdz transakcje na dzialce 126104_9.0015.201"

  • "Sprawdz plan miejscowy i ryzyko powodziowe dla dzialki 126104_9.0015.201"

  • "Znajdz transakcje gruntow w promieniu 5km od centrum Wroclawia powyzej 500 000 PLN"

  • "Porownaj ceny mieszkan na Mokotowie i Woli"

  • "Pokaz rozklad cen nieruchomosci w Polsce"

English:

  • "What's the median apartment price in Krakow in 2025?"

  • "Show transactions at Pulawska 15 in Mokotow"

  • "Find all transactions on parcel 126104_9.0015.201 and then search nearby"

  • "Check the zoning and flood risk for parcel 126104_9.0015.201"

  • "Find land transactions within 5km of Wroclaw center above 500,000 PLN"

  • "Compare apartment prices in Mokotow and Wola districts"

  • "Show the price distribution of real estate in Poland"

Tools

Tool

Description

Key Parameters

search_transactions

Search transactions with filters

location, street, buildingNumber, parcelId, propertyType, marketType, price/date/area range

get_price_statistics

Price/m2 stats by location (residential only)

location (optional)

get_price_distribution

Price histogram

bins, maxPrice

search_by_area

Search transactions by geographic radius

latitude, longitude, radiusKm

get_market_overview

Database overview and stats

(none)

list_locations

List available locations

search (optional)

search_parcels

Search parcels by cadastral ID prefix

q (parcel ID prefix, min 3 chars)

list_parcels_in_area

List the cadastral parcels in an area - light list or full outlines

teryt, location, bbox, lat + lng + radiusKm, or polygon; includeGeometry, minArea/maxArea, street/buildingNumber, cursor

search_by_polygon

Search transactions within a GeoJSON polygon

polygon, propertyType, dateFrom/dateTo

compare_locations

Compare stats across 2-5 districts

districts (comma-separated), propertyType

get_building_breakdown

Per-building breakdown for one transaction (footprint, storeys, est. floor area)

transaction_id (UUID from a search result)

get_parcel_report

Composite dossier for one parcel: core, 13 enrichment layers, transaction history, local price context and municipal context

parcelId (cadastral id or UUID)

resolve_parcel

Resolve a parcel to its cadastral identity

parcelId, q (full cadastral id or 'locality + parcel number' - not a street address), or lat + lng

get_demographics

Population and demographic context for a location

location or teryt, year (or yearFrom/yearTo), category

get_infrastructure_signals

Municipal infrastructure signals (tenders, utilities, capital spending)

location or teryt

estimate_value

Comparable-sales value estimate for a property

area, plus lat + lng or parcelId; rooms, market

get_transaction_flood

Flood risk for the property in a transaction

transaction_id (UUID from a search result)

get_transaction_heritage

Heritage-register status for the property

transaction_id

get_transaction_landslide

Landslide risk for the property

transaction_id

get_transaction_surroundings

Nuisance and land-use context around the property

transaction_id

get_transaction_transit

Public transport accessibility for the property

transaction_id

get_transaction_permits

Building permits recorded for the property

transaction_id

get_transaction_planning

Local zoning and planning status for the property

transaction_id

get_transaction_farmland

Agricultural land-use classification for the property

transaction_id

get_transaction_nature

Nearby forest and overlapping protected natural areas for the property

transaction_id

get_transaction_subsurface

Mining terrains and major groundwater reservoirs under the property

transaction_id

get_transaction_roads

Geometric evidence of road access for the property (distances, road class, access indicator)

transaction_id

Location naming

  • Most cities: use the city name directly (e.g., "Gdansk", "Lublin")

  • Warsaw: "Warszawa" covers all 18 districts at once; name one ("Mokotow", "Srodmiescie", "Wola") to narrow it down

  • Krakow and Lodz work the same way: the city name covers every sub-district, or name one ("Krakow-Podgorze")

  • Neighbourhood names are not administrative units - search by radius or polygon instead

  • Use list_locations to find valid names

Property types

Value

Polish

English

land

Grunt

Land plot

building

Budynek

Building

developed_land

Grunt zabudowany

Developed land

unit

Lokal

Apartment/unit

Workflows

Results include parcel IDs and GPS coordinates, enabling multi-step research:

1. Search by address    -> search_transactions(location="Mokotow", street="Pulawska", buildingNumber="15")
2. Note parcel_id and coordinates from results
3. Search nearby        -> search_by_area(lat=52.19, lng=21.01, radiusKm=2, propertyType="unit")
4. Compare prices       -> get_price_statistics(location="Mokotow")

This mimics how a property appraiser finds comparable transactions for valuation reports.

Starting from the land rather than from a deed is a different route:

1. List the parcels     -> list_parcels_in_area(location="Wawer", minArea=800)
2. Draw the ones you want -> list_parcels_in_area(bbox="21.10,52.20,21.14,52.23", includeGeometry=true)
3. Open one in full     -> get_parcel_report(parcelId="146518_8.0108.27")

Step 1 pages by cursor; step 2 is capped and usually truncated, so narrow the box rather than reading a truncated answer as the parcel list of the area.

Data

  • 8M+ transactions from all of Poland (380 counties)

  • Date range: 2003 - present

  • Source: Polish national RCN registry (Rejestr Cen Nieruchomosci)

  • Refresh: periodic updates from RCN

  • Per-parcel context: zoning, flood and landslide risk, heritage register, building permits and construction activity, transit access, agricultural land use, surroundings, nature (nearby forest and protected areas), subsurface (mining terrains and major groundwater reservoirs), land-use and soil-quality classification, and road access - addressable by cadastral ID

Troubleshooting

"Error: CENOGRAM_API_KEY is required" - This only applies to stdio mode. Make sure CENOGRAM_API_KEY is set in the env block of your MCP config. For HTTP remote, the key goes in the Authorization header instead.

npx hangs or fails - Check your Node.js version with node -v. The stdio mode requires Node.js >= 18. If you're on an older version, use the HTTP remote option instead (no Node.js needed).

A location returns 0 results - The name may not be an administrative unit. Districts and neighbourhoods are two different things: "Mokotow" is a district and works, "Sluzew" is a neighbourhood inside it and does not. Use list_locations(search="...") to find valid names, or search by radius (search_by_area) for anything smaller than a district.

401 Unauthorized (HTTP mode) - The Authorization header must be Bearer cngrm_... (with the Bearer prefix). Double-check that the full API key is included, not just the prefix.

402 Payment Required - The account is out of tokens. On a free account the response says the date from which the balance is back at its weekly 50; the key and the connection stay valid until then. A paid plan lifts the limit - see cenogram.pl/api.

Development

git clone https://github.com/cenogram/mcp-server.git
cd mcp-server
npm install
npm test
npm run build

License

MIT

Available Tools

28 tools
compare_locationsA
Read-only
Inspect

Compare real estate statistics across multiple locations side-by-side. Provide 2-5 district names to compare median price/m², average area, and transaction counts. This tool matches on name only. Call list_locations(search=...) first: use names it flags as RCN districts (rcn_district) — other names (most TERYT unit names) silently return no data here. Requires at least one filter besides districts (e.g., propertyType). Example: compare Mokotów, Wola, Ursynów for apartments. Note: median/average prices are market-based — fractional ownership shares and non-market deeds (public tenders, foreclosures, privileged/subsidized sales) are excluded from price aggregates. Transaction counts and coverage stay complete.

ParametersJSON Schema
NameRequiredDescriptionDefault
floorNoFloor 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.
roomsNoNumber 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.
dateToNoEnd date (YYYY-MM-DD)
streetNoStreet name filter
maxAreaNoMaximum area in m²
minAreaNoMinimum area in m²
dateFromNoStart date (YYYY-MM-DD)
maxPriceNoMaximum price in PLN
minPriceNoMinimum price in PLN
districtsYesComma-separated district names to compare (2-5, must be unique). E.g. 'Mokotów,Wola,Ursynów'
marketTypeNoMarket type filter
buildingTypeNoBuilding type filter (PKOB classification). 'unknown' = no type recorded (NULL); without it such rows are excluded (~39% of buildings have no type).
propertyTypeNoProperty type filter (recommended - API requires at least one filter)
unitFunctionNoUnit/apartment function filter. 'unknown' = no function recorded (NULL); without it such rows are excluded. Garages appear only when 'garage' is selected, not via 'unknown'.
ownershipTypeNoOwnership / 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.
mpzpDesignationNoMPZP zoning designation prefix filter (e.g. 'terenRolniczy', 'budownictwoMieszkanioweJednorodzinne', 'budownictwoMieszkanioweWielorodzinne'). Use 'unknown' for rows with no designation recorded (NULL); distinct from the registry code 'brakMPZPLubWZ'.
transactionTypeNoTransaction type filter. For market analysis, ALWAYS specify to exclude non-market transactions.
includeDemographicsNoAdd a GUS BDL demographics block per district (county-level: population density, wages, unemployment, median age, plus a few cross-source ratios like price-to-income). Districts that don't resolve to a county are omitted from the demographics section.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already cover read-only/non-destructive behavior, and the description adds meaningful behavioral context beyond that: name-only matching, silent no-data outcomes, exclusion of non-market transactions from price aggregates, and clarity that counts/coverage remain complete. This is exactly the kind of extra 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 compact and front-loaded: purpose, constraints, example, then data-quality note. Every sentence contributes either to correct usage or behavioral understanding, with no redundancy or filler.

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?

For an 18-parameter tool with no output schema, the description covers the most critical operational pitfalls: name matching, required filter, and which data is excluded. It does not describe the response shape or failure handling, but the given context is strong and likely sufficient for an agent to invoke the tool correctly.

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. The description adds value beyond the schema by explaining how the districts parameter must be populated (RCN names from list_locations), that an additional filter is required, and by giving a concrete example. This is enough to justify a 4, though not a 5 since most parameter details are already in the schema.

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 uses a specific verb ('Compare') and resource ('real estate statistics across multiple locations side-by-side') and names the exact metrics (median price/m², average area, transaction counts). It clearly differentiates from the many sibling get_* tools by emphasizing the multi-location comparison aspect.

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 guidance: call list_locations first, use names flagged as rcn_district, and warns that other names silently return no data. It also states the hard requirement of at least one filter besides districts and provides a concrete example, leaving little to inference.

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

estimate_valueA
Read-only
Inspect

[Beta] Estimate the market value of an apartment from comparable registered transaction prices near a point. An orientation estimate, NOT a certified appraisal (operat szacunkowy) — it does not account for the unit's condition, finish standard or floor, and does not replace a surveyor's valuation. Address by lat + lng (a point on the map) OR parcelId (a full cadastral id or internal UUID; the parcel centroid is used) — exactly one. area (usable area in m², 10–250) is REQUIRED: there is no per-address floor-area source in Poland, so the caller supplies it. Optional: rooms (1–10) and market (primary/secondary) narrow the comparables; includeComps (default true) echoes the nearest comparables it weighed. Returns the point estimate, a likely and a wide value range, a confidence band, the comparable count, and an as_of date. as_of reflects transaction-data freshness, which lags by county — estimates are NOT directly comparable across cities with different as_of. Apartments only (v1), 10–250 m². Too few comparables near the point → no estimate (the credit is refunded). Costs 5 API tokens, refunded when no estimate is produced. Note: median/average prices are market-based — fractional ownership shares and non-market deeds (public tenders, foreclosures, privileged/subsidized sales) are excluded from price aggregates. Transaction counts and coverage stay complete.

ParametersJSON Schema
NameRequiredDescriptionDefault
latNoLatitude of the apartment (WGS84, Poland). Must be paired with lng. Use this OR parcelId.
lngNoLongitude of the apartment (WGS84, Poland). Must be paired with lat. Use this OR parcelId.
areaYesApartment usable area in m² (REQUIRED, 10–250). Estimates for 300+ m² are unreliable and rejected.
roomsNoRoom count (1–10, optional) — narrows the comparables to ±1 room.
marketNoRestrict comparables to the primary (new-build) or secondary market (optional).
parcelIdNoFull cadastral id (slash or dash form) or internal UUID; the parcel centroid is used. Use instead of lat/lng.
includeCompsNoEcho the nearest comparables the estimate weighed (default true). Set false for the estimate only.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds transparency about beta status, token cost, refund on no estimate, data freshness lag, and exclusion of fractional shares, providing a complete picture of behavior.

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

Conciseness4/5

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

The description is well-structured with sections for purpose, constraints, parameters, returns, and disclaimers. It is slightly verbose but front-loads the main purpose effectively.

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 the tool's complexity (7 parameters, no output schema), the description covers all aspects: what it returns, how it works, limitations, token cost, and edge cases like insufficient comparables. It is comprehensive.

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 coverage is 100%, but the description adds value by explaining why area is required (no floor-area source in Poland), the mutual exclusivity of location parameters, and the effect of optional parameters on narrowing comparables.

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 clearly states the tool estimates market value of an apartment from comparable transactions. It distinguishes itself from a certified appraisal and from sibling tools like search_transactions or get_price_statistics by focusing on estimation.

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 says when to use (orientation estimate) and when not (not a certified appraisal). It also specifies required parameter (area) and mutually exclusive location parameters (lat/lng or parcelId), providing clear guidance.

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

get_building_breakdownA
Read-only
Inspect

Get the building-by-building breakdown for one transaction: footprint area, number of storeys, and estimated total floor area (footprint × storeys) for each building on the property. search_transactions / search_by_area / search_by_polygon return per-transaction building SUMS inline; this tool splits them into individual buildings. Use it after a search when a result has building data and you need the detail (e.g. a developed-land deed covering several buildings). Each building also carries a construction-age estimate derived from building-permit records. It is an ESTIMATE with an interval, never a registry construction date, and the records only start in 2016 — so for most buildings the honest answer is "construction year not established", which is stated explicitly rather than left out. The transaction_id is the id shown on a search result that has building data. Cost: 4 tokens. Returns nothing for a transaction with no buildings.

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result that carries building data.

TDQS

A4.7/5.0
Behavior5/5

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

Goes well beyond the readOnlyHint annotation: it warns that construction-age values are estimates, not registry dates, that permit records only begin in 2016, and that 'not established' is stated explicitly rather than omitted. It also discloses the 4-token cost and the empty result for transactions with no buildings.

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 longer than average but every sentence adds necessary operational detail: what the tool returns, when to use it, data-quality caveats, and empty-result behavior. The key identifiers and usage are front-loaded, with caveats and cost after.

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?

With no output schema present, the description covers return fields (footprint area, number of storeys, estimated total floor area, construction-age estimate), the no-buildings edge case, cost, input origin, and usage context. An agent has enough to invoke it correctly and interpret results.

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 coverage is complete: the input schema already says transaction_id is a UUID from search_transactions/search_by_area/search_by_polygon that carries building data. The description mostly restates this, adding at most a pointer to 'the id shown on a search result'. It provides no substantial meaning beyond the schema.

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 verb and outcome ('Get the building-by-building breakdown for one transaction') and enumerates the exact fields returned (footprint area, storeys, estimated total floor area). It also explicitly distinguishes this tool from the search tools that return per-transaction building sums inline, so an agent can immediately tell what it does and what it is not.

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 gives clear when-to-use guidance: call it after a search when a result has building data and you need per-building detail, e.g. for a developed-land deed. It also contrasts it with search_transactions / search_by_area / search_by_polygon, which return sums, making the choice between sibling tools explicit.

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

get_demographicsA
Read-only
Inspect

Demographic, economic, housing and other local statistics for a Polish location, from GUS BDL (Bank Danych Lokalnych) — Poland's public Central Statistical Office open-data bank. ~50 indicators across 11 categories (population, economy, housing, spatial planning, infrastructure, environment, safety, education, prices) plus a few derived metrics. Address by location (city/county name) OR teryt. A name resolves to county/powiat (4-digit) level; for richer gmina/district-level data (L6) pass a 6 or 7-digit teryt. teryt wins when both are given. Use list_locations to find TERYT codes — neighborhoods/osiedla are NOT addressable here. A query returns the requested level PLUS all parent levels (a gmina query also yields powiat, NUTS3 region and voivodeship indicators). Optional year, or yearFrom+yearTo for a time series, and category to filter. Cost: 1 token.

ParametersJSON Schema
NameRequiredDescriptionDefault
yearNoSingle year (2003-present). Mutually exclusive with yearFrom/yearTo. Omit for the latest available year per indicator.
terytNoTERYT code: 2-digit (voivodeship, e.g. 14), 4-digit (county, e.g. 1465), 6 or 7-digit (gmina, e.g. 1465011). The 7th digit selects the unit type: 3 = urban-rural gmina overall, 4/5 = urban/rural part only, 8 = Warszawa district (1465011 = all of Warszawa, 1465108 = Śródmieście). Wins over location. Use list_locations to find codes.
yearToNoEnd year for a time series (max current year + 1).
categoryNoFilter to these categories. Omit to return all available.
locationNoCity, county, or district name (e.g. 'Warszawa', 'Kraków'). A city/county name resolves to county/powiat level; a Warszawa district name (e.g. 'Mokotów') resolves to that district, another city's delegatura (e.g. 'Kraków-Podgórze') to its parent county. Use this OR teryt. For gmina-level data on other units pass a 6/7-digit teryt instead.
yearFromNoStart year for a time series (min 2003).

TDQS

A4.5/5.0
Behavior4/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 behavioral detail: query results include all parent levels, a name resolves to county level while teryt wins when both are given, and cost is 1 token. This goes well beyond the annotation signal.

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 long but each sentence earns its place: source, indicator scope, addressing rules, hierarchy behavior, and filtering options. Critical constraints are front-loaded, and no filler or repeated schema text is present.

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 flexible read-only lookup with six optional parameters and no output schema, the description covers everything an agent needs: what data comes back, how to specify a location, how to get finer geographic levels, how to filter by category, and how to request a time series. The absence of an output schema is compensated by the explicit parent-level return behavior.

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, but the description adds genuine value: it explains teryt digit-level resolution, the 7th digit unit-type meaning, the precedence of teryt over location, parent-level expansion, and the year vs yearFrom/yearTo semantics. This materially helps an agent choose and combine parameters correctly.

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 verb+resource: it returns demographic, economic, housing, and other local statistics for a Polish location from GUS BDL, with ~50 indicators across 11 categories. This distinguishes it clearly from the many transaction, parcel, and pricing siblings.

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 practical routing guidance: use list_locations to find TERYT codes, pass a 6/7-digit teryt for gmina-level data, and note that neighborhoods/osiedla are NOT addressable here. It doesn't explicitly contrast with sibling tools like compare_locations or get_market_overview, but the domain is clear enough that an agent can infer when this tool is appropriate.

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

get_infrastructure_signalsA
Read-only
Inspect

Signals that a Polish municipality is about to build infrastructure — sewerage, water supply, roads, street lighting, gas network or cycling infrastructure. Three independent public sources: tenders published in the national public procurement bulletin (rolling 12-month window), membership in an agglomeration of the national urban waste-water treatment programme (where collective sewerage exists or is planned), and the municipality's own planned capital expenditure from its multi-year financial forecast. Address by location (city/county name → aggregates every municipality in that county) OR teryt (6-7 digits = one municipality, 4 digits = a county aggregate). teryt wins when both are given. Use list_locations to find codes. Known limits, state them when you report results: the bulletin carries only contracts BELOW the EU procurement thresholds (from 2021), so the largest investments are not visible here. A tender is attributed to the SEAT of the contracting authority, not to the works location — county and national authorities tender works in other municipalities. The category counters therefore include municipal authorities only, while the recent-notice list shows every authority with a flag. Absence of tenders is NOT evidence that a municipality is not investing. Cost: 1 token.

ParametersJSON Schema
NameRequiredDescriptionDefault
terytNoTERYT code: 6 or 7 digits = one municipality (e.g. 146501), 4 digits = a county aggregate (e.g. 1465). Wins over location.
locationNoCity, county, or district name (e.g. 'Warszawa', 'Krotoszyn'). A city/county name aggregates every municipality in the county; a Warszawa district name (e.g. 'Mokotów') narrows to that gmina, another city's delegatura (e.g. 'Kraków-Podgórze') resolves to its parent county. Use this OR teryt.

TDQS

A4.3/5.0
Behavior5/5

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

The description goes far beyond the readOnlyHint/destructiveHint annotations by disclosing the rolling 12-month window, EU-threshold limitation, seat-of-authority attribution caveat, the difference between category counters and the recent-notice list, and the warning that absence of tenders is not evidence of no investment. These are material behavioral limitations an agent must know before reporting results.

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

Conciseness4/5

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

The description is longer than average, but the length is justified by the data-source caveats and usage rules that cannot be safely omitted. It is front-loaded with the core purpose, then moves through addressing, limitations, and cost in a logical order, though some parameter details are redundant with the schema.

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?

Given the tool's complexity and the absence of an output schema, the description does a good job covering data sources, aggregation semantics, and known caveats. It references output elements like 'category counters' and 'recent-notice list' without fully specifying the return shape, but the essential interpretive context is present.

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%, and the input schema already explains teryt formats, aggregation behavior, and the precedence rule. The description largely repeats these points rather than adding new parameter-level meaning; its only additional value is pointing to list_locations for finding codes.

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 verb and resource: it detects signals that a Polish municipality is about to build infrastructure, listing exact infrastructure types. It names the three data sources, making the tool's scope concrete and clearly distinct from the many transaction-focused sibling tools.

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?

It gives explicit usage context: address by location or teryt, with teryt taking precedence, and directs the agent to list_locations for finding codes. It also tells the agent to state known limits when reporting results. It does not explicitly name alternative tools or exclusions, but no sibling directly overlaps this tool's purpose.

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

get_market_overviewA
Read-only
Inspect

Get a comprehensive overview of the Polish real estate transaction database. Returns: total transaction count, date range, breakdown by property type and market type, top locations, price statistics. Note: data quality varies by field - marketType is unknown for ~55% of records, transaction_date missing for ~1.7%. Note: median/average prices are market-based — fractional ownership shares and non-market deeds (public tenders, foreclosures, privileged/subsidized sales) are excluded from price aggregates. Transaction counts and coverage stay complete.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior4/5

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

Annotations only indicate readOnlyHint=true and destructiveHint=false. The description adds important behavioral context, including data quality issues (marketType unknown for ~55%, transaction_date missing for ~1.7%) and exclusions in price aggregates (fractional shares, non-market deeds). This is valuable beyond 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.

Conciseness4/5

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

The description is well-structured with a lead sentence, a list of returns, and bullet-pointed notes. It is slightly verbose but each sentence adds value (data quality, price exclusions). Front-loading is effective.

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?

With zero parameters and no output schema, the description fully compensates by detailing return values and caveats. The tool is well-defined for its purpose as a broad overview, and the caveats about data quality and price calculation are critical for correct interpretation.

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?

There are zero parameters, so the input schema provides full coverage. The description adds no extra meaning for parameters, but no additional documentation is needed. The description is complete and clear.

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 clearly states the tool returns a 'comprehensive overview of the Polish real estate transaction database' and lists specific data elements (total transaction count, date range, breakdowns, top locations, price statistics). This distinguishes it from siblings like get_price_statistics or get_demographics.

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

Usage Guidelines3/5

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

The description implies usage for high-level summary but does not explicitly state when to use this over alternatives like search_transactions or get_price_statistics. No exclusion criteria or when-not-to-use guidance is provided.

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

get_parcel_land_classA
Read-only
Inspect

The official land-use and soil-quality classification recorded for one land parcel, and what it implies for taking the land out of agricultural use. Returns the land-use categories and the soil-quality grades entered for the parcel, whether any of those grades is in the protected I-III range, whether the parcel lies inside a city's administrative boundary (which changes the rule that applies), and a note on the re-designation consequences with the date the legal state behind it was verified. Use it when the question is specifically about the classification or about re-designating farmland. For anything else about the parcel — price history, flood risk, zoning, buildings, permits, surroundings, transport — call get_parcel_report instead: it is one call at a flat price and includes this same classification as one of its sections. Address it by a full cadastral id in the natural '/' form ('142907_2.0014.342/5'), the URL-safe '-' form, or the internal UUID from a search or resolve result. The categories and grades come back as SETS. The source records no area for any of them, so the answer can never say which category prevails on the parcel or give a share — a parcel listing two categories has both, in unknown proportion. This layer answers only where the county publishes the classification; many counties, including several large cities, do not. Four states, told apart explicitly: covered = the county publishes it and the parcel has an entry; covered_no_data = the county publishes it and this parcel has none (a checked negative — still billed); not_covered = the county does not publish it, or we do not hold the parcel (refunded); not_computed = the lookup could not finish in time (refunded — retry). Costs 4 API tokens, refunded on not_covered and not_computed. Not legal advice, and never a statement that a parcel can or cannot be built on.

ParametersJSON Schema
NameRequiredDescriptionDefault
parcelIdYesFull cadastral id ('142907_2.0014.342/5' or the '-' form) or the internal UUID from a search/resolve result.

TDQS

A4.9/5.0
Behavior5/5

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

The description substantially extends the read-only/destructive annotations. It explains that categories and grades return as sets with no area proportions, covers regional coverage limitations, enumerates the four distinct lookup states with their billing/refund behavior, and adds a clear non-legal-advice caveat. No contradiction exists with readOnlyHint=true or destructiveHint=false.

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 organized into clear thematic paragraphs, one for outputs, one for routing, one for input formatting, one for result semantics, one for coverage states, and one for costs and limits. Each sentence adds necessary operational or interpretive value; there is no fluff.

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 there is no output schema, the description carries the burden of explaining the response. It covers what is returned, how values are represented, when the data is absent, how billing and refunds behave, and what limitations apply. This is complete enough for an agent to select and invoke the tool correctly.

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 already documents parcelId with 100% coverage, naming the natural form, dash form, and UUID. The description adds concrete examples and the exact expected notation, including the '/'-separated cadastral format and the URL-safe alternative, which is useful beyond the schema alone.

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 verb and resource: it returns the official land-use and soil-quality classification for one land parcel and what it means for taking land out of agricultural use. It lists the concrete pieces of information returned and explicitly separates this tool from get_parcel_report by naming the alternative for unrelated parcel questions.

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 gives clear when-to-use guidance: 'Use it when the question is specifically about the classification or about re-designating farmland.' It also gives explicit when-not-to-use guidance, naming get_parcel_report and explaining how that sibling includes the same classification in a broader response.

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

get_parcel_reportA
Read-only
Inspect

The whole dossier for one land parcel in a single call: the parcel core (location, area, land use, plan designation), all thirteen enrichment layers (flood risk, heritage listing, landslide risk, subsurface: mining terrains and major groundwater reservoirs, nuisance surroundings, public-transport access, general-plan zoning, buildings on the parcel, recent building activity, agricultural-land eligibility, official land-use & soil-quality classification with its re-designation consequences where the county publishes it, nature: nearby forest and protected areas, roads: geometric road-access evidence measured from carriageway centrelines, which is not a determination of legal access), the parcel's transaction history (newest first, up to 20), a local price context (median zł/m² for the county and the locality over the last 12 months) and a municipal context (a headline demographic/economic subset plus upcoming-infrastructure signals for the gmina). Address it by a full cadastral id in the natural '/' form ('142907_2.0014.342/5'), the URL-safe '-' form, or the internal UUID from a search or resolve result. Each section carries its own state, shown explicitly: covered = a definitive result; covered_no_data = the parcel was checked and nothing was found (still billed); not_covered = outside our data (refunded); not_computed = a live computation could not finish in time (refunded — the rest of the report still returns, so a report can be partial). The two context sections instead use full / low_sample / suppressed / no_data. The buildings section additionally reports how many of the buildings could be given a construction-age estimate from building-permit records. That is an ESTIMATE with an interval, never a registry construction date, and the records only start in 2016, so for most buildings the answer is that the year could not be established — which is stated rather than omitted. Prefer this over calling the per-layer parcel tools one by one — it is one call at a flat price and never costs more than the sum of its parts. Use resolve_parcel first when you only have an address, a coordinate, or a 'locality + number'. Costs 45 API tokens. Billing is by outcome (see the billing line on the response): a parcel that cannot be resolved is fully refunded; a resolved parcel where no layer had data is billed only the core floor (1 token) with the rest refunded; a resolved parcel with at least one covered layer is billed in full.

ParametersJSON Schema
NameRequiredDescriptionDefault
parcelIdYesFull cadastral id ('142907_2.0014.342/5' or the '-' form) or the internal UUID from a search/resolve result.

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the readOnlyHint/destructiveHint annotations, the description explains per-section state semantics (covered, covered_no_data, not_covered, not_computed), billing and refund behavior, partial-report behavior, and the buildings construction-age estimate caveat with its 2016 data limitation. There is no contradiction with 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?

Though long, every paragraph earns its place: contents, ID formats, section states, the buildings estimate caveat, usage preference, and billing. The most important one-line definition is front-loaded, with supporting detail organized clearly afterward.

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 tool with one parameter and no output schema, the description is remarkably complete. It tells the agent what sections to expect, how each section's state should be interpreted, what gets refunded, what a partial report means, and what the token cost is. An agent can confidently select and invoke this tool without additional information.

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 already describes parcelId at 100% coverage, so the baseline is 3. The description adds value by giving concrete accepted forms ('142907_2.0014.342/5', the '-' form, or the internal UUID from a search/resolve result) and by connecting ID resolution to resolve_parcel. This goes slightly beyond the schema without being redundant.

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 verb and resource: 'The whole dossier for one land parcel in a single call.' It then enumerates exactly what the report contains, including core parcel data, enrichment layers, transaction history, price context, and municipal context. This clearly distinguishes it from sibling per-layer tools such as get_flood_risk or get_transaction_roads.

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 gives explicit routing guidance: 'Prefer this over calling the per-layer parcel tools one by one' and 'Use resolve_parcel first when you only have an address, a coordinate, or a locality + number.' This tells the agent exactly when to use this tool versus alternatives.

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

get_price_distributionA
Read-only
Inspect

Get price distribution histogram showing how many transactions fall into each price range. Useful for understanding the overall market price structure in Poland. Note: median/average prices are market-based — fractional ownership shares and non-market deeds (public tenders, foreclosures, privileged/subsidized sales) are excluded from price aggregates. Transaction counts and coverage stay complete.

ParametersJSON Schema
NameRequiredDescriptionDefault
binsNoNumber of price bins (5-50, default 20)
maxPriceNoMaximum price to include (default 3,000,000 PLN)

TDQS

A4.1/5.0
Behavior4/5

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

The note explains that median/average prices exclude fractional ownership and non-market deeds, while transaction counts remain complete. This adds behavioral context beyond the readOnlyHint and destructiveHint annotations, informing agents about data quality and exclusions.

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 brief, front-loaded with the main purpose, and uses a concise note for important exclusions. Every sentence adds value without repetition or verbosity.

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 read-only tool with two parameters and no output schema, the description fully covers the output (histogram) and key behavioral notes. No gaps are apparent given the tool's complexity.

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?

The input schema already provides descriptions and defaults for both parameters (bins and maxPrice). The description does not add further parameter semantics beyond what the schema covers, so baseline score applies.

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 clearly states the tool returns a price distribution histogram showing transaction counts per price range, distinguishing it from siblings like get_price_statistics and get_market_overview. The title 'Price Distribution Histogram' further reinforces the specific resource.

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

Usage Guidelines3/5

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

The description mentions it is 'useful for understanding the overall market price structure in Poland,' providing context but no explicit comparison to alternatives like get_price_statistics or get_market_overview. No when-not-to-use or alternative tool references are given.

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

get_price_statisticsA
Read-only
Inspect

Get price per m² statistics by location for residential apartments in Poland. Note: only covers residential units (lokale mieszkalne). For other property types, use search_transactions. 'Warszawa'/'Kraków'/'Łódź' auto-expand to all sub-districts (Warszawa=19, Kraków=5, Łódź=6). Other names use partial match. Data quality: based on transaction prices from notarial deeds, not asking/listing prices. Coverage varies by county (some have data gaps of 5+ years). Note: median/average prices are market-based — fractional ownership shares and non-market deeds (public tenders, foreclosures, privileged/subsidized sales) are excluded from price aggregates. Transaction counts and coverage stay complete.

ParametersJSON Schema
NameRequiredDescriptionDefault
locationNoFilter by location name. 'Warszawa'/'Kraków'/'Łódź' auto-expand to all sub-districts. Other names use case-insensitive partial match (e.g. 'Wrocł' matches 'Wrocław'). Omit for all Poland.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnlyHint and destructiveHint, but description adds critical context: data source (notarial deeds), coverage gaps, exclusion of fractional ownership and non-market deeds from price aggregates, and retention of transaction counts.

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

Conciseness4/5

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

Well-structured with clear notes, though slightly verbose. Every sentence earns its place, providing essential context without redundancy.

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?

Despite no output schema, description thoroughly covers what statistics are provided, data quality, and exclusions, making it complete for usage.

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% for the single parameter, but description adds valuable behavioral details about auto-expansion and partial matching, going beyond the schema description.

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?

Clearly states the tool retrieves price per m² statistics for residential apartments in Poland, distinguishing it from sibling tools like search_transactions which handle other property types.

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?

Explicitly specifies it only covers residential units and directs to search_transactions for other property types. Also details auto-expansion for major cities and partial match behavior.

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

get_transaction_farmlandA
Read-only
Inspect

Get the parcel-by-parcel agricultural land-eligibility breakdown for one transaction, from official nationwide agricultural land-eligibility data (updated weekly): for each linked parcel with a matched eligible agricultural area — the eligible area in square metres, its share of the parcel (when the parcel's measured area is known), and how many source features compose it. The response also reports how many of the transaction's linked parcels carry a match and the source snapshot date. Useful for due-diligence on land that is actually eligible/maintained as agricultural (beyond what a registry classification says on paper). TWO-STATE: a parcel with no matched eligible area returns nothing — absence of a match is NEVER a statement that the property is non-agricultural (small plots that are not actively farmed are simply absent, the reference layer has its own update cadence, and older transactions can reference renumbered parcels). Cost: 4 tokens (refunded when there is no eligible agricultural area for the linked parcels).

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.6/5.0
Behavior5/5

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

Beyond annotations (readOnlyHint, destructiveHint), description discloses two-state behavior (no match ≠ non-agricultural), cost (4 tokens refunded when no eligible area), and data source freshness (updated weekly). Adds critical interpretative guidance.

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

Conciseness4/5

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

Front-loaded with main purpose, followed by details and important notes. Slightly lengthy but each sentence adds value; well-organized.

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?

Despite no output schema, description explains response structure (eligible area, share, source features, match count, snapshot date). Combined with behavioral notes, provides full understanding for a read-only tool.

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 100% with parameter description. Description adds context that transaction_id comes from specific search tools (search_transactions, search_by_area, search_by_polygon), aiding correct sourcing.

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?

Describes a specific action ('get parcel-by-parcel agricultural land-eligibility breakdown for one transaction') with a clear resource and scope. Distinct from sibling tools which cover other transaction aspects (flood, heritage, etc.).

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?

States the tool is 'useful for due-diligence on land that is actually eligible/maintained as agricultural'. Provides context on when to use, but does not explicitly mention when not to use or alternative tools.

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

get_transaction_floodA
Read-only
Inspect

Get the parcel-by-parcel flood-hazard breakdown for one transaction: for each linked plot that sits in a mapped flood zone — the worst hazard category (high/medium/low, i.e. ~1-in-10-year to ~1-in-500-year), the hazard type (river/coastal/infrastructure), the share of the plot inside the zone, and the full per-scenario list (each with its return period). search_transactions (and search_by_area) surface a per-transaction worst-case flood_risk inline; this tool splits that into the individual parcels and scenarios behind it. Use it after a search when a result shows flood_risk. (search_by_polygon does not include flood inline.) TWO-STATE: a transaction whose land is in no mapped zone returns nothing — absence of a zone is never asserted as "safe". Cost: 4 tokens (refunded when there is no flood data).

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already provide readOnlyHint and destructiveHint, but the description adds substantial behavioral details: the two-state behavior (no return when no flood zone, with warning that absence is not safety), the cost structure (4 tokens, refunded if no flood data), and the exact data returned (worst hazard category, type, share, full per-scenario list).

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

Conciseness4/5

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

The description is well-structured with three paragraphs: main purpose, usage guidance, and edge case with cost. It is moderately long but front-loaded with core functionality. Could be slightly more concise but earns a 4.

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?

The tool has no output schema, but the description comprehensively explains returned data (category, type, share, per-scenario list) and the two-state behavior. For a single-parameter tool, this is fully complete.

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 coverage is 100% with the single parameter having a clear description. The tool description repeats but does not add new information beyond what the schema provides. Baseline 3 is appropriate as schema does the heavy lifting.

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 clearly states 'Get the parcel-by-parcel flood-hazard breakdown for one transaction' with a specific verb and resource. It distinguishes from siblings by noting that search_transactions surfaces inline flood_risk, while this tool splits it into parcels, and search_by_polygon lacks inline flood data.

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?

Explicit guidance on when to use: 'Use it after a search when a result shows flood_risk.' It also clarifies that search_transactions and search_by_area provide inline flood_risk, while search_by_polygon does not, providing clear context for alternatives.

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

get_transaction_heritageA
Read-only
Inspect

Get the parcel-by-parcel heritage-listing breakdown for one transaction: for each linked plot with a detected heritage listing — the status (listed = a protected monument on/at the plot; zone = the plot lies within a protected urban layout or the designated surroundings of a monument), the share of the plot inside the protected area (when measurable), and the individual entries (category, name, function, period, entry date). search_transactions (and search_by_area) surface a per-transaction heritage_status inline; this tool splits that into the individual parcels and entries behind it. Use it after a search when a result shows a heritage listing. (search_by_polygon does not include heritage inline.) TWO-STATE: a transaction with no detected listing returns nothing — absence of a detection is never asserted as "not listed". Indicative data — the regional heritage conservator makes the final, binding determination. Cost: 4 tokens (refunded when there is no heritage data).

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false. Description adds important behavioral details: TWO-STATE (returns nothing if no listing), indicative data caveat, and cost/token refund policy, enhancing transparency beyond annotations.

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

Conciseness4/5

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

Well-structured with purpose first, then usage guidance, then caveats. Slightly verbose with the TWO-STATE explanation and disclaimer, but each sentence adds value.

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?

Despite no output schema, description completely explains output structure (per parcel: status, share, individual entries with fields), intended use case, limitations, and cost. No gaps for a getter tool.

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?

Only parameter transaction_id is fully covered by schema (100%), but description provides crucial context: it must come from a search result (search_transactions/search_by_area/search_by_polygon), adding meaning beyond the schema's format constraint.

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 clearly states the verb 'Get' and the resource 'parcel-by-parcel heritage-listing breakdown for one transaction', differentiating it from sibling tools like search_transactions which only surface inline heritage status.

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?

Explicitly states when to use ('after a search when a result shows a heritage listing'), provides exclusions (search_by_polygon does not include heritage inline), and clarifies that absence of detection is not 'not listed'. Also includes cost and refund behavior.

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

get_transaction_landslideA
Read-only
Inspect

Get the parcel-by-parcel landslide-hazard breakdown for one transaction, based on official landslide-hazard maps (1:10,000 scale): for each linked plot that intersects a mapped hazard area — the worst category ('landslide' = a mapped landslide area, 'threatened' = an area threatened by mass movements), the share of the plot inside the mapped zones, and the per-zone list (each with its source_version_date — the source-record version date, not a survey/observation date). An intersection at this scale means the parcel overlaps a mapped hazard area, not that the parcel itself is a landslide. search_transactions (and search_by_area) surface a per-transaction worst-case landslide_risk inline; this tool splits that into the individual parcels and zones behind it. Use it after a search when a result shows a landslide risk. (search_by_polygon does not include landslide inline.) TWO-STATE: a transaction whose land is in no mapped zone returns nothing — absence of data is never an assertion of safety. Cost: 4 tokens (refunded when there is no landslide data).

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations indicate read-only and non-destructive. Description adds that intersection means overlap, not that the parcel is a landslide; two-state behavior (empty return when no data); cost of 4 tokens refunded when no data. No contradiction with annotations.

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

Conciseness4/5

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

Description is thorough but well-structured. Front-loaded with purpose, then details, usage guidance, and cost. Each sentence adds value, though slightly lengthy. Could be trimmed slightly but still effective.

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 one parameter and no output schema, the description covers all needed context: what the tool does, return data details, when to use, behavioral nuances, and cost. Complete for the tool's complexity.

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?

Only one parameter with 100% schema coverage. Description adds context that the ID comes from search results, but schema already specifies pattern and description. Baseline 3 is appropriate as no extra semantics beyond what schema provides.

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?

Clearly states it gets a parcel-by-parcel landslide-hazard breakdown for one transaction. Distinguishes from siblings by noting that search_transactions and search_by_area surface worst-case inline, while this tool splits into parcels. Also notes that search_by_polygon does not include landslide inline.

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?

Explicitly say to use it after a search when a result shows a landslide risk. Describes when not to expect results (no mapped zone returns nothing, not a safety assertion). Also mentions cost and refund conditions.

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

get_transaction_natureA
Read-only
Inspect

Get the parcel-by-parcel nature breakdown for one transaction: for each linked plot with a nature signal — the nearest forest within 2 km (forest_distance_m in metres, 0 = the plot overlaps forest, with its overlap share) and any overlapping protected natural areas: the sharpest form (protection_rank 1 = national park, 2 = nature reserve, 3 = Natura 2000, 4 = landscape park, 5 = protected landscape, 6 = other), building_restriction ('statutory_ban' = a build ban that follows directly from the Nature Protection Act for national parks and reserves, 'conditional' = restrictions depend on the act that established the area), the share of the plot under protection, and the named areas. This describes the SOURCE of a restriction (statute vs the establishing act), never the outcome of a specific permitting case, and is not legal advice. Forest is an amenity signal (proximity), protected areas a due-diligence one (build limits). Search results do not carry a nature signal, so call this tool directly on a transaction id whenever forest proximity or protected-area build limits matter. Use it after a search on land plots. An empty result is NEVER a statement that building is allowed — this layer does not cover local zoning plans, planning-permission decisions or areas under designation. A buffer zone around a park or reserve IS reported, as form 'buffer_zone' at rank 6, and never as a statutory ban. An empty result also says which kind of empty it is: either the plots were checked and carry no signal, or no nature reference data is held for them yet and nothing was checked — the second is never a finding that there is no forest or protected area. Cost: 4 tokens (refunded on any empty result).

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.2/5.0
Behavior5/5

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

The description gives extensive behavioral disclosure beyond annotations: it clarifies that an empty result is never a guarantee of no restrictions, distinguishes between 'no parcels checked' vs 'no reference data,' and explains that the output describes the source of restrictions, not permitting outcomes. It also states the cost (4 tokens) and refund behavior. No contradiction with readOnlyHint=true.

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?

The description is front-loaded with the core purposeтные and then provides rich semantics. However, it is quite long and includes details like exact protection ranks and the cost that could be presented more concisely or moved to an output schema. Still, each sentence adds meaningful decision-relevant information.

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 only one parameter and no output schema, the description is remarkably complete: it explains input provenance, output meaning, rank semantics, empty-result interpretation, and the source-vs-outcome limitation. It lacks only a brief note about the exact response format, but the semantic coverage is strong.

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?

There is only one parameter and schema coverage is 100%; the schema already names it as a UUID from search results. The description adds the context that the id comes from search_transactions or similar tools, but this is minimal additional semantic value beyond the schema.

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 verb and resource: 'Get the parcel-by-parcel nature breakdown for a single transaction.' It clearly enumerates what the tool returns (forest distance, protection rank, overlap share, named areas) and distinguishes itself from search tools by noting that 'search results do not carry a nature signal.'

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 when-to-use guidance: 'call this tool directly on a transaction id' when forest proximity or protected-area due diligence matters, and it excludes what the tool is not (not legal advice, not about permitting outcomes). It does not name a specific sibling alternative, but it clearly differentiates from the search workflow.

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

get_transaction_permitsA
Read-only
Inspect

Get the building-permit history for one transaction's parcels, from the official national registry of building permits and works notifications (records since 2016): for each case — its kind (permit / notification), the building intent and works type, the statutory object category, the deciding authority, the decision or intake date, the investment address, and the volume. Use it after a search to screen what has been built or approved on the transaction's land — a leading indicator of development activity. Match is by the parcel's current identifier, so splits/merges break the link. 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. Notifications are held only where they were accepted without objection. Cases still pending are not held at all. TWO-STATE: a transaction whose parcels have no registered case returns nothing — an empty result is never a confirmation that nothing was ever planned. Cost: 4 tokens (refunded when there is no record).

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.6/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, so the safety profile is covered. The description adds critical behavioral details: that permits are only held after a decision, outcomes are not included, notifications only if accepted, pending cases are not held, and the TWO-STATE behavior (empty result ≠ no record). This is far beyond baseline and very helpful. No contradiction.

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

Conciseness4/5

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

The description is lengthy but each sentence adds value: data source, data items, usage context, matching limitation, data completeness, TWO-STATE. It is structured in paragraphs and front-loaded with the essential purpose. Slightly verbose but not wasteful.

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 the tool has only one parameter, is a read-only query, and has no output schema, the description covers all necessary aspects: what is returned, what is not, when to use, and common pitfalls. It is fully complete for an agent to invoke correctly.

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 coverage is 100%, so the schema already explains transaction_id well. The description reinforces that it's from a search result but doesn't add much beyond that. Baseline 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 ('Get') and resource ('building-permit history for one transaction's parcels'), and clearly distinguishes it from the sibling tools like get_transaction_planning (which likely deals with planning permissions) and get_transaction_farmland (which is about farmland). It also names the registry and data coverage since 2016. This is clear and unambiguous.

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 tells when to use it: 'Use it after a search to screen what has been built or approved on the transaction's land.' It also notes that it should be used alongside a search result, implying that a transaction_id must come from prior search. The description also warns about the matching limitation (current identifier, so splits/merges break the link). This is strong guidance.

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

get_transaction_planningA
Read-only
Inspect

Get the general-plan (plan ogólny, POG) zoning for one transaction's land: for each linked plot, the planning zones that cover it — zone symbol and name, the share of the plot each zone covers, and the building parameters the plan sets (max building height, max development intensity, max built-up coverage, min biologically active area) — plus any overlay areas (infill development area / obszar uzupełnienia zabudowy, central development area) that sit on top. Coverage is honest and THREE-STATE: 'covered' returns zone data; 'covered_no_data' means the municipality has an adopted general plan but no zone data covers these plots in the data yet; 'not_covered' means no published general-plan data for this municipality yet — this is NEVER a claim that the municipality has no plan. General plans are still being adopted across Poland, so coverage grows over time. Use it for feasibility and permitted-use questions on a plot. Cost: 4 tokens (refunded when there is no zone data for the transaction — 'covered_no_data' or 'not_covered').

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.4/5.0
Behavior5/5

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

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds valuable behavioral details: the three-state coverage with honest semantics, explanation of what each state means, and cost/refund behavior. This goes beyond annotations.

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

Conciseness4/5

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

The description is well-structured, starting with the main purpose, then detailing output, state system, usage, and cost. Each sentence is valuable, though slightly verbose; could be tightened.

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 tool with one parameter and no output schema, the description comprehensively covers the return values (zone data, building parameters, overlays), the three-state coverage, usage guidance, and cost. It leaves no critical gaps for an agent to understand the tool.

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?

The input schema has 100% description coverage for the single parameter (transaction_id), so the schema already provides meaning. The description does not add further parameter-specific information, meeting the baseline of 3.

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 clearly states the tool retrieves general-plan zoning for a transaction's land, specifying the output details (zone symbol, name, share, building parameters, overlay areas) and the three-state coverage system, making it distinct from any sibling tools.

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 explicitly recommends use for feasibility and permitted-use questions on a plot, and mentions cost/refund conditions. While it does not list alternatives or when-not-to-use, the context is clear given no sibling overlaps.

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

get_transaction_roadsA
Read-only
Inspect

Get the plot-by-plot road-access evidence for one transaction: for each linked plot, the distance in meters to the nearest public road, to the nearest road of any kind, and to the nearest motorway/expressway/dual-carriageway — plus, for the nearest public road, the estimated distance to the EDGE of its carriageway, its management category ('national' | 'voivodeship' | 'county' | 'municipal'), its functional class ('motorway' | 'expressway' | 'main_accelerated' | 'main' | 'collector' | 'local' | 'access' | 'other') and whether it runs at ground level (false = it crosses on a viaduct or in a tunnel, so it passes the plot over or under it). Each plot also carries access_indicator ('likely' | 'uncertain' | 'unlikely') and the version of the rule that produced it. access_indicator is GEOMETRIC EVIDENCE measured from carriageway centrelines in reference road-network data. It does NOT determine legal access and says nothing about easements or rights of way, which are recorded in the land register and are not published here — treat it as a lead to verify, never as a conclusion. That is why it has three states and is never a yes/no. Each measurement has a fixed radius: public road 500 m, road of any kind 500 m, motorway/expressway/dual-carriageway 3 km (that last one is a traffic-nuisance proxy, not an access signal). public_road_edge_distance_m is null when the source carries no carriageway width — no median is substituted. Use it for a specific transaction to judge how its land sits relative to the road network. get_parcel_report includes a one-line road-access summary per parcel. TWO-STATE: a null/absent distance means no such road within the search radius in the reference data — it is NEVER a guarantee that none exists. assessed=false means the plot has not been evaluated yet (no statement either way). Cost: 4 tokens (refunded when there is no informative data — no linked plots, or none evaluated yet).

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already indicate readOnlyHint=true and destructiveHint=false, so the tool is read-only enrolled. The description adds significant transparency: it clarifies that access_indicator is geometric evidence, not legal access, explains the TWO-STATE semantics for null distances and assessed=false, and warns about the 3km radius being a traffic-nuisance proxy instead of access signal. This is far beyond the annotation hints.

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

Conciseness4/5

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

The description is detailed and comprehensive, covering semantics, use cases, and caveats. It is somewhat long but each sentence adds value, and key points are front-loaded (what it does, then access_indicator semantics, then measurement radius). No fluff; it is appropriately structured for such a multi-faceted tool.

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 the tool's complexity (multiple distances and attributes per plot, a nuanced indicator, and radius rules), the description is exceptionally complete. It explains all output fields, the meaning of null/absent values, the assessed flag, cost and refund conditions, and how to obtain the transaction_id. With no output schema, this description carries the full burden and succeeds.

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% for the single parameter, with the schema already explaining that it is a transaction ID from search results. The description reinforces this by referencing the same search tools. It adds no new syntax but the parameter is self-explanatory; the baseline for high coverage is 3, and the description's reinforcement justifies a 4.

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 clearly states the tool's purpose: retrieving plot-by-plot road-access evidence for a specific transaction. It specifies the exact data returned (distances to nearest roads, management category, functional class) and references sibling tools (get_parcel_report) to delineate its unique scope. It is specific with verb and resource, making it easy to distinguish from other transaction-related tools.

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 explains when to use this tool: 'Use it for a specific transaction to judge how its land sits relative to the road network.' It also differentiates from get_parcel_report, noting that the latter includes a one-line summary, implying this tool is for detailed evidence. No explicit exclusions but strong contextual guidance.

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

get_transaction_subsurfaceA
Read-only
Inspect

Get the parcel-by-parcel subsurface breakdown for one transaction across two dimensions: mining terrains and major groundwater reservoirs. For each linked plot that overlaps either — the mining-terrain status ('active' | 'former') with its mineral class ('subsidence' = extraction with surface deformation, the actual mining-damage risk; 'surface' = open-pit working, mostly local impact; 'fluid' = borehole extraction; 'other'), the groundwater-reservoir status ('documented' | 'undocumented'), the share of the plot inside each, and the per-object lists (mining terrain: name, oversight authority, validity dates; reservoir: number, name, documentation). A mining terrain is a legally defined zone of anticipated mining influence; its mapped location is approximate — an intersection is an advisory signal to verify with the competent mining-supervision authority, not a legal determination. A groundwater reservoir's extent alone imposes NO restriction; a restriction would come only from an established protection zone, which is not published here. Use it for a specific transaction to see whether its land overlaps a mining terrain or a major groundwater reservoir, and the per-object detail. get_parcel_report includes a one-line subsurface summary per parcel. TWO-STATE: a transaction whose land overlaps neither layer returns nothing — absence of data is never an assertion of safety. Cost: 4 tokens (refunded when there is no subsurface data).

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.6/5.0
Behavior5/5

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

The description goes well beyond the readOnly/destructive annotations by disclosing the two-state behavior (returns nothing when there is no overlap), the advisory nature of mining-terrain intersections rather than legal determinations, and the fact that groundwater extent alone imposes no restriction. It also discloses the 4-token cost and refund condition, which is not visible anywhere else.

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

Conciseness4/5

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

The description is long, but the length is earned: there is no output schema, so the return structure and critical legal/cost caveats must be spelled out. It is front-loaded with the main function, then layers detail and caveats in a logical order, though some phrases could be tightened.

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?

Without an output schema, the description fully compensates by enumerating the per-plot fields, statuses, mineral classes, per-object lists, and the empty-result behavior. It also covers the advisory nature, the non-restriction of groundwater extents, and the alternative tool, leaving an agent with everything needed to call and interpret the tool correctly.

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 coverage is 100%, with transaction_id already documented as a UUID from search results. The description confirms the parameter is a specific transaction ID but does not add new parameter-level meaning beyond the schema, so the baseline of 3 applies.

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 verb and resource: 'Get the parcel-by-parcel subsurface breakdown for one transaction across two dimensions: mining terrains and major groundwater reservoirs.' It clearly differentiates itself from siblings by naming get_parcel_report as a shallower alternative and by scoping to a single transaction.

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 says 'Use it for a specific transaction to see whether its land overlaps a mining terrain or a major groundwater reservoir, and the per-object detail,' and it contrasts with get_parcel_report's one-line summary. This gives the agent a concrete selection rule among many transaction-sibling tools.

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

get_transaction_surroundingsA
Read-only
Inspect

Get the plot-by-plot surroundings profile for one transaction: for each linked plot, the distance in meters to the nearest cemetery, landfill (waste disposal site), sewage treatment plant, industrial/storage area, large industrial plant, intensive livestock farm, high-voltage overhead power line and extra-high-voltage overhead power line, from reference land-use and environmental-registry data. Useful for due-diligence on nearby nuisances. Distances are approximate and measured from the plot boundary; 0 means the plot touches or overlaps such an area. Each category is searched within a fixed radius only: cemetery 1 km, landfill 3 km, sewage treatment 2 km, industrial/storage 1 km, large industrial plant 3 km, intensive livestock farm 3 km, high-voltage overhead power line 1 km, extra-high-voltage overhead power line 1 km. Only overhead high- and extra-high-voltage lines are covered — medium- and low-voltage lines are ubiquitous and carry no signal, and no easement corridor width or substation is published here. TWO-STATE: a null/absent distance means no such object within the search radius in the reference data — it is NEVER a guarantee that none exists. assessed=false means the plot has not been evaluated yet (no statement either way). Cost: 4 tokens (refunded when there is no informative data — no linked plots, or none evaluated yet).

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations declare readOnlyHint=true and destructiveHint=false, and the description adds substantial behavioral context beyond that: distances are approximate, measured from plot boundary, 0 means touching/overlapping, fixed search radii per category, only overhead high/extra-high voltage lines covered, and the two-state null/assessed=false semantics. It also discloses cost and refund conditions. This is exemplary transparency.

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

Conciseness4/5

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

The description is dense but every sentence earns its place: scope, categories, radii, boundary semantics, two-state interpretation, and cost. It is front-loaded with the core purpose. Slightly long, but the complexity of the two-state semantics and per-category radii justifies the length.

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 tool with one parameter, no output schema, and rich annotations, the description covers everything an agent needs: what is returned, how to interpret edge cases, what is not covered, and cost. The absence of an output schema is compensated by the detailed description of the distance semantics and two-state values.

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% and the single parameter (transaction_id) is fully described in the schema with a UUID pattern and provenance. The description adds context by implying the transaction must come from a search result, but the schema already says that. Baseline 3 is exceeded slightly because the description reinforces the source of the ID and the cost implications.

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 ('Get'), a precise resource ('plot-by-plot surroundings profile for one transaction'), and enumerates the exact categories of nuisances covered. It clearly distinguishes itself from sibling tools like get_infrastructure_signals or get_transaction_roads by focusing on environmental nuisances and distances.

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 to use it ('useful for due-diligence on nearby nuisances'), and provides detailed search-radius semantics. It also explains the two-state interpretation (null vs assessed=false), which is critical for correct usage. While it doesn't name a specific alternative tool, the scope is so clearly defined that an agent can route correctly.

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

get_transaction_transitA
Read-only
Inspect

Get the parcel-by-parcel public transport access breakdown for one transaction: for each linked plot, the nearest public transport stop distances per transaction parcel, by mode (rail/metro/tram/bus), from open GTFS data — plus the nearest stop's name for each mode present. A mode is present only when a stop of that mode is within its cap (rail/metro 3000 m, tram 1500 m, bus 1000 m). TWO-STATE: a transaction whose land has no stop within cap in any mode returns nothing — absence of a row is never asserted as "no transit access" (open feeds cover cities and national rail, not every rural area). Cost: 4 tokens (refunded when there is no transit data).

ParametersJSON Schema
NameRequiredDescriptionDefault
transaction_idYesTransaction id (UUID) from a search_transactions / search_by_area / search_by_polygon result.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations only provide readOnlyHint and destructiveHint. The description adds significant behavioral details: use of open GTFS data, distance caps per mode, two-state absence handling, token cost and refund. These go well beyond annotation information.

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 a single paragraph with no wasted words. It front-loads the core purpose, then provides necessary details in a logical order: process, caps, edge cases, cost.

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 the simple input (one parameter) and no output schema, the description fully covers use case, distance caps, absence behavior, token cost, and refund. It leaves no ambiguity about what the tool returns or how it works.

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?

Only one parameter (transaction_id) with schema description covering its source. The tool description does not add further meaning beyond the schema. Schema coverage is 100%, so baseline 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 clearly states it gets 'parcel-by-parcel public transport access breakdown for one transaction,' specifying the resource (transaction), action (get), and scope (parcels, modes, stops). It distinguishes itself from sibling transaction tools by focusing on transit details.

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 explains when to use (getting transit access for a transaction) and details behavior like two-state returns and cost. It lacks explicit when-not-to-use or alternative tools, but the specificity among many siblings provides implicit guidance.

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

list_locationsA
Read-only
Inspect

Browse locations in two modes:

  1. TERYT hierarchy (parent param): Navigate voivodeship → county → municipality → precinct. Returns TERYT codes for use in search_transactions(teryt=...).

    • No parent: 16 voivodeships (2-digit codes)

    • 2-digit: counties (4-digit), 4-digit: municipalities (6-digit), 6-digit: precincts

  2. Name search (search param): Look up a place by name across all levels (voivodeship, county, municipality, precinct). Each match comes with its TERYT code, its parent unit, and the exact follow-up calls to make — use teryt= for precise administrative filtering. Rows also flagged as RCN districts additionally accept the name in search_transactions(location=)/compare_locations. RCN district names that have no TERYT code are listed separately. If both provided, parent takes precedence. Returns administrative units — never streets. A street is not a level of this hierarchy and has no code of its own; to search for parcels on one, pass the name straight to list_parcels_in_area as street=. Use 'location' for quick city searches, 'teryt' for precise administrative filtering (avoids name ambiguity, e.g. 'Wałcz' is both a county and a municipality).

ParametersJSON Schema
NameRequiredDescriptionDefault
parentNoTERYT parent code to browse children. 2-digit (voivodeship → counties), 4-digit (county → municipalities), 6-digit (municipality → precincts). Omit for all voivodeships.
searchNoLook up a place by name (case-insensitive, diacritics-insensitive partial match, e.g. 'wejher' for Wejherowo). Returns TERYT codes plus, where applicable, RCN district names. Ignored when parent is set.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, covering safety. The description adds behavioral details beyond annotations: two modes, precedence rules, that it returns administrative units only, RCN district handling, and the output (TERYT codes, parent unit, follow-up calls). It doesn't mention errors or rate limits, but for a read-only tool the added context is substantial.

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

Conciseness4/5

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

The description is longer than average but well-structured with numbered modes and clear separation. Every sentence adds value, such as the street clarification and the note on RCN districts. It front-loads the two modes and prioritizes key behavior. A slight trim could be made, but it remains efficient for the complexity.

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 the tool's complexity (hierarchy, two modes, output usage), the description is complete. It explains what the tool returns (TERYT codes, parent, follow-up calls), what it does not (streets), and how results feed into other tools. With no output schema, the description covers return semantics adequately, leaving no critical gaps for an agent to call it correctly.

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% with detailed parameter descriptions (parent code lengths, search case-insensitivity). The description reinforces and extends this: explains precedence when both are provided, provides concrete examples (e.g., 'Wałcz'), and links parameters to usage outcomes. This adds value beyond the schema's literal definitions.

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 clearly states the tool's purpose: browsing locations via TERYT hierarchy or name search, returning TERYT codes for use in other tools. It distinguishes itself from sibling location tools by focusing on administrative units and explicitly stating it never returns streets. The verb 'browse' and resource 'locations' are specific, and it differentiates from list_*_locations siblings by covering the general hierarchy.

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 provides explicit guidance on when to use each mode: 'Use location for quick city searches, teryt for precise administrative filtering' and explains parent precedence. It also names alternative tools and conditions, e.g., 'to search for parcels on a street, pass the name straight to list_parcels_in_area as street='. This leaves no ambiguity about selection.

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

list_parcels_in_areaA
Read-only
Inspect

List cadastral parcels in an area — the land plots themselves, NOT transactions. For deeds and prices in an area use search_by_area or search_by_polygon instead. To look up a parcel by an id prefix use search_parcels; to turn one address, coordinate or 'locality + number' into a parcel use resolve_parcel; for everything known about a single parcel use get_parcel_report.

Name the area in one of five ways — at least one is required:

  • teryt: administrative code prefix at any level (2 digits = voivodeship, 4 = county, 6 = municipality, finer allowed); comma-separate several. Browse codes with list_locations.

  • location: a county or city NAME, resolved to its code. A name shared by two counties comes back as an error listing both, never as a guess.

  • bbox: "minLng,minLat,maxLng,maxLat" in WGS84.

  • lat + lng + radiusKm: a circle (all three together).

  • polygon: a GeoJSON Polygon, for a drawn shape. Pass it on its own. A bbox and a circle cannot be combined — together they would mean the overlap of a rectangle and a circle, which is rarely the question.

Two shapes of answer, priced differently:

  • Default: the LIGHT list — parcel id, district and centre point per row, with no outline and no surface. 2 API tokens. Pages by cursor: when more parcels match, the answer hands you an opaque cursor to pass back as cursor=.

  • includeGeometry=true (needs a bbox), or a polygon: OUTLINES — the full GeoJSON polygon of each parcel. 5 API tokens, at most 100 parcels per call (50 by default), no paging.

Truncation is the normal case on outlines, not an edge case. An area the size of a city holds far more parcels than one call returns, so an outline answer is usually marked TRUNCATED and the parcels in it are an arbitrary subset — not the first, nearest or largest. Never report a truncated answer as the parcel list of an area; ask for a smaller area instead.

minArea / maxArea (m²) filter on the registered parcel surface without returning it. They need a narrow scope — a bbox, a circle, a location name, or a teryt of at least 4 digits (county level) — and are refused elsewhere with a message saying what to add. They are not available on the outline calls.

Every row of the light list carries the street address held for that parcel, whether or not you asked about one, and says where it came from: a street on record, one we worked out for a parcel the record left without a street (shown with a note saying so), or — only when a buildingNumber search on the record came back empty — one read off an official address point that falls inside the parcel (also noted). A building number is only ever on record or from that address point, so a worked-out street never carries one. When a page comes back with a requested buildingNumber, it also carries a note on which of the two the number came from. If the street exists in the area but not with that number, the answer says so instead of the generic "no such street". Most rural parcels have no street at all — for those the way in is resolve_parcel with the precinct name and the parcel number, not a street.

  • street: matches whole words of the name, case- and accent-insensitively — 4 letters or digits minimum, 200 characters maximum. It is a NAME, not a pattern: % and _ match themselves. 'Górna' finds 'ulica Górna' and 'Górna 15' but not 'Podgórna', and a fragment like 'Marsza' finds nothing. Both sources are searched at once and a parcel found in both appears once, attributed to the record. Matching folds accents, so 'karmelicka' finds 'Karmelicka' — but it does NOT inflect: pass the name in the NOMINATIVE, because an inflected form like 'Karmelickiej' answers with an empty list. That empty page costs nothing (the tokens are refunded) and carries a suggestions block with close names to retry, so read the suggestions before you conclude anything about the data.

  • buildingNumber: needs street alongside it. Against the record the match is EXACT ('12A' does not find '12a'); RCN often records a compound or split number ('84/92'), so an exact '84' will not find '84/92'. When that comes back empty, the same street+number is tried against official address points instead — that match ignores case ('12a' finds '12A') but is still exact on the number, no compound splitting, and it matches the street by the same whole-word rule as above, not a fragment ('Waszyngtona' finds 'Aleja Waszyngtona', 'szyng' does not). Only when BOTH miss does the page come back empty (the tokens are refunded), listing the numbers held on the street as suggestions to retry. Both need a narrow scope for the same reason minArea does — a bbox, a circle, a teryt of at least 4 digits, or a location name — and neither counts as naming the area: a common street name across the country is a national search, not a question. Neither is available on the outline calls.

Parcel identity is gated: parcel_id comes back for API-token / OAuth callers and for paid or active-trial accounts, and is withheld for everyone else while the location and the outline still come back.

Coverage, so you can allow for it — TWO SEPARATE GAPS:

  1. We hold near-complete coverage of the cadastral register, though not the whole of it and not live: what we hold was measured county by county on a fixed date, so a freshly split, merged or renumbered parcel may not be in yet. This applies to EVERY entrance here, teryt and location included. A short list, and the absence of a truncation marker, mean only that nothing further matched what we hold as of that measurement — never that you have every parcel in the area. Each answer carries a corpus_coverage block: for teryt and location it gives the measured parcels-held and parcels-in-register figures for the counties you asked about; for bbox, circle and polygon those figures are null, because sizing an arbitrary shape needs county boundaries we do not have — the measurement still applies, we just cannot put a number on it for that shape.

  2. Separately, the spatial entrances (bbox, circle, polygon) work off the stored outline, and a small share of the parcels we DO hold keep theirs in a coordinate system those queries cannot read — those are missing from spatial answers specifically. The teryt and location entrances never touch geometry and are unaffected BY THAT SECOND GAP; a parcel whose outline we do not hold shows up there with no location. Neither gap is a reason to distrust what comes back: a returned parcel is a real parcel. They are a reason never to read an empty or short answer as evidence that the land is not there.

Limits: an area over 500 km², a radius over 12.6 km (the same ground) or a polygon over 500 vertices is refused rather than scanned, and a query that outruns its time limit answers with an error asking you to narrow it.

ParametersJSON Schema
NameRequiredDescriptionDefault
latNoLatitude of the circle centre (WGS84). Requires lng and radiusKm.
lngNoLongitude of the circle centre (WGS84). Requires lat and radiusKm.
bboxNoBounding box in WGS84 as "minLng,minLat,maxLng,maxLat", covering at most 500 km². Required for includeGeometry=true.
limitNoMax parcels returned. Light list: up to 1000, default 250. Outlines: up to 100, default 50 — a larger value is clamped there.
terytNoTERYT administrative code prefix (2/4/6 digits or finer), comma-separated for several. Wins over location when both are given.
cursorNoOpaque cursor from the previous light-list answer, to get the next page. Pass it back unchanged; it is not available on outline calls.
streetNoStreet name, matched by whole words within the name, case- and accent-insensitively (min 4 letters or digits): 'Górna' finds 'ulica Górna' and 'Górna 15' but not 'Podgórna', and a fragment like 'Marsza' finds nothing. NOMINATIVE: 'Karmelickiej' does not fold to 'Karmelicka' and answers empty. Needs a bbox, a circle, a location name, or a teryt of at least 4 digits. Not available with includeGeometry or a polygon.
maxAreaNoMaximum parcel surface in m². Same scope requirement as minArea.
minAreaNoMinimum parcel surface in m². Needs a bbox, a circle, a location name, or a teryt of at least 4 digits. Not available with includeGeometry or a polygon.
polygonNoGeoJSON Polygon geometry. Coordinates: [longitude, latitude] pairs, first and last point identical, at most 500 vertices. Always returns outlines. Pass it instead of the other area parameters, not alongside them.
locationNoCounty, city, or district name, resolved to its TERYT code. A Warszawa district name (e.g. 'Mokotów') narrows to that district; another city's delegatura (e.g. 'Kraków-Podgórze') resolves to its parent county. An ambiguous name is an error listing the candidates.
radiusKmNoCircle radius in km (max 12.6 — the radius covering the 500 km² ceiling). Requires lat and lng.
buildingNumberNoBuilding number. Against the record the match is exact ('12A' does not find '12a') and RCN numbering is often compound ('84/92'), so an exact '84' misses '84/92'. When that comes back empty, the same number is tried against official address points instead, case-insensitively ('12a' finds '12A') but still exact, matching the street by the same whole-word rule as street, not a fragment — if that also misses, drop the number and read the numbers off the street's rows. Requires street. Same scope requirement as street.
includeGeometryNoReturn each parcel's full outline instead of the light row (5 tokens instead of 2, at most 100 parcels, no paging). Requires a bbox; with a polygon the outlines come back anyway.

TDQS

A4.9/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, but the description adds substantial behavioral context: truncation is the norm for outlines, coverage gaps (two separate ones) are explained, token costs differ between light and outline calls, paging via cursor, and the fact that empty answers may still be valid. It also explains the gating of parcel_id by account type. All of this goes far beyond the annotations and materially helps the agent reason about results.

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

Conciseness4/5

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

The description is very long, but it is well-structured with clear sections (naming the area, shapes of answer, truncation, coverage, limits) and front-loaded with the core purpose. Every sentence earns its place given the tool's complexity (14 parameters, multiple modes, edge cases). It is not concise, but it is appropriately sized and organized, so it earns a 4 rather than a 5.

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 tool with 14 parameters, no output schema, and multiple pricing/paging modes, the description is remarkably complete. It covers return shapes, truncation semantics, coverage limitations, token costs, paging, and parameter interactions. An agent has everything needed to call this tool correctly and interpret results, including edge cases like refunded tokens and suggestions on empty pages.

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 coverage is 100%, so the baseline is 3, but the description massively enriches parameter semantics. It explains the five ways to name an area and their interactions (e.g., teryt wins over location), the exact matching rules for street (whole-word, accent-insensitive, nominative only), the compound-number behavior for buildingNumber, and the scope requirements that apply to several parameters. This is far beyond what the schema provides.

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 crisp, specific statement: 'List cadastral parcels in an area — the land plots themselves, NOT transactions.' It immediately distinguishes itself from siblings by naming alternatives for deeds/prices, id lookup, address resolution, and full reports. An agent can tell exactly what this tool does and how it differs from every related tool.

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 routes to alternatives: 'For deeds and prices in an area use search_by_area or search_by_polygon instead. To look up a parcel by an id prefix use search_parcels...' It also gives detailed when-to-use guidance for each area-naming method, including constraints like 'a bbox and a circle cannot be combined' and scope requirements for minArea/street. No ambiguity remains about when to pick this tool or a sibling.

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

resolve_parcelA
Read-only
Inspect

Resolve a land parcel to its cadastral identity using exactly ONE of:

  • parcelId: a full cadastral id, either raw '/' form ('142907_2.0014.342/5') or URL-safe '-' form ('142907_2.0014.342-5'), or the internal UUID from search results.

  • q: a full cadastral id, a UUID, OR free-text 'locality name + parcel number' (e.g. 'Sabnie 342/5'). The name may be a gmina name or a cadastral precinct (obręb) name; matching is exact and case-insensitive, so an unusual spelling may miss. A precinct name is not unique nationwide, so an ambiguous name comes back as several candidates rather than a guess. This is NOT a street address: it is a locality name plus a PARCEL number, never a street name plus a building number. For a city address (street + building number) use list_parcels_in_area(street=, buildingNumber=) instead — resolve_parcel will not turn 'Marszałkowska 12' into a parcel.

  • lat & lng: a WGS84 point inside the parcel (returns the parcel(s) containing that point). Returns a list of matching parcels with district, area, and coordinates; 'truncated' when the name+number match was capped. When nothing matches, coverage is not_covered — and what that means depends on the mode. With a FULL cadastral id we confirm the parcel live and add it if it exists, so not_covered there really does mean we could not confirm one. With the DISCOVERY modes (locality name + number, or a coordinate) we only look at the register we hold — near-complete national coverage, though not the whole of it and not live — so not_covered means "not among the parcels we hold", which is a weaker statement, and a fresh change or an unusual spelling is a likelier cause than the parcel not existing. Never report it as "no such parcel". The corpus_coverage block in each answer says how much of the register was actually searched. When the lookup could not be completed at all — a live confirmation that failed, or a name carried by more precincts than one search covers and nothing found among them — coverage is not_computed instead: that is not a statement that the parcel does not exist. Matches found before such a search ran out are returned normally, with 'truncated'. Use this to turn an address point, a coordinate, or a locality+number into a concrete parcel id — then feed that id to search_transactions (parcelId) to see its sale history. Free: resolving a parcel costs no API tokens.

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoFull cadastral id, a UUID, or 'locality name + parcel number' (e.g. 'Sabnie 342/5') — the name may be a gmina or a cadastral precinct (obręb). NOT a street address: for a street + building number use list_parcels_in_area instead. Mutually exclusive with parcelId and lat/lng.
latNoLatitude WGS84. Must be paired with lng. Mutually exclusive with q and parcelId.
lngNoLongitude WGS84. Must be paired with lat. Mutually exclusive with q and parcelId.
parcelIdNoFull cadastral id (slash or dash form) or internal UUID. Mutually exclusive with q and lat/lng.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already mark the tool read-only and non-destructive, and the description adds rich behavioral context beyond that: exact case-insensitive matching, ambiguous-name behavior, the not_covered vs not_computed distinction, truncation, corpus coverage, and the fact that it costs no tokens. This is exactly the kind of operational nuance 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.

Conciseness4/5

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

The description is long, but the material is dense and genuinely relevant: matching semantics, coverage caveats, and mode differences. It is front-loaded with the core purpose and input modes. A little redundancy remains around the not_covered explanation and the street-address exclusion, so it is not maximally concise.

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?

Despite having no output schema, the description covers what a successful result looks like, truncated responses, coverage blocks, failure semantics, and how the tool fits into a larger workflow. For a tool with four optional parameters and no required ones, all essential selection and interpretation information is present.

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 coverage is 100%, so the baseline is 3, but the description goes well beyond the schema: it explains the slash vs dash parcelId forms, that q accepts gmina or obręb names with exact case-insensitive matching, that lat/lng must be a point inside the parcel, and what each match mode returns. These are semantically important details not in the schema.

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 first sentence states a specific verb and resource: 'Resolve a land parcel to its cadastral identity', and the three input modes make the tool's job unambiguous. It also differentiates from siblings by explicitly routing street addresses to list_parcels_in_area and sale-history lookups to search_transactions.

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 gives explicit when-to-use guidance ('Use this to turn an address point, a coordinate, or a locality+number into a concrete parcel id') and names the follow-up tool (search_transactions). It also states a clear exclusion: a city street address should go to list_parcels_in_area, not resolve_parcel.

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

search_by_areaA
Read-only
Inspect

Search real estate transactions within a geographic radius. Returns TRANSACTIONS — deeds and prices — despite the name. For the land plots themselves in an area, use list_parcels_in_area. Best tool for neighborhood/osiedle searches (neighborhoods are not TERYT districts). Radius guide: 0.3-0.5 km for a street, 0.5-1 km for a neighborhood, 2-5 km for a city area. Example: apartments in Wrocław's Nowy Dwór (lat 51.143, lng 16.993, radiusKm=0.7). Area filters (minArea/maxArea) work for all propertyType values. Permalink: every result is shareable on the map. From a result's "id:" line and its "Location: °N, °E" line, build https://cenogram.pl/ceny-transakcyjne?src=mcpstdio#v=1&lat=&lng=&z=16&tx= (drop the °N/°E; lat = the °N number, lng = the °E number) — opens that exact transaction on the map. Omit &tx= for the area only. Field provenance: values are from the notarial deed (RCN) by default; computed values (parcel area summed across plots or converted from hectares, an inferred/reclassified property type) and approximated streets are flagged inline with a neutral [...] note.

ParametersJSON Schema
NameRequiredDescriptionDefault
floorNoFloor 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.
limitNoNumber of results (1-50, default 20)
roomsNoNumber 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.
dateToNoEnd date (YYYY-MM-DD)
landUseNoRecorded 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.
maxAreaNoMaximum area in m²
minAreaNoMinimum area in m² (usable_area_m2 for units, parcel_area for land)
dateFromNoStart date (YYYY-MM-DD)
latitudeYesLatitude (Poland range: 49-55)
maxPriceNoMaximum price in PLN
minPriceNoMinimum price in PLN
radiusKmNoSearch radius in km (0.1-50, default 2). Use 0.5-1 for neighborhoods, 0.3-0.5 for streets.
floodRiskNoFlood-hazard filter. high = most frequent flooding (~1-in-10-year), medium (~1-in-100-year), low = rarest (~1-in-500-year). Selects ONLY transactions whose land sits in a mapped flood zone; absence of a zone is never asserted as 'safe'. Multi-select; e.g. ['medium','high'] = at least medium risk.
longitudeYesLongitude (Poland range: 14-25)
marketTypeNoMarket type: primary (developer) or secondary (resale). ~55% of records have unknown market type and will be excluded when this filter is used.
buildingTypeNoBuilding type filter (PKOB classification). 'unknown' = no type recorded (NULL); without it such rows are excluded (~39% of buildings have no type).
propertyTypeNoProperty type filter
unitFunctionNoUnit/apartment function filter. 'unknown' = no function recorded (NULL); without it such rows are excluded. Garages appear only when 'garage' is selected, not via 'unknown'.
landslideRiskNoLandslide-hazard filter, from official landslide-hazard maps (1:10,000 scale). 'landslide' = the land intersects a mapped landslide area; 'threatened' = an area threatened by mass movements. Selects ONLY transactions whose land intersects a mapped hazard area — an intersection means overlap with a mapped area, not that the parcel itself is a landslide; absence of a zone is never asserted as 'safe'. Multi-select; e.g. ['landslide','threatened'] = any mapped hazard.
ownershipTypeNoOwnership / 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.
heritageStatusNoHeritage-listing filter. listed = a protected monument on/at the property's land; zone = the land lies within a protected urban layout or the designated surroundings of a monument. Selects ONLY transactions where a listing was detected; absence of a detection is never asserted as 'not listed'. Multi-select; e.g. ['listed'] = individually listed properties only.
buildingStoreysNoNumber 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.
transactionTypeNoTransaction type filter. For market analysis, ALWAYS specify to exclude non-market transactions.
maxFootprintAreaNoMaximum 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'.
minFootprintAreaNoMinimum 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'.

TDQS

A4.8/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 substantial non-obvious behavior: field provenance from the notarial deed (RCN), inline flagging of computed/inferred values, and full permalink construction instructions. It goes well beyond the safety profile the annotations provide.

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

Conciseness4/5

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

Front-loaded with the core purpose and the name-misleading caveat, then progressively more detailed. It is long, and the permalink paragraph plus radius guide repeat material also present in the schema, but every block is doing distinct work. Slightly verbose rather than padded.

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 25-parameter tool with no output schema, the description covers what is returned (transactions, deeds, prices), data provenance and flag semantics, and how to share a result. Combined with the fully documented schema, an agent has everything needed to call and interpret it correctly.

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, but the description adds genuine value on top: radius guidance and the note that minArea/maxArea apply across all propertyType values (unit usable area vs parcel area). It does not re-explain most filters, which is correct since the schema does that.

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?

States a specific verb+resource ('Search real estate transactions within a geographic radius') and immediately disambiguates the misleading name by clarifying it returns TRANSACTIONS (deeds and prices), not parcels. It explicitly names the sibling to use for the other interpretation (list_parcels_in_area), so an agent can pick correctly without opening a schema.

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?

Explicit when-to-use ('Best tool for neighborhood/osiedle searches'), a concrete radius heuristic (0.3-0.5 km street, 0.5-1 km neighborhood, 2-5 km city area), a worked example, and a named alternative for the opposite need. This is about as complete as routing guidance gets.

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

search_by_polygonA
Read-only
Inspect

Search real estate transactions within a geographic polygon. Returns TRANSACTIONS — deeds and prices — despite the name. For the land plots themselves inside a drawn shape, pass the same polygon to list_parcels_in_area. Provide a GeoJSON Polygon geometry to search within a custom area. Returns transactions found inside the polygon with coordinates. Use for precise neighborhood/osiedle boundaries. Can estimate coordinates from search_by_area results. For quick searches, start with search_by_area instead. Coordinates are [longitude, latitude]. First and last point must be identical. Permalink: every result is shareable on the map. From a result's "id:" line and its "Location: °N, °E" line, build https://cenogram.pl/ceny-transakcyjne?src=mcpstdio#v=1&lat=&lng=&z=16&tx= (drop the °N/°E; lat = the °N number, lng = the °E number) — opens that exact transaction on the map. Omit &tx= for the area only. Field provenance: values are from the notarial deed (RCN) by default; computed values (parcel area summed across plots or converted from hectares, an inferred/reclassified property type) and approximated streets are flagged inline with a neutral [...] note. Example: {"type":"Polygon","coordinates":[[[21.0,52.2],[21.01,52.2],[21.01,52.21],[21.0,52.21],[21.0,52.2]]]}

ParametersJSON Schema
NameRequiredDescriptionDefault
floorNoFloor 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.
limitNoMax results (1-3000, default 100). MCP displays up to 50 transactions.
roomsNoNumber 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.
dateToNoEnd date (YYYY-MM-DD)
streetNoStreet name filter (partial match)
landUseNoRecorded 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.
maxAreaNoMaximum area in m²
minAreaNoMinimum area in m²
polygonYesGeoJSON Polygon geometry. Coordinates: [longitude, latitude] pairs. First and last point must be identical. Max 500 vertices total.
dateFromNoStart date (YYYY-MM-DD)
districtNoDistrict name filter
maxPriceNoMaximum price in PLN
minPriceNoMinimum price in PLN
marketTypeNoMarket type filter
buildingTypeNoBuilding type filter (PKOB classification). 'unknown' = no type recorded (NULL); without it such rows are excluded (~39% of buildings have no type).
propertyTypeNoProperty type filter
unitFunctionNoUnit/apartment function filter. 'unknown' = no function recorded (NULL); without it such rows are excluded. Garages appear only when 'garage' is selected, not via 'unknown'.
ownershipTypeNoOwnership / 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.
buildingStoreysNoNumber 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.
mpzpDesignationNoMPZP zoning designation filter (exact match). Use 'unknown' for rows with no designation recorded (NULL); distinct from the registry code 'brakMPZPLubWZ'.
transactionTypeNoTransaction type filter. For market analysis, ALWAYS specify to exclude non-market transactions.
maxFootprintAreaNoMaximum 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'.
minFootprintAreaNoMinimum 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'.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already declare readOnlyHint/destructiveHint, but the description adds substantial non-obvious behavior: field provenance (RCN notarial deed by default, computed/approximated values flagged inline with [...]), coordinate conventions and vertex limits, and a full permalink-construction recipe. This is well beyond the structured safety hints.

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

Conciseness4/5

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

Front-loads the core purpose and the transaction-vs-parcel distinction before any detail. The permalink paragraph is bulky and the [longitude, latitude] / first-last-point rules duplicate the schema, but nearly every remaining sentence is actionable rather than filler.

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?

For a 23-parameter tool with no output schema and full schema coverage, the description covers the gaps that matter: what comes back (transactions with coordinates), provenance caveats, and how to turn results into a shareable permalink. It doesn't enumerate the full result shape, but with annotations and schema complete that is a minor omission.

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 coverage is 100%, so the schema already documents all 23 parameters, including coordinate order and the first/last-point-identical rule, which the description merely restates. The inline example polygon and the 'estimate coordinates from search_by_area' hint add some practical value, but this is the baseline case where structured data does the heavy lifting.

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?

States a specific verb+resource (search real estate transactions within a polygon) and immediately clarifies a naming trap: it returns TRANSACTIONS, not parcels, 'despite the name.' It explicitly routes the parcel use case to list_parcels_in_area, distinguishing it from the closest sibling without opening any schema.

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?

Gives explicit conditions: use for precise neighborhood/osiedle boundaries, start with search_by_area for quick searches, and pass the same polygon to list_parcels_in_area if the plots themselves are wanted. Alternatives and when-not-to-use are both named.

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

search_parcelsA
Read-only
Inspect

Search for land parcels by parcel ID prefix (autocomplete). Matches on the ID PREFIX only, never on an area: to list the parcels in a place or a shape use list_parcels_in_area, and to turn an address, a coordinate or 'locality + number' into one parcel use resolve_parcel. Returns matching parcels with their district, area, and GPS coordinates. Useful for finding exact parcel IDs, then searching transactions nearby. Example: search for parcels starting with '146518_8.01'. Coverage: this searches the cadastral register we hold — near-complete national coverage, though not the whole of it and not live — so an empty result more likely means a recent change or a mistyped prefix than that no such parcel exists. Do not report a missing match as "this parcel does not exist". The answer carries a corpus_coverage block with the measured figures for the county the prefix names, and resolve_parcel with the FULL id can still confirm and add a parcel we do not yet hold. Free: searching for parcels costs no API tokens.

ParametersJSON Schema
NameRequiredDescriptionDefault
qYesParcel ID prefix to search for (min 3 chars). E.g. '146518_8.01'
limitNoMax results (1-10, default 10)

TDQS

A4.8/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 goes well beyond them: it discloses corpus coverage limits (national but not complete, not live), how to read an empty result, that a corpus_coverage block is returned, and that the call is free of token cost.

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

Conciseness4/5

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

Front-loaded with the core behaviour and the sibling routing in the first two sentences. The coverage paragraph is long but each sentence carries non-obvious operational guidance; only the trailing 'Free' note is slightly expendable.

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?

No output schema exists, so the description correctly takes on the burden of describing what comes back (district, area, GPS coordinates, corpus_coverage block). Combined with the coverage caveat and the fallback to resolve_parcel, an agent has everything needed to call and interpret it correctly.

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, but the description adds real meaning the schema does not: the match is on the ID PREFIX only, never on an area, plus a concrete example prefix. The limit parameter is left entirely to the schema.

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?

States a specific verb (search) and resource (land parcels) and immediately constrains the match semantics to ID prefix. It names the two sibling tools it is not (list_parcels_in_area, resolve_parcel), letting an agent distinguish it without opening any schema.

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?

Explicit when-to-use ('finding exact parcel IDs', 'searching transactions nearby') and when-not, with a named alternative for each wrong case: list_parcels_in_area for places/shapes and resolve_parcel for address/coordinate/locality lookups. Also covers how to interpret an empty result.

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

search_transactionsA
Read-only
Inspect

Search Polish real estate transactions from the national RCN registry (8M+ records). Returns transaction details: address, date, price, area, price/m², property type. Call list_locations(search=...) first to resolve a place: prefer the returned TERYT code as teryt= (exact administrative match). Pass a name to location= only when the result flags it as an RCN district (rcn_district) — most TERYT names are not valid location= values and silently return zero rows. Example: search for apartments in Mokotów sold in 2024 above 500,000 PLN. Data notes: marketType is NULL for ~55% of records (notary didn't classify) - filtering by marketType excludes them. ~1.7% of records have no transaction_date. Permalink: every result is shareable on the map. From a result's "id:" line and its "Location: °N, °E" line, build https://cenogram.pl/ceny-transakcyjne?src=mcpstdio#v=1&lat=&lng=&z=16&tx= (drop the °N/°E; lat = the °N number, lng = the °E number) — opens that exact transaction on the map. Omit &tx= for the area only. Field provenance: values are from the notarial deed (RCN) by default; computed values (parcel area summed across plots or converted from hectares, an inferred/reclassified property type) and approximated streets are flagged inline with a neutral [...] note. Location matches TERYT districts only - for neighborhoods (osiedla), use search_by_area instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoPage number for pagination (default: 1)
sortNoSort by field (default: date)date
floorNoFloor 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.
limitNoNumber of results (1-50, default 10)
orderNoSort order (default: desc)desc
roomsNoNumber 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.
terytNoTERYT administrative code(s) for precise area filtering. Comma-separated, max 10. 2-digit (voivodeship), 4-digit (county), 6-digit (municipality), or full precinct code (e.g. '321705_2.0054'). Use list_locations to find codes. More precise than 'location' - avoids name ambiguity.
dateToNoEnd date (YYYY-MM-DD)
streetNoStreet name filter, matched anywhere inside the name (e.g. 'Puławska', 'Aleja Waszyngtona'). Give it in the NOMINATIVE and with its Polish diacritics — matching is literal, so 'Karmelickiej' does not find 'Karmelicka' and 'Marszalkowska' does not find 'Marszałkowska'. Either mistake answers with nothing, which reads exactly like 'no such transactions'.
landUseNoRecorded 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.
maxAreaNoMaximum area in m²
minAreaNoMinimum area in m²
dateFromNoStart date (YYYY-MM-DD)
locationNoLocation name - city (e.g. 'Warszawa', 'Kraków', 'Gdańsk') or district (e.g. 'Mokotów', 'Kraków-Podgórze'). 'Warszawa', 'Kraków', 'Łódź' auto-expand to all sub-districts. Prefer teryt= for exact matches; call list_locations(search=...) to confirm a name is valid here — it flags valid ones as rcn_district.
maxPriceNoMaximum price in PLN
minPriceNoMinimum price in PLN
parcelIdNoExact parcel ID as returned in search results (e.g. '146518_8.0108.27'). Must match exactly - copy from a previous search result's parcel_id field.
floodRiskNoFlood-hazard filter. high = most frequent flooding (~1-in-10-year), medium (~1-in-100-year), low = rarest (~1-in-500-year). Selects ONLY transactions whose land sits in a mapped flood zone; absence of a zone is never asserted as 'safe'. Multi-select; e.g. ['medium','high'] = at least medium risk.
marketTypeNoMarket type: primary (developer) or secondary (resale). ~55% of records have unknown market type and will be excluded when this filter is used.
buildingTypeNoBuilding type filter (PKOB classification). 'unknown' = no type recorded (NULL); without it such rows are excluded (~39% of buildings have no type).
propertyTypeNoProperty type filter
unitFunctionNoUnit/apartment function filter. 'unknown' = no function recorded (NULL); without it such rows are excluded. Garages appear only when 'garage' is selected, not via 'unknown'.
landslideRiskNoLandslide-hazard filter, from official landslide-hazard maps (1:10,000 scale). 'landslide' = the land intersects a mapped landslide area; 'threatened' = an area threatened by mass movements. Selects ONLY transactions whose land intersects a mapped hazard area — an intersection means overlap with a mapped area, not that the parcel itself is a landslide; absence of a zone is never asserted as 'safe'. Multi-select; e.g. ['landslide','threatened'] = any mapped hazard.
ownershipTypeNoOwnership / 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.
buildingNumberNoBuilding/house number (e.g. '30', '12A'). Requires location or street to be set.
heritageStatusNoHeritage-listing filter. listed = a protected monument on/at the property's land; zone = the land lies within a protected urban layout or the designated surroundings of a monument. Selects ONLY transactions where a listing was detected; absence of a detection is never asserted as 'not listed'. Multi-select; e.g. ['listed'] = individually listed properties only.
buildingStoreysNoNumber 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.
mpzpDesignationNoMPZP zoning designation filter (exact match, e.g. 'budownictwoMieszkanioweWielorodzinne', 'terenObiektowProdukcyjnychSkladowIMagazynow'). Use 'unknown' for rows with no designation recorded (NULL); distinct from the registry code 'brakMPZPLubWZ' (= 'no plan/WZ' recorded as data).
transactionTypeNoTransaction type filter. For market analysis, ALWAYS specify transactionType to exclude non-market transactions (subsidized, foreclosure, public purpose). ~2% of transactions have unknown type (NULL) and are excluded when this filter is used unless 'unknown' is included.
maxFootprintAreaNoMaximum 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'.
minFootprintAreaNoMinimum 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'.

TDQS

A4.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description nevertheless adds substantial behavioral context beyond the schema: NULL rates (marketType ~55%, no transaction_date ~1.7%), inline provenance flags, and the fact that bad name matches 'silently return zero rows'. Strong additions, but the core safety signals come from annotations.

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

Conciseness4/5

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

Front-loaded with purpose, then usage, then data caveats, permalink, and provenance. For a 31-parameter tool the length is defensible, but the multi-sentence permalink-construction block is dense and leans toward reference-document territory rather than selection guidance.

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?

With 31 parameters, no output schema, and no nested objects, the definition supplies the routing rules, the returned fields, the data caveats, and the sibling alternatives an agent needs to call it correctly. Nothing essential for correct invocation 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 100%, so the baseline is 3 and the schema itself carries most parameter detail. The description adds real value by explaining the teryt-vs-location tradeoff and the silent-zero-row failure mode of incorrect name/diacritic usage, which the schema only partially covers.

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?

States a specific verb+resource with scope ('Search Polish real estate transactions from the national RCN registry (8M+ records)') and enumerates the returned fields. It explicitly distinguishes itself from siblings by naming search_by_area for neighborhoods/osiedla and list_locations for resolving places, so an agent can route correctly without opening schemas.

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?

Gives explicit when-to-use routing: 'Call list_locations(search=...) first to resolve a place', 'prefer the returned TERYT code as teryt=', and restricts location= to results flagged rcn_district. It also names the alternative (search_by_area) and the condition that selects it, plus a worked example query.

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. 12 tool updatesv0.12.0
    • Changedget_demographics2 fields changed
      • changedInput schema / properties / location / description
        Previous value: -"City/county name, resolves to county/powiat level (e.g. 'Warszawa', 'Kraków'). Use this OR teryt. For gmina-level data pass a 6/7-digit teryt instead."New value: +"City, county, or district name (e.g. 'Warszawa', 'Kraków'). A city/county name resolves to county/powiat level; a Warszawa district name (e.g. 'Mokotów') resolves to that district, another city's delegatura (e.g. 'Kraków-Podgórze') to its parent county. Use this OR teryt. For gmina-level data on other units pass a 6/7-digit teryt instead."
      • changedInput schema / properties / teryt / description
        Previous value: -"TERYT code: 2-digit (voivodeship, e.g. 14), 4-digit (county, e.g. 1465), 6 or 7-digit (gmina, e.g. 1465011). Wins over location. Use list_locations to find codes."New value: +"TERYT code: 2-digit (voivodeship, e.g. 14), 4-digit (county, e.g. 1465), 6 or 7-digit (gmina, e.g. 1465011). The 7th digit selects the unit type: 3 = urban-rural gmina overall, 4/5 = urban/rural part only, 8 = Warszawa district (1465011 = all of Warszawa, 1465108 = Śródmieście). Wins over location. Use list_locations to find codes."
    • Changedget_infrastructure_signals1 field changed
      • changedInput schema / properties / location / description
        Previous value: -"City or county name (e.g. 'Warszawa', 'Krotoszyn'). Aggregates every municipality in the county. Use this OR teryt."New value: +"City, county, or district name (e.g. 'Warszawa', 'Krotoszyn'). A city/county name aggregates every municipality in the county; a Warszawa district name (e.g. 'Mokotów') narrows to that gmina, another city's delegatura (e.g. 'Kraków-Podgórze') resolves to its parent county. Use this OR teryt."
    • Addedget_parcel_land_class
    • Addedget_transaction_nature
    • Addedget_transaction_roads
    • Addedget_transaction_subsurface
    • Changedlist_locations1 field changed
      • changedInput schema / properties / search / description
        Previous value: -"Filter locations by name (case-insensitive partial match, e.g. 'Krak' for Kraków districts). Ignored when parent is set."New value: +"Look up a place by name (case-insensitive, diacritics-insensitive partial match, e.g. 'wejher' for Wejherowo). Returns TERYT codes plus, where applicable, RCN district names. Ignored when parent is set."
    • Addedlist_parcels_in_area
    • Changedresolve_parcel1 field changed
      • changedInput schema / properties / q / description
        Previous value: -"Full cadastral id, a UUID, or 'locality name + parcel number' (e.g. 'Sabnie 342/5'). Mutually exclusive with parcelId and lat/lng."New value: +"Full cadastral id, a UUID, or 'locality name + parcel number' (e.g. 'Sabnie 342/5') — the name may be a gmina or a cadastral precinct (obręb). NOT a street address: for a street + building number use list_parcels_in_area instead. Mutually exclusive with parcelId and lat/lng."
    • Changedsearch_by_area4 fields changed
      • 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"
        +}
    • Changedsearch_by_polygon4 fields changed
      • 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"
        +}
    • Changedsearch_transactions7 fields changed
      • changedInput schema / properties / buildingNumber / description
        Previous value: -"Building/house number (e.g. '251C', '12A'). Requires location or street to be set."New value: +"Building/house number (e.g. '30', '12A'). Requires location or street to be set."
      • 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"
        +}
      • changedInput schema / properties / location / description
        Previous value: -"Location name - city (e.g. 'Warszawa', 'Kraków', 'Gdańsk') or district (e.g. 'Mokotów', 'Kraków-Podgórze'). 'Warszawa', 'Kraków', 'Łódź' auto-expand to all sub-districts. Use list_locations to find valid names."New value: +"Location name - city (e.g. 'Warszawa', 'Kraków', 'Gdańsk') or district (e.g. 'Mokotów', 'Kraków-Podgórze'). 'Warszawa', 'Kraków', 'Łódź' auto-expand to all sub-districts. Prefer teryt= for exact matches; call list_locations(search=...) to confirm a name is valid here — it flags valid ones as rcn_district."
      • 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"
        +}
      • changedInput schema / properties / street / description
        Previous value: -"Street name filter (partial match, e.g. 'Puławska', 'Trakt Lubelski')"New value: +"Street name filter, matched anywhere inside the name (e.g. 'Puławska', 'Aleja Waszyngtona'). Give it in the NOMINATIVE and with its Polish diacritics — matching is literal, so 'Karmelickiej' does not find 'Karmelicka' and 'Marszalkowska' does not find 'Marszałkowska'. Either mistake answers with nothing, which reads exactly like 'no such transactions'."
  2. 1 tool updatev0.6.0
    • Changedsearch_by_polygon2 fields changed
      • 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
  3. 23 tool updatesv0.5.0
    • First observedcompare_locations
    • First observedestimate_value
    • First observedget_building_breakdown
    • First observedget_demographics
    • First observedget_infrastructure_signals
    • First observedget_market_overview
    • First observedget_parcel_report
    • First observedget_price_distribution
    • First observedget_price_statistics
    • First observedget_transaction_farmland
    • First observedget_transaction_flood
    • First observedget_transaction_heritage
    • First observedget_transaction_landslide
    • First observedget_transaction_permits
    • First observedget_transaction_planning
    • First observedget_transaction_surroundings
    • First observedget_transaction_transit
    • First observedlist_locations
    • First observedresolve_parcel
    • First observedsearch_by_area
    • First observedsearch_by_polygon
    • First observedsearch_parcels
    • First observedsearch_transactions

TDQS

A4.2/5.0

Scored across 28 tools

Disambiguation4/5

Most tools are clearly separable by resource and action: transaction searches differ by administrative, radius, or polygon scope, and parcel tools distinguish area listing, prefix lookup, single-parcel resolution, and full dossier. The numerous get_transaction_* per-layer breakdown tools target distinct data layers, though the price/statistics group (get_price_statistics, get_price_distribution, compare_locations, get_market_overview) requires careful reading to avoid misselection.

Naming Consistency4/5

Tool names are consistently snake_case and mostly follow verb_noun or get_/search_/list_ patterns, with predictable families such as get_transaction_*, search_*, and get_parcel_*. Minor deviations like search_by_area and search_by_polygon use a search_by_ structure rather than a pure verb_noun pattern, but they remain readable and consistent with the search family.

Tool Count3/5

28 tools is heavy for an MCP server and exceeds the typical 3–15 range, which increases selection burden for an agent. However, the domain is unusually broad—transactions, parcels, enrichment layers, statistics, demographics, and infrastructure—so most tools are not redundant, even if the surface is borderline over-scoped.

Completeness4/5

The server covers a wide read-only surface: transaction and parcel discovery, parcel resolution and reporting, many property/environmental layers, price statistics, demographics, infrastructure signals, and value estimation. A minor gap is the absence of a single general transaction-detail tool that aggregates all per-transaction layers in one call, though search results provide core transaction fields and the per-layer tools cover the details.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides access to Poland's largest business registry database, enabling company search, beneficiary checks, and financial document retrieval via natural language.
    1
    -
  • A
    license
    A
    quality
    C
    maintenance
    Enables searching Polish administrative areas and retrieving real estate transaction data from the official registry via geoportal.gov.pl.
    3
    GPL 3.0