mcpField
I
ImotAI — Bulgarian real estate

ImotAI — Bulgarian real estate

Remote
imotai.bgBusiness & Marketing0Updated 1w ago

About ImotAI — Bulgarian real estate

ImotAI is a read-only MCP server that gives agents access to Bulgarian property listings and market data from imotai.bg. It supports property searches, district statistics, and asking-price estimates based on active listings rather than completed transactions.

Key features

  1. 01List cities and their price districts
  2. 02Search sale and rental listings
  3. 03View listings with district market context
  4. 04Get monthly reports and market statistics
  5. 05Estimate prices from comparable listings

Use cases

  1. 01Find listings by city and budget
  2. 02Compare asking prices across districts
  3. 03Review monthly changes in a city market
  4. 04Estimate a property's price from comparable listings

MCP support

The MCP server provides read-only property search, market statistics, reports, and valuation tools over Streamable HTTP or local stdio, with no API key required. Output fields are allowlisted and exclude broker contact details, descriptions, and exact coordinates.

Configuration

Remote servers need no local install. Pick your client, then copy the config or install in one click.

Endpointhttps://imotai.bg/mcp
Copy install command
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.

Tools

Details

From the project README

ImotAI MCP Server

A Model Context Protocol server that gives AI agents (Claude Desktop, Claude Code, …) a read-only window onto Bulgarian real-estate data from imotai.bg.

It is a thin client over the site's public API — no API keys, no writes, no personal data (broker names, phones and free-text descriptions never leave the API). Numbers are based on current asking prices of active listings, not on closed transactions.

Use it online (no install)

The server runs at https://imotai.bg/mcp (Streamable HTTP, stateless, no key).

  • Claude (claude.ai / desktop app): Settings → Connectors → Add custom connector → https://imotai.bg/mcp
  • Claude Code: claude mcp add --transport http imotai https://imotai.bg/mcp
  • Cursor / VS Code / other clients (mcp.json):
{ "mcpServers": { "imotai": { "url": "https://imotai.bg/mcp" } } }
  • ChatGPT: add a custom connector with https://imotai.bg/mcp (developer mode, depending on plan).

Instructions in Bulgarian: https://imotai.bg/ii-asistenti. Online limits: 30 requests/min per client.

Status

v0.2.0. Six tools (list_districts, search_properties, get_property, get_market_stats, get_market_report, estimate_value), each with an explicit output allowlist; the property tools carry a marketContext block. Two transports: stdio (dist/index.js, local) and Streamable HTTP (src/http.ts, the hosted endpoint above). get_market_report returns the monthly ImotAI market report for a city (median asking price per m², month-over-month change, districts, new listings).

Data: CC BY 4.0 — credit ImotAI (imotai.bg).

Install

git clone https://github.com/pdimiev-prog/imotai-mcp.git
cd imotai-mcp
npm install
npm run build   # produces dist/index.js

Use it in Claude Desktop

Add this to claude_desktop_config.json (use the absolute path to dist/index.js):

{
  "mcpServers": {
    "imotai": {
      "command": "node",
      "args": ["/absolute/path/to/imotai-mcp/dist/index.js"],
      "env": { "IMOTAI_API_URL": "https://imotai.bg/api" }
    }
  }
}

Restart Claude Desktop, then ask something like:

Which districts does ImotAI track in Sofia, and how many active listings are in each?

Claude will call list_districts and answer from the result.

Tools

list_districts

Input: { city: string } — a city slug ("sofia") or its Bulgarian name ("София").

Output:

{
  "city": { "slug": "sofia", "name": "София" },
  "districts": [
    { "name": "Лозенец", "slug": "lozenets", "activeListings": 64 },
    { "name": "Витоша",  "slug": "vitosha",  "activeListings": null }
  ],
  "note": "activeListings is filled only for districts with a public price page (>= 8 offers); a null count does not mean zero."
}

An unknown city returns { "error": "Unknown city \"…\". Recognised city slugs: …" }. Call this first — the slugs it returns are the valid district values for the other tools.

search_properties

Input:

