Skip to main content
Glama
chrischall

booli-mcp

by chrischall

booli-mcp

An MCP server for Booli, the Swedish property portal — search active for-sale listings, sold prices (slutpriser), resolve areas, and compute market statistics, all from Claude.

Developed and maintained by AI (Claude Code). Use at your own discretion and within booli.se's terms of use.

How it works

Booli fronts www.booli.se — including its GraphQL API — with a Cloudflare bot wall that blocks server-side clients. booli-mcp therefore reads Booli's consumer GraphQL API by routing each query through your own signed-in www.booli.se browser tab via the fetchproxy bridge (the Transporter extension), reusing your Cloudflare-cleared session. No Booli login is required — just a normal page view. All tools are read-only.

BOOLI_TRANSPORT selects the path: auto (default — direct fetch first, browser-bridge fallback when walled), fetchproxy (always the bridge), or direct. The fetchproxy fleet shares WS port 37149 (BOOLI_WS_PORT).

Related MCP server: Idealista7 MCP Server

Setup

  1. Install the Transporter (fetchproxy) browser extension and keep a www.booli.se tab open.

  2. On the first request, approve the one-time pairing prompt in Transporter.

  3. Run booli_healthcheck to confirm the path is working. Its transport field says which leg served the probe (direct or fetchproxy) and, once the bridge exists, bridge.session_state says whether the Transporter extension is linked, pair_pending (approve the pair code it names), or extension_disconnected.

Install

// mcp config
{
  "mcpServers": {
    "booli": {
      "command": "npx",
      "args": ["-y", "@chrischall/booli-mcp"]
    }
  }
}

Tools

Tool

What it does

booli_search_areas

Resolve a place name to Booli area ids

booli_search_listings

Search active for-sale listings by area + filters

booli_get_listing

Full detail for one property (active or sold) by residence id

booli_search_sold

Search sold listings (slutpriser) with final prices

booli_market_stats

Median/average sold-price statistics for an area

booli_healthcheck

Probe the data path and report transport (direct / fetchproxy, the BOOLI_TRANSPORT mode) and, once the bridge is up, bridge (role, port, extension link session_state, pending pair code) with a next-step hint

Searches scope by area_id (from booli_search_areas) or a free-text location. Money is SEK, areas m². See docs/BOOLI-API.md for the underlying GraphQL API.

Development

npm install
npm test          # vitest, no network
npm run build     # tsc + esbuild bundle

License

MIT

Available Tools

6 tools
booli_get_listingGet a Booli propertyA
Read-onlyIdempotent

Full detail for one property by its Booli residence id — the number in a booli.se/bostad/ URL, or the residence_id from a search result. Works for both active and sold properties. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
viewNoResponse shape: "compact" (default) drops fields the response already carries elsewhere; "full" returns every field this server understands. compact returns the slim PropertySummary/detail projection; "full" returns Booli's whole GraphQL node.
residence_idYesThe property's residence id (e.g. "4370936" from /bostad/4370936).

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already mark readOnlyHint, idempotentHint, and openWorldHint; the description independently states 'Read-only' and adds useful scope by saying it works for both active and sold properties. It does not discuss rate limits or output size, but for a simple read operation the combination is sufficient.

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 compact sentences with the primary action and identifier format front-loaded. The read-only qualifier is a single closing phrase, and 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?

This is a simple two-parameter read-only tool with strong annotations and full schema coverage, so little else is required. It could have explicitly named the search siblings as the way to find a residence_id when one is not already known, but the description already references search results as a source.

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

Parameters4/5

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

The schema covers 100% of parameters with detailed descriptions, so the baseline is 3; the description adds the operational hint that residence_id can be sourced from a booli.se URL or a search result's residence_id field. This helps the agent know where to obtain the required value beyond the schema's example.

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 'Full detail for one property by its Booli residence id', naming a specific verb, resource, and identifier format. It clearly separates this from the search siblings by focusing on single-property lookup and explicitly notes it covers active and sold properties.

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 tells the agent when to call the tool: when a residence id is already known, either from a booli.se/bostad/<id> URL or from a search result's residence_id field. It does not explicitly name alternative tools, but the by-id framing makes the contrast with search tools clear.

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

