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,000
1,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)
| File | Size | Uploaded | |
|---|---|---|---|
| mcp_591-0.1.1.tar.gz | 90.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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