Skip to content
English

MCP symmetry

The problem

In a classic architecture, the AI agent calls tools on one side and the graphical interface calls a REST API on the other. Two code paths coexist, implemented separately.

Divergences appear quickly:

  • a bug fixed on one side is not fixed on the other;
  • a new field is not exposed everywhere;
  • the validations differ.

The result: two versions of the same feature, with no assurance that they behave identically.


The solution: a single route

Simon has no dedicated REST endpoint per feature. Every action — whether it comes from the agent or the interface — goes through the same MCP server. The agent calls the tools directly; the interface calls them via a single HTTP entry point that relays the call to the same server.

sequenceDiagram
participant UI as Interface
participant S as Server
participant M as Python MCP
UI->>S: Call via the HTTP proxy
S->>M: Tool execution
M->>M: Business logic + change tracking
M-->>S: JSON result
S-->>UI: JSON response
S->>UI: db.changed event
UI->>UI: Refresh the views

The agent follows the same business path, except that it calls the MCP server directly — without going through the proxy.


The benefits

  • Reduced divergence risk — what the agent can do, the interface can generally do, and vice versa. The remaining differences are handled in the forms, views or permissions, not in parallel business logic.
  • A single source of truth — the business logic is implemented only once in the MCP server. Validations, business rules, side effects: everything is in one place.
  • A single place to test — the MCP tool tests automatically cover both paths, agent and interface.
  • Automatic consistency — after each modification, the views refresh automatically, whether the change comes from the agent or the interface.

The trade-offs

  • Performance — each call from the interface transits through the MCP server, a separate process. In practice, the added latency is negligible for accounting operations.
  • Proxy complexity — the server must relay the calls to the Python process and handle errors. But this is generic infrastructure code, not business logic.

Why it works

Simon is agent-first software. The interface is not the main path — it is a visual complement. Building the interface as an MCP client, just like the agent, is consistent with this philosophy.