{
  "markdown": "# Hemnet MCP\n\n[![CI](https://github.com/chrischall/hemnet-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/chrischall/hemnet-mcp/actions/workflows/ci.yml)\n[![npm](https://img.shields.io/npm/v/hemnet-mcp)](https://www.npmjs.com/package/hemnet-mcp)\n[![license](https://img.shields.io/npm/l/hemnet-mcp)](LICENSE)\n\nAn [MCP](https://modelcontextprotocol.io) server for **[hemnet.se](https://www.hemnet.se)**,\nSweden's largest real-estate portal. Search for-sale listings, look up\nsold prices (*slutpriser*), pull full listing detail and photos, compute\nmarket statistics, resolve addresses, and run a Swedish mortgage\ncalculation — all from Claude.\n\n> ⚠️ This project is **built and maintained by AI (Claude)**. It reads\n> hemnet.se through its public GraphQL API. Use at your own discretion\n> and within hemnet.se's terms of service.\n\n## Highlights\n\n- **No configuration.** Hemnet serves its read queries anonymously — no\n  login, no API key, no browser extension. `npx hemnet-mcp` just works.\n- **Sold prices (slutpriser).** Hemnet's signature dataset: achieved\n  final price, asking price, and over/under-asking percentage — the comps\n  an agent needs to value a home.\n- **Swedish-native.** Money in SEK, areas in m², rooms, `bostadsrätt`\n  fees (avgift), energy class, and a mortgage model that follows Swedish\n  rules (amorteringskrav, ränteavdrag).\n- **Embeddable.** Ships as a standalone MCP server *and* as a library so\n  it can be composed into a larger multi-portal server.\n\n## Install\n\n### Claude Code / Claude Desktop (npx)\n\n```json\n{\n  \"mcpServers\": {\n    \"hemnet\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"hemnet-mcp\"]\n    }\n  }\n}\n```\n\n### From source\n\n```bash\ngit clone https://github.com/chrischall/hemnet-mcp\ncd hemnet-mcp\nnpm install\nnpm run build\nnode dist/index.js\n```\n\n## Tools\n\n| Tool | What it does |\n| --- | --- |\n| `hemnet_autocomplete_location` | Resolve a place name (`\"Vasastan\"`) to Hemnet location ids — the starting point for search. |\n| `hemnet_search_listings` | Search active for-sale listings by location + filters (price SEK, rooms, m², property type, keywords). |\n| `hemnet_get_listing` | Full detail for one listing (price, fee, running costs, m², rooms, tenure, energy class, broker, description, photos). |\n| `hemnet_get_listing_photos` | Just the gallery photo URLs. |\n| `hemnet_search_sold` | Search **sold** listings with final price, asking price, and over/under-asking %. |\n| `hemnet_get_sold_listing` | Full detail for one sold listing. |\n| `hemnet_get_market_stats` | Median/average final price and price-per-m² for a location. |\n| `hemnet_compare_listings` | Fetch several listings at once for side-by-side comparison. |\n| `hemnet_get_by_address` | Resolve a free-text street address to a live listing. |\n| `hemnet_calculate_mortgage` | Local Swedish monthly-cost calculator (interest + amortisation + fee, gross & after-tax). No network. |\n| `hemnet_healthcheck` | Verify the Hemnet GraphQL endpoint is reachable. Reports which transport served the probe (`transport`: direct fetch or the browser bridge, plus the configured `HEMNET_TRANSPORT`), the bridge's role/port/extension-link state (`bridge`, once a bridge exists), a classified `error.kind` (e.g. `cloudflare_challenge`, `session_not_ready`) and a next-step hint. |\n\n### Example flow\n\n```\n1. hemnet_autocomplete_location { query: \"Vasastan\" }\n   → location_id 925970\n2. hemnet_search_listings { location_ids: [\"925970\"], rooms_min: 2, price_max: 6000000 }\n   → listing summaries\n3. hemnet_get_market_stats { location_ids: [\"925970\"], housing_form_groups: [\"APARTMENTS\"] }\n   → median final price, price-per-m²\n4. hemnet_calculate_mortgage { price: 4695000, interest_rate: 3.9, monthly_fee: 2800 }\n   → monthly cost, gross and after-tax\n```\n\nOr pass a free-text `location` to any search tool and it resolves the top\nhit for you.\n\n## Money & units\n\nAll output records use **numbers**: `price` / `final_price` /\n`fee_monthly` in SEK, `living_area_sqm` / `land_area_sqm` in m², `rooms`\nas a number. A derived `price_per_sqm` is always included when price and\nliving area allow it (even when Hemnet omits it, common on houses). The\noriginal Hemnet-formatted strings are kept alongside as `*_formatted`.\n\n## Library use\n\nhemnet-mcp is also importable, so it can serve as a Hemnet *portal\nsource* inside a larger project (e.g. a cross-portal realty\norchestrator):\n\n```ts\nimport { createHemnetClient, computeMarketStats } from 'hemnet-mcp';\n\nconst hemnet = createHemnetClient();\nconst { cards } = await hemnet.searchSales({ locationIds: ['925970'] }, { limit: 50 });\nconst stats = computeMarketStats(cards.map(formatSaleCard));\n```\n\nThe library entry (`import … from 'hemnet-mcp'`) re-exports the client,\nthe normalised record types, the pure derivations\n(`computeMarketStats`, `calculateSwedishMortgage`, money/url helpers),\nand every tool registrar (`registerHemnetTools(server, client)` to graft\nthe tools onto your own MCP server).\n\n## Development\n\n```bash\nnpm test               # vitest (mocked transport, no network)\nnpm run test:coverage  # 100% coverage enforced on src/**\nnpm run typecheck\nnpm run build\n```\n\nTests drive every tool and the client through an in-memory fake\ntransport — no live hemnet.se calls. See `CLAUDE.md` for architecture,\nthe GraphQL quirks, and contribution conventions.\n\n## License\n\nMIT\n",
  "bytes": 5334,
  "sha": "af0f15ab4cfed926aa70ebed7ba8ff5a5f9047496cdafef525dc2141b366882f",
  "repo_slug": "chrischall/hemnet-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_chrischall_hemnet_mcp_0568bcae/readme"
}