Skip to main content
Glama

Rank which inputs drive an outcome most (one-at-a-time sensitivity)

rank_inputs_by_impact

Ranks a model's uncertain inputs by how much each one moves a chosen outcome, and returns the data for a tornado chart. A tornado chart is a bar chart with one horizontal bar per input, sorted with the biggest swing at the top. This is a one-at-a-time (OAT) sensitivity analysis. Every input is held at its median while one input at a time is set to low, middle and high values from its own distribution (by default its 5th, 50th and 95th percentiles). The tool records how the outcome's average changes. Use this when you need to know which assumption matters most, so you know what to research or de-risk first. It returns one entry per input, ranked so rank 1 has the biggest impact. Each entry lists the input values tried, the outcome at each, and an elasticity score. Elasticity means how strongly the outcome reacts: roughly, how many percent the outcome moves when the input moves 1 percent. It returns numbers, not an image. Inputs whose distribution produces a list of values are skipped. It always returns a run_id. It runs the model once per input per value tried, so on a big model it can take minutes: if it is not done in about 40 seconds you get status running, and get_simulation_results gives you progress and then the ranking. Cost: without an account, 1 of your 3 free runs per UTC day for each call, even though the analysis runs the model many times (models up to 1,000 trials and 20 nodes); with an account, 1 credit for a small model or 5 for a large one, currently $0.50 per credit. A model that is invalid or over the no-account limits is rejected before running and costs nothing. If it fails mid-run: anonymous, the free run is used; account, already charged, because this tool charges when the analysis starts.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "graph": "<graph>"
    },
    "name": "rank_inputs_by_impact"
  }
}

Input Schema

NameRequiredDescriptionDefault
seedNoOptional whole number that fixes the random draws, so repeating the call gives the same result. Exact repeats are guaranteed only for small runs, where trials × nodes × time periods is at most 100,000.
graphYesThe model: root_nodes (uncertain inputs), calc_nodes (formulas), edges (links; formulas refer to them like {e1}) and run_params (trials and time periods). Same format as run_monte_carlo_simulation's graph, which documents formulas, periods, distributions and financial metrics in full.
detailNoHow much to return. summary (the default): one row per input with its rank, its low and high values, the outcome at each, the swing between them and its elasticity. full: also each input's whole response curve.summary
quantilesNoA list of points in each input's own distribution to try. Each point is a fraction from 0 to 1 naming a percentile: 0.05 is the 5th percentile, the value 5% of outcomes fall below. Default [0.05, 0.5, 0.95]. Give this or num_quantiles, not both.
time_periodNoIndex of the time period to measure, counting from 0: with 12 monthly periods, 11 is month 12. Defaults to the last period. This measures the node's value in that one period, not a total. For a cumulative figure such as year-one profit, add a running-total calc node with formula {e1} + {e2}, where e1 brings in the per-period value and e2 is an edge from the running-total node to itself with delay 1. Then target that node at index 11. This delayed self-edge is allowed; only loops with no delay are errors. In run_monte_carlo_simulation, use a cumsum metric instead.
num_quantilesNoInstead of quantiles: how many points to try, an even whole number from 2 to 10. That many percentiles are spread evenly between the 5th and 95th, and the median (0.5) is added. 2 gives [0.05, 0.5, 0.95]; 4 gives [0.05, 0.275, 0.5, 0.725, 0.95].
target_node_idNoThe id of the outcome node to measure. Defaults to the last calc node in the model, which is usually the final outcome.

Output Schema

