Skip to main content
Glama
Evlek

Evlek — Northern Cyprus Property MCP Server

Official

Evlek MCP Server

MCP Hosted License Coverage MCP Registry

AI-native property discovery for North Cyprus (KKTC). Built on the Model Context Protocol — works in Claude, ChatGPT, Gemini, Cursor, and any MCP-compatible client.

The Evlek MCP server gives AI agents structured, real-time access to North Cyprus property data — search active listings, compare cities and districts, and track the price index. All data is sourced live from evlek.app. Evlek does not offer a rental-yield or investment-return estimate: figures are descriptive asking-price facts only, never a valuation, forecast, or recommendation. Title-deed (koçan) and legal-procedure tools are deliberately not part of the surface: that taxonomy has not passed an independent KKTC legal audit.

License scope

This repository is MIT-licensed for the public manifest, documentation, examples, and reference clients contained here. The hosted Evlek service, evlek.app web app, mobile apps, listing database, AI prompts, business logic, brand assets, name, logo, and trade dress remain proprietary and are not licensed under MIT. See LICENSE for details.


Related MCP server: UK Property Data

Why Evlek MCP

  • AI-first. Built for agentic workflows from day one — not retrofitted on a legacy listing API.

  • Multilingual. Property data in TR, EN, RU, DE, AR (currently exposed via tool descriptions in EN).

  • Verification-aware listings. Evlek surfaces listing and account verification context where available, and the MCP omits contact fields to preserve Evlek's reveal/contact funnel.

  • Built for the region. Optimized for the 6 cities of North Cyprus (Lefkoşa, Girne, Gazimağusa, İskele, Güzelyurt, Lefke) and 100+ districts.

  • Production-grade. OWASP MCP Top 10 aligned — Zod input validation, output sanitization, rate limiting (60/min/IP, 500/min global), Sentry observability.


Quick start

Remote-capable clients (preferred)

Most modern MCP clients (Claude, Cursor, VS Code) connect directly to the Streamable HTTP endpoint — no local bridge needed:

{
  "mcpServers": {
    "evlek": {
      "url": "https://evlek.app/api/mcp"
    }
  }
}

ChatGPT (connector + Deep Research)

Add https://evlek.app/api/mcp as a custom connector. Evlek exposes OpenAI-compatible search and fetch tools, so it works in ChatGPT connectors and Deep Research in addition to developer mode.

Claude Desktop (legacy stdio bridge)

If your client only supports stdio servers, use the pinned mcp-remote bridge. Add this to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "evlek": {
      "command": "npx",
      "args": ["-y", "mcp-remote@0.1.16", "https://evlek.app/api/mcp"]
    }
  }
}

Restart Claude Desktop. The "evlek" server appears in the tools list.

MCP Inspector (test before installing)

npx @modelcontextprotocol/inspector https://evlek.app/api/mcp

Direct API (cURL)

curl -X POST https://evlek.app/api/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

More configs: examples/


Local stdio server (this repository)

This repo is also a runnable MCP server. It answers initialize / tools/list entirely locally from the embedded tool contract (tools.json) and fetches live data from the Evlek data API when a tool is called. It only implements tools — it does not declare the resources or prompts capability, so resources/list and prompts/list return a normal MCP "method not found" error on this bridge; those primitives (see below) are hosted-endpoint-only, reachable via the Streamable HTTP URL above. It also speaks whatever MCP protocol version the pinned @modelcontextprotocol/sdk supports during initialize (currently 2025-11-25), not necessarily the hosted endpoint's 2026-07-28 — tool schemas are identical either way.

npx github:Evlek/evlek-mcp        # or: npm install && npm start
{
  "mcpServers": {
    "evlek": {
      "command": "npx",
      "args": ["-y", "github:Evlek/evlek-mcp"]
    }
  }
}

Smoke-test it (spawns the server and speaks real MCP over stdio):

npm test              # live: initialize + tools/list + a real tools/call
OFFLINE=1 npm test    # offline: introspection works with zero network

Available tools

12 tools · protocol 2026-07-28 · Streamable HTTP JSON-RPC 2.0

Tool

Title

Description

search_listings

Search Northern Cyprus Property Listings

Search live active sale and long-term-rent listings on Evlek. Results are newest-first by default; limit caps returned rows and totalMatched reports the full match count. Returns advertised asking-price and listing facts only; not valuation, verification of property-specific claims, forecast, ranking, or recommendation.

get_price_index

Get Northern Cyprus Price Index

Returns source-dated aggregates of live active Evlek sale or long-term-rent asking prices. Descriptive listing facts only: not completed transactions, a valuation, a forecast, or an investment recommendation.

compare_cities

Compare Northern Cyprus Cities Side-by-Side

Compare source-dated live active-listing asking-price aggregates across 2-4 Northern Cyprus cities. Descriptive listing facts only; not transaction prices, valuation, forecast, ranking, or investment advice.

compare_properties

Compare Evlek Property Listings Side-by-Side

Compare descriptive facts from 2-4 active Evlek sale or long-term-rent listings of the same type. Shows advertised asking price, size and £/m² differences without making a value, suitability, appraisal, or investment judgment. The legacy listing_ids parameter name is still accepted as an alias of listingIds.

get_district_profile

Get Live Asking-Price Context for a Northern Cyprus District

Returns source-dated active sale/long-term-rent listing counts and asking-price aggregates for one district. Any rent-to-price percentage is a derived asking-price ratio, not observed income, net yield, valuation, forecast, ranking, or recommendation.

convert_currency

Currency Conversion (GBP/EUR/USD/TRY)

Converts an entered property asking-price amount across GBP/EUR/USD/TRY when complete, valid, fresh, date-stamped stored FX rates are available; otherwise it fails closed without amounts. Currency conversion only: no payment plan, deposit schedule, installment schedule, acquisition-cost estimate, or advice.

payment_plan

Currency Conversion (payment-plan name reserved)

Currently returns currency conversion only. A real installment/payment-schedule tool is planned under this name; until then it does not produce a payment plan, deposit schedule, or acquisition-cost estimate.

get_listing_detail

Get Full Detail for a Single Evlek Listing

Return a 360° profile of one active Evlek listing by UUID or listing number: title, description, price, location, size, amenities, features, cover image, per-photo captions/tags, and AI virtual-staging before/after pairs (always AI-disclosed). Contact details omitted. Use when: a UUID or listing number is already known. Don't use for: discovery — use search_listings first. The legacy property_id parameter name is still accepted as an alias of propertyId.

search

Search Evlek property listings

Search live Northern Cyprus (KKTC/TRNC) property listings on Evlek with a free-text query. Returns matching listings as id/title/url for the fetch tool. Same data as search_listings — this fixed form exists for the ChatGPT/OpenAI connector contract. Use when: the caller only has a free-text query. Don't use for: structured filters — use search_listings.

fetch

Fetch full Evlek listing detail

Fetch the full detail of one Evlek listing by id (from search): title, description, GBP-normalized price, location, size, amenities. Same data as get_listing_detail — this fixed id-only form exists for the ChatGPT/OpenAI connector contract. Use when: an id from search is known. Don't use for: discovery — use search first.

list_locations

List Valid Evlek Cities and Districts

Return canonical KKTC city slugs plus districts represented by active Evlek sale or long-term-rent listings. Live inventory-location facts only; holiday-home inventory remains unavailable.

get_listing_by_number

Get Evlek Listing by Number

Look up a single Evlek listing by its public listing number (e.g. "EVL-123456", "123456", or a bare number) and return its full detail — same shape as get_listing_detail. Use when: a listing number is known. Don't use for: UUID lookups — use get_listing_detail. The legacy listing_number parameter name is still accepted as an alias of listingNumber.

Every tool declares annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false } — the whole surface is read-only.

Interactive widgets (MCP Apps / SEP-1865)

Three tools additionally ship a sandboxed HTML view that MCP Apps-capable hosts (Claude web/desktop) render inline in the conversation:

Tool

Widget

What you get

search_listings, search

ui://evlek/listing-cards-v2.html

Horizontal carousel of cards (cover photo, price, location) — the whole card is the link, no separate CTA button; opening one drills into the SAME detail view as get_listing_detail, in fullscreen, never an inline half-panel. An opt-in "select to compare" mode sends 2-4 listings to compare_properties, rendered as a comparison table.

get_listing_detail

ui://evlek/listing-detail-v2.html

Photo gallery with AI captions, spec sheet, and a before/after AI virtual-staging comparison slider

get_price_index

ui://evlek/price-index-v2.html

Per-city summary rows inline (avg/median, capped to a few cities to stay compact); the full district breakdown and city-comparison table open in fullscreen, not inline

