Skip to main content
Glama
streeteasy-mcp

streeteasy-mcp

by Alec2435

streeteasy-mcp

A remote MCP server that wraps the StreetEasy GraphQL API so an LLM agent can search and parse NYC rental listings.

It vendors the streeteasy-api client (v0.4.0) and exposes it over either stdio (local) or Streamable HTTP (remote) transport, so it can be connected to by Claude or any MCP client.

IMPORTANT

StreetEasy blocks datacenter/cloud IPs. Its API sits behind PerimeterX bot-detection that 403s cloud/datacenter IPs (AWS, GCP, Railway, etc.). The HTTP build deploys fine and the MCP layer works, but the upstream search_rentals / get_rental_details calls fail from a datacenter unless you do one of:

  • Run the stdio server locally from a normal home connection — see Run as a local MCP server, or

  • Route upstream calls through a residential proxy by setting STREETEASY_PROXY — this is what lets the hosted HTTP build (Railway, etc.) reach the API. See Proxy / bot-detection.

Tools

Tool

Description

search_rentals

Search active NYC rentals by area, price, beds, baths, amenities, pets. Returns compact listings + totalCount, paginated. Each listing includes leadPhotoUrl / photoUrls and a listing url.

get_rental_details

Full detail for one listing id: description, amenities, pricing history, building info, nearby transit/schools, and resolved media — media.photoUrls, media.floorPlanUrls, media.videoLinks (YouTube/Vimeo), media.tour3dUrl.

list_areas

Look up StreetEasy area names ↔ numeric codes (optionally filtered by a search term).

list_amenities

List the valid amenity enum tokens.

search_rentals accepts area names ("MANHATTAN", "Williamsburg", "upper east side") or numeric codes, and validates amenity tokens against the known set.

Media

Photos resolve to Zillow's CDN (photos.zillowstatic.com/fp/{key}-se_large_800_400.jpg), videos to their provider watch URL (YouTube/Vimeo) plus a thumbnail, and 3D tours to a direct tour3dUrl. All are public — no auth required.

Not included: contact info & inquiries

Listing agent contact details and "request a tour" inquiries are not exposed. They live behind StreetEasy's contact flow, which is protected by PerimeterX bot-detection (a "Press & Hold" human check). Automating it would mean evading bot-detection, so it's intentionally left out — the right pattern is to surface the listing url and let a human submit the tour request in their browser.

Related MCP server: Apartment Hunter MCP Server

Endpoints

  • POST /mcp — the MCP Streamable HTTP endpoint (stateless). Requires a bearer token unless MCP_DISABLE_AUTH is set — see Authentication.

  • GET / and GET /health — health checks.

  • OAuth: /.well-known/oauth-authorization-server, /.well-known/oauth-protected-resource, /register, /authorize, /token, /revoke.

Runs over stdio from your machine's residential IP — the configuration that actually reaches StreetEasy.

npm install
npm run build
# register with Claude Code (uses the stdio entry point):
claude mcp add streeteasy -- node "$(pwd)/dist/stdio.js"

Then ask Claude to search rentals. To run the stdio server by hand:

npm run start:stdio

Run as an HTTP server

npm install
npm run build
npm start            # listens on $PORT (default 3000), POST /mcp

Test it with the MCP SDK client (see test-client.mjs):

MCP_URL=http://localhost:3000/mcp node test-client.mjs

Configuration

Env var

Purpose

PORT

Port to listen on. Railway sets this automatically.

PUBLIC_BASE_URL

Public origin the server is reachable at (the OAuth issuer), e.g. https://streeteasy-mcp-production.up.railway.app. Defaults to https://$RAILWAY_PUBLIC_DOMAIN on Railway, else http://localhost:$PORT.

MCP_DISABLE_AUTH

Set to 1/true to disable OAuth and leave /mcp open (handy for local testing with the bundled test-client.mjs).

STREETEASY_PROXY

Optional. HTTP/HTTPS proxy for all upstream StreetEasy calls, e.g. http://user:pass@host:port. Required for cloud/datacenter deploys — use a residential proxy. HTTPS_PROXY / ALL_PROXY are also honored.

Authentication (OAuth 2.1 + Dynamic Client Registration)

The HTTP transport requires OAuth by default — MCP clients (Claude, etc.) run the standard authorization flow automatically, so you usually don't configure anything. The server is a self-contained OAuth 2.1 authorization server:

  • Advertises metadata at /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource.

  • Supports Dynamic Client Registration (RFC 7591) at /register, so clients self-register with no manual client_id / client_secret.

  • /authorize (PKCE S256 required) → /token (authorization-code + refresh), with /revoke for revocation.

  • Unauthenticated POST /mcp returns 401 with a WWW-Authenticate header pointing at the protected-resource metadata, which kicks off discovery + DCR.

