Skip to content

MVA Architecture

Model-View-Agent is not a variation of MVC. It is a new architectural pattern, purpose-built for the age of autonomous AI consumers.

Every software architecture in history assumes a human at the end of the pipeline. MVC renders HTML for browsers. MVVM binds state to visual components. REST exposes resources for mobile apps. All of them rely on a consumer that can interpret ambiguity, navigate inconsistency, and apply domain knowledge that the interface never provided.

AI agents can do none of this. When an agent receives { "amount_cents": 45000 }, it does not know it's cents. It does not know to divide by 100. It does not know that the next action is billing.pay. It guesses — and when it guesses wrong, it hallucinates.

MVA solves this by replacing the human-centric View with the Presenter — a deterministic perception layer that tells the agent exactly what the data means, how to display it, and what to do next.

Attribution

MVA (Model-View-Agent) was created by Renato Marinho at Vinkius Labs and first implemented in mcp-fusion. It is not a fork, extension, or "variation" of MVC — it is a fundamentally new architecture designed for a fundamentally new consumer class.


The Three Layers

text
┌──────────────────────────────────────────────────────────────────────┐
│                         MVA Architecture                             │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌──────────────┐     ┌──────────────────┐     ┌─────────────────┐  │
│  │    MODEL      │     │      VIEW        │     │     AGENT       │  │
│  │              │ ──→ │    (Presenter)    │ ──→ │                 │  │
│  │  Zod Schema   │     │                  │     │  Claude, GPT,   │  │
│  │  Validates    │     │  Domain Rules    │     │  Gemini, Llama  │  │
│  │  Filters      │     │  UI Blocks       │     │                 │  │
│  │  Rejects      │     │  Affordances     │     │  Autonomous     │  │
│  │  unknown      │     │  Guardrails      │     │  consumer that  │  │
│  │  fields       │     │  Composition     │     │  perceives,     │  │
│  │              │     │                  │     │  interprets,    │  │
│  │              │     │                  │     │  and acts        │  │
│  └──────────────┘     └──────────────────┘     └─────────────────┘  │
│                                                                      │
│  Security Boundary     Perception Layer        Autonomous Consumer   │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
LayerRoleImplemented As
ModelDefines the shape and constraints of domain data. Acts as a security boundary when using .strict() — only declared fields pass through.z.object({ ... }).strict()
View (Presenter)Transforms raw data into a Structured Perception Package — data + rules + UI blocks + affordances + guardrails. Domain-level, not tool-level.createPresenter()
AgentThe autonomous consumer. Receives the perception package and acts deterministically based on the structured context it was given.Claude, GPT, Gemini, or any MCP-compatible LLM

The Core Thesis

An AI agent should never have to guess.

Every piece of data should arrive with:

  1. Validation — a schema that rejects what doesn't belong
  2. Interpretation rules — domain knowledge that removes ambiguity
  3. Visual representation — server-rendered charts and diagrams
  4. Action guidance — explicit next steps based on data state
  5. Cognitive limits — bounded results with filter guidance

When all five are present, the agent perceives the domain identically every time. Hallucination is eliminated at the architecture level, not patched at the prompt level.


Concept Map

MVA ConceptWhat It DoesGuide
The TheoryWhy MVC fails for agents, first-principles design of MVARead →
MVA vs MVCFormal layer-by-layer comparison of the two paradigmsRead →
Presenter AnatomyThe 6 responsibilities of the Presenter, lifecycle, compositionRead →
Perception PackageThe 6-block response structure the agent receivesRead →
Agentic AffordancesHATEOAS for AI — data-driven next-action hintsRead →
Context Tree-ShakingJIT domain rules that replace global system promptsRead →
Cognitive GuardrailsTruncation, strict validation, self-healing errorsRead →

Quick Reference: MVA in Code

typescript
import { createPresenter, ui, defineTool } from '@vinkius-core/mcp-fusion';
import { z } from 'zod';

// ── MODEL: Security boundary via Zod schema ──
const invoiceSchema = z.object({
    id: z.string(),
    amount_cents: z.number(),
    status: z.enum(['paid', 'pending', 'overdue']),
    // internal_margin, password_hash → rejected by .strict()
}).strict();  // explicit security boundary

// ── VIEW: The Presenter — agent-centric perception layer ──
const InvoicePresenter = createPresenter('Invoice')
    .schema(invoiceSchema)                                // Model
    .systemRules([                                        // Interpretation
        'CRITICAL: amount_cents is in CENTS. Divide by 100.',
    ])
    .uiBlocks((inv) => [                                  // Visualization
        ui.echarts({ series: [{ type: 'gauge', data: [{ value: inv.amount_cents / 100 }] }] }),
    ])
    .agentLimit(50, (omitted) =>                          // Guardrail
        ui.summary(`⚠️ 50 shown, ${omitted} hidden. Use filters.`)
    )
    .suggestActions((inv) =>                               // Affordance
        inv.status === 'pending'
            ? [{ tool: 'billing.pay', reason: 'Process payment' }]
            : []
    );

// ── AGENT: Receives a Structured Perception Package ──
const billing = defineTool<AppContext>('billing', {
    actions: {
        get_invoice: {
            returns: InvoicePresenter,  // ← One line. Zero boilerplate.
            params: { id: 'string' },
            handler: async (ctx, args) => ctx.db.invoices.findUnique(args.id),
        },
    },
});

The handler returns raw data. The Presenter intercepts it in the execution pipeline, validates through Zod, strips undeclared fields, attaches domain rules, renders charts, applies truncation, and suggests next actions — all automatically. The agent never sees raw JSON. It sees a structured perception package.


Start Reading