FieldTypeNotes
citystring, requiredSlug or Bulgarian name
transactionType"sale" | "rent", required
districtstringSlug from list_districts
propertyTypeenumapartment, house, villa, studio, office, shop, warehouse, land, garage, other
minPrice / maxPricenumberEUR
minArea / maxAreanumberm²
roomsstringCSV, e.g. "2,3"; "5+" for 5 or more
limitinteger 1–25Default 10

Output: { results: [...], total, shown }. Each result has structured fields plus a url to the listing. No contact details, no free-text description, no coordinates.

get_property

Input: { id: string } — the listing's UUID or its URL slug.

Output: { found: true, url, ...structured fields, features: [] }, or { found: false, reason } if there is no such listing. Never returns the broker description, phone/name, or exact coordinates.

get_market_stats

Input: { city: string, district?: string } — slugs or Bulgarian names from list_districts. Omit district for city-level stats.

Output: { available: true, city, district, count, avgPrice, avgPricePerSqm, price: {p25,p50,p75}, pricePerSqm: {p25,p50,p75}, byRooms: [...], neighbouringDistricts: [...], basis, url }. Sale offers, all residential types. Below 8 offers → { available: false, count, reason }. Unknown city/district → { error } pointing at list_districts.

Market context

Both property tools attach a marketContext — "is this listing priced above or below its district":

  • get_property.marketContext is the authoritative per-listing figure from ImotAI's own calculation: districtAveragePricePerSqm, districtMedianPricePerSqm, deviationPercent (+ = pricier than the district), comparableActiveListings, basedOnCount, pricePageUrl.
  • search_properties[].marketContext is a lighter district-level approximation for scanning (one price-page lookup per distinct district): districtAveragePricePerSqm, deviationPercent, comparableListings, basis.

Both are null when the district has fewer than 8 offers or no price page. The two levels use slightly different denominators, so their numbers are close but not identical — the get_property figure is the precise one.

estimate_value

Input:

FieldTypeNotes
citystring, requiredSlug or Bulgarian name from list_districts
districtstring, requiredSlug or Bulgarian name from list_districts
propertyTypeenum, requiredapartment, house, villa, studio, land
areanumber, requiredLiving area in m²
roomsintegerAccepted but not used for filtering

Output:

{
  "available": true,
  "estimate": 208000,
  "rangeLow": 184000,
  "rangeHigh": 240000,
  "basedOnCount": 40,
  "confidence": "medium",          // from sample size; forced "low" for the market blend
  "disclaimer": "…",               // ALWAYS present — show verbatim
  "referenceUrl": "https://imotai.bg/ceni/sofia/lozenets"
}

Below 5 comparable offers it returns { "available": false, "reason": "…", "disclaimer": "…" } — still with a disclaimer. An unknown city or district returns { "error": "…" } pointing at list_districts (no disclaimer there).

confidence is high at ≥ 50 comparable offers, medium at ≥ 15, otherwise low; it is always low when external market data was blended into the figure, and the disclaimer then says so.

⚠️ This is positioning against the CURRENT ASKING PRICES of comparable active listings — not an appraisal, not an official valuation, not based on closed transactions. The disclaimer field is present on every available result; show it to the user verbatim whenever you cite any number from this tool.

Rate limiting

The server allows 60 downstream requests per minute per process (token bucket, refills continuously). Every call to imotai.bg/api counts — a search_properties that resolves three distinct districts spends four requests (one search + three price pages).

When the bucket is empty a tool returns, without throwing:

{ "error": "Твърде много заявки за кратко — изчакайте минута." }

Wait about a minute and retry. The limit is per running server process; a single Claude Desktop client is one process. Override it with IMOTAI_RATE_LIMIT_PER_MIN if you run your own instance.

Configuration

Env varDefaultMeaning
IMOTAI_API_URLhttps://imotai.bg/apiBase URL of the ImotAI public API
IMOTAI_HTTP_TIMEOUT_MS15000Per-request timeout
IMOTAI_RATE_LIMIT_PER_MIN60Max downstream requests per minute (token bucket, per process)

How it works

stdio MCP server (Node ≥ 20, ESM). Each tool maps to one or two calls against the public imotai.bg/api endpoints and reshapes the response through an explicit field allowlist. No state, no cache, no credentials.

Licence

MIT.

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.