Skip to main content
Build a Zillow-style MCP App: listing cards next to an interactive map with price pins. The model opens the view once with search-homes. After that, the view registers its own tools, so follow-ups such as “now the Mission, under $2M” update the open map instead of rendering a second view. The listings are fictional San Francisco homes. Map tiles come from Esri’s keyless Canvas basemaps, so the example needs no listing API or API key.

Try the live example

Ask for homes in San Francisco. Select Fullscreen in the view to see the listing cards, then click a card or pin to load its details.
Open the example in a new tab.
This embedded chat runs its model on Manufact’s servers, which cannot reach tools registered inside the view. Follow-up refinements such as “now the Mission, under $2M” need a host that forwards view tools to the model. To try them, run the example with your own model provider API key.

Run the example

The example is a complete project with about 3,500 lines of view code, so clone it instead of copying it. It requires Node.js 22.22.2 or later.
Open the Inspector URL printed by the CLI, select Chat, and configure a model provider with your own API key. The Inspector forwards view tools to the model only in this mode; the managed Manufact model cannot call them. Send these prompts in order:
The first prompt calls search-homes and opens the view. Each later prompt calls a view tool, and the open map updates in place. Select Fullscreen in the view to switch display modes. The project has four main files:

How it works

The example combines five MCP Apps patterns. Each one works on its own in your server.

Open the view once with the whole dataset

search-homes is the only tool that renders the view. Besides the matching listing IDs, it returns the whole staged catalog in structuredContent, so the view can filter any neighborhood locally without another server call. The tool description tells the model to use the view tools for follow-ups instead of calling search-homes again.
src/index.ts
This excerpt is shortened. The example also accepts minPrice and minBaths filters and returns the median price.

Let the model drive the open view

useViewTool() registers a tool that exists only while the view is mounted. The host lists it to the model, and the handler runs inside the view with access to React state and refs. The example registers seven view tools. This one zooms the Leaflet map:
views/property-search/view.tsx

Keep the model in sync with the view

Users also filter, remove, and select homes by clicking. <ModelContext> reports the current view state to the model, so “remove the most expensive one” refers to what is on screen now:
views/property-search/view.tsx

Load details with an app-only tool

get-listing-details has visibility: "app", so MCP Apps hosts hide it from the model while the view can still call it. The view calls it with useCallTool() when the user selects a card or pin:
src/index.ts
views/property-search/view.tsx

Allow map tiles and fullscreen

The view loads tiles from server.arcgisonline.com, so the tool’s view.csp lists that origin in resourceDomains and connectDomains. Without it, the host’s Content Security Policy blocks the tiles and the map renders blank. The view declares both display modes in viewConfig and requests fullscreen from a button with useDisplayMode():
views/property-search/view.tsx

Adapt it to your app

  • Real listings: replace the staged LISTINGS array with a call to your listing API inside search-homes. Keep the returned catalog small. For large datasets, return only the first page and fetch more from the view with an app-only tool.
  • Another tile provider: change the tile URL in map.tsx, update both CSP lists, and show the attribution your provider’s terms require.
  • Other domains: the same shape fits any “search, then refine” app, such as hotels, restaurants, or job listings. Keep one rendering tool, move refinements into view tools, and report visible state with ModelContext.
See the complete property search example for the runnable project, and Interactivity for more on view tools, app-only tools, and follow-up messages.