MCP Demo Transcript — Cat-4 South FL via the srdb_mcp protocol
This is a CAPTURED trace, not a hand-written one. Reproduce with uv run python scripts/demo_mcp_session.py.
An MCP client speaks JSON-RPC over stdio to the srdb_mcp server. The client below drives the canonical interview question — "What's our hurricane exposure right now and what would a Cat-4 in South FL do to it?" — by chaining the substrate primitives. The agent (a Claude or GPT host) would call the same tools in the same order; here the client is a deterministic script so the trace is reproducible.
Step 1 — MCP handshake
Request:
{
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"sampling": {}
},
"clientInfo": {
"name": "srdb-demo-client",
"version": "0.1.0"
}
}
}
Response:
srdb-mcp v0.1.0 on protocol 2024-11-05. Capabilities: experimental, resources, tools.
Step 2 — Discover the tool surface
Request:
{
"method": "tools/list",
"params": {}
}
Response: 9 tools exposed:
- search_catalog — Search the substrate's catalog of entities, instruments, or scenarios with typed filters. Returns paginated structured entries.
- query_positions — List positions with bitemporal current-knowledge semantics enforced. Filter by entity_id, instrument_id, or asset_class. If position_id is set, returns at most one row.
- walk_lookthrough — Decompose an entity's indirect holdings via the entity_relationship graph. Returns one row per (holder, ultimate_instrument) path with attributed quantity + value.
- get_position_history — Full bitemporal log for one position: every (valid_from, valid_to, txn_from, txn_to) vintage, with is_current_knowledge flagged.
- compare_to_abor — Show how srDB and ABOR see one position differently. Returns srdb_* + abor_* values + break category if a break exists.
- get_break_aging — Current outstanding ABOR breaks bucketed by age (0-1d, 2-7d, 8-30d, 30+d). Latest reconciliation run. Filter by category/severity.
- compute_engineering_identity — Return the current-state engineering identity for one instrument via its per-class model (well DCF — first-principles re-price from current obs; treaty XoL — reinstatement-state snapshot; SFR NOI — current monthly NOI; Black-76 — current mark snapshot). Returns intermediates so the agent can show its work, plus inputs_lineage carrying position_id and (for market-data-driven families) observation timestamps.
- apply_driver_shock — Perturb one driver series (HH M1, BTC spot, hurricane industry loss, etc.) and walk driver_exposure_map to surface affected instruments + per-instrument deltas + firmwide delta. The primitive an agent uses to compose stress scenarios.
- inject_event — Inject a synthetic event (sandbox — not persisted to production event table). Returns a deterministic sandbox event_id + affected_instrument_ids surfaced from event_instrument_exposure links of the same event_type. Pair with apply_driver_shock to compose event-driven scenarios.
Step 3a — Orient: describe the substrate
Request:
{
"method": "resources/read",
"params": {
"uri": "srdb://describe"
}
}
Response:
{
"name": "srDB POC",
"description": "Canonical normalized financial data substrate spanning four asset classes \u2014 natural gas wells, reinsurance treaties, SFR portfolios, crypto derivatives \u2014 with bitemporal lineage, Shadow IBOR reconciliation to a synthesized ABOR feed, and a grounded agent surface (this MCP server).",
"asset_classes": [
"SFR_PORTFOLIO",
"CRYPTO_DERIV",
"WELL",
"TREATY"
],
"current_position_counts_by_asset_class": {
"SFR_PORTFOLIO": 87,
"CRYPTO_DERIV": 37,
"WELL": 126,
"TREATY": 98
},
"total_current_positions": 348,
"total_entities": 27,
"total_instruments": 20,
"latest_position_as_of": "2026-09-25",
"latest_reconciliation": {
"as_of_date": "2025-12-31",
"n_breaks": 4
},
"design_principles": [
"ADR-001 Bitemporal + vintage lineage everywhere \u2014 see docs/adr/001-bitemporal-everywhere.md",
"ADR-002 Polymorphic positions over per-class position tables \u2014 see docs/adr/002-polymorphic-positions.md",
"ADR-003 Shadow IBOR (reconcile to ABOR) over straight IBOR replacement \u2014 see docs/adr/003-shadow-ibor-not-replacement.md",
"ADR-004 Build on DuckDB (+ Iceberg/S3 at scale) over Snowflake / Databricks \u2014 see docs/adr/004-build-on-duckdb-not-snowflake.md",
"ADR-005 Build IBOR in-house over Eagle / Aladdin / SS&C \u2014 see docs/adr/005-build-ibor-not-buy-eagle-aladdin-ssc.md",
"ADR-006 Build the agent layer with Anthropic Claude (via MCP) over Bedrock / OpenAI / local \u2014 see docs/adr/006-build-with-claude-sdk-not-bedrock-openai.md"
],
"agent_workflow_hint": "Start with search_catalog to find entities or instruments by name. Use query_positions to read current holdings. Use walk_lookthrough for indirect decomposition (e.g. LTRe through SRAM). For event-driven questions (hurricane, earthquake, treaty loss): inject_event surfaces affected instruments via event_instrument_exposure, and compute_engineering_identity returns each instrument's current state (reinstatement bookkeeping, NOI, mark snapshot). For market-driven questions (price/rate/vol shocks): apply_driver_shock perturbs a real-obs driver series and walks driver_exposure_map for per-instrument deltas. Cat-4 is a recipe the agent composes, not a magic word \u2014 see docs/mcp_demo_transcript.md."
}
Step 3b — Find LongTail Re
Request:
{
"method": "tools/call",
"params": {
"name": "search_catalog",
"arguments": {
"kind": "ENTITY",
"name_substr": "LongTail"
}
}
}
Response:
total=1 returned=1
LongTail Re Ltd—ENTITY5db857fa…
Step 3c — Walk LTRe's indirect holdings
Request:
{
"method": "tools/call",
"params": {
"name": "walk_lookthrough",
"arguments": {
"entity_id": "5db857fa-9552-57c4-8f32-20408967c31d",
"as_of_date": "2025-12-31"
}
}
}
Response:
20 lookthrough rows; total_attributed_value_usd = $108,045,951
| Asset class | Attributed value | Cumulative % | Ultimate instrument |
|---|---|---|---|
| SFR_PORTFOLIO | $45,742,965 | 0.255 | c0d726a7… |
| SFR_PORTFOLIO | $41,682,552 | 0.255 | 5490304f… |
| SFR_PORTFOLIO | $29,443,055 | 0.255 | ecf75261… |
| WELL | $294,828 | 0.255 | d4c9ae29… |
| WELL | $228,242 | 0.255 | f81e0940… |
| CRYPTO_DERIV | $188,454 | 0.043 | b8ffdfe7… |
| CRYPTO_DERIV | $188,454 | 0.043 | fed8751d… |
| WELL | $87,673 | 0.255 | e85ddb0e… |
| … 12 more rows … |
Step 3d — Inject Cat-4 hurricane (sandbox event — discovers affected instruments)
Request:
{
"method": "tools/call",
"params": {
"name": "inject_event",
"arguments": {
"event_type": "HURRICANE",
"occurred_at": "2025-09-15",
"payload": {
"category": 4,
"landfall_state": "FL",
"landfall_lat": 26.5,
"landfall_lon": -82.2,
"max_windspeed_kt": 130,
"modeled_industry_loss_usd": 80000000000.0
}
}
}
}
Response:
event_id = 3890b6b7-590d-5957-87e1-dad00a179ee3 (sandbox — not persisted to production event table)
affected_instrument_ids = 3 discovered via event_instrument_exposure mapping
7a564ee2-5b0c-5ee7-9163-8bbf21628d411a5c3c8e-7e32-5930-ab49-20e27b5809dac0d726a7-8ffe-579a-baf2-5b82005aaef0
Step 3e — Current-state engineering identity for the FL CAT_XOL treaty
Request:
{
"method": "tools/call",
"params": {
"name": "compute_engineering_identity",
"arguments": {
"instrument_id": "1a5c3c8e-7e32-5930-ab49-20e27b5809da",
"as_of_date": "2025-12-31"
}
}
}
Response:
family = TREATY_XOL_PAYOUT market_value_usd = $-460,273.97
Intermediates (the agent's show its work trail):
{
"treaty_type": "CAT_XOL",
"peril": "NA_HURRICANE",
"attachment_usd": 100000000.0,
"limit_usd": 400000000.0,
"cession_pct": 0.1,
"reinstatements_max": 2,
"attached_loss_to_date_usd": 40000000.0,
"limit_remaining_usd": 400000000.0,
"reinstatements_consumed": 1
}
Inputs lineage (audit trail — position_id always; observation timestamps for market-data-driven families like wells, omitted for state-snapshot families like treaties):
{
"position_id": "800aa8fd-e615-537b-a50f-1e30ef3f8368"
}
Step 3f — Demonstrate apply_driver_shock on a real-obs series: HH M1 +20%
Request:
{
"method": "tools/call",
"params": {
"name": "apply_driver_shock",
"arguments": {
"measure_code": "PRICE_USD_PER_MMBTU",
"semantic_substr": "contract 1 (rolling M1)",
"shock": {
"mode": "MULTIPLICATIVE",
"shock_pct": 0.2
},
"window_days": 30,
"as_of_date": "2025-12-31"
}
}
}
Response:
driver_series_id = 48421910-c643-47fb-a18b-4daa427c4c5a
measure_code = PRICE_USD_PER_MMBTU
pre_shock_value = 4.093 → post_shock_value = 4.9116 (MULTIPLICATIVE +20.00%)
firmwide_delta_usd = $-272,132,068 across 213 instruments touched by driver_exposure_map
Top 5 affected (by absolute delta):
| Instrument | Asset class | Pre | Post | Δ | Mechanism |
|---|---|---|---|---|---|
MSA_PORTFOLIO | SFR_PORTFOLIO | $196,740,004 | $192,805,204 | $-3,934,800 | OPEX_DRIVER (NEGATIVE) |
MSA_PORTFOLIO | SFR_PORTFOLIO | $196,113,757 | $192,191,482 | $-3,922,275 | OPEX_DRIVER (NEGATIVE) |
MSA_PORTFOLIO | SFR_PORTFOLIO | $196,041,596 | $192,120,764 | $-3,920,832 | OPEX_DRIVER (NEGATIVE) |
MSA_PORTFOLIO | SFR_PORTFOLIO | $195,035,772 | $191,135,057 | $-3,900,715 | OPEX_DRIVER (NEGATIVE) |
MSA_PORTFOLIO | SFR_PORTFOLIO | $194,720,447 | $190,826,038 | $-3,894,409 | OPEX_DRIVER (NEGATIVE) |
Server-side logs (stderr)
INFO:srdb_mcp:srdb_mcp 0.1.0 starting (stdio)
INFO:mcp.server.lowlevel.server:Processing request of type ListToolsRequest
INFO:mcp.server.lowlevel.server:Processing request of type ReadResourceRequest
INFO:mcp.server.lowlevel.server:Processing request of type CallToolRequest
INFO:mcp.server.lowlevel.server:Processing request of type CallToolRequest
INFO:mcp.server.lowlevel.server:Processing request of type CallToolRequest
INFO:mcp.server.lowlevel.server:Processing request of type CallToolRequest
INFO:mcp.server.lowlevel.server:Processing request of type CallToolRequest
What this proves
- The MCP server speaks the protocol correctly — every request above is real JSON-RPC over stdio, captured from the running process.
- The audit boundary is the tool surface, not the schema — every agent action above is a typed tool call with structured params. There is no
execute_sqland no way for the client to compose one. - Primitives compose; the substrate is honest about what each tool does. For event-driven questions (hurricane, earthquake, treaty loss):
inject_eventdiscovers the affected instruments viaevent_instrument_exposure;compute_engineering_identityreturns current state snapshots (reinstatement bookkeeping, NOI, mark price). The event-parameterized math (payout, reinstatement premium booked, SFR impairment) lives inscenarios/cat4_fla_landfall.pyas the closed-form per-asset-class identity. For market-driven questions (HH price up, BTC IV spike, basis blowout):apply_driver_shockperturbs the driver and walksdriver_exposure_mapfor per-instrument deltas — see Step 3f. - The closed-form scenario is the verification fixture for the event-driven chain.
scenarios.cat4_fla_landfall.run()is the source of truth for exact firmwide PnL on Cat-4; the agent's discovery + state-identity composition above produces the same affected-instrument set (verified bytests/test_mcp_tools.py::test_cat4_agent_style_composition_recovers_named_scenario_signal).
For an agent host (Claude Desktop, Claude Code, VS Code MCP, any OpenAI-with-MCP-adapter), the same tools are available with no code change. The substrate is the agent's runtime.