Skip to main content
Glama

emlakjet-mcp 🇹🇷

mcp-name: io.github.mohammad-abbasi-sh/emlakjet-mcp

Unofficial read-only MCP server for emlakjet.com, Türkiye's real-estate portal — live listing search (for sale / for rent, by city and district), full listing details with description and 14 spec fields, a district browser, and market price stats (including median price per m²).

Built by Mohammad Abbasi as part of the "Turkey MCP factory" (Sepehr-style pipeline). Not affiliated with emlakjet.com.

For AI agents

Add to your MCP client config (stdio):

{
  "mcpServers": {
    "emlakjet": {
      "command": "uvx",
      "args": ["emlakjet-mcp"]
    }
  }
}

Or run locally: python -m emlakjet_mcp.server (needs mcp<2, httpx).

Related MCP server: dld-mcp

Tools

Tool

Description

emlakjet_search

Search listings — listing_type "satilik"/"kiralik", property_type "daire"/"konut"/"villa", city ("istanbul"), district ("kadikoy"), rooms ("2+1"), min_price/max_price (TRY), min_m2, page 1..50

emlakjet_listing_detail

Full detail of one listing (URL from search, or numeric id): price, description, address, rooms, m², 14 spec fields, images

emlakjet_list_districts

Districts of a city with listing pages: slug + display name

emlakjet_price_stats

Market stats: count, min/max/median/average price (TRY) + median price per m² over N pages

Example output (emlakjet_search / satilik daire, istanbul):

{"listing_type": "satilik", "property_type": "daire", "city": "istanbul",
 "page": 1, "count": 50, "listings": [
  {"id": "20062034", "title": "Yıldırım Yapı'dan Metrobüsün Dibinde …",
   "price_try": 1349000, "rooms": "Stüdyo", "area_m2": 60,
   "location": "Cumhuriyet Mahallesi, Esenyurt", "floor": "3. Kat",
   "url": "https://www.emlakjet.com/ilan/…-20062034"}],
 "summary": {"total_listings": 21024, "cheapest_price_try": 310000}}

Example output (emlakjet_listing_detail / id 20044346):

{"id": "20044346", "title": "Aciliyetten Sancaktepede Site İçi İskanlı Daire",
 "price_try": 5950000, "price_currency": "TRY", "rooms_count": 3, "area_m2": 95,
 "address": {"neighbourhood": "Merve Mahallesi", "district": "Sancaktepe",
  "city": "İstanbul", "country": "TR"},
 "specs": {"Isıtma Tipi": "Kombi Doğalgaz", "Otopark": "Açık & Kapalı Otopark",
  "Kullanım Durumu": "Mülk Sahibi Oturuyor", "Krediye Uygunluk": "Krediye Uygun",
  "Site İçerisinde": "Evet", "Tapu Durumu": "Kat Mülkiyeti", …}}

Example output (emlakjet_price_stats / istanbul kadikoy, 1 page):

{"count": 50, "currency": "TRY", "min": 5650000, "max": 48000000,
 "median": 17100000.0, "average": 18228800.0,
 "median_price_per_m2_try": 162792.21, "pages_scanned": 1}

Notes:

  • Data comes from emlakjet.com's public server-rendered pages (schema.org RealEstateListing/Product JSON-LD) — no key, no login, read-only.

  • Room/price/area filters are applied to the fetched page (the site exposes no server-side room/price filter); the search returns up to 50 listings per page.

  • The site's sort keys were tested live and do not reorder the server-rendered listings, so no sort parameter is offered — sort the returned listings instead.

  • Spec labels are Turkish (Isıtma Tipi, Otopark, Kullanım Durumu, Krediye Uygunluk, Site İçerisinde, Tapu Durumu, Takas, Asansör, Mutfak, Eşya Durumu, Balkon…).

  • Requests are spaced ~0.8s apart to stay polite.

  • Environments behind an MITM proxy: set SSL_CERT_FILE to a CA bundle that trusts the proxy.

Development

