addrbookFor publishers
← The evidence ledger

Evidence row 980439

Observed , by probe.mcp/1.

Kind
mcp.tools
About
endpoint 278214a0-1e9d-4f76-9d11-401752e2e2fc
Recorded
Previous row
None: the first of its kind about this subject
Body SHA-256
deb3e443055c827af521d798459621c60354824e25affd8a67e46e1598812c75
Leaf
0x2da134187b5c344c4cbf0331e4321c5c095cb4d6fa6c2a20875c08e4f9af1a3a

What was observed

{
  "count": 10,
  "tools": [
    {
      "description": "Purchases credits using a payment method already saved from a prior Stripe Checkout session. Use this when an authenticated account is running low on credits and needs more to keep submitting runs or analyses, without a human re-entering card details. See GET /billing/pricing for the current per-credit price. Example: {\"credits\":100}",
      "inputSchema": {
        "description": "Arguments for ``buy_credits`` (neumann#192; mirrors fermi's schema).\n\nAuthentication is required (unlike the free tools above): an anonymous\ncaller gets an ``authentication_required`` tool error. No price literal\nhere by design — see GET /billing/pricing for the current per-credit cost.",
        "properties": {
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Your API key from POST /api/v1/accounts. Required unless you are authenticated via an Authorization: Bearer token.",
            "title": "Api Key"
          },
          "credits": {
            "description": "Number of credits to purchase.",
            "minimum": 1,
            "title": "Credits",
            "type": "integer"
          }
        },
        "required": [
          "credits"
        ],
        "title": "BuyCreditsInput",
        "type": "object"
      },
      "name": "buy_credits"
    },
    {
      "description": "Pre-flight-sizes a graph without running it: estimated peak memory, engine complexity, which tier (small/large) it would run as, and the credit cost. Use this when you want to know what a run will cost or how heavy it is before committing to it, especially for a large or unfamiliar graph. Free; no credits debited. Example: {\"graph\":{\"root_nodes\":[{\"id\":\"root\",\"distribution_type\":\"normal\",\"distribution_params\":{\"mean\":100,\"std\":15}}],\"calc_nodes\":[{\"id\":\"out\",\"formula\":\"{e1}\"}],\"edges\":[{\"id\":\"e1\",\"source\":\"root\",\"target\":\"out\"}],\"run_params\":{\"trials\":1000,\"time_periods\":12}}}",
      "inputSchema": {
        "$defs": {
          "AggregationRequest": {
            "additionalProperties": false,
            "description": "A post-simulation, series-aware metric over one node's full series.\n\nNPV/IRR/payback/CAGR/cumsum are NOT per-period node values: they consume a\ntarget node's complete ``(time_periods x trials)`` matrix AFTER the run and\nreturn one value per trial, summarised into a distribution.\n\nDiscount convention (0-based series index): period ``t=0`` is the present\n(undiscounted) cash flow; period ``t`` is discounted by ``(1+rate)**t``. The\nfirst period is undiscounted.\n\nWarning — two discount conventions coexist; do not mix them. These\naggregations use the **0-based** series index above (first period\nundiscounted). The per-period formula functions ``DISCOUNT(rate,\n{time_period})`` and ``PV(rate, value, {time_period})`` use the **1-based**\n``{time_period}``, so they discount the first period by ``(1+rate)**1``.\n\n\"Investment at period 0\" pattern: model an up-front outlay as a negative\nperiod-0 cash flow in the target node's series; NPV's t=0-undiscounted\nconvention then treats it as the present-value outlay. Do not additionally\ndiscount that first period with ``PV(...,{time_period})`` inside the target\nnode's formula when also requesting an aggregation ``npv`` — combining the\n1-based per-period discount with the 0-based ``npv`` double-shifts the first\nperiod.\n\nPer-period node vs aggregate metric (``prob``): pointing ``prob`` at a\nmulti-period cash-flow NODE via ``target_node_id`` thresholds only that node's\nFINAL-period per-trial value — i.e. ``P(per-period value > x)``, NOT\n``P(NPV > x)``. To get a true ``P(NPV > 0)``, define an ``npv`` aggregation\nfirst, then add a ``prob`` aggregation whose ``target_aggregation_id`` points\nat that ``npv`` id; ``prob`` then thresholds the NPV per-trial vector directly.\nA ``prob`` request targets EITHER a node (``target_node_id``) OR an earlier\naggregation (``target_aggregation_id``) — exactly one, never both.",
            "properties": {
              "function": {
                "description": "One of: npv, irr, payback, discounted_payback, cagr, cumsum, prob, terminal_value, mirr. discounted_payback requires params.rate; npv requires params.rate OR a per-period params.rates curve; prob requires params.op (one of >, >=, <, <=, ==) and params.value; terminal_value requires params.g and params.rate; mirr requires params.finance_rate and params.reinvest_rate.",
                "title": "Function",
                "type": "string"
              },
              "id": {
                "description": "Result key for this metric (unique within the request).",
                "title": "Id",
                "type": "string"
              },
              "params": {
                "additionalProperties": true,
                "description": "Function params, e.g. {'rate': 0.1} for npv/discounted_payback, {'op': '>', 'value': 0} for prob, {'g': 0.02, 'rate': 0.1} for terminal_value, {'finance_rate': 0.1, 'reinvest_rate': 0.08} for mirr.",
                "title": "Params",
                "type": "object"
              },
              "target_aggregation_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "For a ``prob`` request only: the id of an aggregation defined EARLIER in this output_request whose per-trial vector (e.g. an ``npv``) is thresholded. Lets ``P(NPV > 0)`` be expressed directly instead of the per-period ``P(value > x)`` you get by targeting a multi-period node. The referenced aggregation must produce a per-trial vector (npv/irr/payback/discounted_payback/cagr/cumsum/terminal_value/mirr).",
                "title": "Target Aggregation Id"
              },
              "target_node_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "The node whose full per-period series the metric consumes. Required for every metric except a ``prob`` that targets a prior aggregation via ``target_aggregation_id``. Exactly one of ``target_node_id`` / ``target_aggregation_id`` may be set on a ``prob`` request.",
                "title": "Target Node Id"
              }
            },
            "required": [
              "id",
              "function"
            ],
            "title": "AggregationRequest",
            "type": "object"
          },
          "CalcNode": {
            "additionalProperties": false,
            "description": "A computed node. ``formula`` is OPTIONAL.\n\nA null/empty/whitespace formula is allowed: the node is treated as a\nconstant ``0`` every period/trial (incoming edges are ignored — there is no\nimplicit \"sum of incoming edges\"). ``validate_graph`` surfaces this as a\nWARNING, not an error. To sum incoming edges, write the sum explicitly,\ne.g. ``{e1}+{e2}``; for pass-through use ``{e1}``.",
            "properties": {
              "formula": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional expression over incoming edge ids, e.g. '{e1} * 0.5 + {e2}'. To sum incoming edges write '{e1}+{e2}'; for pass-through use '{e1}'. If omitted/empty the node is treated as a constant 0 (sum-of-incoming is not implied); validate_graph reports this as a warning.",
                "title": "Formula"
              },
              "id": {
                "description": "Unique node id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "name": {
                "default": "",
                "description": "Human-readable label.",
                "title": "Name",
                "type": "string"
              }
            },
            "required": [
              "id"
            ],
            "title": "CalcNode",
            "type": "object"
          },
          "Edge": {
            "additionalProperties": false,
            "description": "A directed connection carrying a value from source to target.",
            "properties": {
              "delay": {
                "default": 0,
                "description": "Periods the value is delayed in transit.",
                "minimum": 0,
                "title": "Delay",
                "type": "integer"
              },
              "id": {
                "description": "Unique edge id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "name": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional label.",
                "title": "Name"
              },
              "source": {
                "description": "id of the source node.",
                "title": "Source",
                "type": "string"
              },
              "target": {
                "description": "id of the target node.",
                "title": "Target",
                "type": "string"
              }
            },
            "required": [
              "id",
              "source",
              "target"
            ],
            "title": "Edge",
            "type": "object"
          },
          "OutputRequest": {
            "additionalProperties": false,
            "description": "Which nodes/edges/periods to include in the result.\n\nEmpty lists mean 'all': all nodes, all edges, all time periods.\n``aggregations`` requests post-simulation series metrics (NPV/IRR/...).",
            "properties": {
              "aggregations": {
                "items": {
                  "$ref": "#/$defs/AggregationRequest"
                },
                "title": "Aggregations",
                "type": "array"
              },
              "edges": {
                "items": {
                  "type": "string"
                },
                "title": "Edges",
                "type": "array"
              },
              "nodes": {
                "items": {
                  "type": "string"
                },
                "title": "Nodes",
                "type": "array"
              },
              "time_periods": {
                "items": {
                  "type": "integer"
                },
                "title": "Time Periods",
                "type": "array"
              }
            },
            "title": "OutputRequest",
            "type": "object"
          },
          "PublicGraph": {
            "additionalProperties": false,
            "description": "A complete, validated simulation request — the agent-facing input.\n\nThis is the canonical public shape. Reference integrity (edges point at real\nnodes, output_request references real ids) is validated here so malformed\ngraphs are rejected before they ever reach the engine.",
            "properties": {
              "calc_nodes": {
                "items": {
                  "$ref": "#/$defs/CalcNode"
                },
                "title": "Calc Nodes",
                "type": "array"
              },
              "contract_version": {
                "const": "1.0",
                "default": "1.0",
                "description": "Schema version this graph targets.",
                "title": "Contract Version",
                "type": "string"
              },
              "edges": {
                "items": {
                  "$ref": "#/$defs/Edge"
                },
                "title": "Edges",
                "type": "array"
              },
              "root_nodes": {
                "items": {
                  "$ref": "#/$defs/RootNode"
                },
                "title": "Root Nodes",
                "type": "array"
              },
              "run_params": {
                "$ref": "#/$defs/RunParams"
              }
            },
            "required": [
              "run_params"
            ],
            "title": "PublicGraph",
            "type": "object"
          },
          "RootNode": {
            "additionalProperties": false,
            "description": "A source node that samples from a probability distribution each period.",
            "properties": {
              "delay": {
                "default": 0,
                "description": "Periods to wait before the first sample.",
                "minimum": 0,
                "title": "Delay",
                "type": "integer"
              },
              "distribution_params": {
                "additionalProperties": true,
                "description": "Params for the chosen distribution, e.g. {'mean': 100, 'std': 15}.",
                "title": "Distribution Params",
                "type": "object"
              },
              "distribution_type": {
                "description": "One of the catalog distributions (GET /api/v1/contract).",
                "title": "Distribution Type",
                "type": "string"
              },
              "id": {
                "description": "Unique node id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "interval": {
                "default": 1,
                "description": "Sample every N periods (1 = every period).",
                "minimum": 0,
                "title": "Interval",
                "type": "integer"
              },
              "name": {
                "default": "",
                "description": "Human-readable label.",
                "title": "Name",
                "type": "string"
              },
              "sampling_frequency": {
                "default": "per_period",
                "description": "'once' draws a single value reused across periods.",
                "enum": [
                  "per_period",
                  "once"
                ],
                "title": "Sampling Frequency",
                "type": "string"
              }
            },
            "required": [
              "id",
              "distribution_type",
              "distribution_params"
            ],
            "title": "RootNode",
            "type": "object"
          },
          "RunParams": {
            "additionalProperties": false,
            "description": "Top-level run configuration.",
            "properties": {
              "output_request": {
                "$ref": "#/$defs/OutputRequest"
              },
              "time_periods": {
                "description": "Number of time periods to simulate.",
                "exclusiveMinimum": 0,
                "title": "Time Periods",
                "type": "integer"
              },
              "trials": {
                "description": "Number of Monte Carlo trials.",
                "exclusiveMinimum": 0,
                "title": "Trials",
                "type": "integer"
              }
            },
            "required": [
              "trials",
              "time_periods"
            ],
            "title": "RunParams",
            "type": "object"
          }
        },
        "description": "Arguments for ``estimate`` (runtime/memory pre-flight).",
        "properties": {
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional API key (estimation is free).",
            "title": "Api Key"
          },
          "graph": {
            "$ref": "#/$defs/PublicGraph",
            "description": "The graph to size."
          }
        },
        "required": [
          "graph"
        ],
        "title": "EstimateInput",
        "type": "object"
      },
      "name": "estimate"
    },
    {
      "description": "Sends feedback, a feature request, or a bug report straight to the Neumann team, CC'ing your sender_email so you keep a copy. Use this when something about the service is wrong, missing, or confusing and you want a human to see it directly rather than guessing at a workaround. Anonymous submissions are allowed. Example: {\"feedback_type\":\"feature_request\",\"message\":\"Add CSV export for run results.\",\"sender_email\":\"agent@example.com\"}",
      "inputSchema": {
        "description": "Arguments for ``feedback`` (neumann#114; mirrors fermi's schema).",
        "properties": {
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Your API key from POST /api/v1/accounts (optional). If provided, your account id is attached to the message for context.",
            "title": "Api Key"
          },
          "feedback_type": {
            "description": "The kind of feedback: 'feedback' for general comments, 'feature_request' for new capabilities, 'bug' for issues.",
            "enum": [
              "feedback",
              "feature_request",
              "bug"
            ],
            "title": "Feedback Type",
            "type": "string"
          },
          "message": {
            "description": "Your feedback or request. Be as specific as possible.",
            "maxLength": 5000,
            "minLength": 10,
            "title": "Message",
            "type": "string"
          },
          "sender_email": {
            "description": "Your email address. A copy of your feedback is CC'd here so you have a record of what you submitted.",
            "format": "email",
            "title": "Sender Email",
            "type": "string"
          },
          "sender_name": {
            "anyOf": [
              {
                "maxLength": 200,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Your name (optional).",
            "title": "Sender Name"
          }
        },
        "required": [
          "feedback_type",
          "message",
          "sender_email"
        ],
        "title": "FeedbackInput",
        "type": "object"
      },
      "name": "feedback"
    },
    {
      "description": "Fetches the status and, once available, the summarised result for a previously-submitted run by its run_id. Use this when you want to re-check or re-fetch a run you already submitted (e.g. via run_simulation) without resubmitting the graph -- run_simulation itself already blocks until done and returns the full result directly, so this is not a poll-until-ready step for it. Example: {\"run_id\":\"run_8f3c2a\"}",
      "inputSchema": {
        "description": "Arguments for ``get_results``.",
        "properties": {
          "run_id": {
            "description": "A run id returned by run_simulation.",
            "title": "Run Id",
            "type": "string"
          }
        },
        "required": [
          "run_id"
        ],
        "title": "GetResultsInput",
        "type": "object"
      },
      "name": "get_results"
    },
    {
      "description": "Runs a one-at-a-time tornado sensitivity analysis: sweeps each root node over a set of quantiles (others held at baseline) and measures how the target node responds, ranked by impact. Use this when you need to know which uncertain input most drives an outcome, so you know what to de-risk or estimate more carefully first. Debits one credit for authenticated callers. Example: {\"graph\":{\"root_nodes\":[{\"id\":\"root\",\"distribution_type\":\"normal\",\"distribution_params\":{\"mean\":100,\"std\":15}}],\"calc_nodes\":[{\"id\":\"out\",\"formula\":\"{e1}\"}],\"edges\":[{\"id\":\"e1\",\"source\":\"root\",\"target\":\"out\"}],\"run_params\":{\"trials\":1000,\"time_periods\":12}}}",
      "inputSchema": {
        "$defs": {
          "AggregationRequest": {
            "additionalProperties": false,
            "description": "A post-simulation, series-aware metric over one node's full series.\n\nNPV/IRR/payback/CAGR/cumsum are NOT per-period node values: they consume a\ntarget node's complete ``(time_periods x trials)`` matrix AFTER the run and\nreturn one value per trial, summarised into a distribution.\n\nDiscount convention (0-based series index): period ``t=0`` is the present\n(undiscounted) cash flow; period ``t`` is discounted by ``(1+rate)**t``. The\nfirst period is undiscounted.\n\nWarning — two discount conventions coexist; do not mix them. These\naggregations use the **0-based** series index above (first period\nundiscounted). The per-period formula functions ``DISCOUNT(rate,\n{time_period})`` and ``PV(rate, value, {time_period})`` use the **1-based**\n``{time_period}``, so they discount the first period by ``(1+rate)**1``.\n\n\"Investment at period 0\" pattern: model an up-front outlay as a negative\nperiod-0 cash flow in the target node's series; NPV's t=0-undiscounted\nconvention then treats it as the present-value outlay. Do not additionally\ndiscount that first period with ``PV(...,{time_period})`` inside the target\nnode's formula when also requesting an aggregation ``npv`` — combining the\n1-based per-period discount with the 0-based ``npv`` double-shifts the first\nperiod.\n\nPer-period node vs aggregate metric (``prob``): pointing ``prob`` at a\nmulti-period cash-flow NODE via ``target_node_id`` thresholds only that node's\nFINAL-period per-trial value — i.e. ``P(per-period value > x)``, NOT\n``P(NPV > x)``. To get a true ``P(NPV > 0)``, define an ``npv`` aggregation\nfirst, then add a ``prob`` aggregation whose ``target_aggregation_id`` points\nat that ``npv`` id; ``prob`` then thresholds the NPV per-trial vector directly.\nA ``prob`` request targets EITHER a node (``target_node_id``) OR an earlier\naggregation (``target_aggregation_id``) — exactly one, never both.",
            "properties": {
              "function": {
                "description": "One of: npv, irr, payback, discounted_payback, cagr, cumsum, prob, terminal_value, mirr. discounted_payback requires params.rate; npv requires params.rate OR a per-period params.rates curve; prob requires params.op (one of >, >=, <, <=, ==) and params.value; terminal_value requires params.g and params.rate; mirr requires params.finance_rate and params.reinvest_rate.",
                "title": "Function",
                "type": "string"
              },
              "id": {
                "description": "Result key for this metric (unique within the request).",
                "title": "Id",
                "type": "string"
              },
              "params": {
                "additionalProperties": true,
                "description": "Function params, e.g. {'rate': 0.1} for npv/discounted_payback, {'op': '>', 'value': 0} for prob, {'g': 0.02, 'rate': 0.1} for terminal_value, {'finance_rate': 0.1, 'reinvest_rate': 0.08} for mirr.",
                "title": "Params",
                "type": "object"
              },
              "target_aggregation_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "For a ``prob`` request only: the id of an aggregation defined EARLIER in this output_request whose per-trial vector (e.g. an ``npv``) is thresholded. Lets ``P(NPV > 0)`` be expressed directly instead of the per-period ``P(value > x)`` you get by targeting a multi-period node. The referenced aggregation must produce a per-trial vector (npv/irr/payback/discounted_payback/cagr/cumsum/terminal_value/mirr).",
                "title": "Target Aggregation Id"
              },
              "target_node_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "The node whose full per-period series the metric consumes. Required for every metric except a ``prob`` that targets a prior aggregation via ``target_aggregation_id``. Exactly one of ``target_node_id`` / ``target_aggregation_id`` may be set on a ``prob`` request.",
                "title": "Target Node Id"
              }
            },
            "required": [
              "id",
              "function"
            ],
            "title": "AggregationRequest",
            "type": "object"
          },
          "CalcNode": {
            "additionalProperties": false,
            "description": "A computed node. ``formula`` is OPTIONAL.\n\nA null/empty/whitespace formula is allowed: the node is treated as a\nconstant ``0`` every period/trial (incoming edges are ignored — there is no\nimplicit \"sum of incoming edges\"). ``validate_graph`` surfaces this as a\nWARNING, not an error. To sum incoming edges, write the sum explicitly,\ne.g. ``{e1}+{e2}``; for pass-through use ``{e1}``.",
            "properties": {
              "formula": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional expression over incoming edge ids, e.g. '{e1} * 0.5 + {e2}'. To sum incoming edges write '{e1}+{e2}'; for pass-through use '{e1}'. If omitted/empty the node is treated as a constant 0 (sum-of-incoming is not implied); validate_graph reports this as a warning.",
                "title": "Formula"
              },
              "id": {
                "description": "Unique node id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "name": {
                "default": "",
                "description": "Human-readable label.",
                "title": "Name",
                "type": "string"
              }
            },
            "required": [
              "id"
            ],
            "title": "CalcNode",
            "type": "object"
          },
          "Edge": {
            "additionalProperties": false,
            "description": "A directed connection carrying a value from source to target.",
            "properties": {
              "delay": {
                "default": 0,
                "description": "Periods the value is delayed in transit.",
                "minimum": 0,
                "title": "Delay",
                "type": "integer"
              },
              "id": {
                "description": "Unique edge id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "name": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional label.",
                "title": "Name"
              },
              "source": {
                "description": "id of the source node.",
                "title": "Source",
                "type": "string"
              },
              "target": {
                "description": "id of the target node.",
                "title": "Target",
                "type": "string"
              }
            },
            "required": [
              "id",
              "source",
              "target"
            ],
            "title": "Edge",
            "type": "object"
          },
          "OutputRequest": {
            "additionalProperties": false,
            "description": "Which nodes/edges/periods to include in the result.\n\nEmpty lists mean 'all': all nodes, all edges, all time periods.\n``aggregations`` requests post-simulation series metrics (NPV/IRR/...).",
            "properties": {
              "aggregations": {
                "items": {
                  "$ref": "#/$defs/AggregationRequest"
                },
                "title": "Aggregations",
                "type": "array"
              },
              "edges": {
                "items": {
                  "type": "string"
                },
                "title": "Edges",
                "type": "array"
              },
              "nodes": {
                "items": {
                  "type": "string"
                },
                "title": "Nodes",
                "type": "array"
              },
              "time_periods": {
                "items": {
                  "type": "integer"
                },
                "title": "Time Periods",
                "type": "array"
              }
            },
            "title": "OutputRequest",
            "type": "object"
          },
          "PublicGraph": {
            "additionalProperties": false,
            "description": "A complete, validated simulation request — the agent-facing input.\n\nThis is the canonical public shape. Reference integrity (edges point at real\nnodes, output_request references real ids) is validated here so malformed\ngraphs are rejected before they ever reach the engine.",
            "properties": {
              "calc_nodes": {
                "items": {
                  "$ref": "#/$defs/CalcNode"
                },
                "title": "Calc Nodes",
                "type": "array"
              },
              "contract_version": {
                "const": "1.0",
                "default": "1.0",
                "description": "Schema version this graph targets.",
                "title": "Contract Version",
                "type": "string"
              },
              "edges": {
                "items": {
                  "$ref": "#/$defs/Edge"
                },
                "title": "Edges",
                "type": "array"
              },
              "root_nodes": {
                "items": {
                  "$ref": "#/$defs/RootNode"
                },
                "title": "Root Nodes",
                "type": "array"
              },
              "run_params": {
                "$ref": "#/$defs/RunParams"
              }
            },
            "required": [
              "run_params"
            ],
            "title": "PublicGraph",
            "type": "object"
          },
          "RootNode": {
            "additionalProperties": false,
            "description": "A source node that samples from a probability distribution each period.",
            "properties": {
              "delay": {
                "default": 0,
                "description": "Periods to wait before the first sample.",
                "minimum": 0,
                "title": "Delay",
                "type": "integer"
              },
              "distribution_params": {
                "additionalProperties": true,
                "description": "Params for the chosen distribution, e.g. {'mean': 100, 'std': 15}.",
                "title": "Distribution Params",
                "type": "object"
              },
              "distribution_type": {
                "description": "One of the catalog distributions (GET /api/v1/contract).",
                "title": "Distribution Type",
                "type": "string"
              },
              "id": {
                "description": "Unique node id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "interval": {
                "default": 1,
                "description": "Sample every N periods (1 = every period).",
                "minimum": 0,
                "title": "Interval",
                "type": "integer"
              },
              "name": {
                "default": "",
                "description": "Human-readable label.",
                "title": "Name",
                "type": "string"
              },
              "sampling_frequency": {
                "default": "per_period",
                "description": "'once' draws a single value reused across periods.",
                "enum": [
                  "per_period",
                  "once"
                ],
                "title": "Sampling Frequency",
                "type": "string"
              }
            },
            "required": [
              "id",
              "distribution_type",
              "distribution_params"
            ],
            "title": "RootNode",
            "type": "object"
          },
          "RunParams": {
            "additionalProperties": false,
            "description": "Top-level run configuration.",
            "properties": {
              "output_request": {
                "$ref": "#/$defs/OutputRequest"
              },
              "time_periods": {
                "description": "Number of time periods to simulate.",
                "exclusiveMinimum": 0,
                "title": "Time Periods",
                "type": "integer"
              },
              "trials": {
                "description": "Number of Monte Carlo trials.",
                "exclusiveMinimum": 0,
                "title": "Trials",
                "type": "integer"
              }
            },
            "required": [
              "trials",
              "time_periods"
            ],
            "title": "RunParams",
            "type": "object"
          }
        },
        "description": "Arguments for ``oat_sensitivity`` (one-at-a-time tornado analysis).",
        "properties": {
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Your API key from POST /api/v1/accounts. Debits credits per analysis. Omit to run anonymously (free).",
            "title": "Api Key"
          },
          "graph": {
            "$ref": "#/$defs/PublicGraph",
            "description": "The full simulation graph to analyse (same shape as run_simulation)."
          },
          "num_quantiles": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Even count (2-10) of symmetrical quantiles around the 0.5 baseline. Mutually exclusive with quantiles.",
            "title": "Num Quantiles"
          },
          "quantiles": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Explicit quantiles to sweep each input over (0..1). Mutually exclusive with num_quantiles. Default: [0.05, 0.5, 0.95] (tornado).",
            "title": "Quantiles"
          },
          "seed": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional RNG seed for reproducible perturbed runs.",
            "title": "Seed"
          },
          "target_node_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The output node to measure. Defaults to the graph's last calc node (the usual goal node).",
            "title": "Target Node Id"
          },
          "time_period": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "0-based time period to analyse. Defaults to the last period (time_periods - 1).",
            "title": "Time Period"
          }
        },
        "required": [
          "graph"
        ],
        "title": "OatSensitivityInput",
        "type": "object"
      },
      "name": "oat_sensitivity"
    },
    {
      "description": "Runs a Monte Carlo simulation over a graph of probabilistic root and calculated nodes, returning the full output distribution instead of one guessed number. Use this when you need the range and likelihood of outcomes for a plan driven by uncertain inputs, not just its average case. Both tiers run to completion and return the full result in this same call, never a run_id to poll. Example: {\"graph\":{\"root_nodes\":[{\"id\":\"root\",\"distribution_type\":\"normal\",\"distribution_params\":{\"mean\":100,\"std\":15}}],\"calc_nodes\":[{\"id\":\"out\",\"formula\":\"{e1}\"}],\"edges\":[{\"id\":\"e1\",\"source\":\"root\",\"target\":\"out\"}],\"run_params\":{\"trials\":1000,\"time_periods\":12}}}",
      "inputSchema": {
        "$defs": {
          "AggregationRequest": {
            "additionalProperties": false,
            "description": "A post-simulation, series-aware metric over one node's full series.\n\nNPV/IRR/payback/CAGR/cumsum are NOT per-period node values: they consume a\ntarget node's complete ``(time_periods x trials)`` matrix AFTER the run and\nreturn one value per trial, summarised into a distribution.\n\nDiscount convention (0-based series index): period ``t=0`` is the present\n(undiscounted) cash flow; period ``t`` is discounted by ``(1+rate)**t``. The\nfirst period is undiscounted.\n\nWarning — two discount conventions coexist; do not mix them. These\naggregations use the **0-based** series index above (first period\nundiscounted). The per-period formula functions ``DISCOUNT(rate,\n{time_period})`` and ``PV(rate, value, {time_period})`` use the **1-based**\n``{time_period}``, so they discount the first period by ``(1+rate)**1``.\n\n\"Investment at period 0\" pattern: model an up-front outlay as a negative\nperiod-0 cash flow in the target node's series; NPV's t=0-undiscounted\nconvention then treats it as the present-value outlay. Do not additionally\ndiscount that first period with ``PV(...,{time_period})`` inside the target\nnode's formula when also requesting an aggregation ``npv`` — combining the\n1-based per-period discount with the 0-based ``npv`` double-shifts the first\nperiod.\n\nPer-period node vs aggregate metric (``prob``): pointing ``prob`` at a\nmulti-period cash-flow NODE via ``target_node_id`` thresholds only that node's\nFINAL-period per-trial value — i.e. ``P(per-period value > x)``, NOT\n``P(NPV > x)``. To get a true ``P(NPV > 0)``, define an ``npv`` aggregation\nfirst, then add a ``prob`` aggregation whose ``target_aggregation_id`` points\nat that ``npv`` id; ``prob`` then thresholds the NPV per-trial vector directly.\nA ``prob`` request targets EITHER a node (``target_node_id``) OR an earlier\naggregation (``target_aggregation_id``) — exactly one, never both.",
            "properties": {
              "function": {
                "description": "One of: npv, irr, payback, discounted_payback, cagr, cumsum, prob, terminal_value, mirr. discounted_payback requires params.rate; npv requires params.rate OR a per-period params.rates curve; prob requires params.op (one of >, >=, <, <=, ==) and params.value; terminal_value requires params.g and params.rate; mirr requires params.finance_rate and params.reinvest_rate.",
                "title": "Function",
                "type": "string"
              },
              "id": {
                "description": "Result key for this metric (unique within the request).",
                "title": "Id",
                "type": "string"
              },
              "params": {
                "additionalProperties": true,
                "description": "Function params, e.g. {'rate': 0.1} for npv/discounted_payback, {'op': '>', 'value': 0} for prob, {'g': 0.02, 'rate': 0.1} for terminal_value, {'finance_rate': 0.1, 'reinvest_rate': 0.08} for mirr.",
                "title": "Params",
                "type": "object"
              },
              "target_aggregation_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "For a ``prob`` request only: the id of an aggregation defined EARLIER in this output_request whose per-trial vector (e.g. an ``npv``) is thresholded. Lets ``P(NPV > 0)`` be expressed directly instead of the per-period ``P(value > x)`` you get by targeting a multi-period node. The referenced aggregation must produce a per-trial vector (npv/irr/payback/discounted_payback/cagr/cumsum/terminal_value/mirr).",
                "title": "Target Aggregation Id"
              },
              "target_node_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "The node whose full per-period series the metric consumes. Required for every metric except a ``prob`` that targets a prior aggregation via ``target_aggregation_id``. Exactly one of ``target_node_id`` / ``target_aggregation_id`` may be set on a ``prob`` request.",
                "title": "Target Node Id"
              }
            },
            "required": [
              "id",
              "function"
            ],
            "title": "AggregationRequest",
            "type": "object"
          },
          "CalcNode": {
            "additionalProperties": false,
            "description": "A computed node. ``formula`` is OPTIONAL.\n\nA null/empty/whitespace formula is allowed: the node is treated as a\nconstant ``0`` every period/trial (incoming edges are ignored — there is no\nimplicit \"sum of incoming edges\"). ``validate_graph`` surfaces this as a\nWARNING, not an error. To sum incoming edges, write the sum explicitly,\ne.g. ``{e1}+{e2}``; for pass-through use ``{e1}``.",
            "properties": {
              "formula": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional expression over incoming edge ids, e.g. '{e1} * 0.5 + {e2}'. To sum incoming edges write '{e1}+{e2}'; for pass-through use '{e1}'. If omitted/empty the node is treated as a constant 0 (sum-of-incoming is not implied); validate_graph reports this as a warning.",
                "title": "Formula"
              },
              "id": {
                "description": "Unique node id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "name": {
                "default": "",
                "description": "Human-readable label.",
                "title": "Name",
                "type": "string"
              }
            },
            "required": [
              "id"
            ],
            "title": "CalcNode",
            "type": "object"
          },
          "Edge": {
            "additionalProperties": false,
            "description": "A directed connection carrying a value from source to target.",
            "properties": {
              "delay": {
                "default": 0,
                "description": "Periods the value is delayed in transit.",
                "minimum": 0,
                "title": "Delay",
                "type": "integer"
              },
              "id": {
                "description": "Unique edge id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "name": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional label.",
                "title": "Name"
              },
              "source": {
                "description": "id of the source node.",
                "title": "Source",
                "type": "string"
              },
              "target": {
                "description": "id of the target node.",
                "title": "Target",
                "type": "string"
              }
            },
            "required": [
              "id",
              "source",
              "target"
            ],
            "title": "Edge",
            "type": "object"
          },
          "OutputRequest": {
            "additionalProperties": false,
            "description": "Which nodes/edges/periods to include in the result.\n\nEmpty lists mean 'all': all nodes, all edges, all time periods.\n``aggregations`` requests post-simulation series metrics (NPV/IRR/...).",
            "properties": {
              "aggregations": {
                "items": {
                  "$ref": "#/$defs/AggregationRequest"
                },
                "title": "Aggregations",
                "type": "array"
              },
              "edges": {
                "items": {
                  "type": "string"
                },
                "title": "Edges",
                "type": "array"
              },
              "nodes": {
                "items": {
                  "type": "string"
                },
                "title": "Nodes",
                "type": "array"
              },
              "time_periods": {
                "items": {
                  "type": "integer"
                },
                "title": "Time Periods",
                "type": "array"
              }
            },
            "title": "OutputRequest",
            "type": "object"
          },
          "PublicGraph": {
            "additionalProperties": false,
            "description": "A complete, validated simulation request — the agent-facing input.\n\nThis is the canonical public shape. Reference integrity (edges point at real\nnodes, output_request references real ids) is validated here so malformed\ngraphs are rejected before they ever reach the engine.",
            "properties": {
              "calc_nodes": {
                "items": {
                  "$ref": "#/$defs/CalcNode"
                },
                "title": "Calc Nodes",
                "type": "array"
              },
              "contract_version": {
                "const": "1.0",
                "default": "1.0",
                "description": "Schema version this graph targets.",
                "title": "Contract Version",
                "type": "string"
              },
              "edges": {
                "items": {
                  "$ref": "#/$defs/Edge"
                },
                "title": "Edges",
                "type": "array"
              },
              "root_nodes": {
                "items": {
                  "$ref": "#/$defs/RootNode"
                },
                "title": "Root Nodes",
                "type": "array"
              },
              "run_params": {
                "$ref": "#/$defs/RunParams"
              }
            },
            "required": [
              "run_params"
            ],
            "title": "PublicGraph",
            "type": "object"
          },
          "RootNode": {
            "additionalProperties": false,
            "description": "A source node that samples from a probability distribution each period.",
            "properties": {
              "delay": {
                "default": 0,
                "description": "Periods to wait before the first sample.",
                "minimum": 0,
                "title": "Delay",
                "type": "integer"
              },
              "distribution_params": {
                "additionalProperties": true,
                "description": "Params for the chosen distribution, e.g. {'mean': 100, 'std': 15}.",
                "title": "Distribution Params",
                "type": "object"
              },
              "distribution_type": {
                "description": "One of the catalog distributions (GET /api/v1/contract).",
                "title": "Distribution Type",
                "type": "string"
              },
              "id": {
                "description": "Unique node id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "interval": {
                "default": 1,
                "description": "Sample every N periods (1 = every period).",
                "minimum": 0,
                "title": "Interval",
                "type": "integer"
              },
              "name": {
                "default": "",
                "description": "Human-readable label.",
                "title": "Name",
                "type": "string"
              },
              "sampling_frequency": {
                "default": "per_period",
                "description": "'once' draws a single value reused across periods.",
                "enum": [
                  "per_period",
                  "once"
                ],
                "title": "Sampling Frequency",
                "type": "string"
              }
            },
            "required": [
              "id",
              "distribution_type",
              "distribution_params"
            ],
            "title": "RootNode",
            "type": "object"
          },
          "RunParams": {
            "additionalProperties": false,
            "description": "Top-level run configuration.",
            "properties": {
              "output_request": {
                "$ref": "#/$defs/OutputRequest"
              },
              "time_periods": {
                "description": "Number of time periods to simulate.",
                "exclusiveMinimum": 0,
                "title": "Time Periods",
                "type": "integer"
              },
              "trials": {
                "description": "Number of Monte Carlo trials.",
                "exclusiveMinimum": 0,
                "title": "Trials",
                "type": "integer"
              }
            },
            "required": [
              "trials",
              "time_periods"
            ],
            "title": "RunParams",
            "type": "object"
          }
        },
        "description": "Arguments for ``run_simulation``.",
        "properties": {
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Your API key from POST /api/v1/accounts. Debits credits per run. Omit to run anonymously (free, but no credit accounting).",
            "title": "Api Key"
          },
          "graph": {
            "$ref": "#/$defs/PublicGraph",
            "description": "The full simulation graph (root_nodes, calc_nodes, edges, run_params). See GET /api/v1/contract for valid distribution types."
          },
          "include_histogram": {
            "default": false,
            "description": "Include a per-element histogram in each summary element.",
            "title": "Include Histogram",
            "type": "boolean"
          },
          "seed": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional RNG seed; reproducible only on the small/inline path.",
            "title": "Seed"
          }
        },
        "required": [
          "graph"
        ],
        "title": "RunSimulationInput",
        "type": "object"
      },
      "name": "run_simulation"
    },
    {
      "description": "Runs a simulation once and summarises a target node's worst/median/best outcomes (any percentiles), each paired with a best-effort driving input per root node. Use this when you need a quick worst-case/median/best-case narrative for a plan rather than the full distribution. Debits one credit for authenticated callers. Example: {\"graph\":{\"root_nodes\":[{\"id\":\"root\",\"distribution_type\":\"normal\",\"distribution_params\":{\"mean\":100,\"std\":15}}],\"calc_nodes\":[{\"id\":\"out\",\"formula\":\"{e1}\"}],\"edges\":[{\"id\":\"e1\",\"source\":\"root\",\"target\":\"out\"}],\"run_params\":{\"trials\":1000,\"time_periods\":12}}}",
      "inputSchema": {
        "$defs": {
          "AggregationRequest": {
            "additionalProperties": false,
            "description": "A post-simulation, series-aware metric over one node's full series.\n\nNPV/IRR/payback/CAGR/cumsum are NOT per-period node values: they consume a\ntarget node's complete ``(time_periods x trials)`` matrix AFTER the run and\nreturn one value per trial, summarised into a distribution.\n\nDiscount convention (0-based series index): period ``t=0`` is the present\n(undiscounted) cash flow; period ``t`` is discounted by ``(1+rate)**t``. The\nfirst period is undiscounted.\n\nWarning — two discount conventions coexist; do not mix them. These\naggregations use the **0-based** series index above (first period\nundiscounted). The per-period formula functions ``DISCOUNT(rate,\n{time_period})`` and ``PV(rate, value, {time_period})`` use the **1-based**\n``{time_period}``, so they discount the first period by ``(1+rate)**1``.\n\n\"Investment at period 0\" pattern: model an up-front outlay as a negative\nperiod-0 cash flow in the target node's series; NPV's t=0-undiscounted\nconvention then treats it as the present-value outlay. Do not additionally\ndiscount that first period with ``PV(...,{time_period})`` inside the target\nnode's formula when also requesting an aggregation ``npv`` — combining the\n1-based per-period discount with the 0-based ``npv`` double-shifts the first\nperiod.\n\nPer-period node vs aggregate metric (``prob``): pointing ``prob`` at a\nmulti-period cash-flow NODE via ``target_node_id`` thresholds only that node's\nFINAL-period per-trial value — i.e. ``P(per-period value > x)``, NOT\n``P(NPV > x)``. To get a true ``P(NPV > 0)``, define an ``npv`` aggregation\nfirst, then add a ``prob`` aggregation whose ``target_aggregation_id`` points\nat that ``npv`` id; ``prob`` then thresholds the NPV per-trial vector directly.\nA ``prob`` request targets EITHER a node (``target_node_id``) OR an earlier\naggregation (``target_aggregation_id``) — exactly one, never both.",
            "properties": {
              "function": {
                "description": "One of: npv, irr, payback, discounted_payback, cagr, cumsum, prob, terminal_value, mirr. discounted_payback requires params.rate; npv requires params.rate OR a per-period params.rates curve; prob requires params.op (one of >, >=, <, <=, ==) and params.value; terminal_value requires params.g and params.rate; mirr requires params.finance_rate and params.reinvest_rate.",
                "title": "Function",
                "type": "string"
              },
              "id": {
                "description": "Result key for this metric (unique within the request).",
                "title": "Id",
                "type": "string"
              },
              "params": {
                "additionalProperties": true,
                "description": "Function params, e.g. {'rate': 0.1} for npv/discounted_payback, {'op': '>', 'value': 0} for prob, {'g': 0.02, 'rate': 0.1} for terminal_value, {'finance_rate': 0.1, 'reinvest_rate': 0.08} for mirr.",
                "title": "Params",
                "type": "object"
              },
              "target_aggregation_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "For a ``prob`` request only: the id of an aggregation defined EARLIER in this output_request whose per-trial vector (e.g. an ``npv``) is thresholded. Lets ``P(NPV > 0)`` be expressed directly instead of the per-period ``P(value > x)`` you get by targeting a multi-period node. The referenced aggregation must produce a per-trial vector (npv/irr/payback/discounted_payback/cagr/cumsum/terminal_value/mirr).",
                "title": "Target Aggregation Id"
              },
              "target_node_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "The node whose full per-period series the metric consumes. Required for every metric except a ``prob`` that targets a prior aggregation via ``target_aggregation_id``. Exactly one of ``target_node_id`` / ``target_aggregation_id`` may be set on a ``prob`` request.",
                "title": "Target Node Id"
              }
            },
            "required": [
              "id",
              "function"
            ],
            "title": "AggregationRequest",
            "type": "object"
          },
          "CalcNode": {
            "additionalProperties": false,
            "description": "A computed node. ``formula`` is OPTIONAL.\n\nA null/empty/whitespace formula is allowed: the node is treated as a\nconstant ``0`` every period/trial (incoming edges are ignored — there is no\nimplicit \"sum of incoming edges\"). ``validate_graph`` surfaces this as a\nWARNING, not an error. To sum incoming edges, write the sum explicitly,\ne.g. ``{e1}+{e2}``; for pass-through use ``{e1}``.",
            "properties": {
              "formula": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional expression over incoming edge ids, e.g. '{e1} * 0.5 + {e2}'. To sum incoming edges write '{e1}+{e2}'; for pass-through use '{e1}'. If omitted/empty the node is treated as a constant 0 (sum-of-incoming is not implied); validate_graph reports this as a warning.",
                "title": "Formula"
              },
              "id": {
                "description": "Unique node id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "name": {
                "default": "",
                "description": "Human-readable label.",
                "title": "Name",
                "type": "string"
              }
            },
            "required": [
              "id"
            ],
            "title": "CalcNode",
            "type": "object"
          },
          "Edge": {
            "additionalProperties": false,
            "description": "A directed connection carrying a value from source to target.",
            "properties": {
              "delay": {
                "default": 0,
                "description": "Periods the value is delayed in transit.",
                "minimum": 0,
                "title": "Delay",
                "type": "integer"
              },
              "id": {
                "description": "Unique edge id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "name": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional label.",
                "title": "Name"
              },
              "source": {
                "description": "id of the source node.",
                "title": "Source",
                "type": "string"
              },
              "target": {
                "description": "id of the target node.",
                "title": "Target",
                "type": "string"
              }
            },
            "required": [
              "id",
              "source",
              "target"
            ],
            "title": "Edge",
            "type": "object"
          },
          "OutputRequest": {
            "additionalProperties": false,
            "description": "Which nodes/edges/periods to include in the result.\n\nEmpty lists mean 'all': all nodes, all edges, all time periods.\n``aggregations`` requests post-simulation series metrics (NPV/IRR/...).",
            "properties": {
              "aggregations": {
                "items": {
                  "$ref": "#/$defs/AggregationRequest"
                },
                "title": "Aggregations",
                "type": "array"
              },
              "edges": {
                "items": {
                  "type": "string"
                },
                "title": "Edges",
                "type": "array"
              },
              "nodes": {
                "items": {
                  "type": "string"
                },
                "title": "Nodes",
                "type": "array"
              },
              "time_periods": {
                "items": {
                  "type": "integer"
                },
                "title": "Time Periods",
                "type": "array"
              }
            },
            "title": "OutputRequest",
            "type": "object"
          },
          "PublicGraph": {
            "additionalProperties": false,
            "description": "A complete, validated simulation request — the agent-facing input.\n\nThis is the canonical public shape. Reference integrity (edges point at real\nnodes, output_request references real ids) is validated here so malformed\ngraphs are rejected before they ever reach the engine.",
            "properties": {
              "calc_nodes": {
                "items": {
                  "$ref": "#/$defs/CalcNode"
                },
                "title": "Calc Nodes",
                "type": "array"
              },
              "contract_version": {
                "const": "1.0",
                "default": "1.0",
                "description": "Schema version this graph targets.",
                "title": "Contract Version",
                "type": "string"
              },
              "edges": {
                "items": {
                  "$ref": "#/$defs/Edge"
                },
                "title": "Edges",
                "type": "array"
              },
              "root_nodes": {
                "items": {
                  "$ref": "#/$defs/RootNode"
                },
                "title": "Root Nodes",
                "type": "array"
              },
              "run_params": {
                "$ref": "#/$defs/RunParams"
              }
            },
            "required": [
              "run_params"
            ],
            "title": "PublicGraph",
            "type": "object"
          },
          "RootNode": {
            "additionalProperties": false,
            "description": "A source node that samples from a probability distribution each period.",
            "properties": {
              "delay": {
                "default": 0,
                "description": "Periods to wait before the first sample.",
                "minimum": 0,
                "title": "Delay",
                "type": "integer"
              },
              "distribution_params": {
                "additionalProperties": true,
                "description": "Params for the chosen distribution, e.g. {'mean': 100, 'std': 15}.",
                "title": "Distribution Params",
                "type": "object"
              },
              "distribution_type": {
                "description": "One of the catalog distributions (GET /api/v1/contract).",
                "title": "Distribution Type",
                "type": "string"
              },
              "id": {
                "description": "Unique node id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "interval": {
                "default": 1,
                "description": "Sample every N periods (1 = every period).",
                "minimum": 0,
                "title": "Interval",
                "type": "integer"
              },
              "name": {
                "default": "",
                "description": "Human-readable label.",
                "title": "Name",
                "type": "string"
              },
              "sampling_frequency": {
                "default": "per_period",
                "description": "'once' draws a single value reused across periods.",
                "enum": [
                  "per_period",
                  "once"
                ],
                "title": "Sampling Frequency",
                "type": "string"
              }
            },
            "required": [
              "id",
              "distribution_type",
              "distribution_params"
            ],
            "title": "RootNode",
            "type": "object"
          },
          "RunParams": {
            "additionalProperties": false,
            "description": "Top-level run configuration.",
            "properties": {
              "output_request": {
                "$ref": "#/$defs/OutputRequest"
              },
              "time_periods": {
                "description": "Number of time periods to simulate.",
                "exclusiveMinimum": 0,
                "title": "Time Periods",
                "type": "integer"
              },
              "trials": {
                "description": "Number of Monte Carlo trials.",
                "exclusiveMinimum": 0,
                "title": "Trials",
                "type": "integer"
              }
            },
            "required": [
              "trials",
              "time_periods"
            ],
            "title": "RunParams",
            "type": "object"
          }
        },
        "description": "Arguments for ``scenario_analysis`` (best/median/worst across trials).",
        "properties": {
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Your API key from POST /api/v1/accounts. Debits credits per analysis (priced like one run). Omit to run anonymously (free).",
            "title": "Api Key"
          },
          "graph": {
            "$ref": "#/$defs/PublicGraph",
            "description": "The full simulation graph (same shape as run_simulation)."
          },
          "percentiles": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Scenario percentiles in [0,1]. Default [0.0, 0.5, 1.0] = worst / median / best.",
            "title": "Percentiles"
          },
          "seed": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional RNG seed for a reproducible run.",
            "title": "Seed"
          },
          "target_node_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The output node to summarise. Defaults to the graph's last calc node (the usual goal node).",
            "title": "Target Node Id"
          },
          "time_period": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "0-based time period to analyse. Defaults to the last period (time_periods - 1).",
            "title": "Time Period"
          }
        },
        "required": [
          "graph"
        ],
        "title": "ScenarioAnalysisInput",
        "type": "object"
      },
      "name": "scenario_analysis"
    },
    {
      "description": "Creates (or fetches the existing) public share link for a PERSISTED run from the stored-graph flow, renderable as HTML/JSON/SVG. Use this when you want to hand a result to someone without giving them API access -- only for a run saved via the stored-graph flow: a run_simulation result is ephemeral and has no usable run_id. Requires authentication (api_key argument or an Authorization: Bearer token) to CREATE the link; the resulting share_url itself needs no credential to view. Example: {\"run_id\":\"run_8f3c2a\"}",
      "inputSchema": {
        "description": "Arguments for ``share_result`` (neumann#228).\n\n``run_id`` must be a PERSISTED run from the stored-graph flow (the one\n``POST /api/v1/graphs/{graph_id}/runs`` creates), not a ``run_simulation``\nresult — those are ephemeral and were never written to durable storage, so\nthere is nothing to share (see the tool description for why).",
        "properties": {
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Your API key from POST /api/v1/accounts. Required unless you are authenticated via an Authorization: Bearer token.",
            "title": "Api Key"
          },
          "run_id": {
            "description": "A persisted (stored-graph) run id.",
            "title": "Run Id",
            "type": "string"
          }
        },
        "required": [
          "run_id"
        ],
        "title": "ShareResultInput",
        "type": "object"
      },
      "name": "share_result"
    },
    {
      "description": "Converts a human-style estimate (a min/max range at a stated confidence, or a most-likely value) into the distribution_params a root node needs. Use this when you have a rough verbal estimate like 'between 80 and 120, 90% confident' and need engine-ready parameters rather than guessing them yourself. Free; no credits debited. Example: {\"distribution_type\":\"normal\",\"min_estimate\":80,\"max_estimate\":120,\"percentile_range\":0.9}",
      "inputSchema": {
        "description": "Arguments for ``solve_distribution_parameters``.\n\nFind distribution parameters that fit a min/max range at a given confidence,\nso an agent can turn a human-style 'between X and Y' estimate into engine-ready\n``distribution_params``.",
        "properties": {
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional API key (solving is free).",
            "title": "Api Key"
          },
          "distribution_type": {
            "description": "A catalog distribution, e.g. 'normal', 'triangle', 'beta'.",
            "title": "Distribution Type",
            "type": "string"
          },
          "max_estimate": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "High end of the range (required for most types).",
            "title": "Max Estimate"
          },
          "min_estimate": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Low end of the range (required for most types).",
            "title": "Min Estimate"
          },
          "mode_estimate": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Most-likely value; required for constant/bernoulli/binomial.",
            "title": "Mode Estimate"
          },
          "percentile_range": {
            "default": 0.9,
            "description": "Confidence the [min,max] interval covers, e.g. 0.9 for 90%.",
            "exclusiveMaximum": 1,
            "exclusiveMinimum": 0,
            "title": "Percentile Range",
            "type": "number"
          }
        },
        "required": [
          "distribution_type"
        ],
        "title": "SolveDistributionInput",
        "type": "object"
      },
      "name": "solve_distribution_parameters"
    },
    {
      "description": "Checks a graph for structural problems (cycles, dangling edges, unknown distributions, missing refs) before you run it, returning a list of issues by rule and severity. Use this when you built or edited a graph by hand and want to catch mistakes before spending a run on it. Free; no credits debited. Example: {\"graph\":{\"root_nodes\":[{\"id\":\"root\",\"distribution_type\":\"normal\",\"distribution_params\":{\"mean\":100,\"std\":15}}],\"calc_nodes\":[{\"id\":\"out\",\"formula\":\"{e1}\"}],\"edges\":[{\"id\":\"e1\",\"source\":\"root\",\"target\":\"out\"}],\"run_params\":{\"trials\":1000,\"time_periods\":12}}}",
      "inputSchema": {
        "$defs": {
          "AggregationRequest": {
            "additionalProperties": false,
            "description": "A post-simulation, series-aware metric over one node's full series.\n\nNPV/IRR/payback/CAGR/cumsum are NOT per-period node values: they consume a\ntarget node's complete ``(time_periods x trials)`` matrix AFTER the run and\nreturn one value per trial, summarised into a distribution.\n\nDiscount convention (0-based series index): period ``t=0`` is the present\n(undiscounted) cash flow; period ``t`` is discounted by ``(1+rate)**t``. The\nfirst period is undiscounted.\n\nWarning — two discount conventions coexist; do not mix them. These\naggregations use the **0-based** series index above (first period\nundiscounted). The per-period formula functions ``DISCOUNT(rate,\n{time_period})`` and ``PV(rate, value, {time_period})`` use the **1-based**\n``{time_period}``, so they discount the first period by ``(1+rate)**1``.\n\n\"Investment at period 0\" pattern: model an up-front outlay as a negative\nperiod-0 cash flow in the target node's series; NPV's t=0-undiscounted\nconvention then treats it as the present-value outlay. Do not additionally\ndiscount that first period with ``PV(...,{time_period})`` inside the target\nnode's formula when also requesting an aggregation ``npv`` — combining the\n1-based per-period discount with the 0-based ``npv`` double-shifts the first\nperiod.\n\nPer-period node vs aggregate metric (``prob``): pointing ``prob`` at a\nmulti-period cash-flow NODE via ``target_node_id`` thresholds only that node's\nFINAL-period per-trial value — i.e. ``P(per-period value > x)``, NOT\n``P(NPV > x)``. To get a true ``P(NPV > 0)``, define an ``npv`` aggregation\nfirst, then add a ``prob`` aggregation whose ``target_aggregation_id`` points\nat that ``npv`` id; ``prob`` then thresholds the NPV per-trial vector directly.\nA ``prob`` request targets EITHER a node (``target_node_id``) OR an earlier\naggregation (``target_aggregation_id``) — exactly one, never both.",
            "properties": {
              "function": {
                "description": "One of: npv, irr, payback, discounted_payback, cagr, cumsum, prob, terminal_value, mirr. discounted_payback requires params.rate; npv requires params.rate OR a per-period params.rates curve; prob requires params.op (one of >, >=, <, <=, ==) and params.value; terminal_value requires params.g and params.rate; mirr requires params.finance_rate and params.reinvest_rate.",
                "title": "Function",
                "type": "string"
              },
              "id": {
                "description": "Result key for this metric (unique within the request).",
                "title": "Id",
                "type": "string"
              },
              "params": {
                "additionalProperties": true,
                "description": "Function params, e.g. {'rate': 0.1} for npv/discounted_payback, {'op': '>', 'value': 0} for prob, {'g': 0.02, 'rate': 0.1} for terminal_value, {'finance_rate': 0.1, 'reinvest_rate': 0.08} for mirr.",
                "title": "Params",
                "type": "object"
              },
              "target_aggregation_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "For a ``prob`` request only: the id of an aggregation defined EARLIER in this output_request whose per-trial vector (e.g. an ``npv``) is thresholded. Lets ``P(NPV > 0)`` be expressed directly instead of the per-period ``P(value > x)`` you get by targeting a multi-period node. The referenced aggregation must produce a per-trial vector (npv/irr/payback/discounted_payback/cagr/cumsum/terminal_value/mirr).",
                "title": "Target Aggregation Id"
              },
              "target_node_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "The node whose full per-period series the metric consumes. Required for every metric except a ``prob`` that targets a prior aggregation via ``target_aggregation_id``. Exactly one of ``target_node_id`` / ``target_aggregation_id`` may be set on a ``prob`` request.",
                "title": "Target Node Id"
              }
            },
            "required": [
              "id",
              "function"
            ],
            "title": "AggregationRequest",
            "type": "object"
          },
          "CalcNode": {
            "additionalProperties": false,
            "description": "A computed node. ``formula`` is OPTIONAL.\n\nA null/empty/whitespace formula is allowed: the node is treated as a\nconstant ``0`` every period/trial (incoming edges are ignored — there is no\nimplicit \"sum of incoming edges\"). ``validate_graph`` surfaces this as a\nWARNING, not an error. To sum incoming edges, write the sum explicitly,\ne.g. ``{e1}+{e2}``; for pass-through use ``{e1}``.",
            "properties": {
              "formula": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional expression over incoming edge ids, e.g. '{e1} * 0.5 + {e2}'. To sum incoming edges write '{e1}+{e2}'; for pass-through use '{e1}'. If omitted/empty the node is treated as a constant 0 (sum-of-incoming is not implied); validate_graph reports this as a warning.",
                "title": "Formula"
              },
              "id": {
                "description": "Unique node id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "name": {
                "default": "",
                "description": "Human-readable label.",
                "title": "Name",
                "type": "string"
              }
            },
            "required": [
              "id"
            ],
            "title": "CalcNode",
            "type": "object"
          },
          "Edge": {
            "additionalProperties": false,
            "description": "A directed connection carrying a value from source to target.",
            "properties": {
              "delay": {
                "default": 0,
                "description": "Periods the value is delayed in transit.",
                "minimum": 0,
                "title": "Delay",
                "type": "integer"
              },
              "id": {
                "description": "Unique edge id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "name": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional label.",
                "title": "Name"
              },
              "source": {
                "description": "id of the source node.",
                "title": "Source",
                "type": "string"
              },
              "target": {
                "description": "id of the target node.",
                "title": "Target",
                "type": "string"
              }
            },
            "required": [
              "id",
              "source",
              "target"
            ],
            "title": "Edge",
            "type": "object"
          },
          "OutputRequest": {
            "additionalProperties": false,
            "description": "Which nodes/edges/periods to include in the result.\n\nEmpty lists mean 'all': all nodes, all edges, all time periods.\n``aggregations`` requests post-simulation series metrics (NPV/IRR/...).",
            "properties": {
              "aggregations": {
                "items": {
                  "$ref": "#/$defs/AggregationRequest"
                },
                "title": "Aggregations",
                "type": "array"
              },
              "edges": {
                "items": {
                  "type": "string"
                },
                "title": "Edges",
                "type": "array"
              },
              "nodes": {
                "items": {
                  "type": "string"
                },
                "title": "Nodes",
                "type": "array"
              },
              "time_periods": {
                "items": {
                  "type": "integer"
                },
                "title": "Time Periods",
                "type": "array"
              }
            },
            "title": "OutputRequest",
            "type": "object"
          },
          "PublicGraph": {
            "additionalProperties": false,
            "description": "A complete, validated simulation request — the agent-facing input.\n\nThis is the canonical public shape. Reference integrity (edges point at real\nnodes, output_request references real ids) is validated here so malformed\ngraphs are rejected before they ever reach the engine.",
            "properties": {
              "calc_nodes": {
                "items": {
                  "$ref": "#/$defs/CalcNode"
                },
                "title": "Calc Nodes",
                "type": "array"
              },
              "contract_version": {
                "const": "1.0",
                "default": "1.0",
                "description": "Schema version this graph targets.",
                "title": "Contract Version",
                "type": "string"
              },
              "edges": {
                "items": {
                  "$ref": "#/$defs/Edge"
                },
                "title": "Edges",
                "type": "array"
              },
              "root_nodes": {
                "items": {
                  "$ref": "#/$defs/RootNode"
                },
                "title": "Root Nodes",
                "type": "array"
              },
              "run_params": {
                "$ref": "#/$defs/RunParams"
              }
            },
            "required": [
              "run_params"
            ],
            "title": "PublicGraph",
            "type": "object"
          },
          "RootNode": {
            "additionalProperties": false,
            "description": "A source node that samples from a probability distribution each period.",
            "properties": {
              "delay": {
                "default": 0,
                "description": "Periods to wait before the first sample.",
                "minimum": 0,
                "title": "Delay",
                "type": "integer"
              },
              "distribution_params": {
                "additionalProperties": true,
                "description": "Params for the chosen distribution, e.g. {'mean': 100, 'std': 15}.",
                "title": "Distribution Params",
                "type": "object"
              },
              "distribution_type": {
                "description": "One of the catalog distributions (GET /api/v1/contract).",
                "title": "Distribution Type",
                "type": "string"
              },
              "id": {
                "description": "Unique node id within the graph.",
                "title": "Id",
                "type": "string"
              },
              "interval": {
                "default": 1,
                "description": "Sample every N periods (1 = every period).",
                "minimum": 0,
                "title": "Interval",
                "type": "integer"
              },
              "name": {
                "default": "",
                "description": "Human-readable label.",
                "title": "Name",
                "type": "string"
              },
              "sampling_frequency": {
                "default": "per_period",
                "description": "'once' draws a single value reused across periods.",
                "enum": [
                  "per_period",
                  "once"
                ],
                "title": "Sampling Frequency",
                "type": "string"
              }
            },
            "required": [
              "id",
              "distribution_type",
              "distribution_params"
            ],
            "title": "RootNode",
            "type": "object"
          },
          "RunParams": {
            "additionalProperties": false,
            "description": "Top-level run configuration.",
            "properties": {
              "output_request": {
                "$ref": "#/$defs/OutputRequest"
              },
              "time_periods": {
                "description": "Number of time periods to simulate.",
                "exclusiveMinimum": 0,
                "title": "Time Periods",
                "type": "integer"
              },
              "trials": {
                "description": "Number of Monte Carlo trials.",
                "exclusiveMinimum": 0,
                "title": "Trials",
                "type": "integer"
              }
            },
            "required": [
              "trials",
              "time_periods"
            ],
            "title": "RunParams",
            "type": "object"
          }
        },
        "description": "Arguments for ``validate_graph``.",
        "properties": {
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional API key (validation is free).",
            "title": "Api Key"
          },
          "graph": {
            "$ref": "#/$defs/PublicGraph",
            "description": "The graph to validate."
          }
        },
        "required": [
          "graph"
        ],
        "title": "ValidateGraphInput",
        "type": "object"
      },
      "name": "validate_graph"
    }
  ]
}

