Simba MCP Server
OfficialServer Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| SIMBA_API_KEY | Yes | Your Simba API key (stdio mode only – HTTP callers send their own key as the bearer token) | |
| SIMBA_API_URL | No | Simba API base URL | http://localhost:5005 |
| SIMBA_MCP_ALLOW_LOCAL_FILES | No | Set to '1' to allow local file paths (csv_path) on HTTP/SSE deployments; disabled by default. | 0 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| create_recipe_draftA | Save an encrypted authoring draft without publishing, fitting or consuming an attempt. Supply a UUID draft_id and reuse it with identical content after an uncertain response. Start from get_recipe_draft_template for a new draft, or preserve the complete snapshot from get_recipe_draft when editing. When copying a published recipe, supply its source_revision_id from this study; the immutable link carries inherited influence through publication. Backend validates version and size. |
| get_recipe_draftA | Read the complete authoring snapshot and concurrency version. Preserve all fields when editing. Draft state is incomplete, unvalidated authoring data, not an executable recipe. |
| get_recipe_draft_templateA | Get complete shared wizard defaults, hash and envelope schema. Optionally choose an owned uploaded_file_id or pipeline_version_id (never both) into frozen source bytes with verified lineage and an editable data preview. Copy snapshot into create_recipe_draft and preserve unedited fields. Defaults are not a validated model. Does not create, publish or run anything. |
| publish_recipe_draftA | Publish a saved MMM or VAR draft as immutable recipe revisions. Supply a new UUID publication_id and reuse it with identical arguments after an uncertain response. Batch publication is atomic. Backend compiles the saved snapshot with shared wizard rules; never send separately prepared settings. Does not fit, consume an attempt or designate a champion. On capable backends, automatic MMM priors are resolved at publication and frozen; replay does not rebuild them. VAR requires family-specific evidence assessment; MMM policies cannot establish VAR acceptance. Enabled invalid MMM calibration fails publication; VAR calibration is unsupported. Preserve disabled authoring observations. Check backend capabilities. |
| get_recipe_revision_authoringA | Read the frozen authoring snapshot of a published draft revision. Use its complete snapshot with create_recipe_draft to edit a new copy; the published revision stays unchanged. Legacy revisions without authoring state return an explicit unavailable error. Does not create or fit anything. |
| list_recipe_draftsA | List study draft metadata without loading datasets. Check backend draft capability first. |
| update_recipe_draftA | Replace authoring state using the version from get_recipe_draft. Retain every unedited field, including original priors and source bytes. Stale changes fail; reload and reconcile explicitly. Identical retries return the current draft. Does not publish or launch. |
| get_backend_capabilitiesA | Discover this caller's connected backend features before planning work. Returns only backend advertisements: model families, transformations, priors and workflow operations. A missing advertisement is unknown, not unsupported. Check each field; an advertised feature still requires permission and budget. No model is created and capabilities are not cached across callers. |
| get_data_schemaA | Get the canonical CSV data schema for Simba MMM input files. Returns the JSON Schema specification describing required columns (date, KPI, multiplier, hierarchy), media channel column naming conventions ({channel}_activity, {channel}_spend), constraints (min rows, max file size), and supported date formats. |
| upload_dataA | Upload a CSV dataset to Simba for use in model building. Provide EXACTLY ONE of csv_content (raw CSV text) or csv_path (a file path on the machine running this MCP server). Prefer csv_path for anything beyond trivial size — it avoids passing megabytes of CSV through the conversation. The CSV should follow the canonical schema: one row per time period with date, KPI, multiplier, hierarchy, media activity/spend columns, and optional control variables. IMPORTANT:
Args: csv_content: The full CSV text content (not base64, just raw CSV text). csv_path: Path to a .csv file readable by the MCP server process. name: Optional dataset name for identification. Defaults to the file stem when csv_path is used. filename: Optional original filename to record alongside the dataset. Returns the uploaded file ID (needed for create_model), row/column counts, and any validation warnings. |
| list_uploadsA | List the datasets in your workspace (newest first) — every source, not just API uploads: dashboard/manual uploads and pipeline-ingested datasets appear too (see source_type per file). Returns {files, count, limit, offset} where each file has: id (the
uploaded_file_id create_model needs), filename, original_filename,
source_type, row_count, column_count, created_at. Here Args: limit: Page size (API clamps to 1-500; default 50). offset: Rows to skip (paging). name: Optional case-insensitive substring filter on the original filename. |
| get_uploadA | Get one uploaded dataset's details, including its column schema. Returns id, filename, original_filename, source_type, mime_type, file_size, row_count, column_count, columns ([{name, dtype}, ...] — use these to build create_model's channel/control column arguments without re-reading the CSV), and created_at. Args: file_id: The upload's id, from upload_data's response or list_uploads. |
| list_modelsA | List all Marketing Mix Models for the authenticated user. Returns model name, hash, status (pending/under way/complete/failed), type (mmm/var), hierarchy value, and timestamps. NOTE: All other model endpoints use model_hash (string, e.g. "f835671a25") as the identifier. Use the model_hash from this response. Args:
include_unsaved: Include draft/unsaved models (default false).
limit: Maximum number of models to return (default 50, max 500).
offset: Number of models to skip, for paging past |
| create_modelA | Create and start fitting a new Bayesian Marketing Mix Model. This queues an async model fit and returns immediately with a model_hash. Use get_model_status to poll for progress until status is 'complete'. Priors are calculated automatically using smart defaults based on cost shares, industry benchmarks, and channel-type detection. You can override individual channels via the priors parameter. Args:
uploaded_file_id: The file ID returned by upload_data.
date_column: Name of the date column in the CSV.
kpi_column: Name of the KPI/dependent variable column.
hierarchy_column: Name of the brand/segment column (must have exactly 1 unique value).
channels: List of channel definitions, each with keys: name, activity_column, spend_column.
Example: [{"name": "TV", "activity_column": "tv_grps", "spend_column": "tv_spend"}]
multiplier_column: Column to convert KPI to revenue. Defaults to kpi_column.
control_columns: Non-media control variable column names (e.g. ["price", "distribution"]).
total_media_effect: Controls prior strength. Either an industry name for a benchmark
("FMCG"=6%, "Retail"=9%, "TelCo"=30%, "Financial Services"=19%,
"E-Commerce"=22%, "Other"=12%) or a custom decimal like "0.15"
meaning "I believe all media drives 15% of my KPI". Default "Other".
priors: Optional per-channel prior overrides. Each dict should have "channel" matching
a channels[].name, plus any fields to override: distribution, mean, sd, lower,
upper, transform, adstock_type, effect_period.
Only specified fields are overridden; the rest use smart defaults.
Adstock-kernel fields: half_life_lower/half_life_upper (carryover half-life
bounds in periods — preferred over the legacy decay_lower/decay_upper),
theta_mean/theta_sd (peak-lag prior, adstock_type="delayed" only),
dual_weight_mean/dual_weight_sd (long-term/slow-component share prior,
adstock_type="dual_geometric" only).
SATURATION ANCHOR — state it ONCE, in exactly one of three
mutually exclusive forms (two in one override -> 400 "state
the saturation prior once"):
(1) half_marginal_mean/half_marginal_sd — CANONICAL for
saturation_type="generalized_log" (rejected on other
families): the activity level where MARGINAL returns have
halved, finite at every curvature (#632).
sat_shape_mean MUST accompany the pair in the same override
(#672) — the fold pairs your coefficient with the
stated curvature, so omitting it is a 400, never a silent
default.
(2) half_saturation_mean/half_saturation_sd — the
50%-of-maximum point in activity units, for the
single-parameter families (tanh/michaelis_menten/
negative_exponential). Do NOT use it for generalized_log
near-log work: it overflows below sat_shape_mean 0.00097657
and is rejected with a 400 — precisely the regime that
family exists for.
(3) alpha_sd + scalars — legacy internal coordinates,
accepted for backward compat.
Curvature (generalized_log only): sat_shape_mean/sat_shape_sd
— small values are near-logarithmic, 1.0 is michaelis_menten.
COEFFICIENT in a human coordinate (generalized_log only,
#671): effect_at_avg_mean/effect_at_avg_sd — the
effect share at the channel's AVERAGE activity, as FRACTIONS
(mean in (0, 0.95], sd > 0; 0.2 means 20%). Folded
server-side into mean/sd at the row's operating point with
the same arithmetic as the dashboard. Requires sat_shape_mean
in the same override; cannot be combined with mean/sd
("state the coefficient prior once") or with
half_saturation_*. Stating half_marginal_* + effect_at_avg_*
+ sat_shape_mean together is the full (x*, E, k) triple —
the recommended generalized_log elicitation, since only
beta*k is identified and raw beta spans orders of magnitude.
VERIFY what was applied via get_model's
model_config.priors_resolved: rows carry the FOLDED
mean/sd/scalars/alpha_sd, and overridden_fields lists the
field names you sent.
UNKNOWN KEYS ARE REJECTED with a 400 naming the field
(#630); they used to be dropped silently, fitting a
hybrid of the override and the smart defaults. Common misses:
"beta"/"beta_mean" -> mean, "beta_sd" -> sd, "sat_shape" ->
sat_shape_mean. "name" and "parameter" are rejected too — they
identify the smart-prior row the override merges onto.
trend: Enable dynamic baseline trend component.
seasonality: Enable automatic seasonality detection. The prior sigma on
the Fourier coefficients is chosen for the link (#534):
0.5 under link="log", 10 under "identity". The coefficients
live on the link's scale, so the additive default would
admit e^10x seasonal amplitude on a multiplicative model.
likelihood: Likelihood function: "normal" (default), "lognormal", "logit",
"studentt", "poisson", "negativebinomial", or "quantile".
saturation_type: Diminishing-returns curve family applied to media:
"tanh" (default), "michaelis_menten", "negative_exponential",
or "generalized_log" (two-parameter Box-Cox/power-log family
1 - (1+x/K)^(-shape); tune per channel via the
sat_shape_mean/sat_shape_sd prior fields).
transform_order: "adstock_first" (default: carryover accumulates, then
saturates) or "saturation_first" (each period's spend
saturates, then the effect spreads over time through the
normalized adstock kernel).
link: Model Form. "identity" (default) fits an additive model — components
add on the outcome scale. "log" fits a multiplicative model —
components add on the log scale and media effects are percentage
lifts. Under the removal_lift attribution convention (the API
default), contributions then include an Overlap reconciliation
column; the other conventions (aumann_shapley — the dashboard
default for multiplicative models since #509 —
shapley, and proportional_normalized) allocate the interaction
across components and close exactly WITHOUT an Overlap column
(see get_model_results).
channel_groups: Optional adstock groups: [{"name": ..., "channels":
[...], "share_saturation": bool}]. Member channels tie
their carryover parameters (decay/theta/dual-weight —
plus saturation when share_saturation is true) to one
shared value, e.g. grouping channels into shared
"Long"/"Short" carryover classes. Members are
channels[].name values; each group needs >= 2 members;
groups must be disjoint; and tied members must have
identical adstock_type/effect_period/bound overrides
(the API rejects divergent groups at request time).
control_reference: Control attribution reference points (#452),
multiplicative models (link="log") only: maps control
column names (plus optional "default") to
"auto" | "absent" | "average" | "lowest" | "highest" —
which counterfactual "remove this control" means in
the contributions. "absent" measures against the
variable at zero (legacy behavior; honest only when
zero is observed). "average"/"lowest"/"highest"
reference the control at its observed mean/min/max —
use for controls that never approach zero (price
indices, distribution levels), where a zero
counterfactual produces unbounded contributions and a
negative Base. "auto" detects per control whether
zero is inside the observed data range. Example:
{"default": "auto", "relative_price": "average",
"promo_flag": "absent"}. Omit entirely to keep every
control at "absent" (byte-identical legacy output).
Unknown control names/modes are rejected at request
time; any value other than "absent" requires
link="log". The fit reports the resolution in
model_config.control_references (see
get_model_results).
name: Display name for the created model, honoured verbatim (#575).
Falls back to a generated API_MMM{brand}{hash} string when
omitted. Either way the model starts unsaved — invisible to
list_models unless include_unsaved=true — until save_model
files it into a project.
operating_margin: Scalar operating margin as a decimal fraction in
(0, 1], e.g. 0.18 = 18%. Mutually exclusive with
operating_margin_column (the API 400s when both are given).
Storing a margin unlocks the control_priors: Optional root-level control slope overrides. Each entry names a selected control_columns column with "control", plus transform (N, DM, STA, DDM, LOG), distribution (normal, inversegamma, truncatednormal, halfnormal), mean/sd/lower/upper as applicable. LOG is log(x/mean(x)); STA divides by sample sd without centering. Priors are in transformed units; changing transform does not convert coefficients. Nonempty overrides require backend capability version 1; unsupported or unavailable checks stop before creating a model. Returns the model_hash for status polling. |
| create_var_modelA | Create and start fitting a long-term (VAR) model (#569). VAR models capture the joint dynamics of several series (e.g. sales and
brand-equity metrics) and produce the long-run elasticity bridge behind
the MMM's Args: uploaded_file_id: Dataset id from upload_data (must contain every named column). date_column: Date column name. Cannot also be a series. endogenous_vars: At least two column names — the jointly-modeled series. exogenous_vars: Optional outside drivers; must not overlap the endogenous set. lags: VAR order (>= 1). The dataset needs at least lags + 10 rows with no missing values across the modeled columns. forecast_horizon: Periods forecast for diagnostics (default 12). base_variable: The outcome series (must be endogenous) long-run multipliers are measured against. Required for long-run effects. equity_variables: Endogenous columns (excluding the base) whose long-run IRF multipliers are estimated. Required for long-run effects. lre_horizon: Long-run effects horizon in periods (default 156). lre_ci: Credible-interval mass for the effects table, in (0, 1). var_priors: Advanced prior overrides (lag_coefs / alpha / coefs / noise_chol); unknown keys are rejected. name: Display name for the created model, honoured verbatim (#575). Falls back to a generated API_VAR_* string when omitted. Returns 202-style payload with model_hash; poll get_model_status. |
| link_var_modelA | Link a completed VAR model to an MMM (#569). After linking, the MMM's get_model_results The join is by exact name unless channel_map declares which MMM channels each VAR exogenous series stands for (#682) — required whenever the VAR is fitted on group spends (e.g. four spend groups) while the MMM is tactic-level. Each group's elasticity is allocated across its member channels pro-rata by KPI short-term contribution, so the group's long-run effect is counted exactly once. Validation is strict: keys must be VAR exogenous series, values must be channel names of the (completed) MMM, and no channel may belong to two groups. The map belongs to the link: every link replaces it (omitting channel_map clears any stored map) and unlink clears it. Args: model_hash: The MMM to attach the long-run view to. var_model_hash: The VAR model (from create_var_model). channel_map: Optional {var_exogenous_series: [mmm_channel, ...]} mapping for group-level VARs. |
| unlink_var_modelA | Remove an MMM's VAR link (#569). Idempotent. |
| set_contribution_groupsA | Persist the driver groupings the dashboard contributions view renders (#436) — configure grouping once and every viewer sees it. Each group: {"name": str, "drivers": [column names], "color": "#hex"?, "baseAdjustments": {driver: "min"|"max"|"none"}?}. Driver names are validated against the model's media/control/halo/trademark factors (400 with a did-you-mean hint on typos); each driver may belong to at most one group; baseAdjustments must reference the group's own drivers. The special "_channel_color_overrides" pseudo-group carries a channelColors map instead of drivers. NOTE: this is the CONTRIBUTIONS-VIEW grouping. create_model's channel_groups is the unrelated adstock parameter-sharing feature — do not confuse them. |
| get_contribution_groupsC | Read the stored contribution groups for a model (#436). Legacy dashboard-saved configs are served verbatim. |
| rename_modelA | Rename a model. Changes only the display name; the model's saved/unsaved state is untouched (use save_model to file it into a project). The name is HTML-sanitized server-side and must be non-empty. Args: model_hash: Hash of the model to rename. name: New display name. |
| save_modelA | Save a model into a project under a display name. API-created models start unsaved and are invisible to list_models (without include_unsaved=true) — saving files them into a project so they appear in the default listing and the dashboard's Saved Models. The same saved-models cap applies as in the dashboard: at the cap the API returns a 400 with error_type "saved_limit". Re-saving an already-saved model renames/refiles it without consuming a new slot. Args: model_hash: Hash of the model to save. name: Display name to save under (non-empty). project_id: Optional target project ID; must be a project you own or one shared with a team you belong to. Discover ids with list_projects; create a folder with create_project. Defaults to your default project. |
| unsave_modelA | Release a model's saved slot without deleting anything — the inverse of save_model (#673). Use this for cap management: at the 20-saved-models cap, unsave a model that no longer earns its shelf spot instead of deleting it. The model reverts to the state API-created models start in (unsaved, no project; the name is kept) — it leaves the default listing and the dashboard's Saved Models but stays fully addressable by hash: fetchable, renameable, exportable, re-saveable, and visible via list_models with include_unsaved=true. Idempotent — unsaving an unsaved model is a success with freed_project_id null. delete_model remains failed-only. Two caveats: the UNSAVED pool is auto-pruned by dashboard model creation (at 10+ unsaved models the oldest is hard-deleted, artifacts included), so re-save anything worth keeping rather than parking it unsaved long-term; and unsaving a shared model hides it from every recipient until it is saved again. Args: model_hash: Hash of the model whose slot to release. Returns: {model_hash, is_saved: false, freed_project_id}. |
| list_projectsA | List the projects (the app's model folders) you can file models into. Returns owned and team-shared projects: per project {id, name, is_default, shared_with_team_id, model_count} — team-shared folders carry "shared": true, and model_count counts SAVED models (the set the app's model list shows). Use the ids with save_model(project_id=...) and rename_project. There is deliberately no delete over the API — use the app to delete a project. |
| create_projectA | Create a named project (model folder) to file models into. Names are sanitized the same way model names are (non-empty after HTML sanitization). Args: name: Display name for the new project. team_id: Optional team to share the project with; must be a team you belong to (403 otherwise, 404 for an unknown team). Returns the created project (201) including its id — pass that to save_model(project_id=...). |
| rename_projectA | Rename a project you OWN. Team members can file models into a shared folder but not rename it (owner-only; 404 for a project you don't own). Renaming your default folder is safe: it keeps receiving unqualified saves under its new name. Args: project_id: Id of the project to rename (see list_projects). name: New display name. |
| get_modelA | Get a model's metadata and configuration echo — works for EVERY status, including failed models (unlike get_model_results, which needs 'complete'). Use this to inspect what a model was configured with, why it failed, or where it lives. Returns: id, model_hash, name, status, model_type ("mmm"/"var"), hierarchy_value, periodicity, is_saved, project_id/name, linked_var_model_hash, created_at/completed_at, error (the failure message — non-null only when status is "failed"), and model_config (the create-time configuration echo: data_source, columns, channels, priors as resolved, and the config flags). NOTE: the echo omits a few accepted create_model inputs (operating_margin, annual_discount_rate, reporting_kernel) — absence there does not mean they weren't applied; check the financials results section for the stored margin. Args: model_hash: The model hash (any status). |
| delete_modelA | PERMANENTLY DELETE a FAILED model. Destructive and irreversible. Only models with status "failed" can be deleted over the API — any other status returns a 409 with the model's current status (delete is for cleaning up failed fits, not curating good ones). Deleting also unlinks any MMMs that pointed at it as their VAR model and removes stored artifacts. On success returns {"deleted_model_hash": ..., "status": "deleted"}. Check first with get_model or get_model_status if unsure of the status. Args: model_hash: Hash of the FAILED model to delete permanently. |
| get_model_statusA | Check the fitting progress of a model. Returns status (pending/under way/complete/failed), progress percentage, estimated time remaining, and timestamps. When supported by the backend, fit_liveness reports heartbeat age and the configured stall threshold in seconds, with last_heartbeat_at as Unix seconds. seconds_until_stall_threshold is time to the stale-heartbeat threshold, not fit ETA or an exact kill time. stall_threshold_exceeded does not change the model status. If fit_liveness is absent or available is false, liveness is unknown: do not infer a healthy or stalled fit. Reasons include heartbeat_unavailable and not_fitting. Continue polling with backoff; do not automatically restart a fit. Args: model_hash: The model hash returned by create_model or list_models. |
| get_model_resultsA | Get results from a completed model. Available sections:
The response envelope includes IMPORTANT — channel naming: results are keyed by the channel's ACTIVITY
COLUMN name (e.g. "search_activity"), not by the NOTE: Date values in contributions/coefficients records are millisecond epoch integers. CONTEXT-SIZE TIP: a full pull is very large (curve sections alone are 100 grid points x channels x 5 band columns). In conversational use, request only the sections you need and pass channels=[...] and max_grid_points=20. Args:
model_hash: The model hash.
sections: Comma-separated list of sections to include.
Leave empty for all sections.
Common: "channel_summary,model_stats" for ROI and diagnostics.
format: "json" (default) or "csv". CSV returns
{"format": "csv", "content": "..."} — concatenated
"# section" + CSV blocks, useful for saving to disk.
Filtering below applies to JSON only.
channels: Optional channel filter (matching is case/space-insensitive
and tolerates the _activity/_spend suffix). Applied to curve
sections, decay_curves, saturation, channel_summary,
coefficients, mroi_summary, and mroi_periods rows.
|
| run_optimizerA | Run budget optimization on a completed model. Finds the optimal budget allocation across channels to maximize predicted revenue — or predicted PROFIT with objective="profit" — within the given constraints. PROFIT OBJECTIVE: objective="profit" requires a margin source. If the model was built with an operating margin, it is used automatically; otherwise you MUST pass forward_margin (e.g. 0.18 for an 18% margin) or the API returns an error. Result fields (Revenue, ROI, ExpectedResponse) are then on the profit basis. IMPORTANT:
Returns 202 (async). Use get_optimizer_results to poll until status is "complete". Args: model_hash: Hash of a completed model. total_budget: Total budget in currency units. num_periods: Number of periods to optimize over (matches your planning horizon). gamma: Uncertainty-aversion weight on the outcome spread (the objective is mean - gamma * spread). 0.0 = maximize expected return only (most aggressive); higher values penalize uncertainty harder (more conservative). The dashboard typically uses values in the 0-0.1 range. currency: Currency code (e.g. "USD", "GBP"). bounds: Per-channel min/max budget allocation as PERCENTAGES (0-100). Every channel must appear. Example: {"TV_Impressions": {"lower": 5, "upper": 40}, "Search_Clicks": {"lower": 10, "upper": 50}} laydown_weights: Per-channel spend timing weights. Each value is an array of length num_periods. Weights are relative (normalized internally). Use uniform [1, 1, ...] for even distribution across periods. Example: {"TV_Impressions": [1, 1, 1, 1]} period_cpm: Per-channel cost-per-metric for each period. Each value is an array of length num_periods with positive values. Get baseline CPM from get_scenario_template (avg_cpu_by_channel field). Example: {"TV_Impressions": [10.5, 10.5, 10.5, 10.5]} objective: "revenue" (default) or "profit". See PROFIT OBJECTIVE above. forward_margin: Decimal margin in (0, 1], e.g. 0.18 = 18%. Only used with objective="profit"; required when the model has no stored operating margin. period_multiplier: Optional array of length num_periods converting KPI units to revenue per period over the planning horizon (mirrors the model's multiplier_column, e.g. price). include_historical_effect: Include carryover from historical spend in the predicted response (default True). enable_warm_start: Warm-start the optimizer from a previous solution (default True). optimizer_engine: "slsqp" (hardened SLSQP, default) or "marginal" (water-fill engine: allocates until every funded channel shows the same marginal return; exact profit-hurdle semantics and the tightest optimality certificates, with automatic SLSQP fallback). sigma_penalty: How gamma penalizes outcome spread: "std" (default), "variance" or "frozen" (advanced; smoother alternatives for hard-to-converge runs - leave on "std" normally). group_bounds: Joint constraints over channel SETS (#570), e.g. [{"name": "trade", "channels": ["TV", "Search"], "lower": 40, "upper": 60}] with lower/upper in % of total_budget (same convention as bounds). Groups must be disjoint and jointly feasible with the members' per-channel bounds. Presence forces the slsqp engine. Results gain GroupBounds/GroupBoundsReport columns; a BINDING group's members legitimately sit off the global marginal (they share the group's shadow price). |
| get_optimizer_resultsA | Get budget optimization status and results. Without run_id: returns the MODEL-LEVEL optimizer state. Top-level keys:
With run_id (run_optimizer's response includes it): fetches that specific
run, immune to later runs. Top-level keys include Reading
Args: model_hash: Hash of the model that was optimized. run_id: Optional optimization run id from run_optimizer's response. Pass it to poll a specific run's status/results. |
| get_scenario_templateA | Generate a forward-period scenario template from a completed model. Returns future dates pre-filled with values from 1 year prior, the list of media and control channels, and average cost-per-unit per media channel. IMPORTANT: Always call this before run_scenario or run_optimizer to discover:
The response also includes: operating_margin (the model's stored margin, if set — useful for profit math), variable_transforms (per-variable transform metadata), periodicity, and start_date. WARNING: Template data may contain NaN or null values for channels without historical data. You MUST replace NaN/null with 0 before passing to run_scenario, otherwise the prediction will fail downstream. Args: model_hash: Hash of a completed model. periods_forward: Number of future periods to generate (default 12). |
| run_scenarioA | Run a "what-if" scenario prediction on a completed model. Takes a set of future period rows with channel activity values and
predicts the KPI outcome. Use get_scenario_template first to get
the expected format, channel names, and baseline values. Channel names are
the activity-column keys from the template/results (e.g. "search_activity"),
not the IMPORTANT: Before submitting, replace any NaN/null values in scenario_data with 0. The template from get_scenario_template may contain NaN for channels without historical data, which will cause the prediction to fail. This is async (returns 202 with status "pending"). Poll get_scenario_results until status is "complete" or "failed". Workflow: get_scenario_template -> modify values -> run_scenario -> poll get_scenario_results Args: model_hash: Hash of a completed model. scenario_data: Array of period rows, each a dict with "Date" (YYYY-MM-DD format) and channel activity columns. Channel names must match exactly what get_scenario_template returns in the "channels" field. Example: [{"Date": "2025-01-06", "TV_Impressions": 50000, "Search_Clicks": 1200}] spend_metadata: Optional per-channel spend info for ROI calculation in results. Each entry: {"channel": "TV_Impressions", "metric": "impressions", "cpm": 25.0, "total_spend": 125000, "weekly_spend": [25000, 25000, ...]} rebuild_model: Recompile the model graph before prediction. Must be True (default) for API-initiated scenarios where the model graph is not in memory. evaluate_holdout: Evaluate the scenario against held-out actuals when the scenario period overlaps observed data (default False). skip_slicing: Skip per-channel contribution slicing in the prediction output — faster when only the KPI total is needed (default False). proxy_channels: Optional list of proxy-channel mappings, each mapping a scenario channel to a fitted channel whose transforms it borrows (for channels without their own history). |
| get_scenario_resultsA | Get scenario prediction results. Without run_id: returns the MODEL-LEVEL scenario state — status (pending/complete/failed) and, when complete, the full prediction data including predicted KPI per period, channel contributions, confidence intervals, and base components (intercept, seasonality, trend). This reflects the LATEST scenario on the model — a newer run overwrites it, so a poller can lose sight of the run it submitted. With run_id (run_scenario's response includes it): fetches that specific
saved run, immune to later runs — keys include NOTE: Failed scenarios return status "failed" with an error message in the JSON body (not an HTTP error). Always check the status field. Args: model_hash: Hash of the model the scenario was run on. run_id: Optional scenario run id ("scn_..."), from run_scenario's response or list_runs(artifact="scenario"). |
| update_runA | Rename / annotate a saved optimizer or scenario run. Runs are auto-named at creation (e.g. "$1.2M · 12mo · Jan 5"); renaming makes run history carry the analysis ("holiday cut -10%", "stretch 130%"). Renaming permanently flips the run's auto_named flag to false so future auto-naming never overwrites it. Only the fields you provide are changed. Args: artifact: "optimizer" (run_id "opt_...") or "scenario" ("scn_..."). model_hash: Hash of the model the run belongs to. run_id: The run's stable id from run history. name: New display name (non-empty when given; capped at 255 chars). notes: Free-text annotation. Omit to leave untouched; pass "" to clear. tags: Replacement tag list (max 20 tags, 64 chars each). |
| set_run_pinnedA | Pin or unpin a saved optimizer or scenario run. Declarative and idempotent: setting the current state again is a no-op, so scripts can safely re-run it. Args: artifact: "optimizer" (run_id "opt_...") or "scenario" ("scn_..."). model_hash: Hash of the model the run belongs to. run_id: The run's stable id from run history. pinned: Desired pin state. |
| list_runsA | List a model's saved optimizer or scenario run history. Returns {model_hash, runs, count, limit, offset}. Each run summary has: run_id, name, auto_named, pinned, notes, tags, status, error_details, progress fields while running, key_metrics (optimizer: total_budget, num_periods, gamma, predicted_revenue/roi, ...; scenario: num_periods, total_planned_spend, predicted_outcome, ...; null metrics are omitted — treat every key as optional), and created/started/completed timestamps. Ordering is pinned-first, then newest-first. CAVEATS:
Use get_optimizer_results / get_scenario_results with a run_id to fetch a listed run's full inputs and results; update_run / set_run_pinned to curate it. Args: artifact: "optimizer" (run ids "opt_...") or "scenario" ("scn_..."). model_hash: Hash of the model whose run history to list. limit: Page size (API clamps to 1-200; default 50). offset: Rows to skip (paging). |
| list_studiesB | List project-owned studies, questions, budgets and access rights. |
| create_studyA | Create a study owned by an existing project. Does not launch models. |
| get_studyA | Read a study and its optimistic concurrency version. |
| update_studyA | Update owner-controlled study settings. State is active, paused or archived. Stale versions fail. |
| list_study_recipesA | Read all recipe revisions including exact effective priors, settings and data hashes. Raw datasets are omitted. |
| create_study_recipeA | Freeze a recipe without fitting. Supply source_revision_id when deriving from a published same-study recipe to retain influence ancestry. Optional expected_content_hash binds the validated effective inputs; a mismatch returns 409 and requires a fresh preview. Specification kind api_mmm has request containing create_model API fields; model_snapshot has model_hash and is review-only. |
| revise_study_recipeA | Create an immutable revision. Earlier versions inherit influence automatically; optional source_revision_id additionally links a same-study source recipe. Optional expected_content_hash guards effective inputs (409 requires a fresh preview). Supply the current recipe version; stale edits are rejected (412). Reload list_study_recipes, reconcile changes, then submit the current version; never overwrite blindly. |
| get_recipe_revisionA | Read one exact immutable recipe revision. |
| validate_study_recipeA | Resolve and validate a recipe without creating a run. Returns effective settings and provenance limits. |
| launch_study_runA | Launch a frozen revision within study attempt/concurrency budgets. Requires an active study, immutable executable revision and same-study policy. Budget/state conflicts require inspection, not a new attempt key. Reuse the same submission_key after an ambiguous response; never invent another key for a retry. |
| list_study_runsA | List preserved attempts including pending and failed runs. Supporting backends also return budget with attempts remaining, available slots and blocking reasons. Missing budget means unknown support, not permission to launch. Capacity is rechecked on reservation; recover an uncertain launch with its original submission key. |
| get_study_runA | Read durable run status and the linked model. |
| cancel_study_runB | Request cancellation. Requested and confirmed stopped are distinct states. |
| list_quality_policiesA | Read immutable quality policies for the study. |
| create_quality_policyA | Save project-specific checks. Built-in checks have metric (r_hat_max, mae, rmse, wape, prediction_mae, prediction_rmse, prediction_wape), maximum and required. Custom numeric checks use metric custom:, name, units, operator (lte/gte/between), applicable minimum/maximum and required. Boolean checks use kind=boolean, operator=equals and expected=true/false. Manual checks use kind=manual, equals, expected=true; agents can define these but cannot submit manual sign-off. Custom bounds may be negative. WAPE is a fraction. Prediction-window checks require saved finite actuals/predictions at unique dates after the saved training window; this does not certify untouched holdout provenance. No default thresholds are assumed. Declare at least one required check, use each metric once, and set maximum R-hat at least 1. Optional validation_protocol declares a temporal holdout split, configured sampling minima, R-hat and prediction WAPE limits before both runs launch under this policy. The backend validates policy rules. |
| evaluate_study_runA | Save an immutable assessment. First evaluate without external_evidence to obtain report.basis_hash; then calculate custom metrics from outputs and submit finite numeric or strict boolean values, method and source reference with that expected_basis_hash. The server applies the saved rule; stale model evidence is rejected. External calculations are submitter-reported, not verified. Each submission is complete: omitted custom values stay unevaluated. Manual sign-off requires a signed-in reviewer and is rejected for API keys. No automatic champion promotion. Built-in errors are fitted-window, not holdout; VAR remains unsupported. |
| list_study_evaluationsB | Read preserved quality reports and evidence hashes. Serving available prediction reports appends access audit events. |
| list_study_decisionsB | Read analyst decisions and agent recommendations. |
| get_study_championA | Read incumbent, eligibility blockers, accepted candidates and immutable champion history. Stale champions retain their historical role with review_required. Reported holdout use that informed a candidate revision blocks that revision pending fresh validation; holdout_use lists the declaration IDs. Ordinary viewing does not block. Current analyst-reviewed validation resolutions can clear the exact run acceptance; changed evidence or revoked review reblocks it. Recorded revision ancestry inherits influence. Validation references are reviewer-declared; decision_grade_ready is false until independently qualified. Selection/replacement/revocation require an owner frontend session; MCP cannot promote models. |
| get_study_prediction_accessA | Read partial prediction-access history for this run and matching recorded dataset/windows in this study. Does not expose predictions or add access events. Earlier activity, other result routes and offline work are not covered; absence never proves untouched holdout status. Repeated access does not prove retuning. |
| get_study_validation_resolutionsA | Read analyst validation resolutions and revocations, including current/stale/revoked status re-evaluated against exact evidence. API keys cannot supply human independence sign-off or revoke it; use the signed-in owner UI. No audit serving event is added and no model is fitted or promoted. |
| declare_study_holdout_useA | Append a submitter-reported evidence-use declaration using project-owner credentials and create:models. Read get_study_prediction_access first and reference an access event from this run. Use a fresh UUID declaration_id and reuse it unchanged on retry. informed_revision requires a published affected revision in the same study; other dispositions omit it. Reason must explain actual use. Reported revision influence requires fresh validation for affected revisions; later review-only notes cannot erase it. Does not certify independence, accept or promote a model. API submissions remain identified as reported declarations. |
| assess_study_validation_pairA | Assess a validation pair and append a prediction-access audit event when evidence is available. Checks distinct completed MMM runs launched under the declared protocol, frozen inputs/settings/runtime, configured sampling, saved R-hat, declared prediction windows/WAPE and date coverage. Returns blockers and an evidence hash; does not fit, accept or promote. Includes saved retained chain/draw, ESS and divergence records when available, with null for older models. Optional prelaunch retained_sampling limits require complete native records and check chain/draw minima, bulk/tail ESS minima and maximum divergences; otherwise sampling_qualification is not_declared. Optional require_policy_review checks current signed-in analyst acceptance of each latest same-policy assessment, including freshness and rejection blockers. The holdout_provenance report distinguishes missing evidence, blocked version 1 full-input preprocessing and version 2 training-only preprocessing requiring further provenance review. The prior_provenance report checks recorded automatic-prior source dates and frozen input hashes; missing legacy/uploaded provenance remains unavailable, and recorded inputs after the declared training end are blocked. fresh_validation provides replacement-window preflight for influence reports naming the full-model revision: later windows, replacement policy chronology, recorded prior exposure, retained diagnostics and provenance/review requirements. It never clears champion blocks. External business calculations and untouched holdout history remain unverified; decision_grade_ready stays false. |
| recommend_study_runA | Record a recommendation with evidence. This does not accept or promote a model; analyst acceptance happens in the frontend. |
| adopt_model_into_studyB | Preview an owned completed model and provenance gaps. Set confirm only to attach it to study history; adoption does not refit. |
| compare_study_runsA | Compare 2-20 candidates against one quality policy. Serving prediction evidence appends access audit events. Different datasets are flagged, not ranked. Does not fit or promote models. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 63 tools
The core model/upload/optimizer/scenario tools are distinct, but the recipe and study clusters overlap heavily: create_recipe_draft vs create_study_recipe and get_recipe_revision_authoring vs get_recipe_revision are easy to confuse from names alone. Detailed descriptions resolve most ambiguity, but an agent must read carefully before choosing.
All 63 tools follow a consistent snake_case verb_noun pattern: get_*, list_*, create_*, update_*, run_*, launch_*, evaluate_*, compare_*. Even the longer compound nouns like study_validation_pair and recipe_revision_authoring are internally consistent with their siblings, so the set is highly predictable.
At 63 tools, the server is far above the well-scoped range and feels like a full platform API rather than a focused MCP surface. The broad Simba domain explains some of the count, but the surface would be much more usable split into modeling, run/optimization, and study-governance servers.
The surface covers nearly the entire MMM and VAR lifecycle: schema/upload, model creation/status/results, optimizer/scenario runs, projects, and deep study/recipe/quality governance. It is not a perfect 5 because a few lifecycle actions such as deleting non-failed models/projects, champion promotion, and manual sign-off are deliberately frontend-only and documented as gaps an agent cannot complete.