booli_healthcheckVerify the fetchproxy bridge end-to-endA
Read-onlyIdempotent

Round-trips a small public www.booli.se URL (/graphql) through the fetchproxy bridge and returns diagnostics: the bridge's role (host/peer/null), port, version, the extension link (linked / pair pending / not attached / never answered), the elapsed round-trip time, and a plain-English hint distinguishing 'bridge never came up' from 'extension not connected' from 'real www.booli.se-side problem'. Read-only, no auth required. Call this when a real tool fails and you want to know which hop broke.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

The description goes beyond the readOnlyHint/openWorldHint/idempotentHint annotations by stating 'Read-only, no auth required' and detailing what is returned: role, port, version, extension link state, elapsed time, and a plain-English failure hint. It also discloses the exact behavior of round-tripping a specific URL through the bridge, which is valuable operational context.

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

Conciseness5/5

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

The description is front-loaded with the action and immediately explains the tool's purpose, then lists the key diagnostic outputs. Every sentence adds useful information, and the closing usage directive is concise but highly actionable.

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

Completeness5/5

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

With no output schema, the description carries the burden of explaining return values, and it does: role, port, version, link state, elapsed time, and failure classification. Combined with the explicit when-to-use guidance and auth/read-only disclosure, nothing needed to invoke this tool correctly 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?

There are zero parameters, so the schema has nothing to document; the baseline is 4. The description still clarifies the fixed input it uses (a small public /graphql URL), which is the only parameter-like detail relevant to this tool.

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 ('round-trips') and resource (the fetchproxy bridge via a small public www.booli.se URL), then enumerates exactly what diagnostics are returned. This clearly distinguishes it from sibling data-access tools like booli_search_listings and booli_get_listing.

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

Usage Guidelines5/5

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

The description explicitly says to call this 'when a real tool fails and you want to know which hop broke,' giving a clear trigger condition. It also implicitly separates this diagnostic role from the sibling search/listing tools, which are for normal data access.

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

booli_market_statsBooli sold-price market statisticsA
Read-only

Aggregate sold-price statistics (median/average final price, price per m², average over/under-asking %) for an area on booli.se. Takes the same scope and filters as booli_search_sold, over one page of sold results. Check sample_size before trusting a thin median. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo1-based page (default 1).
sortNoSort key (default: newest published).
viewNoResponse shape: "compact" (default) drops fields the response already carries elsewhere; "full" returns every field this server understands. compact returns the slim PropertySummary/detail projection; "full" returns Booli's whole GraphQL node.
area_idNoBooli area id from booli_search_areas. Provide this OR `location`.
locationNoFree-text place name (e.g. "Nacka", "Södermalm") resolved to its top Booli area. Ignored when `area_id` is set.
ascendingNoSort ascending (default false).
max_roomsNo
min_roomsNo
object_typeNoProperty type(s), comma-separated, from: Lägenhet, Villa, Kedjehus-Parhus-Radhus, Fritidshus, Gård, Tomt/Mark.
max_plot_areaNo
max_sold_dateNoLatest sold date, YYYYMMDD.
min_plot_areaNo
min_sold_dateNoEarliest sold date, YYYYMMDD (e.g. "20240101").
max_sold_priceNoSEK
min_sold_priceNoSEK
max_living_areaNo
min_living_areaNo
max_sold_sqm_priceNoSEK/m²
min_sold_sqm_priceNoSEK/m²
is_new_constructionNotrue = only new production; false = exclude new production.
max_construction_yearNo
min_construction_yearNo

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 the description reinforces this with 'Read-only'. It adds behavioral nuance beyond annotations by warning to check `sample_size` before trusting a thin median and clarifying that aggregation happens over one page of sold 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?

