Skip to main content
Glama
getsimba-ai

Simba MCP Server

Official
by getsimba-ai

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

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

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
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:

  • CSV only (not Excel). Maximum file size: 10 MB (API-enforced).

  • Row minimum: check get_data_schema -> x-simba-constraints.min_rows for the declared minimum; enforcement may be more permissive, and the upload response's warnings field is authoritative. More rows = tighter posteriors (104+ weekly rows recommended).

  • Media columns must follow naming: {channel}_activity and {channel}_spend.

  • Use 0 for inactive periods, not blank or NA.

  • csv_path is only available when the server runs locally (stdio). On HTTP/SSE deployments it is disabled unless SIMBA_MCP_ALLOW_LOCAL_FILES=1.

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 count IS the true total matching the filter (unlike list_runs, where it is the page length). Column names/dtypes are not in the listing — fetch one upload with get_upload for those.

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 limit (default 0).

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 financials results section and lets run_optimizer(objective="profit") use it automatically instead of requiring forward_margin on every call. operating_margin_column: Name of a column in the uploaded CSV holding a per-date margin series. The column may be uniformly in fractions (0, 1] OR uniformly in percentages (1, 100] — the API detects the unit and normalizes percentages; mixed units are rejected. Same unlocks as operating_margin; the column must exist in the uploaded file. CAUTION: the API reads the margin keys from the REQUEST ROOT — a margin placed inside a config dict is silently ignored (no error), and the model fits marginless. attribution: Attribution convention for the contribution decomposition, resolved at fit time: "removal_lift" (the API default; one-at-a-time removal — multiplicative models then emit the Overlap column), "aumann_shapley" (the dashboard default for multiplicative models since #509), "shapley", or "proportional_normalized". Any value other than "removal_lift" requires link="log" (the API rejects it on additive models). The non-removal conventions allocate the interaction across components and close exactly WITHOUT an Overlap column. To reconcile with a dashboard-built multiplicative model, use "aumann_shapley". annual_discount_rate: Annual discount rate (decimal >= 0, e.g. 0.08) used by the display-time financial bridge and cohort ledger PV discounting. Display-time only — does not change the fit. sampler: MCMC sampler overrides, e.g. {"n_samples": 2000, "tune": 1500, "chains": 4, "cores": 2, "target_accept": 0.95}. STRICTLY validated: unknown keys inside sampler are rejected with a 400 naming the field; cores must be 1-8. Only the keys you send are overridden. reporting_kernel: Reporting-kernel class override (#450) for the cohort_ledger section's forward allocation. Shape: {"classes": {...}, "channel_classes": {...}} — ONLY those two top-level keys are accepted (anything else, e.g. "mode", 400s with the unknown key named). channel_classes names channels by channels[].name or activity_column, validated at request time. Affects only how the cohort_ledger allocates effects over the horizon — not the fit, and not the contributions / channel_summary decompositions. (The related "complete" / "in_window" choice is a separate cohort_horizon QUERY parameter on the results endpoint, not part of this config.)

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 long_run_rollup results section. Fit one, then link it to an MMM with link_var_model.

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 long_run_rollup section joins the VAR's long-run elasticities with the MMM's short-term revenue. A VAR links to at most one MMM at a time — the error names the current owner if it is already linked elsewhere.

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_modelB

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_groupsA

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.

Args: model_hash: The model hash returned by create_model or list_models.

get_model_resultsA

Get results from a completed model.

Available sections:

  • channel_summary: per-channel aggregates {Channel, Sales, Spend, Revenue, ROI}.

  • contributions: per-period decomposition (Date, one column per channel, plus Base, Seasonality, Event Effect, Model, Fit Actual, Actual). Values are in KPI/unit space — the multiplier is NOT applied. Use coefficients for per-period revenue. Multiplicative (link="log") models fitted with the removal_lift attribution convention add an Overlap column: a negative shared-synergy reconciliation term so that Base + components + Overlap = Model. Overlap is NOT a channel — never rank it, share it, or feed it to the optimizer/scenarios. Overlap requires BOTH link="log" AND attribution="removal_lift" (the API default): under aumann_shapley (the dashboard default for multiplicative models since #509), shapley, or proportional_normalized, the interaction is allocated across components, which close exactly with NO Overlap column — its absence does NOT mean the model is additive or predates the feature. Control columns are measured against the reference point resolved at fit time (#452, see model_config.control_references) — e.g. "vs. average conditions" for a control that never reaches zero — not necessarily against zero, so a referenced control's series legitimately spans zero.

  • coefficients: per-period per-channel media results table (Date, Channel, Sales, Revenue, Spend, Media Units, ROI, Cost/Revenue/Sales per Media Unit). This is the only per-period revenue-space decomposition.

  • params: fitted posterior means per channel (alpha, decay, cpu, scalars).

  • decay_curves: adstock decay per channel (mean/lower/upper, l_max, adstock_type, curve points; dual-geometric models add decay_slow_* and dual_weight_* parameters).

  • response_curves: 100-point spend-vs-revenue grid per channel with credible bands ({ch}, {ch}_lower, {ch}_lower_50, {ch}_upper_50, {ch}_upper).

  • marginal_curves: same grid for marginal ROI (diminishing returns).

  • saturation: fitted saturation family and parameters (saturation_type is tanh, michaelis_menten, negative_exponential, or generalized_log; per-channel alpha/scale, plus transform_order and — for generalized_log only — per-channel sat_shape).

  • mroi_summary: headline marginal ROI at current spend per channel with a 94% HDI (channel, current_spend, mroi_median, mroi_hdi_3, mroi_hdi_97). Post-#591 posterior fits add two averaging-convention scalars per channel — mroi_allperiods_unweighted_median (+_hdi_3/_hdi_97) and mroi_spendweighted_active_median (+_hdi_3/_hdi_97), with profit variants on margin models — plus a top-level conventions_available array. Channels with no active periods omit the spendweighted fields. Post-#629 fits also carry a *_mean beside every *_median (mroi_mean, mroi_profit_mean, pv_kernel_mass_mean, and the convention variants). The median is what the product displays; the mean is the statistic that reconciles with the marginal-revenue curve, since derivative and mean commute and median does not. Absent on anything fitted before #629 — there is no backfill, so feature-detect rather than assume.

  • mroi_periods: OPT-IN ONLY (#591) — never in the default payload; request it by name in sections. Per-period marginal ROI series: {available, hdi_prob, evaluation_point: "historical_period_spend", rows} with one row per (channel x modelled period): channel, date, spend, mroi_median/_hdi_3/hdi_97, and mroi_profit* on margin models. Models fitted before the artifact existed return {available: false, reason: "fitted_before_mroi_periods"} — refit to enable. Large (channels x periods) — pair with the channels filter.

  • model_stats: fit diagnostics (R², MAPE, Durbin-Watson, Max R_hat, ...).

  • actual_vs_model: actual vs predicted per period with 50%/95% HDIs.

  • long_run_rollup: MMM short-term + VAR long-run revenue rollup per channel; returns {available: false, reason: "no_linked_var_model"} when no VAR model is linked to this MMM. Joins by exact name unless the link declared a channel_map (see link_var_model) — mapped rows carry var_group and an allocated elasticity slice, with group-level truth in metadata.groups. A computed rollup where nothing joined stays available: true but carries reason: "no_channel_overlap" — check metadata.coverage, then declare a channel_map on the link.

  • optimizer: latest optimization results (see get_optimizer_results).

  • predictions: latest scenario prediction rows (see get_scenario_results).

  • posterior: full posterior summary table — one row per model variable with mean, sd, hdi_3%, hdi_97%, and r_hat (quotable 94% HDIs and per-variable convergence).

  • posterior_transforms: the importable transform-parameter posterior grid (what the dashboard's prior builder imports): per-channel alpha mean/sd, decay 94% HDI, dual-weight mean/sd, decay-slow HDI, sat-shape mean/sd, and the adstock structure including tied-group member aliases. Rows key on activity-column names — join via channel_map.

  • r_hat: per-parameter R-hat over ALL posterior variables — including transform RVs such as {channel}_decay that the posterior summary's coefficient rows do not cover. Use it to attribute a bad Max R_hat (model_stats) to a specific parameter block.

  • financials: the model's operating margin ({operating_margin, operating_margin_series}); omitted entirely for marginless models. operating_margin_series is a DATE-STRING-KEYED DICT ({"2024-01-01": 0.18, ...}), not a list of records.

  • cohort_ledger: per-(channel, source-period) forward-allocation ledger — each period's spend is credited with the future effects its adstock carryover earns (horizon slices plus PV-discounted financials from the fit-time cohort kernels). Models fitted before the artifact existed return {available: false, reason: ...} — feature-detect on available.

  • model_config: the resolved model specification (inputs, not posteriors) to audit or reconstruct the create_model call — includes config flags such as saturation_type, transform_order, and link ("log" = multiplicative). Multiplicative models with controls also report control_references (#452): per control, the requested and resolved attribution reference mode, the zero_distance diagnostic behind the "auto" choice, and the posterior-mean q_ref. Models created before these fields existed may omit them. priors_resolved reports what the fit actually consumed (#643): per row, overridden_fields lists only the fields that took effect, and accepted_not_used — present only when non-empty — names any that were accepted but inert for this model's configuration, each with a reason. A prior field can be spelled correctly and still do nothing: theta_* needs adstock_type "delayed", dual_weight_* needs "dual_geometric", sat_shape_* needs saturation_type "generalized_log", and the decay / half-life bounds are ignored FOR "dual_geometric". If a prior you set appears to have had no influence, read accepted_not_used first. The folded coordinates (half_marginal_*, effect_at_avg_*) are never called inert — they land in the row's scalars/alpha_sd/mean/sd.

  • channel_map: canonical identifier mapping, one record per channel: {channel, activity_column, spend_column} as configured at create time. This is the join key between channels[].name and the sections keyed by activity-column name (contributions, decay_curves, posterior_transforms).

The response envelope includes sections_available — trust it over any hardcoded list if the server is newer than these docs.

IMPORTANT — channel naming: results are keyed by the channel's ACTIVITY COLUMN name (e.g. "search_activity"), not by the channels[].name passed to create_model. These exact keys (case- and space-sensitive) must be used in run_optimizer bounds, laydown_weights, and period_cpm. Always read channel_summary first to get the exact keys.

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. contributions is never filtered (its control columns are indistinguishable from channels client-side). max_grid_points: Optional cap on response/marginal curve grid points; records are strided evenly, keeping first and last.

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:

  • Channel names must exactly match model results (case-sensitive, space-sensitive). Results are keyed by the channel's ACTIVITY COLUMN name (e.g. "search_activity"), not by the channels[].name passed to create_model. Call get_model_results with sections="channel_summary" first to get exact names, or use get_scenario_template to discover channel names and their average CPM values.

  • bounds values are percentages of total_budget (0-100), not currency amounts.

  • laydown_weights and period_cpm must be ARRAYS of length num_periods, not scalars. Wrong: {"TV": 10}. Correct: {"TV": [10, 10, 10, 10]}.

  • The same channel keys must appear in all three: bounds, laydown_weights, and period_cpm.

  • All period_cpm values must be positive (> 0).

  • laydown_weights per channel must sum to a positive value (weights are normalized internally).

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: optimizer_status ("none"/"pending"/"under way"/"complete"/"failed"), progress + progress_text while running, and results when complete. This reflects the LATEST run on the model — a newer run overwrites it, so a poller can lose sight of the run it submitted.

With run_id (run_optimizer's response includes it): fetches that specific run, immune to later runs. Top-level keys include run_id, model_hash, status, created_at, label, inputs, and results. Poll THIS form when you need to know whether your own run completed.

Reading results rows — the columns come from DIFFERENT conventions and must not be treated as interchangeable:

  • Revenue / ROI: the optimizer's DECISION math — removal-lift counterfactual revenue at the allocated spend. This is what the solver optimized.

  • OptimizedEvalRevenue / OptimizedEvalROI and HistoricalRevenue / HistoricalROI: fitted-convention COMPARISON columns — the reconciled accounting view matching the model's Contributions panel. Same spend, different question; never mix them with Revenue/ROI in one summary.

  • ObjectiveMarginal: the decision-math marginal return at the optimum (the quantity the solver equalizes across unconstrained channels).

  • MroiAtOptimized / MroiAtOptimizedHdi3 / MroiAtOptimizedHdi97: posterior mROI evaluated at the optimized spend (94% HDI bounds) — a DIFFERENT quantity from ObjectiveMarginal (they can differ by several times); quote the one matching the question asked.

  • Convergence / KKT certificate fields report solver health. All-None placeholder arrays (PeriodResponse etc.) are stripped server-side.

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:

  • Channel names (use these exact names in scenario_data, bounds, laydown_weights, period_cpm)

  • Average CPM per channel (avg_cpu_by_channel — use for period_cpm in run_optimizer)

  • Baseline activity values per channel (rows — use as starting point for scenarios)

  • Media vs control channel classification (variable_classification field)

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 channels[].name passed to create_model.

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 run_id, model_hash, name, status, pinned, notes, tags, key_metrics, timestamps, inputs (the submitted payload), and results. Poll THIS form when you need to know whether your own run completed, or to disambiguate back-to-back scenarios.

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:

  • count is the LENGTH OF THIS PAGE, not the total run count — page until a short page.

  • The optimizer objective ("revenue"/"profit") is NOT in the summary; fetch the specific run (get_optimizer_results with run_id) and read its inputs — profit runs carry objective: "profit" there, revenue runs omit the key.

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).

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/getsimba-ai/simba-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server