Skip to main content
Glama
chrischall

booli-mcp

by chrischall
README.md
# booli-mcp

An MCP server for [Booli](https://www.booli.se), 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 ContextMint Bridge
browser 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`).

## Setup

1. Install **ContextMint Bridge** from its
   [releases page](https://github.com/nullnet-app/contextmint-bridge/releases) — Chrome: download
   the chrome zip, unzip it, and load it unpacked at `chrome://extensions`
   (Developer mode). Safari isn't available yet (it will ship inside the
   ContextMint app, which has no public download), so use Chrome for now.
   Keep a **www.booli.se** tab open.

   ContextMint Bridge is the fetchproxy browser extension under its new name,
   from the same maintainer — fetchproxy's own
   [README](https://github.com/chrischall/fetchproxy#extension) points to it.
   Its source is public at
   [nullnet-app/contextmint-bridge](https://github.com/nullnet-app/contextmint-bridge):
   build it yourself, or check a release zip against the `.sha256` file
   published beside it
   (`shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`).
2. On the first request, approve the one-time pairing prompt in ContextMint
   Bridge.
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
   extension is `linked`, `pair_pending` (approve the pair code
   it names), or `extension_disconnected`.

## Install

```jsonc
// 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`](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

TDQS

A4.2/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a distinct role: diagnostics (healthcheck), ID lookup (get_listing), area resolution (search_areas), active search (search_listings), sold search (search_sold), and aggregates (market_stats). The sold-search vs market-stats boundary could be adjacent, but descriptions explicitly clarify that one returns listings and the other returns aggregate statistics.

Naming Consistency4/5

All tools use a predictable booli_ prefix and snake_case. Most follow a verb_noun pattern (get_listing, search_areas, search_listings, search_sold), with minor deviations like healthcheck and market_stats that are still readable and idiomatic.

Tool Count5/5

Six tools is well-scoped for a read-only property data API: one diagnostic, one area resolver, two search endpoints, one detail endpoint, and one aggregate stats endpoint. Each earns its place without redundancy.

Completeness4/5

The surface covers the core read-only lifecycle: area lookup, active/sold search, listing detail, and market aggregates. Minor gaps exist (e.g., no bulk listing fetch or comparable-listing helper), but agents can work around them by composing existing tools.

Maintenance

ActivityActive
ResponsivenessResponsive