Why this use case fits WebMCP
Planning a trip with an AI today is a copy-paste loop: the model writes a text itinerary, the human re-enters it into a maps app, and neither side ever sees the other's current version. An itinerary is exactly the shared, structured, spatial state WebMCP was made for: the page holds one live map and one schedule, and document.modelContext.registerTool hands the agent the same editing operations the human's buttons call. No server, no API keys — the page is the interface for both actors.
How it improves the user experience
- One truth. Agent tool calls mutate the same store the human edits, so the map and timeline always show the current trip.
- Reviewable AI. Every agent change is applied-but-pending — amber highlight, per-edit Revert, Accept all; editing a pending stop accepts it implicitly, so review never blocks flow. One undo history covers both.
- Real schedules, not wish lists. The page computes place resolution, walk/drive matrices, day clustering, ordering and timed schedules deterministically; the agent contributes names and judgment (
get_planning_guide), never arithmetic. - The agent sees the collaboration.
get_itineraryreturns the timed trip plus what the human changed since its last read plus which of its edits are still pending;get_changesis a revision feed with per-edit fates (pending / accepted / reverted).
What people and agents can now do together — that was difficult or impossible before
Before: the model writes a text itinerary, the human re-types it into a maps app, and every correction is another paste. Now: one live map and schedule that both edit through the same operations, with the agent's changes reviewable in place and its next read showing what the human did.
Ask it to plan 3 days in Tokyo and watch pins drop (plan_trip, ≤12 names, one atomic pending batch). Drag a stop or kick one out — the agent reads your correction and fills the gap (add_place). Tell it you won't have a car and it switches every non-walkable leg to live transit, naming the line and the stop to get off at (set_leg_mode, MOTIS routes — including the ride back to your hotel). Compare a leg by walk / drive / transit before committing (get_leg_options), anchor a different hotel per night (set_lodging), rebalance days (arrange_days, the same function as the human's button), fix an overpacked evening (set_times), or let it clean up after itself (revert_pending) — while you keep dragging, searching and undoing on the same canvas.
How WebMCP was implemented
- Imperative registration only, once, at module scope in the top-level document before React mounts — StrictMode/HMR-safe, feature-detected as
typeof document.modelContext?.registerTool === "function". Without WebMCP the page runs as a plain manual planner with a notice. - Twelve tools (
get_itinerary,get_changes,get_leg_options,plan_trip,add_place,move_stop,set_times,set_leg_mode,set_lodging,arrange_days,revert_pending,get_planning_guide), all inside Chrome's recommended budgets — names ≤30, descriptions ≤500, param descriptions ≤150, results ≤1,500 chars — enforced by an automated audit test.readOnlyHinton the read tools;untrustedContentHintmarks exactly the tools whose results carry external text (Nominatim names, MOTIS headsigns). - Every tool execute is a thin adapter: zod-parse → the same exported store action the UI button imports → result string. Failures are explanatory
ERROR: ...strings; tools are never unregistered. - 30-second budget respected:
plan_tripresolves ≤12 names serially through one app-wide Nominatim queue (≥1.1 s spacing, geocache, 8 s timeout clipped to the deadline) under a 22 s wall-clock deadline that the OSRM phases share. - Pure static site: Nominatim, OSRM and transitous/MOTIS are called directly from the browser; every failure degrades to marked-approximate times or a soft error — the itinerary never blocks.
Try it
Open https://tripcanvas.tillmac.com in Chrome 149+ (the origin-trial token is shipped; or enable chrome://flags/#enable-webmcp-testing) or in the ChatGPT desktop browser with Site tools enabled, then ask your agent: "Plan 3 days in Tokyo — temples, museums, Shibuya and teamLab — we're staying at Hotel Gracery Shinjuku." The "What the agent sees" panel under the schedule prints the exact get_itinerary text live.
Prior work vs. new work
The pure itinerary math (schedule computation, best-insertion, geo, OSRM/MOTIS/Nominatim builders and parsers) and the Leaflet map pane are ported from my pre-challenge project intent-transition-mcp (a Claude-connector MCP server, June–July 2026) and live separated in src/ported/. Everything WebMCP is new for this challenge (2026-08-25 →): the tool layer, the headless trip store with its by-id inverse log (= undo stack = change feed), the pending-edit model and [s#]/[c#] ids, day clustering + arrange, per-night lodging, the Nominatim queue, plan_trip orchestration, transit leg overrides, the handback renderer, and the co-editing canvas UI. Source (MIT): https://github.com/TillMac/tripcanvas
Built With
- leaflet.js
- motis
- nominatim
- openstreetmap
- osrm
- react
- tailwind
- typescript
- vite
- webmcp
- zod
- zustand
Log in or sign up for Devpost to join the conversation.