python3 -m venv .venv && .venv/bin/pip install "mcp<2" httpx pytest
.venv/bin/python -m pytest tests/ -q
  • tests/test_listings.py — offline, parses real captured fixtures

  • tests/test_live.py — 6 cautious live requests against emlakjet.com (needs SSL_CERT_FILE behind the lab proxy)

License

MIT

Available Tools

4 tools
emlakjet_list_districtsB

Districts of a city with listing pages: slug (use with emlakjet_search) and display name. city: slug like "istanbul".

NameRequiredDescriptionDefault
cityNoistanbul
listing_typeNosatilik
property_typeNodaire

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.2/5.0
Behavior3/5

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

No annotations are supplied, so the description carries the full behavioral burden. It does add one genuine behavioral detail — that only districts 'with listing pages' are returned — but says nothing about whether listing_type or property_type change which districts come back, nor about response size or any access requirements.

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

Conciseness4/5

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

Two short sentences, front-loaded with what the tool returns, and no filler. The phrasing 'Districts of a city with listing pages' is slightly compressed and takes a second read, but nothing is wasted.

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

Completeness3/5

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

An output schema exists, so the description needn't detail return values, and it covers the search-integration purpose adequately. However, for a three-parameter tool with zero schema documentation, leaving two parameters entirely unexplained is a meaningful completeness gap.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate and it only covers one of three parameters: city, clarified as a slug like "istanbul". The listing_type and property_type parameters are completely unexplained despite defaulting to 'satilik' and 'daire', so an agent cannot tell whether changing them alters the district list.

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

Purpose4/5

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

The description names a specific resource (districts of a city) and states the two fields returned (slug and display name), which lets an agent distinguish it from emlakjet_listing_detail and emlakjet_price_stats. The verb is nominal rather than explicit ('Districts of a city'), but the intent is unambiguous.

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?

It hints at the workflow by saying the slug should be 'used with emlakjet_search', which implies this is a lookup step before searching. It never states when to call this instead of emlakjet_search directly, nor when the tool is unnecessary (e.g., if the district slug is already known).

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

emlakjet_listing_detailA

Full detail of one listing: title, price (TRY), description, address (neighbourhood/district/city), rooms count, area in m², 14 spec fields (heating, parking, title deed, elevator, balcony, usage, loan eligibility…), images. url_or_id: the listing URL from emlakjet_search, or its numeric id.

NameRequiredDescriptionDefault
url_or_idYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full behavioral burden. It thoroughly discloses the shape of the returned data (TRY pricing, address granularity, 14 spec fields, images), but says nothing about failure modes for invalid ids, rate limits, auth, or whether it is a pure read. Adequate but incomplete for an unannotated tool.

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

Conciseness4/5

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

A single dense sentence plus a short parameter note, front-loaded with the highest-value fact (what is returned) before the argument clarification. Minor waste: listing the individual fields is partly redundant since an output schema exists.

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?

One required parameter, an output schema present, and the description covers both the source of the input value and the shape of the return. It is essentially complete for a straightforward single-listing fetch, with only error/edge-case behavior left unspecified.

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 0% – the schema only names 'url_or_id' as a string. The description compensates by stating it accepts either a listing URL obtained from emlakjet_search or a numeric id, which is meaningful guidance the schema does not provide. It omits id format details or what happens if an id is stale, so not a 5.

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

Purpose5/5

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

States a specific verb and resource ('Full detail of one listing') and enumerates what detail means: title, price in TRY, description, address hierarchy, rooms, area, spec fields, images. This distinguishes it clearly from emlakjet_search, which the description references by name.

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 parameter note 'the listing URL from emlakjet_search' implicitly tells the agent this is a follow-up call after search, which is a clear usage context. It stops short of an explicit when-not clause or mentioning the other siblings (price_stats, list_districts) as alternatives.

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

emlakjet_price_statsA

Market stats for a city (and optional district/rooms): count, min, max, median and average price (TRY) plus median price per m², across the first N search pages (pages: 1..5, default 3; 50 listings per page).