Because the tools expose only public listing data, there's no per-user login: authorization is auto-approved and the issued bearer token simply gates /mcp. Tokens are held in memory (single replica); a restart just makes clients transparently re-register. Set MCP_DISABLE_AUTH=1 to turn the whole layer off.

Proxy / bot-detection

StreetEasy 403s datacenter IPs, so any cloud host (Railway included) must send upstream requests through a residential proxy. Set STREETEASY_PROXY to a proxy URL (credentials may be embedded, e.g. http://user:pass@host:port) and all StreetEasy GraphQL traffic is tunnelled through it. On startup the server logs the proxy in use with credentials redacted (Outbound proxy: http://***:***@host:port).

Rotating residential proxies hand out a fresh exit IP per connection, and a clean IP isn't guaranteed every time, so the client automatically retries a 403 bot-challenge (up to 3 times when a proxy is set) to land on a good IP. A local stdio server on a residential connection doesn't need a proxy.

Deploy on Railway

This repo ships a Dockerfile. With the Railway CLI:

railway login
railway init --name streeteasy-mcp
# Cloud hosts are datacenter IPs — set a residential proxy so calls aren't 403'd:
railway variables --set "STREETEASY_PROXY=http://user:pass@host:port"
railway up
railway domain          # generate a public URL
# Set the OAuth issuer to your public URL (or rely on RAILWAY_PUBLIC_DOMAIN):
railway variables --set "PUBLIC_BASE_URL=https://<your-app>.up.railway.app"

Connect from Claude Code

claude mcp add --transport http streeteasy https://<your-app>.up.railway.app/mcp

The client discovers the OAuth endpoints and registers itself automatically (Dynamic Client Registration) — no client_id / token to configure.

Available Tools

4 tools
get_rental_detailsGet StreetEasy rental detailsB

Fetch full details for a single rental listing by its id (the id field from search_rentals results). Returns description, full amenities/features, pricing history, building info, nearby transit & schools, and media: media.photoUrls and media.floorPlanUrls (CDN image URLs), media.videoLinks (YouTube/Vimeo watch URLs + thumbnails), and media.tour3dUrl (3D walkthrough) when available.

Inputs: listingId (required).

list_amenitiesList StreetEasy amenitiesA

List the valid amenity enum tokens accepted by search_rentals (e.g. WASHER_DRYER, DOORMAN, GYM, PRIVATE_OUTDOOR_SPACE).

Inputs: no named parameters.

list_areasList StreetEasy areasA

List StreetEasy area names and their numeric codes for use in search_rentals. Optionally pass a search term to filter (e.g. 'brooklyn', 'harlem', 'williams'). Names are matched case/spacing-insensitively.

Inputs: search.

search_rentalsSearch StreetEasy rentalsA

Search active NYC rental listings on StreetEasy with filters. Areas accept names (e.g. 'MANHATTAN', 'Williamsburg', 'upper east side') or numeric area codes — use list_areas to discover them. Amenities are uppercase enum tokens — use list_amenities. Returns a compact list of listings plus a totalCount; paginate with page/perPage. Each listing has an id you can pass to get_rental_details, plus leadPhotoUrl and photoUrls (ready-to-view image URLs) and a url to the listing page.

Inputs: areas, minPrice, maxPrice, minBedrooms, +10 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.2/5.0

    Scored across 4 tools

    Disambiguation5/5

    Each tool has a distinct purpose: search_rentals for querying listings, get_rental_details for full info on a specific listing, and list_amenities/list_areas for retrieving valid filter values. No overlap.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern in snake_case (get_rental_details, list_amenities, list_areas, search_rentals), making them predictable and uniform.

    Tool Count5/5

    With 4 tools, the server is well-scoped for its purpose of browsing NYC rental listings. It covers searching, detail retrieval, and necessary enum lookups without bloat or insufficiency.

    Completeness5/5

    The tool surface provides a complete workflow: discover valid filters (amenities/areas), search listings with those filters, and get full details for any listing. No obvious gaps for a read-only rental search API.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      B
      maintenance
      MCP server for the Rentalot API. Manage rental properties, contacts, showings, conversations, and more from any AI assistant.
      12 npm
      1
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      An MCP server for rental apartment aggregation, enabling geographic polygon search, semantic vector search, and LLM-powered analysis. Integrates with AI agents like Claude Desktop to manage apartment hunting workflows.
      15
      2
      MIT
    • F
      license
      Not graded
      quality
      C
      maintenance
      Remote MCP server for SUpost, the Stanford student marketplace. Lets AI agents search active listings, fetch listing details, and read verified market statistics.
      -
    • F
      license
      A
      quality
      D
      maintenance
      MCP server that wraps the Vast.ai REST API to enable LLM agents to search GPU marketplace, rent machines, manage instance lifecycle, run commands, and inspect billing.
      20
      1
      -