Three sentences, no filler. The core purpose is front-loaded, the sibling relationship is stated in the second sentence, and the sample_size caveat is the final actionable warning. 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 22-parameter tool with no output schema, the description is surprisingly complete: it names the output metrics, ties filters to a known sibling, and flags a data-quality caveat. It does not spell out the area requirement, but the schema's area_id/location descriptions already cover that.

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 82%, so the schema already carries most parameter meaning. The description adds little parameter-level detail, though referencing booli_search_sold for scope and filters is useful shorthand. No contradiction or gap large enough to lower below the high-coverage 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 opens with a specific verb and resource: 'Aggregate sold-price statistics' and enumerates exactly what is returned (median/average final price, price per m², over/under-asking %). It clearly differentiates from siblings by framing this as an aggregate tool while booli_search_sold is the underlying per-result search.

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 ties usage to booli_search_sold: 'Takes the same scope and filters as booli_search_sold', which tells the agent when to reach for this tool instead of the search sibling. It also adds the important one-page limitation. It does not explicitly state when not to use it, but the context is strong enough to route correctly.

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

booli_search_areasResolve a Booli areaA
Read-onlyIdempotent

Resolve a place name to Booli areas — municipalities, districts, streets — each with its area_id to pass as area_id into booli_search_listings / booli_search_sold. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results (default 10).
queryYesPlace-name search string (e.g. "Nacka", "Södermalm").

TDQS

A4.1/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, openWorldHint, and idempotentHint. The description adds useful context about the types of areas returned (municipalities, districts, streets) and the area_id output, which complements the annotations without contradicting them.

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, zero waste, front-loaded with the main action and resource. Efficiently communicates purpose, output, and consumption pattern.

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 2-parameter lookup tool with strong annotations, the description fully explains the tool's purpose, output (areas with area_id), and how it feeds into sibling tools. No output schema needed given the context provided.

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

Parameters3/5

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

Schema coverage is 100% (both parameters described with clear descriptions). The description adds little extra meaning beyond what is in the schema, as the schema already covers the parameter semantics adequately.

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 ('Resolve'), a clear resource ('place names to Booli areas'), and explicitly distinguishes from siblings by naming booli_search_listings and booli_search_sold as consumers of the area_id.

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 implies usage when needing area IDs for Booli search tools ('to pass as area_id into booli_search_listings / booli_search_sold'), but does not elaborate on when not to use or alternatives beyond the sibling mention.

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

booli_search_listingsSearch Booli for-sale listingsA
Read-only

Search active for-sale property listings on booli.se. Scope by area_id (from booli_search_areas) or a free-text location, and filter by price, rooms, living area, plot, object type, construction year. Paginated by page; check total_count/pages. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo1-based page (default 1).
sortNoSort key (default: newest published).
viewNoResponse shape: "compact" (default) drops fields the response already carries elsewhere; "full" returns every field this server understands. compact returns the slim PropertySummary/detail projection; "full" returns Booli's whole GraphQL node.
area_idNoBooli area id from booli_search_areas. Provide this OR `location`.
locationNoFree-text place name (e.g. "Nacka", "Södermalm") resolved to its top Booli area. Ignored when `area_id` is set.
ascendingNoSort ascending (default false).
max_roomsNo
min_roomsNo
object_typeNoProperty type(s), comma-separated, from: Lägenhet, Villa, Kedjehus-Parhus-Radhus, Fritidshus, Gård, Tomt/Mark.
max_plot_areaNo
min_plot_areaNo
max_list_priceNoSEK
min_list_priceNoSEK
max_living_areaNo
min_living_areaNo
max_list_sqm_priceNoSEK/m²
min_list_sqm_priceNoSEK/m²
is_new_constructionNotrue = only new production; false = exclude new production.
max_construction_yearNo
min_construction_yearNo

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already supply readOnlyHint and openWorldHint, and the description adds useful behavior beyond them: pagination via 'page' and the instruction to check 'total_count'/'pages'. It also notes the cross-tool dependency on booli_search_areas. 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 three sentences, front-loaded with the core purpose, and each sentence carries distinct information: scope/filters, pagination, and safety. The only redundancy is 'Read-only', which mirrors the annotation but is unobtrusive.

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 20-parameter tool with no output schema, the description covers purpose, scoping, filter dimensions, and pagination behavior. It does not explicitly state that at least one of area_id/location is expected, nor mention sort options, but the schema covers sort and parameter precedence, so the gaps are minor.

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 80%, so the baseline is 3, but the description adds a concise filter grouping and clarifies the area_id/location scoping relationship, including the provenance of area_id from booli_search_areas. It also gives pagination semantics for the page parameter.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Search active for-sale property listings on booli.se.' The 'for-sale' qualifier distinguishes it from booli_search_sold, and the resource 'listings' separates it from area search, market stats, and health check siblings.

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

