Lakeshore Air
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., "@Lakeshore AirText Keren my new arrival time."
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.
Lakeshore Air: an MCP App with two faces
The demo from "The App Inside the Chat" (MCP Dev Summit Toronto, 6 Oct 2026, Keren Fanan and Hadar Geva, Myop).
A made-up airline's "Manage my trip", inside the chat. A customer's flight is delayed. They pick a new flight in the app and press Change, then ask the chat: "Text Keren my new arrival time." It's built on plain @modelcontextprotocol/ext-apps 2.x (MCP Apps, SEP-1865), with no vendor in the path.
What it shows
An MCP App has two faces:
The model's context: the tool results the model reads.
The user's eyes: the
ui://page the host renders.
A view's tools/call result goes back to the view, never to the model. So after the customer changes the flight in the view, the model's next write is built from the old trip: the text says 14:13 instead of 11:28.
The fix measured here: the write carries the version it was built from, and the server refuses an old one.
isError: Not sent. The trip changed after you read it: your message is based on v1-QPHE, the trip is now v2-PZ8H.
Now: LK 418 ... arrives 11:28. Rewrite the message from the current trip, then send it again with tripVersion v2-PZ8H.Tool | Who calls it | What it does |
| model (and app) | the trip, for the model; renders the view |
| model | the current trip and its version |
| model | texts a saved contact; takes |
| app only | the booking and same-day flights, for the view |
| app only | the customer's Change button: idempotent, audited |
Pages:
Page | What it is |
| the airline's own web page |
| the contact's phone, where the texts land |
| the presenter's switches |
The two server-side switches:
Freshness line: a hint added to every result the model gets.
Version check on writes: the fix.
Two view switches, for trying the spec's own bridges on a real host (both off by default):
View hand-off: after Change, the view calls
ui/update-model-context(app.updateModelContext).View message: after Change, the view calls
ui/message(app.sendMessage) with "I changed my flight to LK 418, arriving 11:28." On claude.ai (6 Oct 2026) it landed in the composer unsent, under a caution banner, and waited for the user to press Enter.
Related MCP server: tutu-compass
Run it
npm install
npm start # builds the view, serves on :3071 under /usermcp
npm run reset # the trip: LK 412 delayed, v1, no texts, switches off
npm test # protocol e2e against the running serverURL | What |
| MCP endpoint (stateless Streamable HTTP, no auth) |
| airline web page (the PIN enables its Select buttons) |
| the contact's phone |
| presenter console: Reset, freshness line, version check, view hand-off, view message |
Environment variables:
Variable | Default and meaning |
| 3071 |
|
|
| the public origin |
|
|
|
|
| the clock shown in the app, e.g. |
| adds the canary tool |
To try it in Claude: expose the endpoint over HTTPS and add it as a custom connector (no sign-in). Then open the connector's page and press Connect; a new custom connector gets no tools in chats until you do. Reconnect after every redeploy, because hosts cache the tool list.
To see the view without Claude: use the reference host, ext-apps/examples/basic-host, with SERVERS='["http://localhost:3071/usermcp/mcp"]'.
The flow from the talk
"My flight to SF tomorrow got delayed. Show me my trip and my options." The model calls
my_trip, and the trip renders in the chat.In the view, pick 09:10 (LK 418) and press Change. The view calls the app-only
change_flight, and the model never sees it."Text Keren my new arrival time."
With the version check off: the text says 14:13.
With it on: the first send is refused, and the model rewrites with 11:28.
Tests and measurements
npm test (test/e2e.ts) runs a real MCP client that plays both users. It checks:
tool visibility;
the bundled view resource;
part 1: the stale text gets through;
part 2: the stale write is refused, and the rewrite is sent;
the freshness line in both channels;
that a guessed version is refused;
strict schemas;
per-customer isolation.
npx tsx test/rehearsal.ts <runs> <nothing,line,guard,both> [parallel] is the measurement behind the talk's numbers. It runs real Claude models through headless Claude Code, which has no view, so the change is made through the same app-only tool the view uses. MODEL picks the model (default claude-sonnet-5).
results/ holds the raw runs:
The 30 Sep runs used an earlier wording of the same flow: Vancouver as the destination, and "Dana" as the contact. Flights, times and versions are identical.
claudeai-handoff-sonnet5-2026-10-05.jsontests the spec's hand-off (ui/update-model-context) on claude.ai. The host accepted it, yet 2 of 3 texts still had the old time.
Before you run this anywhere public
This is a demo. The bearer token stands in for the customer. Before you keep it up anywhere public:
Use a real OAuth provider.
Set
allowedHostson the Express app.Add per-customer rate limits.
Set your own
PRESENTER_PIN.
License
MIT, see LICENSE. The bundled font, Instrument Serif, is licensed under the SIL Open Font License.
This server cannot be deployed
Maintenance
Related MCP Connectors
Hosted MCP messaging across owners, tools, and machines, with readable transcripts.
Flight search MCP server providing search, pagination, and itinerary details for AI assistants.
MCP server for Travel & Transportation
Aggregated travel MCP — flights, tours, activities, price checks, visas, and more.
Related MCP Servers
- AlicenseAqualityDmaintenanceA full-stack travel booking MCP server that enables AI clients to search flights, make reservations, cancel bookings, and manage persistent state across sessions.912 npm5MIT
- AlicenseNot gradedqualityCmaintenanceA travel negotiation agent for Russian trips that turns one natural-language request into a plan_trip MCP tool, surfacing budget-vs-connection trade-offs and offering instant plan B rerouting.MIT
- AlicenseNot gradedqualityBmaintenanceMCP server for travel-planning agents to create and manage concise Markdown briefs and validated structured trip documents, without booking or altering travel.MIT
- AlicenseNot gradedqualityBmaintenanceEnables interactive trip planning and booking through MCP Apps cards, with constraint-based scoring, cross-session memory, and a two-phase booking flow that requires explicit confirmation before charging.MIT