Inspiration
Gildongmu means "traveling companion" in Korean. I started it in June 2026 to fix a small, stubborn problem of my own as a screen reader user: I wanted to look up an address and call a place as fast as possible. Map apps make both slow, because their answers live in an interface built around images.
So Gildongmu has no map at all. Everything it knows, it says in words: places, routes, what is around you, and the accessibility details a screen reader user actually needs, such as station elevators, audio beacons, accessible restrooms, stairs-free walking routes and crosswalks with audible signals. Almost all of that comes from Korean public data.
When I read about WebMCP, I realized that this had quietly prepared the app for agents. Every sentence a screen reader user hears is a sentence an agent can be handed. This entry is what happened when I handed them over.
What it does
Gildongmu is a free navigation app for South Korea with no account and no ads, on the web, on iOS, and as an npm command line tool and MCP server. It joins about thirty public and commercial APIs from nineteen organizations and turns them into plain text. As far as I know, it is the first navigation app in Korea where a screen reader user can search places, plan a trip and explore the surroundings with no barrier in between.
For this challenge the web app declares seven WebMCP tools to the browser agent:
- describe_app: what this deployment can do and how the tools chain
- search_places: places, addresses and web results, with refs to pass on
- get_place_info: a place by ref; for stations the timetable, accessibility facilities, live arrivals and barrier-free facilities
- plan_directions: transit, walking and driving summaries for a destination
- get_transit_route_detail: one transit route in full, including the boarding door for a quick exit
- get_route_steps: walking or driving steps as a numbered page
- read_current_view: which screen the app is on and what it shows
Ask the agent "Tell me the first train, the last train and the elevators at Gangdong Station (강동역)" and one tool call brings all of it back. Ask "Seoul Station (서울역) to Gangnam Station (강남역): which car and door should I board to get off next to the elevator?" and while the agent answers, the app in the browser tab has already moved to that route, so the user can turn on VoiceOver and check every line.
Why this use case is a strong fit for WebMCP
The answers were already text. Most navigation apps keep their answer in pixels, so an agent driving a browser has to guess at a canvas. Gildongmu had to write every answer as a sentence for VoiceOver users long before it ever met an agent. Those same sentences are what the tools return, and they come from the same code that draws the screen. The agent cannot be told something the screen does not say.
Neither a plain browser agent nor a server MCP can do this alone. Behind one station answer are four public APIs, each with its own key, its own response format and, in Korea, its own coordinate system. An agent reading the page cannot rebuild that. A server MCP, on the other hand, cannot answer "where am I standing right now", because it has no browser tab. WebMCP sits exactly in between: the page keeps the keys and the location, and the agent asks in words.
Location stays in the browser. A trip starts from the user's current position, which the page already knows. Tool output goes through a list of allowed fields that has no place for coordinates, so the agent's provider receives place names and sentences, never a coordinate pair. Gildongmu has promised since its first release that nothing personal is stored on its servers, and the tools keep that promise.
How it creates a better user experience
For a screen reader user the expensive part is not reaching a screen, it is exploring it. A transit plan on screen is dozens of items, one swipe at a time. As a tool result it is one spoken answer, and the app has still moved to that same screen, so the user can take over and verify anything.
The size of an answer follows the same instinct. A full transit answer came out at 3,700 characters, far past the 1,500 the guidance recommends. Instead of cutting it off, I split it the way I would say it out loud: the recommended route in full, the other routes in one line each, and the details behind a second tool.
Nothing got worse for people. The tools press the same functions a person clicks, and a person always wins. Type a new search or close a section while a tool is running and the tool call ends as superseded. If a dialog is open, the tool declines instead of closing it.
What people and agents can do together that was difficult or impossible before
- "Which car and door do I board so that I get off next to the elevator?" Gildongmu matches a public quick exit dataset to the live route, so get_transit_route_detail returns the boarding door for each leg. No map tells you this. Ask it in the chat, and the app is already sitting on that route.
- "Does Gangdong Station have an elevator, and when is the first train?" One call to get_place_info returns the timetable, the accessibility facilities, the real time arrivals and the barrier-free facilities. Without WebMCP the agent would open four sections one by one, and it could not call the four public APIs behind them at all.
- The handoff goes both ways. The agent and the user share one screen: the tools move the app, and read_current_view reads whatever the person did by hand. The agent can set up a trip that the user finishes by touch, or the user can search by hand and then ask the agent about what is on the screen. Before this, asking an assistant and using an app were two separate places that did not know about each other.
- Honest absence. Every tool tells apart "none", "not known" and "lookup failed", and says outOfCoverage outside Korea instead of inventing a result. A screen reader user cannot glance at a screen to catch a made up answer, so the tools never let the agent guess. The app has followed the same rule for people since version 1.0.
How I implemented WebMCP
I used the imperative API, document.modelContext.registerTool with a name, a description, an input schema and an execute function. Here is how I understand what I built:
- One set of seven tools, registered once at the app root, because an agent reads the tool list once. A tool that is not configured on this deployment is still declared and answers notConfigured. A tool that needs another screen moves there itself.
- Each screen publishes a small bridge to a registry, and a tool reads it at the moment it runs. A tool that waits for a screen waits for a specific place id or sequence number, not for a screen name, so a call about place A cannot be satisfied by place B appearing first.
- Only one tool runs at a time, with a 30 second cap. A place handle is an opaque ref that remembers which search it came from, and a handle from a replaced search returns staleResult with the call that recovers it, rather than pointing at the wrong place.
- Every output leaves through one function. It keeps only the allowed fields, refuses coordinates, trims to the 1,500 character budget item by item, and pages a long answer with an offset. Calls to paid third party APIs are budgeted per provider.
- The human sentences come from the same modules the screen uses, so the screen and the tools cannot drift apart.
It is covered by 19 test files and 104 tests. I checked the contracts by deliberately breaking the implementation and confirming that the tests caught each break, and I checked the deployed site with Chrome DevTools WebMCP inspection.
Challenges I ran into
- How many tools to expose. My first design registered tools per screen, ten in all (nine on the directions screen, one on the home screen), and along the way I weighed going much further: four screen-specific sets adding up to 31 tools, or simply re-exposing the 24 tools my Gemini chat already had. Research pulled the other way. Real sites declare one to ten tools, and both OpenAI and Anthropic advise a small number of high-value tools. I settled on seven, always on, at the app root. Gildongmu is already screen reader friendly, so browser navigation and tool calls can share the work, and seven is a number an agent handles without strain.
- Whether to move the cursor. An early tool moved the screen reader cursor to the item the agent had found. I removed it. What a screen reader user wants from an agent is not help exploring the screen but the exact data, fast, without exploring at all. The tools now return answers, and the screen follows on its own.
- English. Gildongmu supported English before, but unevenly: transit lines, station names, place categories and many status lines still came through in Korean. For this challenge I overhauled English support across the web app, iOS and the CLI, so the agent's English answers and the English screen now say the same thing.
Accomplishments that I'm proud of
- The information a screen reader user needs to get around, from station elevators to the boarding door, is now one question away for an agent, and the same screen is one tap away for the person.
- The seven tools return exactly the text the screen shows. There is no separate agent copy of the answers to drift.
- Coordinates never leave the browser, and that is enforced by the code, not by a promise.
What I learned
The accessibility contract and the agent contract turned out to be the same contract. Every rule I had written for screen readers, that text is the source of truth, that one line is one object, that you never make things up, that "none" and "unknown" and "failed" are three different words, was exactly what made the tools trustworthy. Building for screen reader users first made the app ready for agents without a rewrite. And almost everything the tools answer with comes from public data and open source software. What is public should stay public, and WebMCP felt like the natural next door for that data to walk through.
What's next
- Guidance tools: start, read and stop a live walking guidance session from the agent, once I finish testing it on real streets.
- More Korean public and local services, each one becoming one more thing the agent can ask about.
- I hope other people build apps like this for wheelchair users, deaf users and travelers with other needs, and that the code helps them start.
Testing instructions for judges
Open https://gildongmu.dodoplanet.space/en in the ChatGPT desktop app's built-in browser (GPT-5.6 Sol or Terra; WebMCP is off in Luna), or in Chrome 149 or newer with chrome://flags/#enable-webmcp-testing. No login is required. Coverage is South Korea only.
In the ChatGPT desktop app the built-in browser lives in the Work tab: start a chat with no project, open the side panel (Option-Command-B), choose Browser, and enter the URL. Then ask the agent to use the page open in its browser tab. Station names work best with the Korean name alongside.
- "Which tools does the Gildongmu page open in your browser tab offer?"
- "Tell me the first train, the last train and the elevators at Gangdong Station (강동역)."
- "Seoul Station (서울역) to Gangnam Station (강남역): which car and door should I board to get off next to the elevator?"
- "Read me the walking directions, ten steps at a time."
- After the third one, look at the browser tab: the app is already on the route screen the agent described.
Prior work and new work
Gildongmu existed before the submission period. The navigation app itself (the API integrations, the accessibility contracts, the iOS app, the CLI and the server MCP package) is prior work and is not part of this entry.
Added during the submission period (2026-08-27 to 2026-08-30, about thirty commits prefixed "webmcp"; verify with git log --grep webmcp --since 2026-08-26):
- src/lib/webmcp/** (the seven tools, tool lock, opaque refs, output allowlist and budget, view registry)
- src/hooks/useWebMcpTools.ts and src/hooks/useAxisBridge.ts
- the bridges published by PlaceSearch, PlaceDetail and DirectionsView
- the shared sentence modules extracted so that screen and tool share one source
- the privacy clause for agent output in all six locales
- English support overhaul (2026-08-31 to 2026-09-02): English transit and station data, romanized bilingual place names, English place categories, and English in the CLI and MCP server. Not WebMCP code itself, but done for this entry so that the agent's English answers match the English screen
Design record: docs/superpowers/specs/2026-08-27-webmcp-tool-layer-design.md, docs/superpowers/specs/2026-08-29-webmcp-wave2-design.md, docs/research/RESEARCH-2026-08-29-webmcp-deployed-validation.md. Full write-up: https://github.com/Engccer/gildongmu/blob/main/docs/WEBMCP.md
Built With
- kakao
- naver
- next.js
- odsay
- react
- typescript
- vercel
- webmcp
Log in or sign up for Devpost to join the conversation.