Skip to main content

mcp-591

An MCP server that lets AI assistants search property listings on 591.com.tw, Taiwan's largest real estate platform.

Disclaimer: This project scrapes data from an undocumented API. It is intended for personal research only. Do not use it for bulk or high-frequency requests.

Also available in: 繁體中文

Example

User: 幫我搜尋青埔周邊 10 年內的大樓,總價控制在 1200 萬左右

Claude calls search_sale with the inferred parameters:

{
  "region": "桃園市",
  "section": "中壢區",
  "shape": "電梯大樓",
  "age": "5_10",
  "price_str": "1000_1400",
  "keywords": "青埔"
}

Claude: 青埔周邊 1,0001,400 萬、10 年內電梯大樓,共找到 5年內 135 筆、510年 146 筆,以下整理 CP 值較高的物件:...

Requirements

  • Python 3.14+
  • uv

Installation

git clone <repo>
cd mcp-591
uv sync

Usage

As an MCP Server (Claude Desktop / Claude Code)

The repo ships a .mcp.json that Claude Code picks up automatically:

{
  "mcpServers": {
    "591": {
      "command": "uv",
      "args": ["run", "mcp-591"],
      "cwd": "${PWD}"
    }
  }
}

Four tools are exposed:

search_sale — Search for sale listings

Parameter Type Description
region str (required) County/city name, e.g. 桃園市
section str District, e.g. 中壢區. Omit to search the whole county.
kind str Property type, default 住宅. Options: 住宅 / 店面 / 辦公 / 廠房 / 車位 / 套房 / 土地 / 住辦
shape str Building type: 公寓 / 電梯大樓 / 透天厝 / 別墅
pattern str Room count: 1房 / 2房 / 3房 / 4房 / 5房以上
toilet str Bathroom count: 1衛 / 2衛 / 3衛 / 4衛 / 5衛以上
area str Floor area range (坪): 10_20 / 20_30 / 30_40 / 40_50 / 50_60 / 60_100 / 100_150 / 150_200
age str Building age: _5 (under 5 yrs) / 5_10 / 10_20 / 20_30 / 30_40 / 40_ (40+ yrs)
price_str str Price range in 萬 NTD, e.g. 1000_1500 or 1000_1250,1250_1500
keywords str Free-text search, e.g. 捷運 (MRT)
page_size int Results per page, max 30 (default 30)
first_row int Pagination offset (default 0)

get_sale_detail — Fetch full listing details

Parameter Type Description
post_id str Listing ID from a search_sale result

Returns: floor area breakdown (main area / common-area ratio), floor, building age, nearby transit, parking, fitment, mortgage estimate, contact info, and description.

search_rent — Search for rental listings

Parameter Type Description
region str (required) County/city name, e.g. 桃園市
section str District, e.g. 中壢區. Omit to search the whole county.
kind str Room type: 整層住家 / 獨立套房 / 分租套房 / 雅房 / 車位
shape str Building type: 公寓 / 電梯大樓 / 透天厝 / 別墅
pattern str Room count: 1房 / 2房 / 3房 / 4房 / 5房以上
price_str str Monthly rent range in NTD, e.g. 10000_20000
keywords str Free-text search, e.g. 捷運 (MRT)
first_row int Pagination offset (default 0). Use next_first_row from the previous response.

get_rent_detail — Fetch full rental listing details

Parameter Type Description
post_id str Listing ID from a search_rent result

Returns: price, deposit, floor area, floor, building type, layout, address with lat/lng, lease period, move-in date, pet/cooking/gender policies, facilities, contact info, and description.

Running the client directly (debugging)

# Search 桃園市中壢區
uv run python -m mcp_591.client 桃園市 中壢區

# With filters: shape pattern toilet area age
uv run python -m mcp_591.client 桃園市 中壢區 電梯大樓 3房 2衛 30_40 _5

Argument order: <county> [district] [shape,...] [pattern,...] [toilet,...] [area] [age]. Pass an empty string "" to skip an intermediate argument.

Development & Testing

# Install with dev dependencies
uv sync --dev

# Unit tests (no network, uses fixtures)
uv run pytest

# Integration tests (hits the real 591 API)
uv run pytest -m integration

Test layout

tests/
├── fixtures/
│   ├── search_sale.json   # Captured sale search response
│   ├── sale_detail.json   # Captured sale detail response
│   ├── search_rent.json   # Captured rent search response
│   └── rent_detail.json   # Captured rent detail response
├── test_server.py         # Unit tests: filtering and tool logic
└── test_integration.py    # Integration tests (skipped by default)

To refresh fixtures (requires network):

uv run python -c "
import json
from mcp_591.client import Client591
c = Client591()
json.dump(c.search_sale(region_id=6, section_ids=[67], kind=9, page_size=5),
          open('tests/fixtures/search_sale.json', 'w'), ensure_ascii=False, indent=2)
json.dump(c.get_sale_detail(19708683),
          open('tests/fixtures/sale_detail.json', 'w'), ensure_ascii=False, indent=2)
json.dump(c.search_rent(region_id=6, section_ids=[67], kind=1),
          open('tests/fixtures/search_rent.json', 'w'), ensure_ascii=False, indent=2)
json.dump(c.get_rent_detail(21103645),
          open('tests/fixtures/rent_detail.json', 'w'), ensure_ascii=False, indent=2)
"

Metadata

Release files for mcp-591 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-591 0.1.1
File Size Uploaded
mcp_591-0.1.1.tar.gz 90.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-591 0.1.1
File Interpreter ABI Platform
mcp_591-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 103.8 kB

Release files / mcp_591-0.1.1.tar.gz

Download URL mcp_591-0.1.1.tar.gz
Size 90.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f326ad794c88f63cf29cba0e07f12ad56f5aff0485c0df8340f16f767947fc84
BLAKE2b-256 checksum
How to use checksums
9dbcb70daaf4500cd183d48d9036b54e61136ffc77b1dba3f9e7d49be258faba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 24, 2026.

Transparency log

Release files / mcp_591-0.1.1-py3-none-any.whl

Download URL mcp_591-0.1.1-py3-none-any.whl
Size 13.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
102fb0541436a05117907627f5ffde03990edb3cad96da89a65622b2a7fc9693
BLAKE2b-256 checksum
How to use checksums
f8817667ba8c4e12f3b0e233b0c5cd9147d162a6ee9fab28dcdfd43f7fa7ee7b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page