Views are static, self-contained HTML — no bundler, no third-party JS. Listing data reaches them only at runtime over postMessage and is written with textContent, never innerHTML. CSP is declared per resource (_meta.ui.csp) and limited to the public listing-photo origin.

See TOOLS.md for full input schemas, parameter details, and response examples.

Resources (12) & resource templates (2)

resources/list returns 12 resources on the hosted endpoint — 9 read-only evlek:// data resources plus the 3 ui:// interactive-widget resources described above (pre-declared so a host can pre-cache them). Parameterized templates are separate, via resources/templates/list:

  • Templates (2): evlek://price-index/{city} · evlek://district/{city}/{district}

  • Data resources (9): per-city price indexes (girne, iskele, lefkosa, gazimagusa, guzelyurt, lefke), a sample district profile (Girne/Alsancak), and 2 orientation guides — evlek://guides/neighborhood-personas, evlek://guides/universities.

  • Widget resources (3): ui://evlek/listing-cards-v2.html, ui://evlek/listing-detail-v2.html, ui://evlek/price-index-v2.html — see "Interactive widgets" above.

Prompts (2)

  • property_scenario — Illustrative Property Scenario with Separate Live Facts

  • student_rental_scenario — Illustrative Student-Rental Scenario


Example prompts

  • "Find 2-bedroom flats for rent in Girne under £1,500/month."

  • "Show me apartments in Girne under £150,000."

  • "What's the median sale price per square meter in Lefkoşa?"

  • "Compare Kyrenia and Famagusta — which has more active listings and how do median asking prices differ?"

  • "What does a district profile for Alsancak look like?"

  • "Convert £150,000 to EUR, USD, and TRY."


Coverage

  • Cities: 6 (Girne, İskele, Lefkoşa, Gazimağusa, Güzelyurt, Lefke)

  • Districts: 100+

  • Currency: GBP primary; TRY/USD/EUR normalized to GBP server-side using live daily exchange rates

  • Tool descriptions: EN · Listing data fields: TR + EN


Architecture

The Evlek MCP server runs as a hosted endpoint at https://evlek.app/api/mcp. It speaks the Model Context Protocol over Streamable HTTP (JSON-RPC 2.0), protocolVersion 2026-07-28, and exposes tools, resources, resource templates, and prompts. Discovery metadata is published at /.well-known/mcp.json.

This repository contains:

  • server.json — MCP Registry manifest

  • TOOLS.md — Full tool reference (JSON schemas + examples)

  • CHANGELOG.md — Notable changes to the tool surface, including removed/renamed tools

  • examples/ — Configuration files for Claude Desktop, Cursor, VS Code

  • CONTRIBUTING.md — How to file issues and propose docs improvements

The full server implementation (database schemas, API routes, AI prompt engineering, listing pipeline) is hosted at evlek.app and remains proprietary.

Security model

Per OWASP MCP Top 10: per-IP rate limit 60/min, global 500/min, 30s hard timeout, Zod input validation, output sanitization (prompt-injection defense), max 10 results per query, Supabase anon key + RLS, no stack traces leaked, Sentry observability.

To report a security issue, email hello@evlek.app.


Status

  • MCP version: 2.1.0 (live)

  • Protocol: 2026-07-28

  • Primitives: 12 tools · 9 data resources + 3 interactive widget resources · 2 resource templates · 2 prompts

  • Auth: none (public read-only)

  • Endpoint: https://evlek.app/api/mcp

  • MCP Registry: app.evlek/mcp-server


License

MIT — see LICENSE. MIT covers the public manifest, documentation, examples, and reference clients in this repository only (see License scope above). The hosted Evlek service (web app, mobile apps, listing data, AI prompts, database schemas, business logic) is proprietary.

Trademark notice: "Evlek" is a trademark of Onur Dokuzoğlu. The MIT license does not grant rights to use the "Evlek" name, logo, or branding except as described in this README. To request brand usage permission, contact hello@evlek.app.



Built in North Cyprus by an architect, not a software firm. Powered by Anthropic Claude, Supabase, Vercel, and the Model Context Protocol.

Available Tools

12 tools
compare_citiesCompare Northern Cyprus Cities Side-by-SideA
Read-only
Inspect

Compare source-dated live active-listing asking-price aggregates across 2-4 Northern Cyprus cities. Descriptive listing facts only; not transaction prices, valuation, forecast, ranking, or investment advice.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeNoSale or rent (default: sale)
citiesYesCities to compare (2-4)

Output Schema

ParametersJSON Schema
NameRequiredDescription
typeYes
citiesYes
dataAsOfYes
dataSourceNo
isEstimateNo
metricTypeNo

TDQS

A4.3/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, so the safety profile is covered. The description adds meaningful behavioral context by specifying that it returns source-dated live active-listing asking-price aggregates and descriptive listing facts only, which clarifies the nature and limitations of the data 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.

Conciseness5/5

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

The description is a single, tightly written sentence that front-loads the action and resource, then adds the important exclusions. Every element earns its place; there is no redundancy or filler.

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

Completeness5/5

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

With annotations covering the read-only/destructive profile, a fully described input schema, an output schema present, and a description that states scope, data type, and exclusions, the description is complete for an agent to correctly select and invoke this tool. Return format is not needed because an output schema exists.

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

Parameters3/5

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

Schema description coverage is 100%, so the input schema already documents both parameters. The description reinforces the 2-4 city constraint and the sale/rent context, but it does not add substantial meaning beyond what the schema already provides. Baseline 3 is appropriate here.

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 clear verb ('Compare') and a specific resource ('source-dated live active-listing asking-price aggregates across 2-4 Northern Cyprus cities'). It also distinguishes itself from valuation, forecast, and investment tools by explicitly excluding those categories, making it easy for an agent to identify what this tool does.

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 provides clear context for when to use the tool: comparing city-level asking-price aggregates for 2-4 Northern Cyprus cities, for sale or rent. It also gives exclusions (not transaction prices, valuation, forecast, ranking, or investment advice). However, it does not explicitly name alternative sibling tools such as compare_properties or get_price_index, so the when-not-to-use guidance is present but not fully explicit.

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

compare_propertiesCompare Evlek Property Listings Side-by-SideA
Read-only
Inspect

Compare descriptive facts from 2-4 active Evlek sale or long-term-rent listings of the same type. Shows advertised asking price, size and £/m² differences without making a value, suitability, appraisal, or investment judgment. The legacy listing_ids parameter name is still accepted as an alias of listingIds.

ParametersJSON Schema
NameRequiredDescriptionDefault
listingIdsYesEvlek listing UUIDs or listing numbers (2-4)

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYes
missingNo
listingsYes
dataSourceNo
isEstimateNo
metricTypeNo

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, so the safety profile is covered. The description adds meaningful behavioral context: it only compares factual listing data and avoids subjective judgments, shows specific outputs (price, size, £/m²), and documents that the legacy alias `listing_ids` is accepted. This goes beyond the structured 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?

Three sentences, each carrying distinct value: core function, output scope and non-judgment boundary, and alias note. The most important constraints are front-loaded, and there is no filler or repetition of schema content.

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, a complete output schema, and annotations covering safety, the description covers all needed guidance: input count and type constraints, active and same-type prerequisites, what it returns, what it avoids, and legacy compatibility. Nothing critical 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 description coverage is 100%, so the baseline is 3. The description adds extra meaning by clarifying that only listings of the same type and active listings should be compared, and by revealing the legacy `listing_ids` alias. These details are not present in the schema itself, raising the value above baseline.

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 the specific verb 'Compare' with a clear resource: descriptive facts from 2-4 active Evlek sale or long-term-rent listings of the same type. It distinguishes itself from sibling tools like compare_cities by focusing on property listings, and from listing lookups by emphasizing side-by-side comparison of facts.

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 clearly scopes when to use the tool: comparing descriptive facts from 2-4 active listings of the same type. It also provides an explicit when-not by stating it makes no value, suitability, appraisal, or investment judgment. It does not name alternative sibling tools, but the use case is well-defined enough to guide an agent.

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

convert_currencyCurrency Conversion (GBP/EUR/USD/TRY)A
Read-only
Inspect

Converts an entered property asking-price amount across GBP/EUR/USD/TRY when complete, valid, fresh, date-stamped stored FX rates are available; otherwise it fails closed without amounts. Currency conversion only: no payment plan, deposit schedule, installment schedule, acquisition-cost estimate, or advice.

ParametersJSON Schema
NameRequiredDescriptionDefault
priceYesEntered property asking-price amount; not a deposit or installment.
currencyNoCurrency of the price (default GBP).