NameRequiredDescriptionDefault
run_idNo
statusNocompleted
billingNoWho you are and what this call cost: principal, auth source, credits debited and balance, or the anonymous allowance left today.
resultsNoOne entry per input, in rank order (rank 1 = biggest impact).
tornadoNo
progressNoPresent while the run is queued or running.
next_stepNoWhat to do next while the run is still going.
quantilesYesThe percentiles of each input that were tried, as fractions.
time_periodYesThe period measured (index counted from 0).
runs_executedYesInternal simulation runs used: 1 baseline plus inputs × quantiles. You are billed once.
target_node_idYesThe outcome node measured.
credits_debitedNoCredits charged (0 without an account).
baseline_outcomeNoThe outcome's mean with every input at its median.
inputs_not_shownNo
estimated_secondsNoRough total run time, in seconds.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed19 schema fields changed
    • removedInput schema / properties / api_key
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Your Neumann API key. Get one by creating an account (POST https://neumann.kromatic.com/api/v1/accounts, which returns the key once); setup docs: https://kromatic.com/mcp/neumann. Leave it out if your connection is already signed in, or to use the free no-account tier.",
      -  "title": "Api Key"
      -}
    • addedInput schema / properties / detail
      Added value: +{
      +  "default": "summary",
      +  "description": "How much to return. summary (the default): one row per input with its rank, its low and high values, the outcome at each, the swing between them and its elasticity. full: also each input's whole response curve.",
      +  "enum": [
      +    "summary",
      +    "full"
      +  ],
      +  "title": "Detail",
      +  "type": "string"
      +}
    • changedOutput schema / $defs / BillingInfo / properties / auth_source / description
      Previous value: -"How you were identified: bearer (a signed-in connection token), api_key (the api_key argument) or anonymous."New value: +"How you were identified: bearer (a credential sent in the Authorization: Bearer header) or anonymous."
    • changedOutput schema / $defs / BillingInfo / properties / auth_source / enum
      Previous value: -[
      -  "bearer",
      -  "api_key",
      -  "anonymous"
      -]New value: +[
      +  "bearer",
      +  "anonymous"
      +]
    • changedOutput schema / $defs / BillingInfo / properties / charged_to / enum
      Previous value: -[
      -  "anonymous_allowance",
      -  "credits",
      -  "none"
      -]New value: +[
      +  "anonymous_allowance",
      +  "free_daily_run",
      +  "credits",
      +  "none"
      +]
    • addedOutput schema / $defs / BillingInfo / properties / free_run_limits
      Added value: +{
      +  "anyOf": [
      +    {
      +      "$ref": "#/$defs/SignedInLimits"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "The free signed-in tier's bounds. Null unless the account signed in with Kromatic."
      +}
    • addedOutput schema / $defs / BillingInfo / properties / free_runs_remaining_today
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Free signed-in runs left in the current UTC day, counting this call. Null unless the account signed in with Kromatic.",
      +  "title": "Free Runs Remaining Today"
      +}
    • addedOutput schema / $defs / BillingInfo / properties / free_runs_reset_at
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "ISO-8601 instant the free signed-in runs next refill (the next UTC midnight). Null unless the account signed in with Kromatic.",
      +  "title": "Free Runs Reset At"
      +}
    • addedOutput schema / $defs / RunProgress
      Added value: +{
      +  "description": "How far a queued or running run has got.",
      +  "properties": {
      +    "done": {
      +      "title": "Done",
      +      "type": "integer"
      +    },
      +    "percent": {
      +      "description": "0 to 100.",
      +      "title": "Percent",
      +      "type": "number"
      +    },
      +    "total": {
      +      "title": "Total",
      +      "type": "integer"
      +    },
      +    "unit": {
      +      "description": "trials for a simulation; runs (internal simulations) for a sensitivity sweep.",
      +      "enum": [
      +        "trials",
      +        "runs"
      +      ],
      +      "title": "Unit",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "percent",
      +    "done",
      +    "total",
      +    "unit"
      +  ],
      +  "title": "RunProgress",
      +  "type": "object"
      +}
    • addedOutput schema / $defs / SignedInLimits
      Added value: +{
      +  "description": "The free signed-in tier's bounds (neumann#334), rendered from ``Settings``.",
      +  "properties": {
      +    "max_nodes": {
      +      "description": "Maximum nodes in a free run's graph.",
      +      "title": "Max Nodes",
      +      "type": "integer"
      +    },
      +    "max_trials": {
      +      "description": "Maximum trials in a free run.",
      +      "title": "Max Trials",
      +      "type": "integer"
      +    },
      +    "runs_per_day": {
      +      "description": "Free runs per UTC calendar day.",
      +      "title": "Runs Per Day",
      +      "type": "integer"
      +    }
      +  },
      +  "required": [
      +    "runs_per_day",
      +    "max_trials",
      +    "max_nodes"
      +  ],
      +  "title": "SignedInLimits",
      +  "type": "object"
      +}
    • addedOutput schema / $defs / TornadoRow
      Added value: +{
      +  "description": "One input's bar in the tornado chart.",
      +  "properties": {
      +    "baseline_input": {
      +      "description": "The input's median, where it is held otherwise.",
      +      "title": "Baseline Input",
      +      "type": "number"
      +    },
      +    "elasticity": {
      +      "description": "Roughly the % change in the outcome per 1% change in the input (unsigned).",
      +      "title": "Elasticity",
      +      "type": "number"
      +    },
      +    "high_input": {
      +      "description": "The input at the highest percentile tried.",
      +      "title": "High Input",
      +      "type": "number"
      +    },
      +    "input_id": {
      +      "title": "Input Id",
      +      "type": "string"
      +    },
      +    "low_input": {
      +      "description": "The input at the lowest percentile tried.",
      +      "title": "Low Input",
      +      "type": "number"
      +    },
      +    "name": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "title": "Name"
      +    },
      +    "outcome_at_high": {
      +      "description": "The outcome's mean with the input at high_input.",
      +      "title": "Outcome At High",
      +      "type": "number"
      +    },
      +    "outcome_at_low": {
      +      "description": "The outcome's mean with the input at low_input.",
      +      "title": "Outcome At Low",
      +      "type": "number"
      +    },
      +    "rank": {
      +      "description": "1 = the input with the biggest impact.",
      +      "title": "Rank",
      +      "type": "integer"
      +    },
      +    "swing": {
      +      "description": "abs(outcome_at_high - outcome_at_low): the bar's length.",
      +      "title": "Swing",
      +      "type": "number"
      +    }
      +  },
      +  "required": [
      +    "rank",
      +    "input_id",
      +    "baseline_input",
      +    "low_input",
      +    "high_input",
      +    "outcome_at_low",
      +    "outcome_at_high",
      +    "swing",
      +    "elasticity"
      +  ],
      +  "title": "TornadoRow",
      +  "type": "object"
      +}
    • addedOutput schema / properties / baseline_outcome
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "number"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "The outcome's mean with every input at its median.",
      +  "title": "Baseline Outcome"
      +}
    • addedOutput schema / properties / estimated_seconds
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "number"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Rough total run time, in seconds.",
      +  "title": "Estimated Seconds"
      +}
    • addedOutput schema / properties / inputs_not_shown
      Added value: +{
      +  "default": 0,
      +  "title": "Inputs Not Shown",
      +  "type": "integer"
      +}
    • addedOutput schema / properties / next_step
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "What to do next while the run is still going.",
      +  "title": "Next Step"
      +}
    • addedOutput schema / properties / progress
      Added value: +{
      +  "anyOf": [
      +    {
      +      "$ref": "#/$defs/RunProgress"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Present while the run is queued or running."
      +}
    • addedOutput schema / properties / run_id
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Run Id"
      +}
    • addedOutput schema / properties / status
      Added value: +{
      +  "default": "completed",
      +  "enum": [
      +    "completed",
      +    "running",
      +    "queued"
      +  ],
      +  "title": "Status",
      +  "type": "string"
      +}
    • addedOutput schema / properties / tornado
      Added value: +{
      +  "items": {
      +    "$ref": "#/$defs/TornadoRow"
      +  },
      +  "title": "Tornado",
      +  "type": "array"
      +}
  2. Added

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: discloses that list-valued inputs are skipped, that a run_id is always returned, that the model runs once per input per value, that ~40s yields status=running, and a detailed cost model including free-run consumption, credit pricing, and what happens on mid-run failure. The idempotentHint=false is consistent with nondeterminism when no seed is given.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence, with mechanics, output shape, timeout and cost following in logical order. It is long, and the tornado-chart and elasticity pedagogy could be trimmed, but nearly every sentence carries actionable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex, nested-schema, non-idempotent analysis tool, the description supplies everything an agent needs: mechanics, skipped inputs, async polling path, output contents, and cost/failure semantics. An output schema exists and the description still summarizes what is returned, so nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 7 parameters (quantiles, num_quantiles, detail, time_period, target_node_id). The description restates the default 5th/50th/95th percentiles and defines elasticity, but adds little parameter meaning beyond the schema — baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource — ranks a model's uncertain inputs by how much each moves a chosen outcome — and immediately frames it as a one-at-a-time (OAT) sensitivity analysis returning tornado-chart data. This clearly separates it from run_monte_carlo_simulation and summarize_outcome_scenarios.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit use case ('which assumption matters most, so you know what to research or de-risk first') and names get_simulation_results as the follow-up for polling. It doesn't explicitly say when NOT to use it versus the Monte Carlo siblings, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources