Inspiration

Agents are getting good at acting on the web, but almost every agentic product still asks you to pick one of two shapes.

An agent that advises: it talks about your work from a chat panel, and you translate its advice into the application by hand.

An agent that operates: it acts through tools or APIs, and you find out afterwards what changed.

Both give something up. The first leaves the agent outside the work. The second takes the human out of the loop at exactly the moment the stakes are highest.

We wanted to know what a third shape looks like: what if the application itself were the shared surface, where a human and an agent reason about the same problem, and the human keeps authority over what becomes real?

That question is what made WebMCP interesting to us. Not as a way to make an existing app agent-compatible, but as a way to let a page say these are the actions that make sense right now — and to have that answer change as the human works.

What it does

MUTUA demonstrates the model through one focused scenario: software launch recovery.

A team is four weeks from a September 30 launch. Five engineers, a $420,000 budget, a stated tolerance of 15 % workload overload. Everything is on track.

Then one QA engineer becomes unavailable. You mark it in the interface. The workspace recomputes: peak load 134 %, overload 34 %, launch slipping two working days.

You ask the agent to keep the September launch without increasing burnout.

It reads the same state you are looking at, and creates Proposal A — on time, +$12,000, overload down to 4 %, but the Analytics dashboard deferred out of launch scope. Your plan has not changed. This is a proposal, sitting beside reality, with every operation spelled out in a readable diff.

Analytics is a commitment you made, so you lock it. Proposal A immediately shows a conflict — it is never rewritten behind your back, just re-measured against your new constraint and frozen for comparison.

You ask for another option. Proposal B — on time, +$4,000, 9 % overload, no scope loss, every lock respected. It gets there differently: instead of dropping a feature, it defers work that was never a launch commitment, splits QA effort across whoever has the skill and the room, and books the smallest useful block of contractor capacity.

You compare them side by side, on numbers the application computed.

Then the moment the whole project is built around. Look at the Agent Capabilities panel: commit_proposal is not there. The agent does not have the capability to make this real. You click Approve Proposal B, and it appears.

You say use B. The agent commits. The plan becomes September 30, 9 % overload, $424,000, full scope — and every step, human and agent, is in the timeline with its author.

The four primitives

Shared state. One store backs the interface and every WebMCP tool. There is no agent-side copy of reality that can drift out of date.

Proposal state. Agent changes are explicit reversible operations applied to a cloned plan. Exactly one tool can touch canonical state, and it is gated.

Human locks. A locked item cannot be rescoped, delayed, reassigned or resized. The lock is enforced when an operation is attempted and re-evaluated against proposals that already exist.

Dynamic capability surface. The set of registered WebMCP tools is a function of workflow phase. Comparison does not exist before simulation. Commit does not exist before approval.

How we used WebMCP

Twelve semantic capabilities, grouped by what they are for:

Observeget_workspace_state, get_active_scenario, inspect_constraint, list_conflicts Proposecreate_proposal, modify_proposal, add_constraint, lock_entity Evaluatesimulate_proposal, compare_scenarios Finalizediscard_proposal, commit_proposal

They are never all registered at once. A capability map turns the current phase into a tool set, and the registry synchronises against the WebMCP host on every material state change — registering what became meaningful, unregistering what did not.

The Capability Inspector in the interface renders the live registry, not the map, so what a judge reads is exactly what an agent can call.

There is deliberately no tool for approval. That transition belongs to the interface, and to the person using it.

How we built it

Next.js 15, React 19, TypeScript, Zustand, Zod, Tailwind CSS. No backend, no database, no ML, no external API on the golden path.

Every material mutation — from a click or from a tool — follows the same path: validate, apply, bump the state version, re-score every scenario, recompute the phase, refresh the WebMCP registry, append an audit event, persist.

The consequence engines are pure functions. The agent chooses operations; the application computes consequences: deadline slip, per-person load, recovery spend, scope loss, constraint results. No model calculates anything, which is why the demo replays identically and the tests can assert exact figures.

The recovery planner is deterministic and is not a lookup table. It implements two policies with genuinely different trade-offs — one that will spend more and sacrifice scope to keep tasks whole, one that preserves scope by fragmenting work and buying the minimum outside capacity. Which policy applies is read from the state of the workspace: once every non-critical launch commitment is locked, the first has nothing left to give. The lock does not filter operations; it changes which recovery is possible at all.

Challenges we ran into

Designing for collaboration instead of automation. The easy build is a bag of tools that edit application state directly. We rejected it, and then had to design an actual lifecycle — propose, review, simulate, constrain, adapt, approve, commit — where each transition is legible.

Making a lock mean something. It is trivial to reject an operation that targets a locked entity. It is harder to decide what happens to a proposal that was already valid when the lock arrives. Rewriting it silently would have destroyed the story we were telling, so proposals are re-scored after every change and surface as conflicts instead.

Calibrating the dataset. The demo numbers had to fall out of the engine, not be typed into a component. Getting a dataset where the baseline is healthy, one absence produces 34 % overload, and the two policies land on 4 % / +$12k and 9 % / +$4k took real iteration — and it is guarded by tests that assert the exact values.

Making capability changes visible. Dynamic registration is invisible by nature. The Capability Inspector exists so that the contract between the application and the agent is something you can watch change.

Accomplishments we're proud of

MUTUA reaches what we think of as the third level of WebMCP use.

Level one, the agent can understand the application — it reads structured state.

Level two, the agent can participate — it creates and modifies visible, reversible proposals.

Level three, the application governs the agent — its current state determines which capabilities exist at all.

The third level is the submission. And it is not decorative: commit_proposal is unregistered before approval and independently re-validates approval, simulation freshness, state version and hard constraints in its handler. A test calls it directly, bypassing the registry, and asserts the refusal.

What we learned

Agent capabilities can be part of the user experience.

We stopped asking which tools should this agent have and started asking which actions make sense in this exact application state. That turns tool design from an API problem into an interaction design problem — and WebMCP is what makes the question answerable, because the page's own state is right there to answer it with.

What's next for MUTUA

Extract the shared-state and capability lifecycle into reusable primitives, and prove them in a second domain — incident response is the obvious one, because it has the same shape: observe, investigate, propose mitigation, human authorisation, execution capability unlocked.

The same model fits procurement, staffing, infrastructure operations, financial planning and compliance. We deliberately did not build any of them. One workflow implemented deeply demonstrates WebMCP better than five implemented shallowly.

Built With

Share this project:

Updates