-
-
-
Same brief, prompt-only versus map-grounded New Orleans.
-
Real OpenStreetMap geometry locked for Lower Manhattan
-
Ten typed WebMCP tools exposed directly by the page
-
Six native calls completed with visible execution receipts
-
The agent stops before paid image generation
-
Editorial montage made from authentic production captures
Inspiration
AI image models can draw maps that look authoritative while inventing streets, landmarks, and spatial relationships. That is harmless as wall art, but dangerous when somebody might plan from it. I built MapTruth to make the real place—not the model—the source of geographic truth, while still letting an AI do what it is good at: interpreting intent and styling evidence.
What it does
Ask an image model for a map of a real place and it can draw something beautiful, confident, and geographically false. MapTruth changes the input to that process. A person chooses a place and writes a brief; MapTruth locks a live OpenStreetMap view, resolves requested features against OpenStreetMap, and generates two images side by side: one from the prompt alone and one grounded in the sourced map.
The comparison makes the failure mode visible. In the New Orleans demo, the ungrounded result invents a plausible city. The grounded result preserves the large-scale relationship among Lake Pontchartrain, the city, and the Mississippi River, and marks only places resolved within the locked view.
Why WebMCP
The page—not the model—owns the map and its invariants. Through
document.modelContext.registerTool, MapTruth exposes ten typed browser tools
for focusing a place, navigating, inspecting and locking the live map, marking
features from OpenStreetMap, verifying geography, and staging a comparison.
An agent calls those tools directly instead of interpreting a screenshot or
scraping UI text.
That changes what an agent is allowed to invent. The model may decide what kinds of places a brief needs, but it never supplies their coordinates. OpenStreetMap locates them. Anything that cannot be resolved inside the locked view is dropped and reported rather than approximately placed.
The app's visible six-step assistant walkthrough uses WebMCP's native
executeTool() path when it is available, so judges can watch the agent call
the same registered tools that another browser agent discovers. It leaves a
receipt for each action and stops at the human approval gate before any paid
image generation.
A better user experience
Without WebMCP, an assistant would have to guess from pixels or automate fragile controls. Here it receives named, typed capabilities and compact structured results. A person can see the same state, source attribution, verification counts, geometry hashes, and approval boundary the agent sees. The interface also has a manual fallback, so the product remains usable in a browser that does not yet expose WebMCP.
What people and agents do together
- The person chooses the real place, states the purpose, and approves cost.
- The agent turns that intent into a sequence of explicit browser-tool calls.
- OpenStreetMap supplies locations and geometry.
- MapTruth rejects unsupported places, verifies the locked evidence, and records tool receipts.
- The image model styles the evidence; it does not supply the evidence.
How it was built
MapTruth is a React and TypeScript application built with Vite. MapLibre GL JS renders the live map. Nominatim resolves the requested city; Overpass provides nearby OpenStreetMap features. The browser integration registers ten WebMCP tools with JSON schemas, annotations, bounded outputs, and untrusted-content hints. Vercel Functions proxy the external services and image generation.
Examples use checked-in snapshots captured from the same live pipeline so a
demo does not stall on a public service. A separate verification script launches
installed Chrome with WebMCP enabled, discovers all ten tools through
document.modelContext.getTools(), and executes inspect_map_context through
the browser's own document.modelContext.executeTool().
Challenges
The difficult part was not drawing a map. It was defining a trust boundary an agent could not casually cross: the model can name candidates but cannot set a coordinate; geometry must belong to the current locked place; stale locks must be rejected; and paid generation must require visible human approval. Public geocoding and Overpass services also vary in latency, so the experience needed deterministic examples without pretending they were a separate data path.
Accomplishments
- Ten discoverable WebMCP tools operate a real map workflow rather than a toy counter or hidden demo route.
- Native discovery and execution are tested in installed Chrome, with no mocked model context in the production verifier.
- Every generated comparison has a visible source line and OpenStreetMap inspection link.
- Agent activity is legible to the person and stops before cost.
- The same app remains usable manually when WebMCP is unavailable.
What I learned
Reliable agent UX comes from moving important guarantees out of prompts and into the page's tool contract. Structured tools make collaboration clearer, but the strongest result comes from deliberately limiting each participant: the model names, OpenStreetMap locates, the page verifies, and the person decides.
What's next
Next I would add saved, shareable evidence bundles; compare OpenStreetMap changes over time; and support more source layers while keeping the same provenance contract. The most useful extension is not more autonomous drawing, but better ways to inspect why a place was accepted or rejected.
Honest limits
MapTruth verifies that generation received geometry derived from the current OpenStreetMap view. It does not claim that every generated pixel is cartographically exact or that OpenStreetMap is perfectly complete or current. The prompt-only image is deliberately untrusted. Example snapshots are marked as snapshots; typing a new city exercises the live service path.
Built during the challenge
The repository was created on August 26, 2026 and its first commit is dated the same day, after the challenge submission period opened on August 25. The full implementation history is visible in the public commit log.
Built With
- github
- maplibre
- openstreetmap
- react
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.