rentals-search-mcp
Static Go MCP for long-term residential rental
search (apartments, houses, condos, townhomes) via the
RentCast API.
Built for ai-gantry / LOCAL_AGENT: lean
tool surface, stdio only, CGO_ENABLED=0 binary that fits distroless.
Search + recommend + listing handoff — never applies, contacts landlords, or
signs leases.
Naming follows
ai-gantry MCP tool naming:
host server id rentals → tools like rentals__listings_search (tool names do
not repeat the server id).
Publish from a personal GitHub account only (never a work org). CI /
GoReleaser / badges are scaffolded and light up after the personal remote
exists — see TODO.md.
What this is (and is not)
| In scope |
Out of scope |
| Long-term for-rent residential listings (US) |
Short-term / vacation stays (Airbnb, Google Hotels) |
| Apartments, houses, condos, townhomes, multi-family |
Retail / office / industrial commercial leases |
| Rent estimates + zip market stats |
Applying, touring, or signing leases |
| Listing URL / contact handoff |
Purchasing or escrow |
Commercial / tiny retail spaces (e.g. a small Seattle grocery mart) need a
different data source and almost certainly a different MCP package —
see docs/commercial-spaces.md.
| Tool |
Description |
listings_search |
City/zip/neighborhood/radius search + beds/baths/rent/type + new_this_week / days_old_max |
listings_get |
One listing by RentCast listing id |
rent_estimate_get |
Long-term rent AVM for an address (+ comps when available) |
markets_get |
Aggregate rent / listing stats for a US zip code |
areas_resolve |
Local neighborhood → zips / lat/lng (Seattle presets; no API) |
link_format |
Fallback public search URL (no API call) |
account_get |
Local usage counter (used/left) + dashboard link — RentCast has no public quota API |
Host names: rentals__listings_search, rentals__listings_get,
rentals__rent_estimate_get, rentals__markets_get, rentals__areas_resolve,
rentals__link_format, rentals__account_get.
Agent contract
[areas_resolve] → listings_search → [listings_get] → present listing url / contact
↘ markets_get / rent_estimate_get for context
- Where + budget:
listings_search with city+state, zip_code /
zip_codes, or neighborhood (e.g. Capitol Hill), plus beds/price/type.
Use new_this_week or days_old_max for fresh listings.
- Neighborhoods:
areas_resolve (list_all=true or neighborhood=Ballard)
when the human names a Seattle area — then pass neighborhood into search.
- Detail:
listings_get when the human picks a candidate id.
- Context (optional):
markets_get for zip averages; rent_estimate_get
when comparing a specific address to “fair rent”.
- Handoff: give the human the listing URL / contact fields. Do not
impersonate the renter or submit applications.
pets_wanted / parking_wanted / laundry_wanted are soft preferences only
— RentCast does not expose those filters; confirm on listing_url.
Setup
- Create a RentCast account (Developer plan =
50 free API requests / month).
- Export the key:
export RENTCAST_API_KEY=...
# optional (tests / proxies):
# export RENTCAST_BASE_URL=https://api.rentcast.io/v1
Docker / containers
The binary is static (CGO_ENABLED=0) and fine in distroless — pass
RENTCAST_API_KEY via env/secrets, never bake it into the image.
Local usage counter caveat: account_get / search usage persist under
RENTCAST_USAGE_FILE (default: OS user config dir). In Docker that path is
usually ephemeral (or unwritable in distroless), so counts reset on
recreate and can undercount real RentCast spend. Mitigations:
- Mount a volume and set
RENTCAST_USAGE_FILE=/data/rentcast-usage.json, or
- Treat the dashboard as source of truth and/or set
RENTCAST_USAGE_TRACK=0
Multiple containers without a shared usage file each keep their own counter.
Development
make help # list targets
make tools # install goimports-reviser + golangci-lint v2
make install-hooks # git pre-commit: autofix + lint + test + coverage ≥70%
make check # same checks as the pre-commit hook
make cli # static binary → ./bin/rentals-search-mcp
make self-test
Coverage ≥70% is mandatory locally (make coverage / pre-commit) and in CI.
Status: MVP client wired. US-wide long-term residential search (Seattle is just
the first use case). Remaining publish steps are in TODO.md.
Releasing
GoReleaser publishes static binaries on v* tags (see .github/workflows/release.yml).
Requires a personal GitHub remote first.
make version # show VERSION + next patch (dry-run)
make release # patch bump, commit VERSION, tag, push
make release BUMP=minor
make release TAG=v0.1.0
Archive name for ai-gantry download_url:
rentals-search-mcp_{version}_{os}_{arch}.tar.gz
Run as MCP (stdio)
./bin/rentals-search-mcp
Logs go to stderr only — stdout is reserved for the MCP protocol.
Example Cursor / client config:
{
"mcpServers": {
"rentals": {
"command": "rentals-search-mcp",
"env": {
"RENTCAST_API_KEY": "…"
}
}
}
}
ai-gantry wiring (when published)
[[server]]
name = "rentals"
command = "rentals-search-mcp"
download_tag = "latest"
download_url = "https://github.com/shotah/rentals-search-mcp/releases/download/{tag}/rentals-search-mcp_{version}_{os}_{arch}.tar.gz"
Do not publish this to a work GitHub org. Use a personal account / org
(module path assumes shotah).
More consumer notes: docs/ai-gantry.md.
License
MIT