Operator environment
The analyst fires the event and reads the stakeholder table.
21 of 27 stakeholder positions valued · 6 not applicable · showing 7
EVA is reached four ways: the operator environment, the HTTP API, EVA Chat and the Model Context Protocol. MCP is an interface mechanism, not a second analytical implementation. For the same request, the computation, the model identity and the refusal state are the same whichever door it arrives through.
Every figure below was produced by a run performed through a real MCP server subprocess and reproduced identically over the HTTP API, from the canonical payload.
The demonstration used the US housing ecosystem and fired a borrower home-sale payoff event through the live MCP server, on the route named beneath the result.
What happens to the mortgage chain when the borrower sells the home and pays off the loan?
Tool: run_event_impact_with_inputs
{
"ecosystem_id": "us_housing_v9",
"event_code": "HOU_BORR_HOME_SALE_PAYOFF",
"fire_date": "2026-05-05",
"valuation_date": "2026-05-05",
"inputs": { … canonical loan and conditions … }
}The asset value change is zero because the lender receives par on the firing date; the investor position is a separate measure and is extinguished.
The loan and servicing calculations were returned with model/version identity, input/output hashes, run identity and source lineage in the EVA result.
A borrower sells the house and pays off the loan. The canonical request was issued over the HTTP API and through a real MCP server subprocess. Both returned byte-identical results and the same run identifier. The panels below show that recorded run as each interface presents it.
The analyst fires the event and reads the stakeholder table.
21 of 27 stakeholder positions valued · 6 not applicable · showing 7
The same firing requested in conversation. The numbers are reported, not generated.
The engine fired HOU_BORR_HOME_SALE_PAYOFF on 2026-05-05 and returned the full impact set.
HOU_LOAN_CONV_30 $383,540 → $0, a change of −$383,540, VALUED.
HOU_MSR $12,181 → $0, a change of −$12,181, VALUED.
HOU_MBS_PT $427,729 unchanged. HOU_PROPERTY $560,000 unchanged.
The loan and MSR are extinguished by the full prepayment; the MBS pass-through and property values are unchanged.
The payload the operator environment is rendering — model identity, provenance and hashes intact.
POST /api/v1/firing/fire-event "asset_id": "HOU_LOAN_CONV_30", "valuation_model": "LoanLedgerCashflowModel", "modifier_binding": "PrepaymentFullModifier", "status": "VALUED", "baseline_value": 383540.04688121786, "impacted_value": 0.0, "delta": -383540.04688121786, "delta_pct": -1.0, "model_version": "0.6.0", "implementation_id": "mortgagekit.valuation.loan_pv .LoanCashflowDCFModel:v0.6", "inputs_hash_impacted": "dfd990d12193c28e…", "reason": "full prepayment: lender receives par on firing date"
A tool call from an external client over a real stdio subprocess. The result arrives inside a governance envelope.
tools/call → run_event_impact_with_inputs
"eva_governance": {
"source": "EVA",
"authority": "All numbers in
eva_result are computed by EVA's
engine. Numbers not present were
not computed.",
"narration_rules": "Report fields
verbatim. Do not invent, estimate,
or requalify."
},
"eva_result": {
"engine": "engine10",
"run_id": "engine10::d4922ecf…"
}
engine10::d4922ecf4d39294ffe7920d0a218a50cThe interfaces differ in what they render. They do not differ in what was computed. The operator environment draws a table, chat writes a sentence, the API returns the payload and MCP wraps it in a governance envelope — and the analysis beneath them is the same analysis.
A second result, from the chat surface. Chat sent a reduced request and returned a different run identifier. Firing the HTTP route with those same reduced arguments reproduces the chat identifier exactly — engine10::4f4e251e… on both. The run identifier is a function of the request, not of the interface. Change the request and the identity changes; change only the door and it does not.
Every figure, field name, model identifier and hash fragment above is taken verbatim from the recorded run. The operator-environment and chat panels are composed renderings of that run rather than captured screens.
The EVA MCP surface registers a fixed allowlist of 33 tools. Requests outside that surface are returned as structured refusals rather than being improvised by the adapter.
A request for run_decision_policy was refused by name inside the governed response envelope.
status: ERROR error_code: TOOL_NOT_ALLOWED "run_decision_policy" is not in the EVA MCP allow-list
A bogus event code sent through an allowed tool produced EVA's own catalog error, carried across MCP without being reinterpreted.
status: ERROR error_code: UNKNOWN_EVENT EVT_DOES_NOT_EXIST_XYZ
The surface covers analytical execution, explanation, discovery and glossary access. The adapter does not add a second analytical implementation.
run_event_impact
run_event_impact_with_inputs
Deterministic event consequence execution.
run_decision_impact
compute_reaction
Bounded decision consequence and payoff/minimax analysis.
explain_run
list_ecosystems
list_personas
list_events
define_term
Read stored runs and discover the available analytical vocabulary.
MCP is one of four ways in. The analytical result remains an EVA result, with its model identity, run identity, evidence and refusal state intact — identical to the result the same request returns through any other interface.
external client
↓
MCP
↓
EVA tool dispatcher
↓
EVA
↓
evidence-bearing result