Usage Guidelines4/5

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

It names booli_search_areas as the source for area_id and offers a free-text location alternative, which provides clear context for when to use this tool. It does not explicitly state when to prefer booli_search_sold or exclude other alternatives, so it stops short of full when/when-not guidance.

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

booli_search_soldSearch Booli sold listings (slutpriser)A
Read-only

Search sold properties (slutpriser) on booli.se with the achieved final price and over/under-asking % — the comparables for valuation. Scope by area_id or free-text location, filter by sold price, sold date, rooms, area, object type. Paginated by page. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo1-based page (default 1).
sortNoSort key (default: newest published).
viewNoResponse shape: "compact" (default) drops fields the response already carries elsewhere; "full" returns every field this server understands. compact returns the slim PropertySummary/detail projection; "full" returns Booli's whole GraphQL node.
area_idNoBooli area id from booli_search_areas. Provide this OR `location`.
locationNoFree-text place name (e.g. "Nacka", "Södermalm") resolved to its top Booli area. Ignored when `area_id` is set.
ascendingNoSort ascending (default false).
max_roomsNo
min_roomsNo
object_typeNoProperty type(s), comma-separated, from: Lägenhet, Villa, Kedjehus-Parhus-Radhus, Fritidshus, Gård, Tomt/Mark.
max_plot_areaNo
max_sold_dateNoLatest sold date, YYYYMMDD.
min_plot_areaNo
min_sold_dateNoEarliest sold date, YYYYMMDD (e.g. "20240101").
max_sold_priceNoSEK
min_sold_priceNoSEK
max_living_areaNo
min_living_areaNo
max_sold_sqm_priceNoSEK/m²
min_sold_sqm_priceNoSEK/m²
is_new_constructionNotrue = only new production; false = exclude new production.
max_construction_yearNo
min_construction_yearNo

TDQS

A4.2/5.0
Behavior4/5

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

The description adds context beyond the readOnlyHint annotation: it identifies the return content (final price, over/under-asking %), says it's read-only, and describes scoping/filter/pagination behavior. It does not contradict annotations and covers the main operational traits expected of a read-only search; it lacks only rate-limit/result-volume caveats.

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 front-load the purpose and key output, then compress scoping, filters, pagination, and safety into a compact second sentence. No filler or repetition of schema details.

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 22-parameter read-only search with a rich schema, the description covers the essentials: what it returns, how to scope/filter, pagination, and read-only safety. It doesn't explicitly contrast with booli_search_listings or describe response-shape variants, but the schema fills most remaining gaps.

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

Parameters3/5

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

Schema coverage is 82%, so the schema already documents most parameters; the description's grouping into 'scope', 'filter', and 'paginated' adds a useful mental model but no new format or syntax. It does not elaborate on the handful of parameters missing from schema descriptions, so baseline 3 is appropriate.

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

Purpose5/5

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