What the leaf hashes

{"body":"deb3e443055c827af521d798459621c60354824e25affd8a67e46e1598812c75","id":980439,"kind":"mcp.tools","method":"probe.mcp/1","observed_us":1793233768395492,"prev":null,"subject":"278214a0-1e9d-4f76-9d11-401752e2e2fc","subject_kind":"endpoint"}

Proof

Fold these into the leaf in order, hashing each sorted pair with keccak256, to reach the root of (242798 rows).

  1. 0x2da138a88052646e927f1bfd031b41ac2b6acf55daef0cdfe3066338a44c1ecb
  2. 0xbe138f196b996357e1c143d47c2372b301414708f8bc2175ada455cc7891f8fa
  3. 0xe08a74a824538930d5d888a71f637428da0c69cb8b9f03bd3bc127e6f2f20dc3
  4. 0x40580a3740c884dec55489262ff91a6dd0d61c5bf189cc08c6ed7a599bd619cf
  5. 0xfcdc5016bbf95082f5bb21dae10e3736941885390975d458a3fab188b9ff87bd
  6. 0x8ffac6ddf70ec9dee63931f4b105f33e792addc1fd44f5e2e6c7ac7e9fc71840
  7. 0xcb1014f8a822ce6c8ce04fe2da7724a29bb8013dadea03676c66976c38322916
  8. 0x95d5bc90bd0dfeb0b3992f17eecaaeb505955ccdfee487896bbc9a337f0d875f
  9. 0xa26d3b935b6b1aee74159dc2fb932050a6c06c0b62eb6af66fa6405676f09b0c
  10. 0x5aa0f50bb837c5530910308a9808229603f0aba835661f2ae00c6e64e12ae6a6
  11. 0xd59e07aef123c2302ace088c2c15fe82545a75869a9ab07cc002ca9c84b6204c
  12. 0x5bfac22f03332f6db6902b8936b63972ec34cc699ff205fadff981288e2b3097
  13. 0x53104aada45a8c2f9002ac93098831a2cf0cef1895679463ed8dabcf75a7fa24
  14. 0xcaae1928370ce22d2a564247e7948dcda78bb8c3ef9a7d8bdfa6e00f84c1e28c
  15. 0x00268e62f7d5ca6313e0e60afdc2bd4f52c6dbdb3b4b4d27e01e634b4bcb1d2c
  16. 0x1c3764b490d23b94e5ac838c89f8d3850dedb0819196f367da2479c7a88bf2c0
  17. 0xd76435ead496863d8b0bfab3434f54cd11da3c49d104fc4064b9cb3381567bbd
  18. 0xd56e61af23709ed9f460471e3c08400c0142ee83e1fd9057e46350d12edf9c07
Day root
0xc050555c6b023f2aefb6536efb9f0760b92c30a0d06c572b7daf63db259ea17c
Chained
0x4cde8bae2042512e1bec11650628f0293556311cc4ea74d99ffddf02b671a7d6
Published
On Arc Testnet, block 69753317: 0x9e85c340732f416e431b111fae72f7624870125f7f379af2732eb6c2ba8cf6a1

How to check it · This row as JSON