streeteasy-mcp

streeteasy-mcp

A remote MCP server that wraps the StreetEasy GraphQL API to enable LLM agents to search and parse NYC rental listings.

Category
Visit Server

README

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.

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.

Run as a local MCP server (recommended)

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.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured