What inspired this

I kept losing the same thing. Someone would send me a Reel about a tool, a recipe, or a workflow. I'd save it. Two weeks later I'd want the link, the install steps, the tool name, or the recipe's ingredient list, and the video was right there in my library useless, because to answer any of those questions I had to either re-watch it or sit there transcribing it for an agent that couldn't see it.

What I built For this challenge I exposed the ORANO desk web app at oranoai.com/workspace as a WebMCP surface and added nine tools that map directly to the actions a user can already take on the page:

How I built it The desk is a single static workspace/index.html that loads one JS file, js/workspace.js. On load the script checks for document.modelContext and, when it's there, calls registerWebMCP() which registers the nine tools. Each tool is a plain object: a JSON Schema, an annotations block (readOnlyHint for read tools, untrustedContentHint for evidence), and an execute function that calls the same /v1 API the human UI already uses. That was the load-bearing decision: the agent doesn't get a parallel API. It shares apiRequest(), navigate(), and renderProject() with the UI, so the page state and the agent's view are literally the same state.

The backend is the same FastAPI service that runs the mobile and web apps. The endpoints (/v1/projects, /v1/projects/{id}/context, /v1/profile/tasks, /v1/search, etc.) already existed to power the UI — WebMCP just gives the agent the same endpoints with structured schemas and bounded responses. The personal MCP server at /mcp/ (FastMCP) exposes the same selector through get_project_context for accounts that prefer an MCP-style integration.

One concrete example of the contract. When a tool changes what's on screen (save_video, search, list_tasks), the execute function calls navigate() or renderProject() after the API call returns, so what the user sees matches what the agent was told. There's no parallel "API response" and "UI response" — there is just the workspace, and both participants read it.

What I learned A few things that changed how I think about this:

Agents are users, not API clients. Treating them as a separate integration channel — a separate auth flow, a separate surface, a separate data model — duplicated evidence and made the human the bottleneck. The breakthrough was giving the agent the same code path the UI uses, and the same render path so what the agent sees is what the user sees. The hard problem was boundaries, not schemas. Once the page can ask for the transcript, you have to decide how much. A bounded character budget, an allow-list of fields, and untrustedContentHint on evidence blocks were the minimum to make this safe for a real account with real saves. WebMCP made the product more human. The agent and the user doing the same work on the same data, with the same UI affordances, is the point. Writing tight tool descriptions ("List ORANO projects… use this before opening a project") forced me to write the spec for an agent that has no other context, which also helped me explain it better to humans.

Challenges I faced Optimistic loading. The workbench opens with a shimmer skeleton the same shape as the real layout, so the page never looks empty while the project bundle is in flight. Cheaper to ship than a real data-fetch waterfall, and the result feels loaded within the first paint. Click-to-play embeds. Eagerly loading YouTube and Instagram iframes on every project view is slow and noisy. The page renders a thumbnail poster with a click-to-play badge; the iframe (with autoplay=1 so the user gesture counts) only loads when the user clicks. The visible state is honest about what is and is not playing.

Public lab vs. authenticated desk. Two surfaces, one product. The lab exposes six tools on a guest workspace for evaluation; the desk exposes nine tools on a real account for daily use. Both share the same evidence contract, so a workflow that works in the lab is the same workflow that works in the desk once you sign in.

Built With

Share this project:

Updates

Submission history