Skip to content

Agent operability (MCP)

Because a Mateu screen travels as a self-describing wire model (fields with types and validation, the actions available, navigation commands), it is not only something a renderer turns into pixels — it is something an agent can operate. A Mateu app is therefore a second plane on the same contract: the rendering plane (the web/native renderers) and the agent-operability plane — an MCP server that exposes each screen as tools any agent (Claude, Antigravity, an internal copilot) can discover and run.

Think of it as “a renderer of agents”: same self-describing model, tools instead of pixels.

This page is the half where an agent operates an app a developer defined. For the other half — where an LLM writes the UI definition from a prompt, validated against the published schema — see Prompt-to-app (AI authoring).

ToolWhat it does
mateu_list_routesThe navigable routes of the app (from its menu) → [{route, caption}].
mateu_describe_screenLoad a route → a flat screen: title, fields (id, label, dataType, required, value, options), actions (id, label), listing (if any), state.
mateu_run_actionRun an action id (optionally seeding field values) → the resulting screen.
mateu_searchSearch a listing screen by free text (and optional filters).

The projection rules (how a UIIncrementDto becomes this flat screen) are normative and specified in Wire specification → Agent operability, so every host produces the same result.

  • Sidecar — frontend/mcp-server/, a zero-dependency Node MCP server. It speaks only the public wire, so it operates a Java, .NET or Python backend with no backend change. Point it at a URL and go. This is the quickest way to try it, and it covers every backend today.
  • Native endpoint — the backend serves the same MCP projection directly, so an app can also be an MCP with no sidecar to deploy, enforcing permissions natively. Available on Java (every adapter: Spring MVC, Spring WebFlux, Micronaut, Quarkus, Helidon MP), Python (FastAPI) and .NET (ASP.NET Core) — all at POST /mateu/mcp, all sharing one projection. It is off by default everywhere: enable it with mateu.mcp.enabled=true (Java), MateuOptions.Mcp = true (.NET), add_mateu(..., mcp=True) (Python) or MATEU_MCP_ENABLED=true (.NET and Python). It gives any caller holding a valid token a programmatic way to drive every screen, which the application has to decide to expose.

Authorization is enforced by the backend, not by the MCP layer: @EyesOnly, @ReadOnlyUnless and @DisabledUnless are applied server-side over the caller’s JWT. The MCP inherits that — it never opens a wider path. An action a token may not run never reaches the wire, so it never appears as a tool result. The sidecar simply relays a MATEU_TOKEN bearer to the backend.

Register the sidecar as an MCP server (stdio):

{
"mcpServers": {
"mateu": {
"command": "node",
"args": ["frontend/mcp-server/index.mjs"],
"env": {
"MATEU_BASE_URL": "http://localhost:8080",
"MATEU_TOKEN": "<optional bearer>"
}
}
}
}

Then an agent can, for example: mateu_list_routes → mateu_describe_screen("bookings") → read the fields and filters → mateu_search("bookings", "smith") → mateu_run_action("bookings", "export").

The in-app assistant uses the same projection

Section titled “The in-app assistant uses the same projection”

The built-in AI chat (@AI(sse=…)) is the other face of the same idea. With every message it now sends a self-describing projection of the screen the user is looking at — the same shape the MCP produces: the current fields (id, label, dataType, value) and the actions available. So the assistant fills forms and runs actions precisely instead of guessing from raw state, and it drives the UI by returning the wire events the frontend already applies (navigation-requested, dispatched events…). One projection, two consumers: external agents (MCP) and the in-app assistant.

Terminal window
cd frontend/mcp-server && npm test # projection (against the conformance corpus) + protocol
MATEU_BASE_URL=http://localhost:8080 node e2e/mcp-probe.mjs # end-to-end against a live backend

See frontend/mcp-server/README.md for the full tool surface and configuration.