Output Schema

ParametersJSON Schema
NameRequiredDescription
fxNo
amountsYes
priceGBPYes
dataSourceNo
inputCurrencyYes
usesStoredRateNo

TDQS

A4.4/5.0
Behavior5/5

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

Annotations already mark the tool as read-only and non-destructive, and the description adds valuable behavior beyond that: it requires fresh date-stamped rates and fails closed without amounts if conditions are unmet. This gives the agent a clear expectation of success and failure modes.

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

Conciseness5/5

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

Two sentences deliver the purpose, scope, preconditions, and failure mode with no filler. The core action and limitations are front-loaded, making the tool easy to scan and understand.

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?

The description, together with the schema and annotations, gives a solid picture of when and how the tool behaves. An output schema exists so return details are not the description's responsibility. It could be slightly more explicit about whether all four currencies are returned at once, but the current wording is sufficient for selection and invocation.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents the price amount and currency well. The description reinforces that the input is a property asking-price amount and not a deposit or installment, but it does not add new parameter-level detail 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 states a specific verb and resource: converting an entered property asking-price amount across GBP/EUR/USD/TRY. It also clearly delimits the tool's scope by excluding payment plans, deposit schedules, and other related calculations, distinguishing it from sibling tools like payment_plan.

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 clear context: this is only for currency conversion of an asking price, not for payment schedules or cost advice. It also states a precondition (complete, valid, fresh, date-stamped FX rates) and the failure behavior. It does not explicitly name alternative tools for the excluded use cases, but the exclusion itself provides practical routing guidance.

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

fetchFetch full Evlek listing detailA
Read-only
Inspect

Fetch the full detail of one Evlek listing by id (from search): title, description, GBP-normalized price, location, size, amenities. Same data as get_listing_detail — this fixed id-only form exists for the ChatGPT/OpenAI connector contract. Use when: an id from search is known. Don't use for: discovery — use search first.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesEvlek listing id (UUID) from search

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
urlYes
textYes
titleYes
photosNo
metadataNo
coverImageUrlNo

TDQS

A4.3/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, so the safety profile is covered. The description adds useful behavioral context: it is id-only, returns GBP-normalized price, and mirrors get_listing_detail's 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.

Conciseness5/5

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

The description is well-structured and front-loaded: it opens with the action and resource, then narrows to contract context and explicit usage rules. Every sentence contributes useful information without unnecessary filler.

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

Completeness5/5

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

For a one-parameter read-only tool with a rich output schema and annotations already present, the description covers what the tool does, what data it returns, when to use it, and when not to. Nothing critical is missing for correct invocation.

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

Parameters3/5

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

The schema has 100% coverage for its single required parameter, including the UUID-from-search meaning. The description reinforces 'by id (from search)' but adds no meaning beyond the schema, so the baseline score of 3 is appropriate.

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

Purpose5/5

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

The description states a specific verb and resource: 'Fetch the full detail of one Evlek listing by id', and enumerates the exact data fields returned. It also distinguishes this tool from get_listing_detail by explaining it is the fixed id-only connector-contract form.

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 explicitly gives a use condition ('Use when: an id from search is known'), a don't-use condition ('Don't use for: discovery'), and names the alternative ('use search first'). However, because get_listing_detail is described as returning the same data, the description doesn't fully clarify when to choose fetch over get_listing_detail for non-connector use.

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

get_district_profileGet Live Asking-Price Context for a Northern Cyprus DistrictA
Read-only
Inspect

Returns source-dated active sale/long-term-rent listing counts and asking-price aggregates for one district. Any rent-to-price percentage is a derived asking-price ratio, not observed income, net yield, valuation, forecast, ranking, or recommendation.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityYesCity containing the district. Slug, Turkish name, or exonym (Kyrenia/Nicosia/Famagusta/Morphou).
districtYesDistrict name (2-60 chars), matched accent/case-insensitively against the active-listing district list

Output Schema

ParametersJSON Schema
NameRequiredDescription
cityYes
rentNo
saleNo
dataAsOfNo
districtYes
truncatedNo
dataSourceNo
metricTypeNo
personaContextsNo
ratioMetricTypeNo
cleanSampleTotalYessale.count + rent.count — clean sample size (IQR outliers excluded), not raw active listings
isObservedIncomeNo
askingRentToAskingPricePctNo

TDQS

A4.2/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. The description adds valuable behavioral context: data is source-dated, reflecting active listings, and any rent-to-price percentage is a derived ratio rather than observed income, yield, valuation, forecast, ranking, or recommendation. This prevents misinterpretation of results.

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

Conciseness5/5

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

The description is two sentences with no filler. The first sentence front-loads the core behavior, and the second sentence adds an essential caveat about how rent-to-price percentages should be interpreted.

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 full schema coverage, annotations, and an output schema, the description is nearly complete. It adds the right disclaimers and scope. A small gap is the absence of any explicit pointer to sibling tools for multi-district comparisons, though this is not required for invoking 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 description coverage is 100%, so both city and district parameters are fully documented there. The description adds no parameter-specific details beyond the single-district scope, so it does not need to compensate for any schema gap.

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?

Description states a specific verb and resource: 'Returns source-dated active sale/long-term-rent listing counts and asking-price aggregates for one district.' It clearly identifies a single-district profile tool and distinguishes it from siblings like compare_cities or get_price_index.

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 clear context: use this tool when you need asking-price and listing-count aggregates for one district. It does not explicitly name alternatives or exclusions, but the single-district scope and output type make the intended usage reasonably obvious.

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

get_listing_by_numberGet Evlek Listing by NumberA
Read-only
Inspect

Look up a single Evlek listing by its public listing number (e.g. "EVL-123456", "123456", or a bare number) and return its full detail — same shape as get_listing_detail. Use when: a listing number is known. Don't use for: UUID lookups — use get_listing_detail. The legacy listing_number parameter name is still accepted as an alias of listingNumber.

ParametersJSON Schema
NameRequiredDescriptionDefault
listingNumberYesEvlek listing number, e.g. "EVL-123456", "123456", or the bare number 123456.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNo
urlNo
cityNo
typeNo
foundYes
priceNo
titleNo
photosNo
areaSqmNo
fxRatesNo
bedroomsNo
currencyNo
districtNo
factTypeNo
featuresNo
listedAtNo
priceGbpNo
amenitiesNo
bathroomsNo
furnishedNo
dataSourceNo
isEstimateNo
photoCountNo
photosShownNo
coverImageUrlNo
listingNumberNo
monthlyRentGbpNo
pricePerSqmGBPNo
virtualStagingNo
photosTruncatedNo
locationPrecisionNo

TDQS

A4.7/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, so the safety profile is known. The description adds useful behavior beyond that: it returns 'full detail — same shape as get_listing_detail' and documents the accepted legacy `listing_number` alias. No contradictions 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?

Three sentences pack purpose, boundary conditions, return shape, and alias information without any filler. Key scoping information is front-loaded before the alternatives and alias notes.

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 lookup with a single required parameter and an output schema, the description fully covers what the tool does, when to use it, what not to use it for, and the parameter alias. Nothing material is missing for correct invocation.

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

Parameters4/5

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

Schema coverage is 100%, so the schema already documents listingNumber with examples. The description adds the legacy alias `listing_number` and clarifies the acceptable formats ('EVL-123456', '123456', or bare number), which goes beyond the schema's already-good documentation.

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 object: 'Look up a single Evlek listing by its public listing number.' It immediately differentiates itself from get_listing_detail by contrasting public-number lookups with UUID lookups, so an agent can distinguish the two tools without inspecting 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?

Provides explicit guidance: 'Use when: a listing number is known. Don't use for: UUID lookups — use get_listing_detail.' It also covers the legacy parameter alias, which helps agents handle older call patterns correctly.

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

get_listing_detailGet Full Detail for a Single Evlek ListingA
Read-only
Inspect

Return a 360° profile of one active Evlek listing by UUID or listing number: title, description, price, location, size, amenities, features, cover image, per-photo captions/tags, and AI virtual-staging before/after pairs (always AI-disclosed). Contact details omitted. Use when: a UUID or listing number is already known. Don't use for: discovery — use search_listings first. The legacy property_id parameter name is still accepted as an alias of propertyId.