The description names a specific verb ('Search'), resource ('sold properties (slutpriser) on booli.se'), and distinctive output ('achieved final price and over/under-asking %'). It clearly separates this from active-listing searches by emphasizing 'sold' and 'comparables for valuation', so an agent can distinguish it from booli_search_listings and booli_market_stats.

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 states the use case ('the comparables for valuation') and gives the scoping pattern (`area_id` or free-text `location`), plus filter dimensions and pagination. It doesn't explicitly name alternative tools or when not to use it, so it earns a 4 rather than a 5.

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 updatesv1.3.1
    • Changedbooli_get_listing2 fields changed
      • removedInput schema / properties / compact
        Removed value: -{
        -  "description": "Return a slim summary instead of the full raw record (default false).",
        -  "type": "boolean"
        -}
      • addedInput schema / properties / view
        Added value: +{
        +  "description": "Response shape: \"compact\" (default) drops fields the response already carries elsewhere; \"full\" returns every field this server understands. compact returns the slim PropertySummary/detail projection; \"full\" returns Booli's whole GraphQL node.",
        +  "enum": [
        +    "compact",
        +    "full"
        +  ],
        +  "type": "string"
        +}
    • Changedbooli_market_stats2 fields changed
      • removedInput schema / properties / compact
        Removed value: -{
        -  "description": "Return slim summary records (default true). Set false for full raw fields.",
        -  "type": "boolean"
        -}
      • addedInput schema / properties / view
        Added value: +{
        +  "description": "Response shape: \"compact\" (default) drops fields the response already carries elsewhere; \"full\" returns every field this server understands. compact returns the slim PropertySummary/detail projection; \"full\" returns Booli's whole GraphQL node.",
        +  "enum": [
        +    "compact",
        +    "full"
        +  ],
        +  "type": "string"
        +}
    • Changedbooli_search_listings2 fields changed
      • removedInput schema / properties / compact
        Removed value: -{
        -  "description": "Return slim summary records (default true). Set false for full raw fields.",
        -  "type": "boolean"
        -}
      • addedInput schema / properties / view
        Added value: +{
        +  "description": "Response shape: \"compact\" (default) drops fields the response already carries elsewhere; \"full\" returns every field this server understands. compact returns the slim PropertySummary/detail projection; \"full\" returns Booli's whole GraphQL node.",
        +  "enum": [
        +    "compact",
        +    "full"
        +  ],
        +  "type": "string"
        +}
    • Changedbooli_search_sold2 fields changed
      • removedInput schema / properties / compact
        Removed value: -{
        -  "description": "Return slim summary records (default true). Set false for full raw fields.",
        -  "type": "boolean"
        -}
      • addedInput schema / properties / view
        Added value: +{
        +  "description": "Response shape: \"compact\" (default) drops fields the response already carries elsewhere; \"full\" returns every field this server understands. compact returns the slim PropertySummary/detail projection; \"full\" returns Booli's whole GraphQL node.",
        +  "enum": [
        +    "compact",
        +    "full"
        +  ],
        +  "type": "string"
        +}
  2. 6 tool updatesv1.0.0
    • Changedbooli_get_listing3 fields changed
      • removedInput schema / properties / booli_id
        Removed value: -{
        -  "description": "The listing's Booli id (e.g. \"1579812\").",
        -  "type": "string"
        -}
      • addedInput schema / properties / residence_id
        Added value: +{
        +  "description": "The property's residence id (e.g. \"4370936\" from /bostad/4370936).",
        +  "type": "string"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "booli_id"
        -]New value: +[
        +  "residence_id"
        +]
    • Removedbooli_get_sold
    • Changedbooli_market_stats13 fields changed
      • changedInput schema / properties / area_id / description
        Previous value: -"Booli area id(s) from booli_search_areas, comma-separated for several (e.g. \"76,16\")."New value: +"Booli area id from booli_search_areas. Provide this OR `location`."
      • addedInput schema / properties / ascending
        Added value: +{
        +  "description": "Sort ascending (default false).",
        +  "type": "boolean"
        +}
      • removedInput schema / properties / bbox
        Removed value: -{
        -  "description": "Bounding box \"lat_lo,lng_lo,lat_hi,lng_hi\" (SW then NE corner).",
        -  "type": "string"
        -}
      • removedInput schema / properties / center
        Removed value: -{
        -  "description": "Coordinate \"lat,lng\" (e.g. \"59.34674,18.0603\"); use with `dim`.",
        -  "type": "string"
        -}
      • removedInput schema / properties / dim
        Removed value: -{
        -  "description": "Rectangle size in metres \"w,h\" (e.g. \"400,500\"), used with `center`.",
        -  "type": "string"
        -}
      • removedInput schema / properties / limit
        Removed value: -{
        -  "description": "Default 30, max 100.",
        -  "maximum": 100,
        -  "minimum": 1,
        -  "type": "integer"
        -}
      • addedInput schema / properties / location
        Added value: +{
        +  "description": "Free-text place name (e.g. \"Nacka\", \"Södermalm\") resolved to its top Booli area. Ignored when `area_id` is set.",
        +  "type": "string"
        +}
      • removedInput schema / properties / max_rent
        Removed value: -{
        -  "description": "SEK/month",
        -  "minimum": 0,
        -  "type": "number"
        -}
      • changedInput schema / properties / object_type / description
        Previous value: -"Property type(s), comma-separated, from: villa, lägenhet, gård, tomt-mark, fritidshus, parhus, radhus, kedjehus."New value: +"Property type(s), comma-separated, from: Lägenhet, Villa, Kedjehus-Parhus-Radhus, Fritidshus, Gård, Tomt/Mark."
      • removedInput schema / properties / offset
        Removed value: -{
        -  "description": "Pagination offset.",
        -  "maximum": 9007199254740991,
        -  "minimum": 0,
        -  "type": "integer"
        -}
      • addedInput schema / properties / page
        Added value: +{
        +  "description": "1-based page (default 1).",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • removedInput schema / properties / q
        Removed value: -{
        -  "description": "Free-text area search (e.g. \"Nacka\", \"Södermalm\"). One of q / area_id / center / bbox scopes the search.",
        -  "type": "string"
        -}
      • addedInput schema / properties / sort
        Added value: +{
        +  "description": "Sort key (default: newest published).",
        +  "enum": [
        +    "published",
        +    "listPrice",
        +    "listSqmPrice",
        +    "rooms",
        +    "livingArea",
        +    "rent",
        +    "plotArea"
        +  ],
        +  "type": "string"
        +}
    • Changedbooli_search_areas8 fields changed
      • removedInput schema / properties / lat
        Removed value: -{
        -  "description": "Latitude; use together with `lng`.",
        -  "type": "number"
        -}
      • changedInput schema / properties / limit / description
        Previous value: -"Default 10, max 50."New value: +"Max results (default 10)."
      • removedInput schema / properties / lng
        Removed value: -{
        -  "description": "Longitude; use together with `lat`.",
        -  "type": "number"
        -}
      • removedInput schema / properties / only_with_listings
        Removed value: -{
        -  "description": "Only return areas that currently have listings for sale.",
        -  "type": "boolean"
        -}
      • removedInput schema / properties / only_with_sold
        Removed value: -{
        -  "description": "Only return areas that have sold listings.",
        -  "type": "boolean"
        -}
      • removedInput schema / properties / q
        Removed value: -{
        -  "description": "Place-name search string (e.g. \"Nacka\").",
        -  "type": "string"
        -}
      • addedInput schema / properties / query
        Added value: +{
        +  "description": "Place-name search string (e.g. \"Nacka\", \"Södermalm\").",
        +  "type": "string"
        +}
      • addedInput schema / required
        Added value: +[
        +  "query"
        +]
    • Changedbooli_search_listings13 fields changed
      • changedInput schema / properties / area_id / description
        Previous value: -"Booli area id(s) from booli_search_areas, comma-separated for several (e.g. \"76,16\")."New value: +"Booli area id from booli_search_areas. Provide this OR `location`."
      • addedInput schema / properties / ascending
        Added value: +{
        +  "description": "Sort ascending (default false).",
        +  "type": "boolean"
        +}
      • removedInput schema / properties / bbox
        Removed value: -{
        -  "description": "Bounding box \"lat_lo,lng_lo,lat_hi,lng_hi\" (SW then NE corner).",
        -  "type": "string"
        -}
      • removedInput schema / properties / center
        Removed value: -{
        -  "description": "Coordinate \"lat,lng\" (e.g. \"59.34674,18.0603\"); use with `dim`.",
        -  "type": "string"
        -}
      • removedInput schema / properties / dim
        Removed value: -{
        -  "description": "Rectangle size in metres \"w,h\" (e.g. \"400,500\"), used with `center`.",
        -  "type": "string"
        -}
      • removedInput schema / properties / limit
        Removed value: -{
        -  "description": "Default 30, max 100.",
        -  "maximum": 100,
        -  "minimum": 1,
        -  "type": "integer"
        -}
      • addedInput schema / properties / location
        Added value: +{
        +  "description": "Free-text place name (e.g. \"Nacka\", \"Södermalm\") resolved to its top Booli area. Ignored when `area_id` is set.",
        +  "type": "string"
        +}
      • removedInput schema / properties / max_rent
        Removed value: -{
        -  "description": "SEK/month",
        -  "minimum": 0,
        -  "type": "number"
        -}
      • changedInput schema / properties / object_type / description
        Previous value: -"Property type(s), comma-separated, from: villa, lägenhet, gård, tomt-mark, fritidshus, parhus, radhus, kedjehus."New value: +"Property type(s), comma-separated, from: Lägenhet, Villa, Kedjehus-Parhus-Radhus, Fritidshus, Gård, Tomt/Mark."
      • removedInput schema / properties / offset
        Removed value: -{
        -  "description": "Pagination offset.",
        -  "maximum": 9007199254740991,
        -  "minimum": 0,
        -  "type": "integer"
        -}
      • addedInput schema / properties / page
        Added value: +{
        +  "description": "1-based page (default 1).",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • removedInput schema / properties / q
        Removed value: -{
        -  "description": "Free-text area search (e.g. \"Nacka\", \"Södermalm\"). One of q / area_id / center / bbox scopes the search.",
        -  "type": "string"
        -}
      • addedInput schema / properties / sort
        Added value: +{
        +  "description": "Sort key (default: newest published).",
        +  "enum": [
        +    "published",
        +    "listPrice",
        +    "listSqmPrice",
        +    "rooms",
        +    "livingArea",
        +    "rent",
        +    "plotArea"
        +  ],
        +  "type": "string"
        +}
    • Changedbooli_search_sold13 fields changed
      • changedInput schema / properties / area_id / description
        Previous value: -"Booli area id(s) from booli_search_areas, comma-separated for several (e.g. \"76,16\")."New value: +"Booli area id from booli_search_areas. Provide this OR `location`."
      • addedInput schema / properties / ascending
        Added value: +{
        +  "description": "Sort ascending (default false).",
        +  "type": "boolean"
        +}
      • removedInput schema / properties / bbox
        Removed value: -{
        -  "description": "Bounding box \"lat_lo,lng_lo,lat_hi,lng_hi\" (SW then NE corner).",
        -  "type": "string"
        -}
      • removedInput schema / properties / center
        Removed value: -{
        -  "description": "Coordinate \"lat,lng\" (e.g. \"59.34674,18.0603\"); use with `dim`.",
        -  "type": "string"
        -}
      • removedInput schema / properties / dim
        Removed value: -{
        -  "description": "Rectangle size in metres \"w,h\" (e.g. \"400,500\"), used with `center`.",
        -  "type": "string"
        -}
      • removedInput schema / properties / limit
        Removed value: -{
        -  "description": "Default 30, max 100.",
        -  "maximum": 100,
        -  "minimum": 1,
        -  "type": "integer"
        -}
      • addedInput schema / properties / location
        Added value: +{
        +  "description": "Free-text place name (e.g. \"Nacka\", \"Södermalm\") resolved to its top Booli area. Ignored when `area_id` is set.",
        +  "type": "string"
        +}
      • removedInput schema / properties / max_rent
        Removed value: -{
        -  "description": "SEK/month",
        -  "minimum": 0,
        -  "type": "number"
        -}
      • changedInput schema / properties / object_type / description
        Previous value: -"Property type(s), comma-separated, from: villa, lägenhet, gård, tomt-mark, fritidshus, parhus, radhus, kedjehus."New value: +"Property type(s), comma-separated, from: Lägenhet, Villa, Kedjehus-Parhus-Radhus, Fritidshus, Gård, Tomt/Mark."
      • removedInput schema / properties / offset
        Removed value: -{
        -  "description": "Pagination offset.",
        -  "maximum": 9007199254740991,
        -  "minimum": 0,
        -  "type": "integer"
        -}
      • addedInput schema / properties / page
        Added value: +{
        +  "description": "1-based page (default 1).",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • removedInput schema / properties / q
        Removed value: -{
        -  "description": "Free-text area search (e.g. \"Nacka\", \"Södermalm\"). One of q / area_id / center / bbox scopes the search.",
        -  "type": "string"
        -}
      • addedInput schema / properties / sort
        Added value: +{
        +  "description": "Sort key (default: newest published).",
        +  "enum": [
        +    "published",
        +    "listPrice",
        +    "listSqmPrice",
        +    "rooms",
        +    "livingArea",
        +    "rent",
        +    "plotArea"
        +  ],
        +  "type": "string"
        +}
  3. 7 tool updatesv0.0.0
    • First observedbooli_get_listing
    • First observedbooli_get_sold
    • First observedbooli_healthcheck
    • First observedbooli_market_stats
    • First observedbooli_search_areas
    • First observedbooli_search_listings
    • First observedbooli_search_sold

TDQS

A4.4/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a clear, non-overlapping purpose: area lookup, healthcheck, active listing search, single-listing details, sold search, and market stats. The only close pair (search_sold vs market_stats) is distinguished by raw comparables vs aggregate analytics.

Naming Consistency4/5

All tools share the booli_ prefix and most follow a verb_noun pattern (search_areas, search_listings, get_listing, search_sold, market_stats). booli_healthcheck is the one outlier as a compound noun without an action verb, but it is still recognizable and not confusing.

Tool Count5/5

Six tools is well-scoped for a focused real-estate search server. Each tool fills a distinct need without redundancy, and the count feels neither thin nor bloated.

Completeness5/5

The domain is read-only property search, and the surface covers the full workflow: resolve area, search active listings, drill into a listing, search sold comparables, and get aggregate statistics. Healthcheck adds operational completeness for diagnosing failures.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    Not graded
    maintenance
    Enables AI assistants to search and analyze Swedish real estate data from Booli.se using natural language queries. Supports property searches with comprehensive filtering options and location discovery through GraphQL API integration.
    3
    1
    -
  • A
    license
    C
    quality
    D
    maintenance
    Enables access to Idealista API for searching and retrieving property listings across Spain, Portugal, and Italy. Supports various property types including homes, apartments, garages, commercial properties, offices, and land with detailed filtering options.
    14
    3
    MIT
  • A
    license
    Not graded
    quality
    F
    maintenance
    Provides real-time access to Zillow real estate data, enabling property search, details, Zestimates, market trends, and mortgage calculations via natural language.
    10
    48
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables searching Korean apartment listings, market prices, and recent transactions via Naver Real Estate through natural language.
    6
    MIT