onehome-mcp
Summary: onehome-mcp lets Claude search and inspect the OneHome (CoreLogic) listings your agent shared with you, explore each property in depth, and run local real-estate math — all through a bearer-token session you supply.
Find listings — list your agent's shared groups (
onehome_get_groups), fetch an agent-curated saved search by id (onehome_get_saved_search), or get a saved search plus its inflated listings in one call (onehome_get_saved_search_with_listings).Search — browse listings inside a group/saved share with paging and sort (
onehome_search_properties), or run free-text suggestion search by address/MLS number across feeds (onehome_search_suggestions).Resolve addresses — turn a free-text street address into a portal URL + listing id (
onehome_get_by_address), or bulk-resolve up to 100 structured addresses concurrently (onehome_resolve_addresses).Inspect properties — full record by id or URL with prices, beds/baths/sqft, lot size, tax, HOA, lat/lng, and parsed features (
onehome_get_property); full photo gallery with multiple CDN sizes and room descriptions (onehome_get_property_photos).Compare and bulk fetch — side-by-side facts for 2–8 listings (
onehome_compare_properties) or up to 200 listings in one call (onehome_bulk_get), both with per-row error capture.Neighborhood data — Local-Logic primary/high schools (
onehome_get_schools) and walk/transit/bike/car friendliness scores (onehome_get_walk_score) for a lat/lng.Run the math locally — PITI mortgage breakdown with tax/insurance/HOA/PMI (
onehome_calculate_mortgage) and 28/36 DTI max-affordability solver (onehome_calculate_affordability); no network calls.Raw access — send any read-only GraphQL document and variables to services.onehome.com via
onehome_graphql(mutations/subscriptions refused).Manage auth and sessions — check your profile (
onehome_get_user), register additional magic-link/JWT/email-token sessions across multiple agents or MLSes (onehome_set_auth), force which session is active (onehome_set_active_session), list all sessions and what they scope (onehome_get_session_context), and smoke-test auth + reachability (onehome_healthcheck).
Provides a read-only GraphQL escape hatch: pass a raw GraphQL document, an operation name, and variables, and the server returns the full unmodified response envelope (data, errors, status) from the OneHome GraphQL API. Mutations and subscriptions are refused, and a "full" view mode returns the payload byte-for-byte for debugging upstream schema behavior.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@onehome-mcp what homes did my agent save for me?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
onehome-mcp
MCP server for OneHome (CoreLogic) — search the listings your real-estate agent curated for you, fetch property details + photos, compare houses side-by-side, and run mortgage / affordability math from within Claude.
Sister project to zillow-mcp, redfin-mcp, compass-mcp, and homes-mcp. Same tool ergonomics — different upstream auth model.
This project was developed and is maintained by AI (Claude). Use at your own discretion.
What's different about OneHome
OneHome isn't a public listings site. Buyers usually reach it through a magic link an agent emails them — https://portal.onehome.com/...?token=eyJ.... That token query param IS the per-user bearer that the portal SPA hands to every GraphQL request.
So instead of routing every fetch through your signed-in browser tab (like the other realty MCPs), onehome-mcp talks directly to services.onehome.com/graphql from Node, with Authorization: Bearer <jwt> attached. We support three ways to source that bearer:
Mode | How to enable | Notes |
|
| Paste the raw bearer from devtools Network panel. Most direct. |
|
| Paste the full URL your agent sent — we extract the |
| (no env) + ContextMint Bridge browser extension installed (Chrome: load the release's chrome zip unpacked; Safari isn't available yet — it will ship inside the ContextMint app, so use Chrome for now) + signed-in | We wait for your tab to fire any GraphQL request, snapshot the Authorization header, and reuse it. |
ContextMint Bridge is the fetchproxy browser extension under its new name, from the same maintainer — fetchproxy's own README (fetchproxy#extension) points to it. Its source is public at nullnet-app/contextmint-bridge: build it yourself, or check a release zip against the .sha256 file published beside it (shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256).
Related MCP server: armls-spark-mcp-server
Tools
Tool | What it does |
| Smallest auth probe — returns your OneHome profile (name, email) and the groups your agent shared. |
| List the OneHome "groups" your agent has shared with you (each one a market / curated listing bucket). |
| Fetch an agent-curated saved search by id — name, filter criteria, polygon, and the OSK listing ids that compose the share. |
| The "show me my saved homes" flow in one round trip — saved search plus its inflated listings. |
| Listings within a group; optionally scoped to a saved search. |
| Free-text suggestion search (address, MLS #) across all feeds. |
| Resolve a single free-text street address to a listing's portal URL + id. |
| Bulk-resolve up to 100 structured addresses to portal URLs + listing ids; concurrent, per-row error capture. |
| Full property record by listing id or portal URL. |
| Fetch up to N listings in one call — one structured row per id, per-row error capture. |
| Full media gallery — Thumbnail / Medium / Large variants + room descriptions. |
| 2-8 listings side-by-side. Per-row error capture; calls are concurrent. |
| Local-Logic primary + high schools near a lat/lng. |
| Local-Logic walk / transit / bike / car friendliness scores. |
| Power-user escape hatch — send a raw read-only GraphQL document (queries only; mutations and subscriptions are refused) with variables. |
| Local PITI calculator. Same math as the other realty MCPs. |
| Local 28/36 DTI solver — max home price you can afford. |
| Add another authenticated session at runtime (magic link / JWT / email-token) for buyers holding shares across multiple agents. |
| Force a specific registered session to be the active one (overrides MLS-suffix routing). |
| List every registered session — auth mode, token expiry, and the group / saved-search / agent scope each bootstrapped. |
| End-to-end auth + GraphQL smoke check with token-expiry diagnostics. |
Install
The simplest path is the published Claude plugin (.mcpb install). Its settings take an optional OneHome magic link or bearer token (both stored as sensitive values); leave both blank to use browser-bridge capture instead. For local dev:
git clone https://github.com/chrischall/onehome-mcp
cd onehome-mcp
npm install
npm run buildThen point your MCP host at node /abs/path/to/onehome-mcp/dist/bundle.js with one of:
// claude_desktop_config.json
{
"mcpServers": {
"onehome-mcp": {
"command": "node",
"args": ["/abs/path/to/onehome-mcp/dist/bundle.js"],
"env": {
"ONEHOME_MAGIC_LINK": "https://portal.onehome.com/en-US/properties/map?token=eyJ..."
}
}
}
}Development
npm test # vitest, mocked transport, no network
npm run test:watch
npm run test:coverage
npx tsc --noEmit
npm run build # tsc --noEmit + esbuild → dist/bundle.jsTests use a FakeTransport (in tests/helpers.ts) that registers per-operationName handlers — there's no live network in the test suite. The tests/index.test.ts smoke check loads the same tool registrations src/index.ts uses against an in-memory MCP client/server pair, so "I wrote the tool file but forgot to wire it up" mistakes fail loudly.
License
MIT.
Available Tools
21 toolsonehome_bulk_getBulk-fetch OneHome listings by idARead-onlyIdempotent
Fetch up to 200 OneHome listings in a single call. Returns one structured row per input id (no side-by-side summary table — use onehome_compare_properties for that). Each row is either { listing_id, status: "ok", property } on success or { listing_id, status, error_kind, retryable, error } on failure (status = error_kind: timeout / bridge_down / pending are retryable, protocol / other are real misses) — one bad id never fails the whole call. Calls fan out concurrently against ListingById, capped at 6 in flight to avoid swamping the bridge; transient timeouts are retried once per row before being captured as an error. The whole call is bounded by an overall deadline: any row still unsettled comes back status: "pending" with a top-level pending count — re-run just those ids. The envelope reports count / ok / errored. extracted_features is populated per row automatically. The raw description (PublicRemarks) is omitted by default — pass include_description: true to keep it. group_id defaults to the magic-link session context.
Inputs: listing_ids (required), group_id, saved_search_id, include_description.
onehome_calculate_affordabilityCalculate max affordable home priceARead-onlyIdempotent
Solve for the maximum home price you can afford under the standard 28/36 DTI rule. Inputs: monthly income, recurring monthly debts (car loans, student loans, etc.), down payment, interest rate, and optional property-tax rate / insurance / HOA / loan term. Output: max home price, the binding constraint (front-end vs back-end), and the full PITI breakdown at that price. Same math across the realty MCP cohort (@chrischall/realty-core). No network — pure local math.
Inputs: down_payment (required), interest_rate (required), monthly_income (required), hoa_monthly, +6 more.
onehome_calculate_mortgageCalculate mortgage payment (local)ARead-onlyIdempotent
Local-only mortgage payment calculator. Returns a full PITI breakdown (principal + interest, property tax, insurance, HOA, PMI) and total interest over the life of the loan. No network call — fully deterministic, safe to use for scenario comparison without burning a fetch. Provide either down_payment OR down_payment_percent; defaults to 20%. Property tax can be given as property_tax_annual or property_tax_rate (% of home price). PMI applies automatically when LTV > 80% and pmi_rate is provided.
Inputs: home_price (required), interest_rate (required), pmi_rate, hoa_monthly, +6 more.
onehome_compare_propertiesCompare OneHome listings side-by-sideARead-onlyIdempotent
Fetch 2 or more OneHome listings and align their facts side-by-side. Each target may supply listing_id (preferred) or url (a portal URL). Returns the full per-property record (with extracted_features populated) per row. Per-target errors are captured per-row — one bad target will not fail the whole call. Calls are concurrent. The raw description is omitted from each row by default (include_description: true to keep it). The redundant summary table is also opt-in via include_summary: true — by default only rows[] is returned, which already carries every fact.
Inputs: targets (required), view, group_id, include_summary, +1 more.
onehome_get_by_addressResolve a OneHome listing by street addressARead-onlyIdempotent
Resolve a free-text street address (with optional city/state/zip) to a OneHome listing's canonical portal URL and id in one call. Walks a 2-rung ladder: (1) ListingSuggestionsSearch against the magic-link saved-search scope; (2) when that misses, search-fallback — page-walks the broader saved-search (or raw listings(groupId)) pool bounded by the same groupId and fuzzy-matches input address tokens. Returns { url, listing_id, address, resolved, matched_via } where matched_via: "suggestions" | "search_fallback" reports which rung produced the hit. When no listing matches, returns { resolved: false, error: "no listing found" } rather than throwing. Read-only; safe to call repeatedly.
Inputs: address (required), zip, city, view, +2 more.
onehome_get_groupsList my OneHome agent groupsARead-onlyIdempotent
List the OneHome groups your agent has shared with you. Share member e-mails and the agent's e-mail/phones are omitted unless include_contacts: true. For full agent / registered users, returns the GraphQL user.groups list. For magic-link consumer-share sessions (a single shared group), synthesizes a one-entry list from the checkToken session context.
Inputs: include_contacts.
onehome_get_propertyFetch full details for a OneHome listingARead-onlyIdempotent
Fetch full details for a single OneHome listing by id or portal URL. Returns address, list / close / previous price, $/sqft, beds/baths/sqft, lot size (raw lot_size {area, units} plus the derived lot_size_acres — null, never 0, for condos / lotless listings), year built, lat/lng, status, HOA fee, annual tax, virtual-tour URL, the primary photo, and an extracted_features block (lake_front, hot_tub, basement, furnished, dock, community) keyword-parsed from the description. The raw description (PublicRemarks) is omitted by default — pass include_description: true to keep it; in most cases the extracted features cover what callers need. OneHome scopes every listing to a group/market — group_id defaults to the magic-link session context; pass it explicitly only if you need to query a different group.
Inputs: url, group_id, listing_id, saved_search_id, +1 more.
onehome_get_property_photosFull photo gallery for a OneHome listingARead-onlyIdempotent
Fetch the full media gallery for a OneHome listing. Returns one entry per image with Thumbnail / Medium / Large CDN URLs, dimensions, the listing-room description (LongDescription), and display order. Pass either listing_id or a portal URL.
Inputs: url, group_id, listing_id.
onehome_get_saved_searchFetch a OneHome saved search by idARead-onlyIdempotent
Fetch the agent-curated saved search by its id (UUID). Returns the search's name, filter criteria (filters[]), polygon, listing count, and the full list of OSK listing ids that compose the consumer share (listing_ids). Pass include_listing_ids: false to suppress the listing-id array if you only need the metadata. This is the canonical consumer-readable endpoint; the by-groupId variant is agent-only. saved_search_id defaults to the MCP's session context when omitted.
Inputs: saved_search_id, include_listing_ids.
onehome_get_saved_search_with_listingsFetch a saved search and inflate its listings in one callARead-onlyIdempotent
Combo tool: the "show me my saved homes" flow in a single round trip. Internally runs GetSavedSearchBySearchId to fetch the saved search (name, filters, polygon, listingIds) and then GetSavedListings to inflate those listingIds into full property records — the same two-call sequence as calling onehome_get_saved_search followed by onehome_search_properties(saved_search_id=...), but exposed as one tool so the magic-link-to-listings consumer flow is a single MCP call. Returns { saved_search, listings, count, page_info }. Both saved_search_id and group_id default to the magic-link session context. Sort defaults to property.MajorChangeTimestamp DESC (Newest). Listings are returned via the GraphQL listing-card projection (buildGetSavedListings), which does NOT include PublicRemarks — so there is no raw description to opt back into here. Use onehome_get_property(listing_id) per row when you need the full description for a specific listing. view: "brief" answers one line per listing instead: address · price — date of its last change — status, change (e.g. a new listing or a price decrease), inside the untrusted-data envelope as data: string[], with -- none for an empty saved search and -- N of M shown when the page holds fewer listings than the search.
Inputs: view, group_id, page_num, page_size, +4 more.
onehome_get_schoolsLocal-Logic primary + high schools near a lat/lngARead-onlyIdempotent
Fetch the Local-Logic school data for a coordinate — separate primary and high-school lists, each entry with name, attributes (types/grades/programs/levels), and proximity (walking distance + straight-line distance). Returns an error field with HTTP details if the consumer session does not have access (the schools endpoint is sometimes agent-only). lat/lng usually come from onehome_get_property (latitude / longitude).
Inputs: lat (required), lng (required), language.
onehome_get_session_contextInspect every registered OneHome sessionARead-onlyIdempotent
Returns one entry per registered session — its session_id, auth_mode, token expiry, and session scope (group_id / saved_search_id / agent_id / contact_id / mls_id) the MCP bootstrapped from each checkToken exchange. active_session_id flags which session answers by default; per-listing routing uses the active session when its mls_id matches the listing's ~MLS suffix, else the one session that matches (several matches error — pick one with onehome_set_active_session). Tools default unspecified group_id / saved_search_id arguments from the active session's context, so this is the easiest way to see what they'll default to. Single-session use (the common case) returns a one-entry sessions[].
Inputs: no named parameters.
onehome_get_userGet the signed-in OneHome user profileARead-onlyIdempotent
Returns the OneHome user profile + the consumer-share groups attached. Share member e-mails and the agent's e-mail/phones are omitted unless include_contacts: true. For full agent / registered users, queries the GraphQL user endpoint. For magic-link consumer-share sessions (where user { } is access-denied), falls back to the data captured during the checkToken exchange — email, contact id, group/savedSearch ids, and the agent who shared with you.
Inputs: view, include_contacts.
onehome_get_walk_scoreLocal-Logic location scores near a lat/lngARead-onlyIdempotent
Local-Logic location scores for a coordinate — pedestrian / car / cycling / transit friendliness, plus proximity summaries for groceries, restaurants, parks, primary + high schools. Each score is a { value, text } pair (value 0-5, text a one-line description). Returns an error field with HTTP details if the upstream rejected the request.
Inputs: lat (required), lng (required), language.
onehome_graphqlSend a raw GraphQL document to services.onehome.comARead-only
Power-user escape hatch — send a raw GraphQL document with variables. Returns the whole { data, errors, status, url } envelope, unprojected, so you can read upstream schema errors directly. Note the default: view is compact, which strips image/avatar URLs out of data (every envelope key and every non-media field is kept). Pass view: 'full' when you need the envelope byte for byte — worth doing if you are here because a payload is not what you expected, so a missing field is never this server's doing. Operation names live in the portal bundle; common ones include GetOneHomeUser, GetListings, GetPins, ListingById, MediaListingById, GetSavedSearches, ListingSuggestionsSearch. (LocalLogic schools/walk-score are REST endpoints, not GraphQL operations — use onehome_get_schools / onehome_get_walk_score.) Pass query (the full document body), an operation_name matching the document, and any variables as JSON. Read-only: documents containing a mutation or subscription operation — or that cannot be parsed as a read-only query document — are refused.
Inputs: query (required), operation_name (required), view, variables.
onehome_healthcheckVerify OneHome auth + GraphQL reachabilityARead-onlyIdempotent
Round-trip a minimal authenticated query through the configured transport. Picks GetSavedSearchBySearchId for magic-link consumer-shares (works for them) or GetOneHomeUser for agent/registered sessions. Returns the auth mode, token expiry, fetchproxy bridge role (when applicable), elapsed time, and any error detail. Run this first when a tool fails — it isolates "is auth wired up?" from "is the API itself misbehaving?".
Inputs: no named parameters.
onehome_resolve_addressesBulk-resolve street addresses to OneHome URLs + listing_idsARead-onlyIdempotent
Resolve up to 100 structured addresses to OneHome canonical portal URLs + listing OSK ids in one call. Each input is a {address, city?, state?, zip?} object. Output preserves input order; one row per input, either {resolved: true, url, listing_id, address} or {resolved: false, error, query}; a row that failed (rather than genuinely missed) also carries status = error_kind and retryable — timeout / bridge_down / pending mean retry it, not "no listing". The whole call is bounded by an overall deadline; unsettled rows come back status: "pending" with a top-level pending count. Walks the exact same 2-rung ladder as onehome_get_by_address via the shared helper (rung 1: ListingSuggestionsSearch against the magic-link saved-search scope; rung 2: search-fallback page-walking the broader saved-search / raw-listings pool bounded by groupId) — bulk and single cannot diverge. Each row surfaces matched_via: "suggestions" | "search_fallback" so callers see which rung produced the hit. Concurrent fan-out capped at 6 in flight to avoid swamping the upstream. Per-row errors captured — one bad address never fails the whole batch. group_id defaults to the magic-link session context. Read-only; safe to call repeatedly.
Inputs: addresses (required), group_id.
onehome_search_propertiesSearch listings inside a OneHome group / saved shareARead-onlyIdempotent
Fetch listings inside a OneHome consumer-share. Two modes:
With
saved_search_id: fetch the agent-curated collection (the standard 'Homes at ' view). The MCP first resolves the saved search's listingIds and then inflates them via listingsBySavedSearchId — this is the only mode that works for non-agent consumer accounts.With just
group_idand nosaved_search_id: try the rawlistings(groupId, browseParameter)endpoint. If page 0 comes back empty with no reported results (the access-restricted shape consumer-shares hit) AND the session context has asavedSearchIdfor that same group, the tool falls back to the saved-search path and marks the responsefell_back_to_saved_search: true. If there's no fallback target it raises a clear error rather than silently returning empty. An empty later page (paging past the end) is returned as an empty page, never swapped for the saved-search collection.
Both args default from the MCP's bootstrapped session context (the magic-link checkToken response) when neither is passed explicitly. Sort is MajorChangeTimestamp DESC ('Newest') unless overridden. include_dislikes: false by default — flip it on to include listings you've thumbs-downed in OneHome.
Listings here are returned via the GraphQL listing-card projection, which does NOT include PublicRemarks — so there is no description field on search results and no include_description flag to opt into one. Each listing carries the structured extracted_features object instead. Use onehome_get_property(listing_id) per row when you need the full description for a specific listing.
Inputs: group_id, page_num, page_size, sort_field, +3 more.
onehome_search_suggestionsFree-text suggestion search across MLS feedsARead-onlyIdempotent
Cross-feed suggestion search by address, MLS number, or partial query. Bypasses the group/saved-search structure and hits the global suggestion endpoint — useful for "find an address" or "look up by MLS number". Returns id, address parts, beds/baths, list price, thumbnail per match. Inflate any result with onehome_get_property. Optional group_id scopes suggestions to one OneHome market.
Inputs: query (required), group_id.
onehome_set_active_sessionSwitch which registered OneHome session is activeAIdempotent
Force a specific registered session to be the active one. Useful when MLS-suffix routing picks the wrong session (e.g. two shares in the same MLS, a free-text search across multiple MLSes, or a listing without a ~MLS suffix). Pass a session_id previously returned by onehome_set_auth or surfaced in onehome_get_session_context. The active session answers any request without a ~MLS-suffixed listing id AND any ~MLS request whose MLS matches its own; a ~MLS id matching several other sessions errors until you pick one here.
Inputs: session_id (required).
onehome_set_authRegister an additional OneHome session at runtimeADestructive
Provide a magic-link URL, a raw JWT bearer, or an email-token to ADD another authenticated session to the MCP — useful when a buyer holds shares across multiple agents/MLSes (one magic link per share). The MCP detects the input shape (URL → extract ?token=; 3-segment JWT → use directly; otherwise → treat as email-token and exchange via /api/authentication/checkToken), registers a new direct-bearer transport, and marks it active. Previously-registered sessions stay registered — switch back with onehome_set_active_session(session_id), or let MLS-suffix routing (~CANOPY, ~HCAOR, …) pick automatically per listing. The response includes the assigned session_id, the new active_session_id, the auth_mode/status, the session_context the checkToken response yielded, and a bearer_fingerprint of the resolved JWT (first 8 + … + last 4 chars) — never the full bearer. SECURITY: the input itself sits in your chat history; treat magic links as short-lived credentials.
Inputs: input (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 21 tools
Most tools have clearly distinct resource/action targets, but there is overlap between `onehome_get_saved_search_with_listings` and the explicit `onehome_get_saved_search` + `onehome_search_properties` two-step flow, and between address-resolution tools (`onehome_search_suggestions`, `onehome_get_by_address`, `onehome_resolve_addresses`). The descriptions clarify intended use, but an agent could still reasonably hesitate between these related paths.
The server maintains a strong `onehome_` prefix and mostly consistent snake_case verb-noun patterns (get_property, search_properties, calculate_mortgage). Minor deviations like `onehome_bulk_get` (noun-verb order) and `onehome_healthcheck` (noun rather than verb phrase) keep it from perfect consistency.
At 21 tools, the surface is on the heavy side for a consumer real-estate share server. Most tools earn their place, but the combo tool plus its constituent tools, and three separate address-resolution tools, contribute to a somewhat bloated surface.
The read-oriented consumer-share domain is well covered: property details, photos, schools, walk score, search, saved searches, bulk/compare operations, mortgage/affordability math, and session/auth management. Minor gaps exist around listing history or richer market data, but no obvious dead ends for the primary consumer workflows.
Maintenance
Related MCP Connectors
US property search and full listing detail (Redfin-sourced) as agent tools.
Redfin property search and full listing detail as agent tools.
Real estate CRM for Claude and ChatGPT: find leads and listings, report on pipeline, log follow-ups.
Search SimplyRETS MLS listings and open houses; read listing and market analytics.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides real-time access to Zillow real estate data, enabling property search, details, Zestimates, market trends, and mortgage calculations via natural language.6 npm56MIT
- FlicenseNot gradedqualityDmaintenanceEnables Claude to query ARMLS Spark/FlexMLS real estate data including active listings, comparable sales, market statistics, and open houses via MCP tools.-
- AlicenseAqualityAmaintenanceEnables natural language access to Redfin real estate data, including property search, details, photos, market reports, price history, climate risk, and saved homes/searches, by routing requests through your own signed-in browser session.22523 npm3MIT
- AlicenseAqualityAmaintenanceCompass real-estate access as an MCP server for Claude — search listings, fetch property details, photo galleries, price history, and run affordability/mortgage math, all via natural language.18329 npmMIT