ParametersJSON Schema
NameRequiredDescriptionDefault
propertyIdYesEvlek listing UUID or listing number (e.g. "EVL-123456", "123456")

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNo
urlNo
cityNo
typeNo
foundYes
priceNo
titleNo
photosNo
areaSqmNo
fxRatesNo
bedroomsNo
currencyNo
districtNo
factTypeNo
featuresNo
listedAtNo
priceGbpNo
amenitiesNo
bathroomsNo
furnishedNo
dataSourceNo
isEstimateNo
photoCountNo
photosShownNo
coverImageUrlNo
listingNumberNo
monthlyRentGbpNo
pricePerSqmGBPNo
virtualStagingNo
photosTruncatedNo
locationPrecisionNo

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the annotations (readOnlyHint=true, destructiveHint=false), the description discloses meaningful behaviors: contact details are omitted, AI virtual-staging is always disclosed, and only active listings are returned. These details inform an agent about content boundaries and policy compliance beyond what the annotations or schema state.

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 information-dense but every clause earns its place: main behavior, field list, exclusions, usage guidance, and alias note. It is front-loaded with the core purpose and avoids redundant restatement of the title.

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 single-parameter, read-only tool with an output schema present, the description covers everything an agent needs: what is returned, what is omitted, when to use it, and how to identify the listing. No critical gaps remain.

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 description coverage is 100%, so the schema already documents the parameter well. The description adds value by clarifying that the propertyId can be a UUID or listing number and by noting the legacy 'property_id' alias is still accepted, which the schema does not mention.

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 and resource: 'Return a 360° profile of one active Evlek listing by UUID or listing number,' followed by a concrete list of included fields. It clearly distinguishes itself from discovery-oriented tools by naming search_listings as the alternative, making its role 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?

Explicit guidance is provided: 'Use when: a UUID or listing number is already known. Don't use for: discovery — use search_listings first.' This gives both positive and negative usage conditions and names the exact alternative, leaving no inference required.

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

get_price_indexGet Northern Cyprus Price IndexA
Read-only
Inspect

Returns source-dated aggregates of live active Evlek sale or long-term-rent asking prices. Descriptive listing facts only: not completed transactions, a valuation, a forecast, or an investment recommendation.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoFilter to a single city (omit for all cities). Slug, Turkish name, or exonym (Kyrenia/Nicosia/Famagusta/Morphou).
typeNoSale or rent (default: sale)

Output Schema

ParametersJSON Schema
NameRequiredDescription
typeYes
citiesYes
dataAsOfYes
dataSourceNo
isEstimateNo
metricTypeNo
totalListingsNo

TDQS

A4.1/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, so the safety profile is clear. The description adds meaningful context beyond that: data is 'source-dated', 'live active', and based on 'asking prices' only, and it clarifies that output is descriptive facts rather than investment advice. This helps the agent interpret results correctly.

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

Conciseness5/5

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

Two tight sentences with zero waste. The first states the action and key qualifiers; the second draws a clear boundary of what the data is not. Every phrase contributes to understanding.

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 lightweight read-only tool with two optional, fully documented parameters and an output schema, the description covers the essential semantics, scope, and limitations. An agent can safely invoke it and know what kind of output to expect without missing critical context.

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% parameter description coverage, so the description does not need to compensate. It echoes the 'sale or rent' distinction from the type parameter but adds no meaning beyond what the schema already provides. 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?

Description names a specific verb ('Returns'), a clear resource ('source-dated aggregates of live active Evlek sale or long-term-rent asking prices'), and explicitly scopes away from completed transactions, valuations, forecasts, and recommendations. This distinguishes it from sibling listing/search tools, which target individual properties or comparisons.

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 use for market-level asking-price analytics and explicitly lists exclusions ('not completed transactions, a valuation, a forecast, or an investment recommendation'). However, it does not explicitly name an alternative tool or state a direct routing condition such as 'use this for aggregates, use search for listings', so the guidance is more implied than explicit.

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

list_locationsList Valid Evlek Cities and DistrictsA
Read-only
Inspect

Return canonical KKTC city slugs plus districts represented by active Evlek sale or long-term-rent listings. Live inventory-location facts only; holiday-home inventory remains unavailable.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoOptional — limit districts to a single city. Slug, Turkish name, or exonym (Kyrenia/Nicosia/Famagusta/Morphou).

Output Schema

ParametersJSON Schema
NameRequiredDescription
citiesYes
truncatedNo
dataSourceNo
isEstimateNo

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already mark the tool as read-only and non-destructive; the description adds that results are live inventory-location facts only and that holiday-home inventory is unavailable. This usefully discloses the data-source behavior and a meaningful limitation beyond what annotations state.

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 concise at two sentences, front-loads the core purpose, and every sentence carries meaningful scope information. No filler or redundant restatement of the title or schema.

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 one optional parameter, an output schema, and clear annotations, the description covers purpose, scope, live-inventory behavior, and an explicit exclusion. Nothing essential is missing for an agent to select and invoke it 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?

The input schema already provides 100% coverage for the single optional city parameter, including accepted forms like slug, Turkish name, or exonym. The description adds no additional parameter-level detail, so the baseline score 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 states a specific verb and resource: it returns canonical KKTC city slugs plus districts represented by active Evlek sale or long-term-rent listings. It clearly scopes the result set and distinguishes itself from broader search or comparison tools by emphasizing live inventory-location facts.

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 makes clear that this is for canonical city/district data derived from active sale or long-term-rent listings and explicitly excludes holiday-home inventory. It does not name a specific sibling alternative, but the exclusion and live-inventory framing give the agent clear contextual guidance on when to use it.

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

payment_planCurrency Conversion (payment-plan name reserved)A
Read-only
Inspect

Currently returns currency conversion only. A real installment/payment-schedule tool is planned under this name; until then it does not produce a payment plan, deposit schedule, or acquisition-cost estimate.

ParametersJSON Schema
NameRequiredDescriptionDefault
priceYesEntered property asking-price amount; not a deposit or installment.
currencyNoCurrency of the price (default GBP).

Output Schema

ParametersJSON Schema
NameRequiredDescription
fxNo
amountsYes
priceGBPYes
dataSourceNo
inputCurrencyYes
usesStoredRateNo

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint and non-destructive behavior. The description adds meaningful context by revealing that this is a temporary placeholder that only returns currency conversion, going beyond what the annotations convey and preventing false expectations about payment-plan outputs.

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 two concise sentences. The first front-loads the actual current behavior, and the second prevents misuse by listing what the tool does not do and explaining the placeholder situation. Every sentence earns its place.

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 simple two-parameter tool with an output schema and safety annotations, the description covers the essential caveat that the tool name is misleading. It could have pointed explicitly to convert_currency as the canonical sibling, but nothing critical is missing for correctly invoking a basic currency conversion.

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

Parameters3/5

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

Schema description coverage is 100%, so the baseline is 3. The description itself adds no parameter-specific detail; the schema already explains that price is the asking price and not a deposit or installment, and currency is the price currency.

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

Purpose4/5

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

The description clearly states the tool currently performs currency conversion only, and explicitly disclaims payment-plan, deposit, and acquisition-cost outputs. This distinguishes it from the misleading name, though it does not explicitly differentiate it from the sibling convert_currency.

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 the tool should be used for currency conversion and warns against using it for payment plans or related estimates. However, it never explicitly says when to prefer this tool over the sibling convert_currency, and it lacks clear when-to-use versus when-not-to-use guidance.

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

search_listingsSearch Northern Cyprus Property ListingsA
Read-only
Inspect

Search live active sale and long-term-rent listings on Evlek. Results are newest-first by default; limit caps returned rows and totalMatched reports the full match count. Returns advertised asking-price and listing facts only; not valuation, verification of property-specific claims, forecast, ranking, or recommendation.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoSlug, Turkish name, or exonym (Kyrenia/Nicosia/Famagusta/Morphou).
poolNoOnly listings with a pool
typeNoListing type
limitNoResult count (integer 1-10, default 5)
gardenNoOnly listings with a garden
offsetNoRows to skip (pagination, default 0)
sortByNoSort order (default: newest)
parkingNoOnly listings with parking
seaViewNoOnly listings flagged sea_view
bedroomsNoBedroom count (integer 0-10)
districtNoDistrict name (e.g. Alsancak), matched accent/case-insensitively against the active-listing district list
elevatorNoOnly listings with an elevator
maxPriceNoMax price in GBP
minPriceNoMin price in GBP
furnishedNoOnly furnished listings
propertyTypeNoRaw property type (apartment, villa, …) or K75 group slug: house (villa+detached+bungalow), land, commercial

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYes
offsetYes
fxRatesNo
rankingNo
factTypeNo
listingsYes
dataSourceNo
isEstimateNo
sortAppliedYes
totalMatchedYes
appliedFiltersYes

TDQS

A4.2/5.0
Behavior5/5

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

