MCP Gateway Spec — Formal Specification, v0.1
A governed surface for insurance agents acting across one or more carrier-core systems. Defines eight primary operations, five IR primitives, an audit-trail record, and a multi-carrier composition protocol. The gateway is the control plane; inference advises.
1. Status
v0.1 — draft. Spec text is CC-BY-4.0. Reference code is Apache-2.0.
v1.0 ships when at least one carrier-core adapter and one MGA-side client implement five of the eight primary operations against pinned IR with signed audit and pass the conformance fixtures.
2. Conformance
A gateway is conformant with v0.1 if and only if it satisfies all of the following:
- Implements at least five of the eight primary operations in §3.
- Emits a signed audit-trail record (§5) for every operation, with
joulespopulated for every model call. - Supports IR pinning at session start; refuses operations whose pinned IR has been rotated.
- Implements
decision.replayfor any prior trace it issued. - Exposes
prepare/commit/abortif it participates in multi-carrier composition (§6); otherwise declaressaga_only. - Treats inference as advisory: no operation's outcome is determined by a model call alone.
3. Operations — formal signatures
carrier.compose.atomic
(steps: Step[]) → ComposedTrace
All-or-nothing across N carrier gateways. 2PC where every target declares it; saga otherwise with compensation functions. The trace contains per-carrier sub-traces.
ir.pin
(contract_id: URI, version: semver) → SessionPin
Binds a session to a specific IR version. Pins recorded in audit-trail ir_pins[]. Drift on either side terminates the session.
decision.replay
(trace_id: UUID) → ReplayedDecision
Re-runs the prior decision against the pinned IR. Output: byte-identical decision + drift report if any pinned IR has changed.
appetite.match
(risk_ir: SubmissionIR) → MatchResult[]
Queries the appetite-IR registry. Each result carries { carrier, program, confidence, basis }. Inference fallback only when explicitly authorized by the session.
form.assemble
(coverage_form_ir: URI, schedule: Schedule) → PolicyForm
Deterministically assembles a policy form from coverage-form-IR + schedule. Free-generation is not permitted.
rate.diff
(plan_v1: URI, plan_v2: URI) → FilingDelta
Filing-grade structural diff: factor changes, territory updates, ILF deltas, base-rate moves, with per-state regulatory-impact flags.
claim_event.append
(claim_id: UUID, event_ir: ClaimEventIR) → AppendReceipt
Append-only Merkle ledger. Receipt includes prev-event hash, ledger position, signature.
hitl.require
(op: OperationRef, threshold_policy_id: URI) → HITLAttachment
Attaches a human-approval gate to an operation. Threshold policies are versioned; approvals are signed and replayable.
4. IR primitive schemas
All five IR primitives are semver-versioned and content-addressed. Pinned at session start.
rate-plan-IR
rate-plan-IR:
id: string
version: semver
content_hash: blake3
effective_dates_by_state: { state: { from, to? } }
filing_ids: [ string ]
prior_version: ref?
base_rates: { lob, territory_code, value }
factors: [ { name, classes, values } ]
territory_tables: { state: { code → name } }
ilfs: [ { layer, factor } ]
min_premium: by_state_lob
max_premium: by_state_lobcoverage-form-IR
coverage-form-IR:
id: string
version: semver
content_hash: blake3
iso_aais_ref: { source: enum[ISO|AAIS|carrier], code, edition }
coverage_parts: [ { id, name, limits[], deductibles[] } ]
exclusions: [ { id, text, scope } ]
conditions: [ { id, text } ]
definitions: [ { term, text } ]
endorsements: [ { id, name, modifies[], schedule_binding } ]
schedule_binding_rules: [ rule ]claim-event-IR
claim-event-IR:
claim_id: string
event_id: string
event_type: enum[fnol|reserve_change|payment|subro_open|subro_recovery|close|reopen]
ts: timestamp
actor: { principal_id, role }
monetary_delta: { amount, currency, ledger_account }
reserve_delta: { amount, line, period }
document_refs: [ doc_hash ]
prev_event_hash: bytes32 # Merkle chain
signature: bytesappetite-IR
appetite-IR:
id: string
version: semver
class_codes: { naics?, sic?, iso_gl? }
states_in: [ state ]
states_out: [ state ]
hazard_limits: { hazard_code → cap }
premium_bounds: { min, max }
expiring_carrier_rules: [ predicate ]
exception_predicates: [ { predicate, reason_code } ]submission-IR
submission-IR:
acord_form_ref: { form_id, edition }
fields: { name: { value, source, confidence, provenance_uri } }
required_field_table: by_carrier
attachments: [ { kind, ref, doc_hash } ]
signature: bytes5. Audit trail — JSON Schema
One signed record per operation. Records are append-only; prev_event_hash chains the log into a Merkle structure.
{
"trace_id": "uuid",
"parent_trace_id": "uuid?",
"ts_start": "rfc3339",
"ts_end": "rfc3339",
"actor": {
"principal_id": "did|opaque",
"role": "string",
"on_behalf_of": "principal_id?"
},
"operation": { "name": "string", "version": "semver" },
"ir_pins": [
{ "kind": "rate-plan-IR|coverage-form-IR|claim-event-IR|appetite-IR|submission-IR",
"id": "uri", "version": "semver", "hash": "bytes32" }
],
"inputs": {
"schema_version": "semver",
"hash": "bytes32",
"redacted_payload_ref": "uri"
},
"rule_evaluations": [
{ "rule_id": "string", "version": "semver",
"result": "passed|failed|n/a", "basis": "string" }
],
"model_calls": [
{ "provider": "string", "model_id": "string",
"prompt_hash": "bytes32", "response_hash": "bytes32",
"tokens": "int", "joules": "float" }
],
"decision": {
"outcome": "string",
"confidence": "float",
"basis": "deterministic | inference | hybrid"
},
"hitl": {
"required": "bool",
"approver": "principal_id?",
"approval_ts": "rfc3339?",
"policy_id": "string",
"policy_version": "semver"
},
"outputs": {
"schema_version": "semver",
"hash": "bytes32",
"artifact_refs": [ "uri" ]
},
"prev_event_hash": "bytes32",
"signature": "bytes"
} 6. Multi-carrier composition
The composition session is server-side state: pinned IR set, target carrier-gateway list, 2PC coordinator, compensation registry.
Each participating carrier MCP gateway implements:
prepare(op: Operation) → reservation_id— validates and holds resources without committing.commit(reservation_id)— finalizes.abort(reservation_id)— releases.
Gateways that cannot implement 2PC declare saga_only; the coordinator falls back to a saga with the compensation function declared per operation. Idempotency keys per step are required.
Output: one ComposedTrace with per-carrier sub-traces and (if applicable) an applied-compensations log.
7. Joule metering
Every model_calls[] entry in the audit trail carries a joules field measured by the gateway's runtime. Composed traces aggregate per-operation joules. This is the unit of cost.
8. Versioning
The gateway spec is semver-versioned. IR primitives are independently semver-versioned and content-addressed. Audit-trail records carry both the operation version and the IR pin versions, so future readers can resolve every artifact deterministically.
9. Security
The gateway composes proven primitives. mTLS between agent and gateway. Capability tokens for operation scope. DID-based signing on audit records. Merkle-chained audit log. Content-addressed IR.
Detailed engineering reference: implementation notes ship in the reference repository under SECURITY.md.