NameRequiredDescriptionDefault
cityNoistanbul
pagesNo
roomsNo
districtNo
listing_typeNosatilik
property_typeNodaire

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does well on the most important behavioral trait: it discloses that stats are computed only over the first N pages (1..5, default 3) at 50 listings per page, so the agent knows results are a sample, not an exhaustive market census. It does not mention latency, rate limits, auth, or whether zero-result searches return empty/null stats, which keeps it below a 5.

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

Conciseness4/5

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

A single dense sentence with the metric list front-loaded and the sampling constraints in a trailing parenthetical; there is no filler. It is slightly overloaded with parentheticals, but every clause carries information.

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

Completeness3/5

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

An output schema exists, so return values need not be spelled out, and the description usefully previews the metric set anyway. Against a 6-parameter tool with zero schema coverage, though, the omission of listing_type and property_type semantics (including that defaults restrict results to for-sale apartments) leaves a real gap.

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 0% across 6 parameters, so the description must compensate. It covers city, district, rooms, and pages (including the 1..5 range and default 3), but says nothing about listing_type (default 'satilik') or property_type (default 'daire') — two parameters whose allowed values and defaults an agent cannot infer without them.

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 states a specific verb+resource combination: it computes aggregate market statistics (count, min, max, median, average, median price per m²) for a city with optional district/rooms filters. This clearly separates it from emlakjet_search or emlakjet_listing_detail, though it never names those siblings explicitly and only alludes to 'search pages'.

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?

Usage is implied rather than stated: the optional district/rooms and the pages cap suggest when this tool is appropriate, and the mention of 'search pages' hints that listing-level browsing belongs to another tool. However, there is no explicit when-to-use/when-not guidance and no pointer to emlakjet_search as the alternative for individual listings.

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. 4 tool updatesv0.1.0
    • First observedemlakjet_list_districts
    • First observedemlakjet_listing_detail
    • First observedemlakjet_price_stats
    • First observedemlakjet_search

TDQS

A3.6/5.0

Scored across 4 tools

Disambiguation4/5

Each tool maps to a clearly different job: paged search of compact listings, full record fetch by URL/id, district slug lookup, and aggregate market statistics. The only mild overlap is that emlakjet_search with min/max price can be used for price discovery that emlakjet_price_stats also serves, but the aggregate-vs-per-listing distinction is spelled out clearly.

Naming Consistency3/5

The emlakjet_ prefix and snake_case are consistent throughout, which is good. However the action pattern is mixed: some names use verbs (search, list_districts) while others are noun phrases (listing_detail, price_stats), so there is no single verb_noun convention.

Tool Count4/5

Four tools is on the lean side but each covers a distinct stage of the real-estate lookup workflow (discover → inspect → resolve location → analyze market). Nothing feels redundant, though a consumer might want one or two more helpers.

Completeness4/5

The surface covers the core read-only lifecycle: search, detail retrieval, district resolution, and aggregate pricing stats, with pagination and filtering documented. A minor gap is the absence of a city-list tool, so an agent must already know valid city slugs like 'istanbul' before calling list_districts or search.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Enables users to access the Realty In Ca1 API to search for residential and commercial property listings, view detailed property information, and retrieve neighborhood demographics or statistics. It supports filtering by geographic location, price range, building type, and other real estate characteristics.
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables querying 1.6M+ Dubai Land Department sales transactions and 9.5M+ Ejari rental contracts with flexible filters by area, property type, bedrooms, and date range.
    1
    34 PyPI
    1
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables querying livo.ge real estate listings through MCP, including search, listing details, geo lookups, reference dictionaries, and new development projects.
    7
    14 npm
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Gives AI agents read-only access to Bulgarian real-estate data from imotai.bg, letting them list districts, search and fetch active listings, pull district-level market statistics, and estimate values from current asking prices. All results are field-allowlisted and rate limited, with no credentials, broker contact details, or written descriptions exposed.
    5
    MIT