Beyond the annotations (readOnlyHint=true, destructiveHint=false), the description discloses default ordering, that limit caps returned rows, that totalMatched reports the full match count, and explicitly states what the tool does NOT return (valuation, verification, forecast, ranking, recommendation). This is rich, non-contradictory context that meaningfully shapes agent expectations.

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

Conciseness5/5

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

Three compact sentences: the first states the action, the second explains ordering and count semantics, and the third lists explicit exclusions. No filler or repetition, and key facts are front-loaded.

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

Completeness5/5

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

For a 16-parameter tool with 100% schema coverage and an output schema, the description covers all necessary operational context: purpose, default order, pagination semantics, and explicit disclaimers about result scope. An agent can select and invoke it correctly without needing additional details.

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 schema documents all 16 parameters. The description adds value by defining 'limit' as capping rows, introducing 'totalMatched' as the full match count, and clarifying that the search targets sale and long-term-rent listing types. This goes slightly beyond the schema descriptions.

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

Purpose4/5

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

The description identifies a specific verb ('Search') and resource ('live active sale and long-term-rent listings on Evlek'), with the title adding 'Northern Cyprus Property Listings'. It does not explicitly contrast with sibling 'search', but the scope and platform-specific wording make the tool's purpose distinguishable.

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?

Implied usage is clear: use this tool to find active sale and long-term rent listings, with default newest-first ordering and pagination. However, it does not name any alternatives or state when to prefer get_listing_by_number, compare_cities, or search instead.

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. 19 tool updatesv2.1.0
    • Removedassess_title_risk
    • Changedcompare_cities9 fields changed
      • addedInput schema / properties / cities / items / description
        Added value: +"Slug, Turkish name, or exonym (Kyrenia/Nicosia/Famagusta/Morphou)."
      • removedInput schema / properties / cities / items / enum
        Removed value: -[
        -  "girne",
        -  "iskele",
        -  "lefkosa",
        -  "gazimagusa",
        -  "guzelyurt",
        -  "lefke"
        -]
      • addedOutput schema / properties / cities / items
        Added value: +{
        +  "properties": {
        +    "activeCount": {
        +      "type": "number"
        +    },
        +    "city": {
        +      "type": "string"
        +    },
        +    "hasData": {
        +      "type": "boolean"
        +    },
        +    "lowSample": {
        +      "type": "boolean"
        +    },
        +    "medianPrice": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "medianPricePerSqm": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "p25Price": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "p75Price": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "provenance": {
        +      "properties": {
        +        "agencies": {
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "maxAgencyShare": {
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "publishers": {
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "singleSource": {
        +          "type": "boolean"
        +        }
        +      },
        +      "required": [
        +        "publishers",
        +        "agencies",
        +        "maxAgencyShare",
        +        "singleSource"
        +      ],
        +      "type": "object"
        +    },
        +    "slug": {
        +      "type": "string"
        +    },
        +    "topDistrict": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "topDistrictMedianPrice": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "withheldReason": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "slug",
        +    "city",
        +    "activeCount",
        +    "hasData"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / dataAsOf
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / dataSource
        Added value: +{
        +  "type": "string"
        +}
      • removedOutput schema / properties / generatedAt
        Removed value: -{
        -  "type": "string"
        -}
      • addedOutput schema / properties / isEstimate
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / metricType
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / required
        Added value: +[
        +  "type",
        +  "dataAsOf",
        +  "cities"
        +]
    • Changedcompare_properties8 fields changed
      • addedInput schema / properties / listingIds
        Added value: +{
        +  "description": "Evlek listing UUIDs or listing numbers (2-4)",
        +  "items": {
        +    "description": "Evlek listing UUID or listing number (e.g. \"EVL-123456\", \"123456\")",
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • removedInput schema / properties / listing_ids
        Removed value: -{
        -  "description": "Evlek listing UUIDs (2-4)",
        -  "items": {
        -    "description": "Evlek listing UUID",
        -    "type": "string"
        -  },
        -  "type": "array"
        -}
      • changedInput schema / required
        Previous value: -[
        -  "listing_ids"
        -]New value: +[
        +  "listingIds"
        +]
      • addedOutput schema / properties / dataSource
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / isEstimate
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / listings / items
        Added value: +{
        +  "properties": {
        +    "area": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "bathrooms": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "bedrooms": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "city": {
        +      "type": "string"
        +    },
        +    "currency": {
        +      "type": "string"
        +    },
        +    "district": {
        +      "type": "string"
        +    },
        +    "id": {
        +      "type": "string"
        +    },
        +    "monthlyRentGbp": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "number": {
        +      "type": "string"
        +    },
        +    "price": {
        +      "type": "number"
        +    },
        +    "priceGbp": {
        +      "type": "number"
        +    },
        +    "pricePerSqm": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "title": {
        +      "type": "string"
        +    },
        +    "type": {
        +      "type": "string"
        +    },
        +    "url": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "title",
        +    "price",
        +    "priceGbp",
        +    "type",
        +    "url"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / metricType
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / required
        Added value: +[
        +  "count",
        +  "listings"
        +]
    • Addedconvert_currency
    • Changedfetch5 fields changed
      • addedOutput schema / properties / coverImageUrl
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / metadata / properties
        Added value: +{
        +  "areaSqm": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "bedrooms": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "city": {
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "currency": {
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "district": {
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "listedAt": {
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "locationPrecision": {
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "monthlyRentGbp": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "priceGBP": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "pricePerSqmGBP": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "type": {
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / metadata / required
        Added value: +[
        +  "city",
        +  "district",
        +  "type",
        +  "bedrooms",
        +  "areaSqm",
        +  "priceGBP",
        +  "pricePerSqmGBP",
        +  "monthlyRentGbp",
        +  "currency",
        +  "listedAt",
        +  "locationPrecision"
        +]
      • addedOutput schema / properties / photos
        Added value: +{
        +  "items": {
        +    "properties": {
        +      "caption": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "tags": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "url": {
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / required
        Added value: +[
        +  "id",
        +  "title",
        +  "text",
        +  "url"
        +]
    • Removedforeign_buyer_roadmap
    • Changedget_district_profile18 fields changed
      • addedInput schema / properties / city / description
        Added value: +"City containing the district. Slug, Turkish name, or exonym (Kyrenia/Nicosia/Famagusta/Morphou)."
      • removedInput schema / properties / city / enum
        Removed value: -[
        -  "girne",
        -  "iskele",
        -  "lefkosa",
        -  "gazimagusa",
        -  "guzelyurt",
        -  "lefke"
        -]
      • changedInput schema / properties / district / description
        Previous value: -"District name (2-60 chars)"New value: +"District name (2-60 chars), matched accent/case-insensitively against the active-listing district list"
      • addedOutput schema / properties / askingRentToAskingPricePct
        Added value: +{
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / cleanSampleTotal
        Added value: +{
        +  "description": "sale.count + rent.count — clean sample size (IQR outliers excluded), not raw active listings",
        +  "type": "number"
        +}
      • addedOutput schema / properties / dataAsOf
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / dataSource
        Added value: +{
        +  "type": "string"
        +}
      • removedOutput schema / properties / grossYieldPct
        Removed value: -{
        -  "type": [
        -    "number",
        -    "null"
        -  ]
        -}
      • addedOutput schema / properties / isObservedIncome
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / metricType
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / personaContexts
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • removedOutput schema / properties / personas
        Removed value: -{
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": "array"
        -}
      • addedOutput schema / properties / ratioMetricType
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / rent / properties
        Added value: +{
        +  "count": {
        +    "type": "number"
        +  },
        +  "maturity": {
        +    "enum": [
        +      "olgun",
        +      "öncü",
        +      "biriktiriyor"
        +    ],
        +    "type": "string"
        +  },
        +  "median": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "medianPerSqm": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "p25": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "p75": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "provenance": {
        +    "properties": {
        +      "agencies": {
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "maxAgencyShare": {
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "publishers": {
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "singleSource": {
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "publishers",
        +      "agencies",
        +      "maxAgencyShare",
        +      "singleSource"
        +    ],
        +    "type": "object"
        +  },
        +  "status": {
        +    "enum": [
        +      "proven",
        +      "preliminary",
        +      "collecting"
        +    ],
        +    "type": "string"
        +  },
        +  "withheldReason": {
        +    "enum": [
        +      "insufficient_sample",
        +      "no_value",
        +      null
        +    ],
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / sale / properties
        Added value: +{
        +  "count": {
        +    "type": "number"
        +  },
        +  "maturity": {
        +    "enum": [
        +      "olgun",
        +      "öncü",
        +      "biriktiriyor"
        +    ],
        +    "type": "string"
        +  },
        +  "median": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "medianPerSqm": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "p25": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "p75": {
        +    "type": [
        +      "number",
        +      "null"
        +    ]
        +  },
        +  "provenance": {
        +    "properties": {
        +      "agencies": {
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "maxAgencyShare": {
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "publishers": {
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "singleSource": {
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "publishers",
        +      "agencies",
        +      "maxAgencyShare",
        +      "singleSource"
        +    ],
        +    "type": "object"
        +  },
        +  "status": {
        +    "enum": [
        +      "proven",
        +      "preliminary",
        +      "collecting"
        +    ],
        +    "type": "string"
        +  },
        +  "withheldReason": {
        +    "enum": [
        +      "insufficient_sample",
        +      "no_value",
        +      null
        +    ],
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • removedOutput schema / properties / totalActive
        Removed value: -{
        -  "type": "number"
        -}
      • addedOutput schema / properties / truncated
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / required
        Added value: +[
        +  "city",
        +  "district",
        +  "cleanSampleTotal"
        +]
    • Removedget_legal_info
    • Changedget_listing_by_number16 fields changed
      • addedInput schema / properties / listingNumber
        Added value: +{
        +  "description": "Evlek listing number, e.g. \"EVL-123456\", \"123456\", or the bare number 123456.",
        +  "type": [
        +    "string",
        +    "number"
        +  ]
        +}
      • removedInput schema / properties / listing_number
        Removed value: -{
        -  "description": "Evlek listing number, e.g. \"EVL-123456\" or \"123456\".",
        -  "type": "string"
        -}
      • changedInput schema / required
        Previous value: -[
        -  "listing_number"
        -]New value: +[
        +  "listingNumber"
        +]
      • addedOutput schema / properties / dataSource
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / factType
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / fxRates
        Added value: +{
        +  "properties": {
        +    "base": {
        +      "enum": [
        +        "GBP"
        +      ],
        +      "type": "string"
        +    },
        +    "isFallback": {
        +      "type": "boolean"
        +    },
        +    "rates": {
        +      "properties": {
        +        "EUR": {
        +          "type": "number"
        +        },
        +        "TRY": {
        +          "type": "number"
        +        },
        +        "USD": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "EUR",
        +        "USD",
        +        "TRY"
        +      ],
        +      "type": "object"
        +    },
        +    "source": {
        +      "enum": [
        +        "database",
        +        "fallback"
        +      ],
        +      "type": "string"
        +    },
        +    "updatedAt": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "base",
        +    "rates",
        +    "source",
        +    "updatedAt",
        +    "isFallback"
        +  ],
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / isEstimate
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / locationPrecision
        Added value: +{
        +  "enum": [
        +    "exact",
        +    "district",
        +    "city"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / monthlyRentGbp
        Added value: +{
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / photosShown
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / photosTruncated
        Added value: +{
        +  "type": "number"
        +}
      • removedOutput schema / properties / titleDeedBand
        Removed value: -{
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
      • removedOutput schema / properties / titleDeedLabel
        Removed value: -{
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
      • removedOutput schema / properties / titleDeedType
        Removed value: -{
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
      • addedOutput schema / properties / virtualStaging
        Added value: +{
        +  "properties": {
        +    "available": {
        +      "type": "boolean"
        +    },
        +    "disclosure": {
        +      "type": "string"
        +    },
        +    "items": {
        +      "items": {
        +        "properties": {
        +          "afterUrl": {
        +            "type": "string"
        +          },
        +          "beforeUrl": {
        +            "type": "string"
        +          },
        +          "provenance": {
        +            "properties": {
        +              "digitalSourceType": {
        +                "type": "string"
        +              },
        +              "generatedAt": {
        +                "type": "string"
        +              },
        +              "humanReview": {
        +                "type": "string"
        +              },
        +              "kind": {
        +                "type": "string"
        +              },
        +              "model": {
        +                "type": "string"
        +              },
        +              "modelVersion": {
        +                "type": "string"
        +              },
        +              "originalRetained": {
        +                "type": "boolean"
        +              },
        +              "outputId": {
        +                "type": "string"
        +              },
        +              "outputSha256": {
        +                "type": "string"
        +              },
        +              "provider": {
        +                "type": "string"
        +              },
        +              "version": {
        +                "type": "number"
        +              },
        +              "visibleDisclosureApplied": {
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "roomType": {
        +            "type": "string"
        +          },
        +          "style": {
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / required
        Added value: +[
        +  "found"
        +]
    • Changedget_listing_detail16 fields changed
      • addedInput schema / properties / propertyId
        Added value: +{
        +  "description": "Evlek listing UUID or listing number (e.g. \"EVL-123456\", \"123456\")",
        +  "type": "string"
        +}
      • removedInput schema / properties / property_id
        Removed value: -{
        -  "description": "Evlek listing UUID",
        -  "type": "string"
        -}
      • changedInput schema / required
        Previous value: -[
        -  "property_id"
        -]New value: +[
        +  "propertyId"
        +]
      • addedOutput schema / properties / dataSource
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / factType
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / fxRates
        Added value: +{
        +  "properties": {
        +    "base": {
        +      "enum": [
        +        "GBP"
        +      ],
        +      "type": "string"
        +    },
        +    "isFallback": {
        +      "type": "boolean"
        +    },
        +    "rates": {
        +      "properties": {
        +        "EUR": {
        +          "type": "number"
        +        },
        +        "TRY": {
        +          "type": "number"
        +        },
        +        "USD": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "EUR",
        +        "USD",
        +        "TRY"
        +      ],
        +      "type": "object"
        +    },
        +    "source": {
        +      "enum": [
        +        "database",
        +        "fallback"
        +      ],
        +      "type": "string"
        +    },
        +    "updatedAt": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "base",
        +    "rates",
        +    "source",
        +    "updatedAt",
        +    "isFallback"
        +  ],
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / isEstimate
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / locationPrecision
        Added value: +{
        +  "enum": [
        +    "exact",
        +    "district",
        +    "city"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / monthlyRentGbp
        Added value: +{
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / photosShown
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / photosTruncated
        Added value: +{
        +  "type": "number"
        +}
      • removedOutput schema / properties / titleDeedBand
        Removed value: -{
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
      • removedOutput schema / properties / titleDeedLabel
        Removed value: -{
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
      • removedOutput schema / properties / titleDeedType
        Removed value: -{
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
      • addedOutput schema / properties / virtualStaging
        Added value: +{
        +  "properties": {
        +    "available": {
        +      "type": "boolean"
        +    },
        +    "disclosure": {
        +      "type": "string"
        +    },
        +    "items": {
        +      "items": {
        +        "properties": {
        +          "afterUrl": {
        +            "type": "string"
        +          },
        +          "beforeUrl": {
        +            "type": "string"
        +          },
        +          "provenance": {
        +            "properties": {
        +              "digitalSourceType": {
        +                "type": "string"
        +              },
        +              "generatedAt": {
        +                "type": "string"
        +              },
        +              "humanReview": {
        +                "type": "string"
        +              },
        +              "kind": {
        +                "type": "string"
        +              },
        +              "model": {
        +                "type": "string"
        +              },
        +              "modelVersion": {
        +                "type": "string"
        +              },
        +              "originalRetained": {
        +                "type": "boolean"
        +              },
        +              "outputId": {
        +                "type": "string"
        +              },
        +              "outputSha256": {
        +                "type": "string"
        +              },
        +              "provider": {
        +                "type": "string"
        +              },
        +              "version": {
        +                "type": "number"
        +              },
        +              "visibleDisclosureApplied": {
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "roomType": {
        +            "type": "string"
        +          },
        +          "style": {
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / required
        Added value: +[
        +  "found"
        +]
    • Removedget_market_overview
    • Changedget_price_index9 fields changed
      • addedInput schema / properties / city / description
        Added value: +"Filter to a single city (omit for all cities). Slug, Turkish name, or exonym (Kyrenia/Nicosia/Famagusta/Morphou)."
      • removedInput schema / properties / city / enum
        Removed value: -[
        -  "girne",
        -  "iskele",
        -  "lefkosa",
        -  "gazimagusa",
        -  "guzelyurt",
        -  "lefke"
        -]
      • addedOutput schema / properties / cities / items
        Added value: +{
        +  "properties": {
        +    "city": {
        +      "type": "string"
        +    },
        +    "count": {
        +      "type": "number"
        +    },
        +    "districts": {
        +      "items": {
        +        "properties": {
        +          "count": {
        +            "type": "number"
        +          },
        +          "district": {
        +            "type": "string"
        +          },
        +          "lowSample": {
        +            "type": "boolean"
        +          },
        +          "medianPrice": {
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "medianPricePerSqm": {
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "provenance": {
        +            "properties": {
        +              "agencies": {
        +                "type": [
        +                  "number",
        +                  "null"
        +                ]
        +              },
        +              "maxAgencyShare": {
        +                "type": [
        +                  "number",
        +                  "null"
        +                ]
        +              },
        +              "publishers": {
        +                "type": [
        +                  "number",
        +                  "null"
        +                ]
        +              },
        +              "singleSource": {
        +                "type": "boolean"
        +              }
        +            },
        +            "required": [
        +              "publishers",
        +              "agencies",
        +              "maxAgencyShare",
        +              "singleSource"
        +            ],
        +            "type": "object"
        +          },
        +          "status": {
        +            "type": "string"
        +          },
        +          "withheldReason": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          }
        +        },
        +        "required": [
        +          "district",
        +          "count",
        +          "lowSample",
        +          "medianPrice"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "lowSample": {
        +      "type": "boolean"
        +    },
        +    "medianPrice": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "medianPricePerSqm": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "p25Price": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "p75Price": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "provenance": {
        +      "properties": {
        +        "agencies": {
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "maxAgencyShare": {
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "publishers": {
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "singleSource": {
        +          "type": "boolean"
        +        }
        +      },
        +      "required": [
        +        "publishers",
        +        "agencies",
        +        "maxAgencyShare",
        +        "singleSource"
        +      ],
        +      "type": "object"
        +    },
        +    "status": {
        +      "enum": [
        +        "proven",
        +        "preliminary",
        +        "collecting"
        +      ],
        +      "type": "string"
        +    },
        +    "withheldReason": {
        +      "enum": [
        +        "insufficient_sample",
        +        "no_value",
        +        null
        +      ],
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "city",
        +    "count",
        +    "status",
        +    "lowSample",
        +    "withheldReason",
        +    "medianPrice",
        +    "districts"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / dataAsOf
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / dataSource
        Added value: +{
        +  "type": "string"
        +}
      • removedOutput schema / properties / generatedAt
        Removed value: -{
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
      • addedOutput schema / properties / isEstimate
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / metricType
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / required
        Added value: +[
        +  "type",
        +  "dataAsOf",
        +  "cities"
        +]
    • Removedget_yield_estimate
    • Changedlist_locations6 fields changed
      • changedInput schema / properties / city / description
        Previous value: -"Optional — limit districts to a single city slug."New value: +"Optional — limit districts to a single city. Slug, Turkish name, or exonym (Kyrenia/Nicosia/Famagusta/Morphou)."
      • removedInput schema / properties / city / enum
        Removed value: -[
        -  "girne",
        -  "iskele",
        -  "lefkosa",
        -  "gazimagusa",
        -  "guzelyurt",
        -  "lefke"
        -]
      • addedOutput schema / properties / dataSource
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / isEstimate
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / truncated
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / required
        Added value: +[
        +  "cities"
        +]
    • Changedpayment_plan11 fields changed
      • removedInput schema / properties / offPlan
        Removed value: -{
        -  "description": "True if off-plan (under construction).",
        -  "type": "boolean"
        -}
      • changedInput schema / properties / price / description
        Previous value: -"Property price."New value: +"Entered property asking-price amount; not a deposit or installment."
      • addedOutput schema / properties / amounts / properties
        Added value: +{
        +  "EUR": {
        +    "type": "number"
        +  },
        +  "GBP": {
        +    "type": "number"
        +  },
        +  "TRY": {
        +    "type": "number"
        +  },
        +  "USD": {
        +    "type": "number"
        +  }
        +}
      • addedOutput schema / properties / amounts / required
        Added value: +[
        +  "GBP",
        +  "EUR",
        +  "USD",
        +  "TRY"
        +]
      • addedOutput schema / properties / dataSource
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / fx / properties
        Added value: +{
        +  "asOf": {
        +    "type": "string"
        +  },
        +  "base": {
        +    "enum": [
        +      "GBP"
        +    ],
        +    "type": "string"
        +  },
        +  "rates": {
        +    "properties": {
        +      "EUR": {
        +        "type": "number"
        +      },
        +      "GBP": {
        +        "type": "number"
        +      },
        +      "TRY": {
        +        "type": "number"
        +      },
        +      "USD": {
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "GBP",
        +      "EUR",
        +      "USD",
        +      "TRY"
        +    ],
        +    "type": "object"
        +  },
        +  "source": {
        +    "enum": [
        +      "stored_current_rates"
        +    ],
        +    "type": "string"
        +  }
        +}
      • addedOutput schema / properties / fx / required
        Added value: +[
        +  "base",
        +  "source",
        +  "asOf",
        +  "rates"
        +]
      • removedOutput schema / properties / offPlan
        Removed value: -{
        -  "type": "boolean"
        -}
      • addedOutput schema / properties / usesStoredRate
        Added value: +{
        +  "type": "boolean"
        +}
      • removedOutput schema / properties / warnings
        Removed value: -{
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": "array"
        -}
      • addedOutput schema / required
        Added value: +[
        +  "inputCurrency",
        +  "priceGBP",
        +  "amounts"
        +]
    • Changedsearch8 fields changed
      • addedOutput schema / properties / appliedFilters
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "bedrooms": {
        +      "type": "number"
        +    },
        +    "city": {
        +      "type": "string"
        +    },
        +    "district": {
        +      "type": "string"
        +    },
        +    "elevator": {
        +      "type": "boolean"
        +    },
        +    "furnished": {
        +      "type": "boolean"
        +    },
        +    "garden": {
        +      "type": "boolean"
        +    },
        +    "maxPrice": {
        +      "type": "number"
        +    },
        +    "minPrice": {
        +      "type": "number"
        +    },
        +    "parking": {
        +      "type": "boolean"
        +    },
        +    "pool": {
        +      "type": "boolean"
        +    },
        +    "propertyType": {
        +      "type": "string"
        +    },
        +    "seaView": {
        +      "type": "boolean"
        +    },
        +    "type": {
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / criteria
        Added value: +{
        +  "items": {
        +    "properties": {
        +      "key": {
        +        "type": "string"
        +      },
        +      "note": {
        +        "type": "string"
        +      },
        +      "state": {
        +        "enum": [
        +          "applied",
        +          "unresolved",
        +          "not_supported"
        +        ],
        +        "type": "string"
        +      },
        +      "value": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "key",
        +      "value",
        +      "state"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / fxRates
        Added value: +{
        +  "properties": {
        +    "base": {
        +      "enum": [
        +        "GBP"
        +      ],
        +      "type": "string"
        +    },
        +    "isFallback": {
        +      "type": "boolean"
        +    },
        +    "rates": {
        +      "properties": {
        +        "EUR": {
        +          "type": "number"
        +        },
        +        "TRY": {
        +          "type": "number"
        +        },
        +        "USD": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "EUR",
        +        "USD",
        +        "TRY"
        +      ],
        +      "type": "object"
        +    },
        +    "source": {
        +      "enum": [
        +        "database",
        +        "fallback"
        +      ],
        +      "type": "string"
        +    },
        +    "updatedAt": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "base",
        +    "rates",
        +    "source",
        +    "updatedAt",
        +    "isFallback"
        +  ],
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / listings
        Added value: +{
        +  "items": {
        +    "properties": {
        +      "areaSqm": {
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "bedrooms": {
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "city": {
        +        "type": "string"
        +      },
        +      "coverImageUrl": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "currency": {
        +        "type": "string"
        +      },
        +      "district": {
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "listingNumber": {
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "locationPrecision": {
        +        "enum": [
        +          "exact",
        +          "district",
        +          "city"
        +        ],
        +        "type": "string"
        +      },
        +      "monthlyRentGbp": {
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "price": {
        +        "type": "number"
        +      },
        +      "priceGbp": {
        +        "type": "number"
        +      },
        +      "propertyType": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "title": {
        +        "type": "string"
        +      },
        +      "type": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "id",
        +      "title",
        +      "city",
        +      "district",
        +      "price",
        +      "priceGbp",
        +      "currency",
        +      "type",
        +      "url"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / nearbyAlternatives
        Added value: +{
        +  "properties": {
        +    "listings": {
        +      "items": {
        +        "properties": {
        +          "areaSqm": {
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "bedrooms": {
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "city": {
        +            "type": "string"
        +          },
        +          "coverImageUrl": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "currency": {
        +            "type": "string"
        +          },
        +          "district": {
        +            "type": "string"
        +          },
        +          "id": {
        +            "type": "string"
        +          },
        +          "listingNumber": {
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "locationPrecision": {
        +            "enum": [
        +              "exact",
        +              "district",
        +              "city"
        +            ],
        +            "type": "string"
        +          },
        +          "monthlyRentGbp": {
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "price": {
        +            "type": "number"
        +          },
        +          "priceGbp": {
        +            "type": "number"
        +          },
        +          "propertyType": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "title": {
        +            "type": "string"
        +          },
        +          "type": {
        +            "type": "string"
        +          },
        +          "url": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "title",
        +          "city",
        +          "district",
        +          "price",
        +          "priceGbp",
        +          "currency",
        +          "type",
        +          "url"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "relaxed": {
        +      "enum": [
        +        "district",
        +        "maxPrice"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "relaxed",
        +    "listings"
        +  ],
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / outOfScope
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / unresolved
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / required
        Added value: +[
        +  "results"
        +]
    • Changedsearch_listings24 fields changed
      • changedInput schema / properties / city / description
        Previous value: -"City to filter"New value: +"Slug, Turkish name, or exonym (Kyrenia/Nicosia/Famagusta/Morphou)."
      • removedInput schema / properties / city / enum
        Removed value: -[
        -  "girne",
        -  "iskele",
        -  "lefkosa",
        -  "gazimagusa",
        -  "guzelyurt",
        -  "lefke"
        -]
      • addedInput schema / properties / district
        Added value: +{
        +  "description": "District name (e.g. Alsancak), matched accent/case-insensitively against the active-listing district list",
        +  "type": "string"
        +}
      • addedInput schema / properties / elevator
        Added value: +{
        +  "description": "Only listings with an elevator",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / furnished
        Added value: +{
        +  "description": "Only furnished listings",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / garden
        Added value: +{
        +  "description": "Only listings with a garden",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Rows to skip (pagination, default 0)",
        +  "minimum": 0,
        +  "type": "number"
        +}
      • addedInput schema / properties / parking
        Added value: +{
        +  "description": "Only listings with parking",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / pool
        Added value: +{
        +  "description": "Only listings with a pool",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / propertyType
        Added value: +{
        +  "description": "Raw property type (apartment, villa, …) or K75 group slug: house (villa+detached+bungalow), land, commercial",
        +  "enum": [
        +    "apartment",
        +    "residence",
        +    "villa",
        +    "twin",
        +    "detached",
        +    "bungalow",
        +    "penthouse",
        +    "studio",
        +    "duplex",
        +    "shop",
        +    "office",
        +    "warehouse",
        +    "whole_building",
        +    "hotel",
        +    "residential_land",
        +    "commercial_land",
        +    "farmland",
        +    "house",
        +    "land",
        +    "commercial"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / seaView
        Added value: +{
        +  "description": "Only listings flagged sea_view",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / sortBy
        Added value: +{
        +  "description": "Sort order (default: newest)",
        +  "enum": [
        +    "newest",
        +    "price_asc",
        +    "price_desc",
        +    "area_desc",
        +    "price_per_sqm_asc"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / type / enum
        Previous value: -[
        -  "sale",
        -  "rent",
        -  "daily"
        -]New value: +[
        +  "sale",
        +  "rent"
        +]
      • addedOutput schema / properties / appliedFilters
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "bedrooms": {
        +      "type": "number"
        +    },
        +    "city": {
        +      "type": "string"
        +    },
        +    "district": {
        +      "type": "string"
        +    },
        +    "elevator": {
        +      "type": "boolean"
        +    },
        +    "furnished": {
        +      "type": "boolean"
        +    },
        +    "garden": {
        +      "type": "boolean"
        +    },
        +    "maxPrice": {
        +      "type": "number"
        +    },
        +    "minPrice": {
        +      "type": "number"
        +    },
        +    "parking": {
        +      "type": "boolean"
        +    },
        +    "pool": {
        +      "type": "boolean"
        +    },
        +    "propertyType": {
        +      "type": "string"
        +    },
        +    "seaView": {
        +      "type": "boolean"
        +    },
        +    "type": {
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / dataSource
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / factType
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / fxRates
        Added value: +{
        +  "properties": {
        +    "base": {
        +      "enum": [
        +        "GBP"
        +      ],
        +      "type": "string"
        +    },
        +    "isFallback": {
        +      "type": "boolean"
        +    },
        +    "rates": {
        +      "properties": {
        +        "EUR": {
        +          "type": "number"
        +        },
        +        "TRY": {
        +          "type": "number"
        +        },
        +        "USD": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "EUR",
        +        "USD",
        +        "TRY"
        +      ],
        +      "type": "object"
        +    },
        +    "source": {
        +      "enum": [
        +        "database",
        +        "fallback"
        +      ],
        +      "type": "string"
        +    },
        +    "updatedAt": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "base",
        +    "rates",
        +    "source",
        +    "updatedAt",
        +    "isFallback"
        +  ],
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / isEstimate
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / listings / items
        Added value: +{
        +  "properties": {
        +    "areaSqm": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "bedrooms": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "city": {
        +      "type": "string"
        +    },
        +    "coverImageUrl": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "currency": {
        +      "type": "string"
        +    },
        +    "district": {
        +      "type": "string"
        +    },
        +    "id": {
        +      "type": "string"
        +    },
        +    "listingNumber": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "locationPrecision": {
        +      "enum": [
        +        "exact",
        +        "district",
        +        "city"
        +      ],
        +      "type": "string"
        +    },
        +    "monthlyRentGbp": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "price": {
        +      "type": "number"
        +    },
        +    "priceGbp": {
        +      "type": "number"
        +    },
        +    "propertyType": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "title": {
        +      "type": "string"
        +    },
        +    "type": {
        +      "type": "string"
        +    },
        +    "url": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "title",
        +    "city",
        +    "district",
        +    "price",
        +    "priceGbp",
        +    "currency",
        +    "type",
        +    "url"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / ranking
        Added value: +{
        +  "properties": {
        +    "of": {
        +      "type": "number"
        +    },
        +    "pooled": {
        +      "type": "number"
        +    },
        +    "scope": {
        +      "enum": [
        +        "complete",
        +        "partial"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "scope",
        +    "pooled",
        +    "of"
        +  ],
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / sortApplied
        Added value: +{
        +  "enum": [
        +    "newest",
        +    "price_asc",
        +    "price_desc",
        +    "area_desc",
        +    "price_per_sqm_asc"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / totalMatched
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / required
        Added value: +[
        +  "count",
        +  "totalMatched",
        +  "offset",
        +  "sortApplied",
        +  "listings",
        +  "appliedFilters"
        +]
    • Removedstudent_housing
    • Removedsuggest_neighborhood
  2. 18 tool updatesv1.6.0
    • First observedassess_title_risk
    • First observedcompare_cities
    • First observedcompare_properties
    • First observedfetch
    • First observedforeign_buyer_roadmap
    • First observedget_district_profile
    • First observedget_legal_info
    • First observedget_listing_by_number
    • First observedget_listing_detail
    • First observedget_market_overview
    • First observedget_price_index
    • First observedget_yield_estimate
    • First observedlist_locations
    • First observedpayment_plan
    • First observedsearch
    • First observedsearch_listings
    • First observedstudent_housing
    • First observedsuggest_neighborhood

TDQS

A3.9/5.0

Scored across 12 tools

Disambiguation2/5

Several tools have overlapping boundaries: `search` and `search_listings` serve the same data, `fetch`, `get_listing_detail`, and `get_listing_by_number` are all single-listing detail retrievers with subtle ID-type differences, and `payment_plan` currently duplicates `convert_currency`'s behavior. Descriptions help, but the distinctions are easy to get wrong.

Naming Consistency4/5

Most tool names follow a consistent `verb_noun` snake_case pattern (`search_listings`, `compare_cities`, `convert_currency`, `list_locations`). `search` and `fetch` are bare verbs and `payment_plan` is a noun phrase, which are minor deviations from an otherwise readable set.

Tool Count4/5

Twelve tools is a reasonable count for a property-data server, but a few tools are redundant (`search`, `fetch`, `get_listing_by_number`) or placeholder (`payment_plan`), so the set is slightly over-inclusive rather than tightly scoped.

Completeness4/5

The read-only property domain is well covered: listing search, detailed retrieval, price aggregates, city/district comparisons, currency conversion, and location inventory all exist. The main gaps are the promised payment-plan functionality that is not yet implemented and unavailability of holiday-home inventory, but core workflows succeed.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Provides comprehensive Australian planning property reports, including zoning, overlays, land size, and utility information for AI assistants. This high-performance MCP server is built for Cloudflare Workers and enables real-time property data retrieval through an HTTP-based interface.
    -