Simba MCP Server
OfficialClick on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Simba MCP ServerShow me the channel contributions and ROI for my latest model"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Simba MCP Server
Simba is a Bayesian Marketing Mix Modeling (MMM) platform. This Marketing Mix Modeling MCP server lets AI assistants interact with your models directly — upload data, build models, check results, and run budget optimizations through natural language in Claude, Cursor, or Claude Code.
Installation
pip install simba-mcpOr run directly without installing:
uvx simba-mcpRelated MCP server: Meta Ads MCP
Quick Start
Cursor IDE
Add to your Cursor MCP settings (.cursor/mcp.json in the workspace or global settings):
{
"mcpServers": {
"simba": {
"command": "uvx",
"args": ["simba-mcp"],
"env": {
"SIMBA_API_URL": "https://demo.simba-mmm.com",
"SIMBA_API_KEY": "simba_sk_..."
}
}
}
}Claude Code
Add to your Claude Code MCP config:
{
"mcpServers": {
"simba": {
"command": "uvx",
"args": ["simba-mcp"],
"env": {
"SIMBA_API_URL": "https://demo.simba-mmm.com",
"SIMBA_API_KEY": "simba_sk_..."
}
}
}
}Claude API (MCP Connector)
Use the remote Streamable HTTP transport with the Anthropic MCP connector:
import anthropic
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
messages=[{"role": "user", "content": "List my Simba models"}],
mcp_servers=[
{
"type": "url",
"url": "https://demo.simba-mmm.com/mcp",
"name": "simba",
"authorization_token": "simba_sk_...",
}
],
tools=[{"type": "mcp_toolset", "mcp_server_name": "simba"}],
betas=["mcp-client-2025-11-20"],
)Available Tools
Tool | Description |
| Get the canonical CSV schema for MMM input files |
| Upload a CSV dataset to Simba |
| List previously uploaded datasets |
| One upload's details, including its column schema |
| List all models with their status |
| Configure and start fitting a new MMM model |
| Model metadata + config echo — works for any status, incl. failed |
| Permanently delete a FAILED model (409 for any other status) |
| Rename a model without saving it |
| File a model into a project (makes it visible to default |
| Release a saved model's slot (non-destructive inverse of |
| List the projects (model folders) you can file models into |
| Create a named project, optionally team-shared |
| Rename a project you own |
| Poll fitting progress for a model |
| Get results (ROI, contributions, response curves, diagnostics, and more) |
| Fit a long-term (VAR) model |
| Attach/detach a VAR model to an MMM for the |
| Persist/read the contributions-view driver groupings |
| Run budget optimization on a completed model |
| Get optimizer status and results (latest, or a specific |
| Generate a forward-period template for scenario planning |
| Run a "what-if" scenario prediction |
| Get scenario results (latest, or a specific |
| List a model's saved optimizer/scenario run history |
| Rename/annotate a saved run (notes, tags) |
| Pin/unpin a saved run |
Example Prompts
Try these with any connected AI assistant:
Explore your models:
"List my Simba models and show me the channel ROI summary for the most recent complete model."
Build a model:
"Upload this CSV data to Simba and create a new MMM model with TV, Search, and Social as media channels. Use 'revenue' as the KPI and 'date' as the date column."
Check progress:
"What's the fitting status of model a1b2c3d4?"
Get results:
"Show me the model diagnostics and channel contributions for model a1b2c3d4."
Optimize budget:
"Run a budget optimization on model a1b2c3d4 with $1M total budget over 12 months. Set TV bounds to 5-40% and Search to 10-50%. Use uniform laydown weights."
Response curves:
"Show me the response curves for model a1b2c3d4. At what spend level does TV hit diminishing returns?"
Scenario planning:
"Get a scenario template for model a1b2c3d4 for the next 12 weeks. Then run a scenario where I increase TV by 20% and cut Search by 10%. What happens to revenue?"
Full workflow:
"I have marketing data I want to analyze. First get the schema so I know what format is needed, then upload my data, create a model, and once it's done show me the ROI by channel."
Agent Skills
The skills/ directory ships workflow skills in the
Agent Skills format (SKILL.md per skill) —
install them into any skills-aware agent (e.g. Claude Code) alongside this
MCP server:
Skill | Covers |
Upload → create → poll → reading results correctly (section semantics, channel naming, attribution/Overlap rules, context-size controls) | |
Optimizer payload conventions, revenue vs profit, polling by run_id, decision- vs comparison-column semantics, run curation | |
Prior-override payloads: smart-default merging, strict rejection, the half-saturation / half-marginal / half-life anchor families | |
Long-term (VAR) modeling: create → poll → link → long_run_rollup |
The skills are documentation artifacts — they ride the repo, not the wire protocol.
Gotchas & Tips
Things that commonly trip up both AI agents and humans:
Hosted server: your bearer token IS your login
On HTTP deployments each request is authenticated with the caller's own
Authorization: Bearer simba_sk_... token — there is no server-side shared
key. If tool calls return "No API key on this request", your MCP client
isn't sending the token (check the authorization_token / headers setting
in its config).
Channel names are exact-match
Model results are keyed by the channel's activity column name (e.g. "search_activity", "TV_impressions"), not by the channels[].name you passed to create_model. Keys can contain spaces and matching is case-sensitive and space-sensitive — the optimizer and scenario tools use them as dictionary keys.
Always call get_model_results with sections="channel_summary" first to see exact channel keys, then use those verbatim in optimizer/scenario payloads.
Results sections
get_model_results serves these sections (request only what you need via sections=):
channel_summary, contributions (KPI/unit space — multiplier not applied), coefficients (per-period per-channel revenue table), params, decay_curves, response_curves, marginal_curves, saturation, mroi_summary (marginal ROI at current spend with 94% HDI; post-#591 fits add the allperiods_unweighted / spendweighted_active convention scalars, and post-#629 fits add a *_mean beside every *_median — the median is displayed, the mean is what reconciles with the marginal-revenue curve), mroi_periods (opt-in only — the per-period marginal ROI series; never in the default payload, request it by name), model_stats, actual_vs_model, long_run_rollup, optimizer, predictions, posterior, financials, model_config. The response's sections_available field is authoritative if the server is newer than these docs.
Models are identified by model_hash
All model endpoints use the string model_hash (e.g. "f835671a25") returned by create_model and list_models.
API-key management is deliberately not exposed
The /api/v1/keys endpoints (create/list/revoke API keys) are session-auth only and have no MCP tools by design: a server holding one key must not be able to mint or revoke keys. Manage keys in the Simba UI (Profile → API Keys).
Optimizer arrays, not scalars
laydown_weights and period_cpm must be objects of arrays, each array having exactly num_periods elements:
// Wrong
"period_cpm": {"TV": 10}
// Correct
"period_cpm": {"TV": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]}The same channel keys must appear in bounds, laydown_weights, and period_cpm. Bounds values are percentages (0-100) of total_budget, not currency amounts.
Clean NaN from scenario templates
The template from get_scenario_template may contain NaN/null for channels without historical data. Replace them with 0 before passing to run_scenario:
import math
for row in scenario_data:
for key, val in row.items():
if val is None or (isinstance(val, float) and math.isnan(val)):
row[key] = 0Three endpoints are async
These return 202 and require polling:
Action | Start | Poll |
Fit model |
|
|
Optimize |
|
|
Scenario |
|
|
Poll every 5-10 seconds. Check the status field for "complete" or "failed".
Data upload requirements
CSV only (not Excel). Maximum 10 MB (API-enforced).
Row minimum: check
get_data_schema→x-simba-constraints.min_rows; the upload response'swarningsfield is authoritative. More rows = tighter posteriors (104+ weekly rows recommended).Media columns:
{channel}_activityand{channel}_spendper channel.Use
0for inactive periods, not blank or NA.Large file? Pass
csv_path(a local file path) instead ofcsv_content— the server reads it directly instead of the CSV going through the conversation. Local (stdio) servers only; disabled on HTTP/SSE deployments unlessSIMBA_MCP_ALLOW_LOCAL_FILES=1.
Common Errors
Error | Cause | Fix |
| No API key or expired key | Check |
| Key doesn't have the needed scope | Create a key with all scopes |
| Payload missing required keys | Check the tool's parameter list |
| Model still fitting or failed | Poll |
| Scalar instead of array, or wrong length | Use arrays matching |
| Zero or negative CPM | All CPM values must be > 0 |
| Mismatched channel names | Same keys in bounds, laydown_weights, and period_cpm |
| Column name typo | Check CSV headers match exactly |
| CSV too large | Reduce file size or aggregate data |
Direct API Access
The MCP server wraps the Simba REST API. For scripting, CI/CD, or environments without MCP, you can call the API directly.
When to use MCP vs direct API
MCP (via AI assistant) | Direct API (curl / Python) | |
Best for | Exploratory analysis, conversational workflows | Automated pipelines, scheduled jobs, scripts |
Async polling | Assistant handles it automatically | You implement poll-until-complete logic |
Data cleaning | Assistant cleans NaN/null, builds payloads | You write the data prep code |
Reproducibility | Conversational | Scriptable, version-controlled |
Both use the same API keys with the same scopes.
Quick start (Python)
import requests, time
BASE = "https://demo.simba-mmm.com"
HEADERS = {"Authorization": "Bearer simba_sk_..."}
# Upload data
with open("marketing_data.csv", "rb") as f:
r = requests.post(f"{BASE}/api/v1/ingest",
headers={**HEADERS, "Content-Type": "text/csv"},
data=f.read(), params={"name": "q1_data"})
file_id = r.json()["id"]
# Create model
r = requests.post(f"{BASE}/api/v1/models", headers=HEADERS, json={
"data_source": {"uploaded_file_id": file_id},
"date_column": "date",
"kpi_column": "revenue",
"hierarchy_column": "brand",
"channels": [
{"name": "TV", "activity_column": "tv_grps", "spend_column": "tv_spend"},
{"name": "Search", "activity_column": "search_impressions", "spend_column": "search_spend"},
],
"total_media_effect": "Retail",
})
model_hash = r.json()["model_hash"]
# Poll until complete
while True:
status = requests.get(f"{BASE}/api/v1/models/{model_hash}/status",
headers=HEADERS).json()
if status["status"] in ("complete", "failed"):
break
print(f"Fitting... {status.get('progress', '?')}%")
time.sleep(10)
# Get results
results = requests.get(f"{BASE}/api/v1/models/{model_hash}/results",
headers=HEADERS,
params={"sections": "channel_summary,model_stats"}).json()
for ch in results["results"]["channel_summary"]:
print(f"{ch['Channel']}: ROI {ch['ROI']:.1f}")Quick start (curl)
API_KEY="simba_sk_..."
BASE="https://demo.simba-mmm.com"
# Upload data
curl -X POST "$BASE/api/v1/ingest?name=q1_data" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: text/csv" \
--data-binary @marketing_data.csv
# Create model (replace uploaded_file_id with id from upload)
curl -X POST "$BASE/api/v1/models" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"data_source": {"uploaded_file_id": 1}, "date_column": "date", "kpi_column": "revenue", "hierarchy_column": "brand", "channels": [{"name": "TV", "activity_column": "tv_grps", "spend_column": "tv_spend"}]}'
# Poll status (replace MODEL_HASH)
curl "$BASE/api/v1/models/MODEL_HASH/status" -H "Authorization: Bearer $API_KEY"
# Get results
curl "$BASE/api/v1/models/MODEL_HASH/results?sections=channel_summary,model_stats" \
-H "Authorization: Bearer $API_KEY"API Key Setup
The MCP server authenticates with the same API keys used by the Simba REST API. Create a key with the required scopes:
Go to Profile > API Keys in the Simba UI
Click Create Key
Set scopes:
ingest,read:models,read:results,create:models,optimize,scenarioCopy the key (shown only once)
How the key is supplied depends on where the server runs:
Local (stdio — Cursor, Claude Code): set it as the
SIMBA_API_KEYenvironment variable in your MCP config (the examples above).Hosted (
https://demo.simba-mmm.com/mcp): send it as the HTTPAuthorization: Bearerheader — theauthorization_tokenfield in the Claude MCP connector config. Every caller uses their own key (v0.2.2+): the server never shares an identity between callers, a request without a key gets a structured 401 with guidance, and you only ever see your own account's models.
Configuration
Environment Variable | Description | Default |
| Simba API base URL |
|
| Your Simba API key (stdio mode only — HTTP callers send their own key as the bearer token) | (required for stdio) |
Transport Modes
The server supports all MCP transport modes:
# stdio (default) — for Cursor, Claude Code
simba-mcp
# Streamable HTTP — for remote deployment
simba-mcp --transport streamable-http --port 8100
# SSE — legacy transport
simba-mcp --transport sse --port 8100
# Or via uvicorn directly
uvicorn simba_mcp.server:app --host 0.0.0.0 --port 8100License
MIT
Available Tools
29 toolscreate_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.
| Name | Required | Description | Default |
|---|---|---|---|
| link | No | identity | |
| name | No | ||
| trend | No | ||
| priors | No | ||
| sampler | No | ||
| channels | Yes | ||
| kpi_column | Yes | ||
| likelihood | No | normal | |
| attribution | No | ||
| date_column | Yes | ||
| seasonality | No | ||
| channel_groups | No | ||
| control_columns | No | ||
| saturation_type | No | tanh | |
| transform_order | No | adstock_first | |
| hierarchy_column | Yes | ||
| operating_margin | No | ||
| reporting_kernel | No | ||
| uploaded_file_id | Yes | ||
| control_reference | No | ||
| multiplier_column | No | ||
| total_media_effect | No | Other | |
| annual_discount_rate | No | ||
| operating_margin_column | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it is exceptionally transparent: it discloses async queuing, immediate hash return, polling needs, unsaved-model visibility, commit via save_model, strict validation (unknown keys rejected with 400), and the operating_margin_column root-caveat. It also explains resolved priors in get_model for verification.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The structure is front-loaded with a one-paragraph summary followed by an Args block, and each parameter gets its own explanation, which is appropriate for 24 complex parameters. However, the description is long and includes internal ticket references (#630, #672, etc.) and repeated caveats that add noise without helping tool selection or invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a complex creation endpoint: it covers the async return contract, model state lifecycle, validation behavior, and all parameter semantics. Since there is no output schema, it correctly states that the return value is a model_hash for status polling; no critical invocation information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does: every one of the 24 parameters is explained, including defaults, valid values, mutually exclusive pairs, and cross-parameter constraints. The priors section in particular adds meaning far beyond the schema's bare additionalProperties.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource: 'Create and start fitting a new Bayesian Marketing Mix Model.' It also differentiates from siblings by describing the async fit-and-poll lifecycle with get_model_status and clearly separates this from create_var_model's domain. The purpose is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states exactly what happens on use: it queues an async fit and returns immediately, and directs the agent to poll get_model_status until 'complete'. It does not explicitly enumerate when to choose this over create_var_model, but the resource type ('Bayesian Marketing Mix Model') makes the context clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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=...).
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| team_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so thoroughly. It discloses name sanitization behavior, team membership requirements with specific 403/404 outcomes, and the 201 response including the returned ID. These non-obvious behaviors go well beyond what a bare 'create' description would provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, well-organized, and front-loaded with the core purpose. Each sentence earns its place: purpose, sanitization rule, parameter details, and return value/workflow. There is no fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter create operation with no output schema, the description is complete enough: it states the return status and ID, explains the optional team parameter and its failure modes, and shows how the result feeds into save_model. No critical information for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does. It explains that name is a display name subject to sanitization, and that team_id is optional, must belong to the caller, and yields specific error codes otherwise. This adds substantial meaning beyond the bare property titles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Create a named project (model folder) to file models into.' It clearly distinguishes this from model-creation siblings by framing the project as a container for models, and the final sentence ties its purpose to save_model.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It does not explicitly enumerate when-not-to-use or alternatives, but it provides clear usage context: create a project as a destination for models, then pass the returned ID to save_model. The team_id constraint and error statuses further guide appropriate invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| lags | No | ||
| name | No | ||
| lre_ci | No | ||
| var_priors | No | ||
| date_column | Yes | ||
| lre_horizon | No | ||
| base_variable | No | ||
| exogenous_vars | No | ||
| endogenous_vars | Yes | ||
| equity_variables | No | ||
| forecast_horizon | No | ||
| uploaded_file_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full behavioral burden. It discloses the asynchronous nature ('Create and start fitting'), the return pattern ('Returns 202-style payload with model_hash; poll get_model_status'), data prerequisites ('at least lags + 10 rows'), strict parameter handling ('unknown keys are rejected'), and naming behavior ('honoured verbatim... falls back to generated API_VAR_*'). This goes well beyond a basic mutation description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but the tool has 12 parameters and the length is mostly earned. It is front-loaded with a clear one-sentence purpose followed by structured Args. Minor noise includes issue-tracker references like '(#569)' and '(#575)', which don't aid an agent in calling the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 12-parameter tool with no output schema and no annotations, the description is remarkably complete: it explains the statistical purpose, the workflow position, every parameter's semantics, constraints, defaults, asynchronous return behavior, and the follow-up status-polling call. An agent has enough information to invoke this tool correctly and know what to do next.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate fully for the schema. It does: every parameter in the schema is listed in an Args block with its role, constraints, and inter-parameter restrictions (e.g., date_column cannot also be a series, exogenous_vars must not overlap endogenous_vars, base_variable must be endogenous, equity_variables excludes the base). This is exemplary supplementary guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Create and start fitting a long-term (VAR) model'. It also clarifies how this fits into the broader MMM workflow by mentioning the long-run elasticity bridge and explicitly telling the agent to link it with link_var_model, which differentiates it from the generic create_model sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when this tool is appropriate: 'VAR models capture the joint dynamics of several series... produce the long-run elasticity bridge behind the MMM's long_run_rollup results section.' It also gives workflow sequencing ('Fit one, then link it to an MMM with link_var_model'). It doesn't explicitly list exclusions or contrast against generic create_model, but the context is clear enough for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and succeeds: it discloses irreversibility, the 409 error behavior for non-failed models, side effects on linked MMMs, removal of stored artifacts, and the exact success response shape. This is exemplary for a destructive mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence earns its place: the destructive warning is front-loaded, followed by status constraints, side effects, response format, and a pre-check hint. The Args section is minimal and directly tied to the parameter. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no annotations and no output schema, the description fully equips the agent to invoke the tool correctly: when it is allowed, what happens on failure, what side effects to expect, what response to expect, and how to avoid mistakes. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It does so by clarifying that model_hash refers to the hash of the FAILED model to delete, adding meaning beyond the bare string type. For a single simple parameter this is sufficient, though not deeply detailed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('permanently delete') and resource ('FAILED model'), clearly distinguishing it from read-only sibling tools like get_model and get_model_status. The capitalization and 'destructive and irreversible' warning make the operation unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states the only valid use case: deleting models with status 'failed'. It also names the alternatives to check first (get_model, get_model_status) and explains that other statuses return a 409, so the agent knows when not to use the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_contribution_groupsA
Read the stored contribution groups for a model (#436). Legacy dashboard-saved configs are served verbatim.
| Name | Required | Description | Default |
|---|---|---|---|
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral disclosure burden. It adds a useful behavioral detail: 'Legacy dashboard-saved configs are served verbatim.' However, it does not address what happens for invalid or missing model hashes, auth requirements, or possible transformations for non-legacy configs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two terse sentences with the main action front-loaded. The legacy-config note earns its place and does not add clutter, so the structure is efficient and scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a low-complexity, single-parameter read tool, so a very long description is not required. Still, with no output schema and no annotations, the description leaves the return shape and error behavior to inference; mentioning the legacy verbatim case helps but does not fully complete the picture.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, and the description does not explain 'model_hash' beyond associating it with a model. The parameter name is somewhat self-explanatory, but the description offers no guidance on where the hash comes from, its format, or how it should be supplied, leaving an uncompensated gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Read') and identifies the resource ('stored contribution groups for a model'). It clearly differentiates this getter from the sibling 'set_contribution_groups' tool without needing to open schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for retrieving stored contribution groups, but it provides no explicit guidance on when to prefer it over alternatives or when it should not be used. The existence of a setter sibling is evident from the sibling list, but the description does not explicitly route the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully carries the burden. It discloses that the tool returns a JSON Schema specification and enumerates the major contents (required columns, naming conventions, constraints, date formats). It also implies a read-only, side-effect-free 'get' operation, though it doesn't explicitly say so.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences: the first states the tool's purpose, the second lists exactly what the returned schema covers. Every sentence earns its place with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless getter, the description is complete: it names the resource, the return type, and the categories of information inside the returned schema. No additional detail about parameters or side effects is needed, and there is no output schema requiring separate explanation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there are no parameter semantics to explain. The baseline for a no-parameter tool is 4, and the description adds meaningful context about what the returned schema contains without needing to document inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Get') and a specific resource ('canonical CSV data schema for Simba MMM input files'), and clarifies that it returns a JSON Schema specification. The scope is unambiguous and clearly distinct from sibling tools that handle runs, models, or uploads.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes clear this is the tool to use when you need the schema for Simba MMM input files, which is useful context before uploading or validating data. It doesn't mention explicit exclusions, but no close alternative exists among the siblings, so no when-not guidance is necessary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full responsibility, and it discloses key behaviors: it returns data for any status, error is non-null only when status is 'failed', and the configuration echo omits some accepted create_model inputs. This is substantive behavioral context beyond the bare 'get' action.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the essential scope and usage, then organized into returns and caveats with clear formatting. The length is justified because there is no output schema to carry the return-field details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with no annotations and no output schema, the description provides comprehensive detail: behavior, return fields, failure semantics, and a known caution about omitted echo fields. Nothing required to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, model_hash, is described in Args with the added semantic 'any status', clarifying that the tool works with failed models. Schema coverage is 0%, but the single parameter is simple and the description gives enough context for correct invocation, though it does not give a format or example.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names the action ('Get'), the resource ('model's metadata and configuration echo'), and scope ('works for EVERY status, including failed models'). It explicitly differentiates from get_model_results, which needs status 'complete', so an agent can disambiguate without reading definitions of other tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states concrete use cases: inspect configuration, diagnose failure, or locate a model. It also names the alternative get_model_results as not applicable to failed models, giving an explicit when/when-not condition. The note about checking financials results for stored margin adds additional guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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
coefficientsfor per-period revenue. Multiplicative (link="log") models fitted with the removal_lift attribution convention add anOverlapcolumn: 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.
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | json | |
| channels | No | ||
| sections | No | ||
| model_hash | Yes | ||
| max_grid_points | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description carries the full behavioral burden and succeeds remarkably: it discloses CSV envelope structure, millisecond-epoch dates, per-section availability flags, version-dependent fields with no backfill, filtering exceptions, and the critical fact that results are keyed by activity-column names. It also warns about feature-detecting server-version differences rather than assuming hardcoded behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very long, but the section-list format and Args block are highly structured and almost every sentence carries operational value. It loses a point because critical cross-cutting guidance—channel naming, epoch dates, and the context-size tip—is buried toward the end, so a truncating client could miss essential usage constraints.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no output schema, no annotations, and many distinct result sections, this description is exhaustively complete. It documents shapes, key types, section availability, caveats, version differences, and even how to detect unavailable artifacts, leaving essentially no ambiguity about what calling this tool will return.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully document the parameters, and it does. Each parameter is explained in Args, including the meaning of model_hash, comma-separated sections, JSON vs CSV format with its return envelope, channel filtering semantics (case/space-insensitivity and the contributions exception), and max_grid_points striding behavior. This goes well beyond the bare input schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence 'Get results from a completed model' gives a specific verb and resource, and the extensive section list concretely defines what kinds of results exist. It is clearly differentiated from sibling retrieval tools like get_optimizer_results and get_scenario_results, which are referenced only as sub-sections of this broader results endpoint.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong practical usage guidance, such as recommending 'channel_summary,model_stats' for ROI and diagnostics, advising 'request only the sections you need' in conversational use, and explaining when mroi_periods is opt-in. It even includes behavioral prohibitions like never treating Overlap as a channel. However, it does not explicitly state when to choose this tool over get_optimizer_results or get_scenario_results, only pointing readers to those tools for those sections.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It goes beyond a generic status check by enumerating exact statuses (pending/under way/complete/failed) and specifying returned data: progress percentage, estimated time remaining, and timestamps. It does not discuss side effects or polling semantics, but 'check' and 'progress' make the non-mutating behavior reasonably clear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured: a one-sentence purpose, a clear listing of return contents, and an Args block with the necessary parameter guidance. Every sentence adds actionable information and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity tool with one parameter and no output schema, the description covers purpose, return values, and parameter provenance sufficiently for correct invocation. It could be improved by explicitly contrasting with get_model_results, but nothing essential for calling the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides only a bare type and title for model_hash, with 0% schema description coverage. The description compensates fully by explaining that model_hash is 'returned by create_model or list_models', giving the agent a precise way to obtain the required value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Check') and a specific resource ('model') with a clear scope ('fitting progress'). It distinguishes itself naturally from siblings like get_model_results and list_models by focusing on progress rather than final outputs or metadata.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage context by noting that model_hash comes from create_model or list_models, but it does not explicitly state when to use this tool versus alternatives such as get_model_results. There is no exclusionary guidance or conditional routing, so the usage is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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/OptimizedEvalROIandHistoricalRevenue/HistoricalROI: fitted-convention COMPARISON columns — the reconciled accounting view matching the model's Contributions panel. Same spend, different question; never mix them withRevenue/ROIin 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.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | No | ||
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden and does so thoroughly. It discloses the overwrite hazard, explains the meaning of result columns, warns against mixing incompatible metrics, and notes that placeholder arrays are stripped server-side.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but structured with clear headings, bullets, and mode-based sections. Every section adds necessary information about behavior, parameter usage, or result semantics, and the opening sentence immediately states the core function.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and no annotations, this description is exceptionally complete. It covers both invocation modes, return key structures, column interpretation pitfalls, and parameter semantics, leaving an agent well-equipped to call the tool correctly and interpret its results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains run_id's provenance from run_optimizer's response, its purpose for polling a specific run, and its optional/default nature. model_hash is described as the hash of the optimized model, which is sufficient given the schema's required string field.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Get budget optimization status and results.' It clearly distinguishes the two modes (model-level latest run vs. specific run via run_id) and ties to run_optimizer, making the tool's purpose unmistakable even among many siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance on when to use each form: without run_id for the latest model-level state, with run_id to poll a specific run. It warns that a newer run can overwrite the latest view and explicitly tells the agent to poll with run_id when it needs to know whether its own run completed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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").
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | No | ||
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full behavioral burden and meets it thoroughly. It discloses that newer runs overwrite the latest scenario, that run_id-scoped results are immune to later runs, and that failed scenarios return status 'failed' with an error in the JSON body rather than as an HTTP error, even advising to always check the status field.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but tightly organized with paragraph breaks and an Args list. Every section carries functional information, and the key distinction between run_id modes is placed early before the detailed response fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and no annotations, this description is remarkably complete: it covers both call modes, response contents, failure semantics, parameter sources, and the overwrite pitfall. An agent has enough to select the correct form, construct arguments, and interpret results correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it does. It explains model_hash as the model identifier and gives rich semantics for run_id, including its format ('scn_...'), its source, and how its presence changes the response shape and reliability of the result.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns scenario prediction results and distinguishes two modes: latest scenario state versus a specific saved run identified by run_id. However, it does not explicitly differentiate this tool from the sibling get_model_results, relying on the 'scenario' resource framing rather than naming the alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance for both forms: without run_id for the latest model-level scenario, and with run_id when polling your own run or disambiguating back-to-back scenarios. It also explains where run_id comes from (run_scenario or list_runs) and warns about the overwrite behavior.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| model_hash | Yes | ||
| periods_forward | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full behavioral burden and does so comprehensively. It discloses response contents, field-by-field meaning, the NaN/null risk, mandatory preprocessing before passing data downstream, and the consequence of ignoring the warning.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with a summary, an important usage block, a response-fields note, a warning, and parameter definitions. Despite substantial content, it is front-loaded and every section earns its place; no filler or vague language.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and no annotations, the description is unusually complete. It covers purpose, prerequisite usage, return fields, parameter semantics, an edge-case warning, and downstream integration details. An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It describes model_hash as 'Hash of a completed model' and periods_forward as 'Number of future periods to generate (default 12),' adding domain meaning that the bare schema does not provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with a specific verb and resource: 'Generate a forward-period scenario template from a completed model.' It clearly enumerates what the response contains and positions the tool as a prerequisite for run_scenario and run_optimizer, which distinguishes it from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States explicitly 'IMPORTANT: Always call this before run_scenario or run_optimizer' and then lists exactly what to discover and how to use those values downstream. This gives an agent unambiguous when-to-use guidance and prevents misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| file_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It fully discloses the return payload, including the exact structure of columns and their intended downstream use for create_model, which is valuable behavioral context. It doesn't cover error cases or permissions, but for a simple retrieval tool the return contract is the most important behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and efficient: a one-sentence purpose statement, a compact return field list, and a short Args section. Every sentence adds value, and the most important information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter getter with no output schema, the description is largely complete: it lists all returned fields and gives the one required input with provenance. It could be more explicit about read-only behavior or error conditions, but those are minor gaps given the simplicity of the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only defines file_id as an integer with no description, so the description fully compensates. It explains that file_id is the upload's id and explicitly tells the agent where to obtain it (upload_data response or list_uploads), which is exactly the semantic meaning needed to call the tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get', the resource 'one uploaded dataset's details', and highlights the column schema. This makes the tool's purpose immediately obvious and sufficiently distinguishes it from list_uploads (listing) and upload_data (creation), even though it doesn't explicitly name get_data_schema as an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives useful context by telling the agent that file_id comes from upload_data's response or list_uploads, and explains how the returned columns can be used to build create_model arguments. However, it does not explicitly state when to choose this tool over siblings like get_data_schema or list_uploads, leaving the comparison to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| model_hash | Yes | ||
| channel_map | No | ||
| var_model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so thoroughly: it discloses side effects (map replacement, unlink clearing), the pro-rata allocation rule, exact-name matching, strict validation rules, and the error naming the current owner for an already-linked VAR.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed but front-loaded: one-sentence purpose, then behavior, then validation, then args. The length is justified by the tool's complexity (group allocation, map lifecycle, strict validation) and every paragraph adds operational information rather than repeating schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given three parameters, no annotations, and no output schema, the description provides enough for a correct call: required vs optional args, channel_map semantics, validation, ownership constraint, and resulting behavior in get_model_results. No critical operational gap is apparent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the Args section must compensate. It defines model_hash as the MMM to attach, var_model_hash as the VAR from create_var_model, and explains channel_map's shape, optionality, validation, and link-scoped lifecycle. This goes well beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Link a completed VAR model to an MMM.' It clarifies the linking relationship and its observable effect on get_model_results, and the restrictions distinguish it from unlink_var_model and other model tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explains why linking is useful (long_run_rollup joins VAR elasticities with MMM revenue), when channel_map is required ('required whenever the VAR is fitted on group spends ... while the MMM is tactic-level'), and notes the one-link-per-VAR constraint. It does not explicitly say 'use unlink_var_model to remove a link,' though the unlink behavior is mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No | ||
| include_unsaved | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses the user-scoped nature of the list, the status/type fields returned, the include_unsaved behavior, and pagination semantics with default/max limits. It does not mention ordering or error behavior, but it provides substantially more behavioral transparency than a minimal description would.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and efficient: the purpose is front-loaded, the return fields are summarized in one sentence, a critical cross-tool note is set apart, and the Args block is compact and readable. Every sentence adds useful information, and there is no filler or tautology.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple list operation with three optional parameters and no output schema. The description covers what the tool does, what it returns, how to page, how to include unsaved models, and how the returned model_hash connects to all other model endpoints. Nothing essential for correct selection or invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides only titles and defaults, with 0% description coverage. The description compensates fully by explaining each parameter: include_unsaved includes draft/unsaved models, limit is the maximum number with a default of 50 and max of 500, and offset is the number to skip for paging. This is exactly the meaning an agent needs beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List all Marketing Mix Models for the authenticated user.' It goes on to enumerate the returned fields, making the tool's role clear and distinguishing it from narrower siblings like get_model or get_model_status. The scope is explicit, and the distinction between listing all models versus retrieving a specific one is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool by explaining that all other model endpoints require a model_hash and that list_models is the source of that hash: 'Use the model_hash from this response.' It does not explicitly name alternatives or exclusions, such as 'use get_model for a single model,' but the guidance is strong enough for an agent to infer the appropriate use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden and does so thoroughly. It discloses that only owned and team-shared projects are returned, the exact fields per project, the 'shared' flag behavior, the meaning of model_count (SAVED models, not all models), and the intentional absence of delete in the API.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact but information-dense, with a clear progression: what the tool lists, what it returns, how to use the ids, and the one intentional API limitation. Every sentence adds value; nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-argument tool with no output schema and no annotations, the description is complete. It explains the return payload, field semantics, downstream usage, and the missing delete capability. An agent could invoke this correctly with no further information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is nothing meaningful to document; the baseline for parameter semantics is therefore 4. The description correctly focuses on output semantics instead, which is appropriate for a parameterless list operation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List the projects (the app's model folders) you can file models into.' This clearly states what the tool does and clarifies what a 'project' is in domain terms. It is distinct from sibling tools like save_model or rename_project, and the follow-up about ids reinforces that distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent how to use returned ids: 'Use the ids with save_model(project_id=...) and rename_project.' It also provides an important when-not: 'There is deliberately no delete over the API — use the app to delete a project.' This gives practical guidance beyond a bare list function.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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:
countis 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 carryobjective: "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).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No | ||
| artifact | Yes | ||
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden, and it does so thoroughly. It reveals the exact response shape, ordering (pinned-first, newest-first), the non-obvious page-local meaning of `count`, and the missing optimizer objective caveat. It also documents API clamping on limit, which is exactly the kind of behavioral detail an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: Returns, Ordering, CAVEATS, alternative tool routing, and Args. The one-sentence purpose is front-loaded, and the caveats are truncated to the two genuinely non-obvious behaviors rather than enumerated exhaustively. Structure with labeled sections makes it easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema and no annotations, the description is essentially complete on its own. It defines the top-level return object, run summary fields including key_metrics examples, nullable key behavior, ordering, paging semantics, and caveats that would otherwise cause incorrect agent behavior. The only minor omissions (e.g., status enum values) are not necessary for successfully calling and interpreting this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully compensate; it does. Each parameter is given meaningful semantics: artifact values with run id prefixes, model_hash purpose, limit page size with API clamp and default, and offset as rows to skip for paging. This far exceeds the bare type/title information in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List a model's saved optimizer or scenario run history.' It also distinguishes itself from sibling tools by explicitly pointing to get_optimizer_results/get_scenario_results for fetching full run details. The artifact types ('optimizer' vs 'scenario') further clarify scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage guidance is explicit: use this tool to list run summaries, and use get_optimizer_results / get_scenario_results with a run_id when full inputs and results are needed. It also names update_run / set_run_pinned for curation and warns to page until a short page, which is actionable routing to alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| limit | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it delivers: newest-first ordering, inclusion of all source types, true-total count behavior, API clamping of limit, and the explicit absence of column names/dtypes. It also notes the id field's role for create_model, which is valuable behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured and efficient: overview, return shape, caveats, and argument details. Every sentence adds information an agent needs, including the count-vs-page-length warning and the pointer to get_upload for deeper metadata.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has no output schema and no annotations, but the description defines the complete return shape ({files, count, limit, offset}) and every field on each file. It also covers pagination, filtering, and the next-step alternative, making it fully actionable for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides only defaults and no descriptions, so there is 0% schema coverage. The description fully compensates by explaining limit with clamping and default, offset as paging, and name as a case-insensitive substring filter on the original filename.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List the datasets in your workspace (newest first)'. It also distinguishes this tool from siblings by clarifying it covers every source type, not just API uploads, and from get_upload by stating what this listing does and does not include.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when this tool is appropriate: listing datasets with pagination and filtering. It explicitly directs the agent to get_upload when column names/dtypes are needed, and it distinguishes the count semantics from list_runs to prevent misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full behavioral disclosure. It states that only the display name changes, that the saved/unsaved state is unaffected, that the name is HTML-sanitized server-side, and that it must be non-empty. These are concrete behavioral traits beyond the basic rename operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tight and well-structured: one summary line, a two-sentence behavioral clarification, and a two-line Args list. Every sentence adds value, and there is no redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter rename tool with no output schema, the description covers purpose, behavior, parameter meanings, and constraints. The only minor gap is the absence of return-value or error-condition details, but nothing essential is missing for making a correct call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates by defining both arguments: 'model_hash: Hash of the model to rename' and 'name: New display name.' This gives the agent precise meaning for each parameter, plus the text adds the non-empty constraint on name.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Rename a model,' a specific verb and resource, and immediately distinguishes itself from siblings by stating 'Changes only the display name; the model's saved/unsaved state is untouched.' This makes it clear this tool is not save_model or unsave_model, which are present in the sibling list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly provides a when-not-to-use signal: 'the model's saved/unsaved state is untouched (use save_model to file it into a project).' This directs the agent to the correct alternative and clarifies the exact boundary of this tool's responsibility.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| project_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations available, the description carries the behavioral burden. It discloses the owner-only restriction, the 404 behavior for non-owned projects, and the important default-folder behavior after renaming. It does not mention the return value or side effects beyond that, but the key mutation behaviors are covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with ownership and key caveats, followed by a clear Args section. Each sentence adds useful context, though the team-members example could be tightened without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter mutation with no output schema and no annotations, this description covers the critical context: who can rename, what error to expect, and what happens to the default folder. Missing return behavior is a minor gap, not a blocker.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It gives one-line explanations for both parameters, but 'project_id' and 'name' largely restate the schema titles. The only genuinely new information is 'see list_projects' and the word 'display' for the name, which is moderate compensation but not detailed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with 'Rename a project you OWN,' which clearly identifies the verb, resource, and ownership constraint. It is distinct from the sibling rename_model, so an agent can tell this tool is for projects, not models.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context: owner-only access, 404 for projects you don't own, and a note that renaming the default folder is safe. It doesn't explicitly contrast with rename_model or say when not to use this tool, but 'see list_projects' gives a useful pointer for obtaining the correct project_id.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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[].namepassed 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).
| Name | Required | Description | Default |
|---|---|---|---|
| gamma | Yes | ||
| bounds | Yes | ||
| currency | Yes | ||
| objective | No | revenue | |
| model_hash | Yes | ||
| period_cpm | Yes | ||
| num_periods | Yes | ||
| group_bounds | No | ||
| total_budget | Yes | ||
| sigma_penalty | No | std | |
| forward_margin | No | ||
| laydown_weights | Yes | ||
| optimizer_engine | No | slsqp | |
| enable_warm_start | No | ||
| period_multiplier | No | ||
| include_historical_effect | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it delivers: it discloses the 202 async contract, error conditions (missing margin), internal normalization of laydown weights, engine fallback behavior, and group-bound side effects on marginality semantics. This goes well beyond what the schema alone could reveal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but every section earns its place for a 16-parameter optimizer with significant constraints. It front-loads the main purpose, then groups related warnings in IMPORTANT bullets and documents each arg consistently. No filler or repeated schema text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex async tool with 16 params, nested objects, and no output schema, the description is complete: it covers all required inputs, prerequisite discovery steps, post-invocation polling, and key result-field semantics. An agent has enough context to invoke correctly and know what happens next.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, yet the description compensates for every parameter: gamma's formula and typical range, bounds as percentages with a worked example, laydown_weights/period_cpm array-length requirements, forward_margin's precise conditions, and even optimizer_engine behavior. This is exemplary parameter-level documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Run budget optimization on a completed model' and immediately states the outcome ('optimal budget allocation across channels to maximize predicted revenue — or predicted PROFIT'). This unambiguously distinguishes it from scenario-running or model-building siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear workflow context: call get_model_results or get_scenario_template first to obtain channel names/CPM, and poll get_optimizer_results after the 202. It does not explicitly contrast with run_scenario, but the prerequisites and post-steps are strong enough guidance for correct use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| model_hash | Yes | ||
| skip_slicing | No | ||
| rebuild_model | No | ||
| scenario_data | Yes | ||
| proxy_channels | No | ||
| spend_metadata | No | ||
| evaluate_holdout | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral disclosure burden, and it does so thoroughly. It reveals the async 202/pending behavior, the need to poll until completion, the NaN failure mode, the rebuild_model requirement for API-initiated scenarios, and the performance implications of skip_slicing. No annotation contradiction exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Though lengthy, the description is efficiently organized: a one-line summary, a critical NaN warning front-loaded, an async note, a compact workflow, then per-parameter details. Every sentence adds necessary information, and headings/separators make the size navigable for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex async tool with no output schema and zero schema-level parameter help, the description is remarkably complete. It covers prerequisites, input format, parameter semantics, failure conditions, async polling, and the intended workflow. An agent has nearly everything needed to call the tool correctly and interpret the follow-up step.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% property description coverage, so the description must compensate for all seven parameters. It does this completely: model_hash is explained, scenario_data has a concrete example and format details, spend_metadata shows the exact per-entry structure, and each boolean parameter gets its meaning and default. This is exemplary parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb-resource pairing: "Run a what-if scenario prediction on a completed model." It clearly distinguishes this from siblings by naming the workflow (get_scenario_template -> run_scenario -> get_scenario_results) and by clarifying that channel names come from the template/results, not from create_model.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong usage context: use get_scenario_template first, then modify values, then run_scenario, then poll get_scenario_results. It also states the async polling requirement. It does not explicitly say when not to use run_scenario versus a sibling like run_optimizer, so it misses the full 5, but the workflow guidance is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| model_hash | Yes | ||
| project_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden, and it does so thoroughly. It discloses side effects (saving files the model into a project), the saved-models cap with the specific 400 error_type 'saved_limit', the fact that re-saving renames/refiles without consuming a new slot, and ownership/sharing requirements for project_id.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded: a one-sentence summary is followed by a concise behavioral context paragraph, a cap/error note, and a three-item Args block. Every sentence adds information needed for correct invocation, with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter mutation tool with no output schema, the description covers all required inputs, optional inputs, defaults, constraints, side effects, error behavior, and relevant sibling tooling. Nothing an agent needs in order to select and invoke this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no per-parameter descriptions, so the description's Args section must add meaning. It does: model_hash is defined as the hash of the model to save, name is a non-empty display name, and project_id is optional, scoped by ownership/sharing, and defaults to the default project. This fully compensates for the 0% schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Save a model into a project under a display name.' It also clarifies the otherwise subtle purpose by explaining that API-created models are unsaved until this call, and that saving makes them visible in list_models and the dashboard. This clearly distinguishes it from sibling operations like unsave_model and rename_model.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: API-created models start unsaved and need this call to appear in default listings. It also points agents to list_projects and create_project for discovering/creating project IDs. However, it does not explicitly contrast the tool with rename_model or unsave_model, so some alternative selection guidance is left implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| model_hash | Yes | ||
| contribution_groups | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses validation rules (driver names validated against model factors, each driver in at most one group, baseAdjustments must reference own drivers), error behavior (400 with did-you-mean hint on typos), and the special pseudo-group. It does not mention side effects (overwrite vs append) or authentication, but the given details are substantial and specific.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than typical but every sentence delivers value: purpose, per-group schema, validation rules, pseudo-group, and an explicit disambiguation. The structure with bullets and a NOTE improves scanability. It is not overly verbose given the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the essential input structure, validation rules, and the critical distinction from a sibling tool. It does not describe the return value (no output schema) or idempotency, but given the tool's complexity, the provided context is nearly comprehensive for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clearly explains the structure of contribution_groups (name, drivers, optional color, optional baseAdjustments, and the special pseudo-group) and gives validation constraints. It does not explicitly describe model_hash, but the name is self-explanatory and likely clear enough. Overall it adds strong semantic value beyond the loose schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action (persist) on a specific resource (driver groupings for the dashboard contributions view) and clarifies its scope with context ('configure grouping once and every viewer sees it'). It also distinguishes this from the unrelated create_model channel_groups feature, so an agent can differentiate it from the sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly routes the agent away from create_model's channel_groups and clarifies this is the contributions-view grouping. It implies when to use (to set persistent dashboard groupings) but does not mention the read sibling get_contribution_groups or provide explicit 'use this when' conditions. The note about confusion adds clarity, so it's nearly a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| pinned | Yes | ||
| run_id | Yes | ||
| artifact | Yes | ||
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It explicitly reveals the key safety property: setting the current state again is a no-op and safe to re-run. It also explains run_id prefix conventions (opt_/scn_) and parameter roles, which adds meaningful behavior context beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the purpose, followed by the idempotence note, then a compact and structured Args list. Every sentence contributes useful information, with no filler or repetition of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given four required parameters, no schema descriptions, no annotations, and no output schema, the description covers the essential invocation details and the main behavioral guarantee. It could mention return behavior or error cases, but as a simple setter tool the provided information is sufficient for correct use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the Args section is the only explanation of parameters. It fully describes all four parameters: artifact with allowed values and id prefixes, model_hash, run_id, and pinned. This goes well beyond the bare schema and gives agents everything needed to populate the arguments correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Pin or unpin a saved optimizer or scenario run.' It clearly identifies the action and the two artifact types, and this is distinct from sibling tools such as run_scenario, get_scenario_results, and update_run. It is not a tautology and names the exact operation being performed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context by stating the tool is 'declarative and idempotent' and that 'scripts can safely re-run it,' which helps agents decide when repeated invocation is safe. It does not explicitly name alternatives or state when not to use this tool versus update_run, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unlink_var_modelB
Remove an MMM's VAR link (#569). Idempotent.
| Name | Required | Description | Default |
|---|---|---|---|
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds one genuinely useful behavioral trait, 'Idempotent', which tells the agent that repeated calls are safe and have the same effect. However, with no annotations at all, more context—such as whether unlinking is reversible or what happens if no link exists—would be needed for full transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded with the core purpose. The '#569' reference is noise that doesn't help an agent invoke the tool, but the overall structure is otherwise excellent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter unlink operation, the description covers the basic action and includes an important idempotency caveat. It is minimally viable, but it leaves 'VAR link' undefined and offers no usage guidance or parameter clarification, so an agent is left to infer some context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has a single required parameter, model_hash, with no description beyond its title. The tool description does not clarify what this hash represents, what format it should take, or how it relates to the MMM being unlinked, so it fails to compensate for the 0% schema description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb, 'Remove', with a concrete resource, 'an MMM's VAR link', which makes the tool's purpose immediately clear. It also inherently contrasts with the sibling tool link_var_model, so an agent can tell them apart without further investigation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given about when to use this tool versus link_var_model or any other sibling. Although the operation is implied by the name, the description never states the conditions under which unlinking is appropriate or what prerequisites must exist.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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}.
| Name | Required | Description | Default |
|---|---|---|---|
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full behavioral disclosure burden and handles it thoroughly: no deletion, state transition, retention of hash-addressability, visibility changes, idempotent behavior, auto-pruning consequences, and shared-model implications. This is exemplary for a state-changing tool lacking annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average, but every section contributes: core definition, use-case context, state semantics, caveats, return shape, and parameter explanation. The most important information is front-loaded, with caveats and details logically arranged.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations and no output schema, the description is remarkably complete: it specifies the return value, side effects, idempotence, lifecycle interactions, and edge cases. An agent has everything needed to decide when to call this tool and what to expect.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. The Args block explains that model_hash is 'the hash of the model whose slot to release,' which adds meaning beyond the bare string type. It could have specified how the hash is obtained (e.g., from create_model or list_models), but the semantic role is clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb-resource pair: 'Release a model's saved slot without deleting anything' and explicitly frames it as the inverse of save_model. This clearly distinguishes it from delete_model and other siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete when-to-use guidance: cap management at the 20-saved-models limit, unsave rather than delete when a model no longer earns its slot. It also contrasts with delete_model, states idempotence, and warns when unsaving is risky (shared models, auto-pruned unsaved pool).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| tags | No | ||
| notes | No | ||
| run_id | Yes | ||
| artifact | Yes | ||
| model_hash | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full disclosure burden and does so well. It reveals the permanent flip of the auto_named flag, the partial-update behavior, notes clearing semantics via empty string, and field constraints like the 255-character name cap and tag limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and then scoped through a clearly structured Args list. The short rationale with naming examples is not filler; it explains the permanent auto_named flag behavior that matters for using the tool correctly. No sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for 6 parameters and covers required fields, allowed values, behavioral nuances, and constraints. The only notable gap is that it does not describe the return value or error behavior, which is relevant because there is no output schema and no annotations to supply that context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does. It explains every parameter beyond the schema: the artifact type and id prefixes, that model_hash identifies the run's model, the meaning of run_id, name as a non-empty capped display name, notes as clearable free text, and tags as a replacement list with size limits.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Rename / annotate a saved optimizer or scenario run.' It clearly distinguishes this tool from run execution, retrieval, and model/project rename tools among the siblings by naming the exact action and artifact types it operates on.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The first sentence gives clear context for when to use the tool: when a saved run needs renaming or annotating. It also explains why renaming is useful and clarifies that only provided fields are changed, but it does not explicitly name alternatives or state when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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
warningsfield 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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| csv_path | No | ||
| filename | No | ||
| csv_content | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the behavioral transparency burden. It discloses the 10 MB API-enforced limit, CSV-only restriction, authoritative warnings field, required media column naming conventions, zero-fill requirement for inactive periods, and the local-only availability of csv_path. This goes well beyond a minimal disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every block earns its place: a one-sentence summary, a clarity rule, structured constraints, and a compact Args section. Important caveats are front-loaded and highlighted with 'IMPORTANT', so an agent can quickly identify critical requirements.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema and no annotations, the description tells the agent what the tool returns (uploaded file ID needed for create_model, row/column counts, validation warnings) and points to get_data_schema for the canonical input format. This is complete enough for an agent to invoke the tool correctly in most environments.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions cover 0% of the parameters, so the description must compensate, and it does thoroughly. It explains csv_content as raw CSV text, csv_path as a server-readable file path, name's default behavior from the file stem, and filename's purpose as a recorded original filename. It also adds the exclusivity constraint between csv_content and csv_path.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Upload'), a resource ('CSV dataset to Simba'), and its purpose ('for use in model building'). This clearly differentiates it from sibling tools like list_uploads, get_upload, and create_model by focusing on the ingestion step.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: provide exactly one of csv_content or csv_path, prefer csv_path for large data, and check get_data_schema for row minimums. It also specifies when csv_path is unavailable (HTTP/SSE deployments), making the selection context clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
29 tool updates
v0.3.2- First observed
create_model - First observed
create_project - First observed
create_var_model - First observed
delete_model - First observed
get_contribution_groups - First observed
get_data_schema - First observed
get_model - First observed
get_model_results - First observed
get_model_status - First observed
get_optimizer_results - First observed
get_scenario_results - First observed
get_scenario_template - First observed
get_upload - First observed
link_var_model - First observed
list_models - First observed
list_projects - First observed
list_runs - First observed
list_uploads - First observed
rename_model - First observed
rename_project - First observed
run_optimizer - First observed
run_scenario - First observed
save_model - First observed
set_contribution_groups - First observed
set_run_pinned - First observed
unlink_var_model - First observed
unsave_model - First observed
update_run - First observed
upload_data
TDQS
Every tool targets a distinct resource and action. get_model vs get_model_status vs get_model_results are clearly separated by result type (metadata, progress, analysis sections). run_optimizer vs run_scenario, and their respective get_* results tools, are unambiguous. Even related tools like update_run and set_run_pinned have distinct purposes (renaming/annotating vs pinning).
Tool names follow a consistent verb_noun pattern throughout: get_, list_, create_, run_, set_, update_, rename_, save_, unsave_, delete_. All use snake_case, and similar operations are named uniformly (e.g., create_model/create_var_model, list_models/list_projects/list_runs/list_uploads, get_optimizer_results/get_scenario_results). No mixing of conventions.
With 29 tools, the surface is large and exceeds the 'too many' threshold of 25+. While each tool serves a distinct purpose in a comprehensive MMM workflow, the sheer number is likely to overwhelm an agent and suggests a more granular API than necessary. The core functionality could be consolidated (e.g., merging run management tools or providing a single results fetch with section parameters).
The tool set covers the full MMM lifecycle: data upload/schema, model creation (MMM and VAR), linking, results retrieval (many sections), optimization, scenarios, run history, and project management. Minor gaps include no ability to delete runs or projects, no model config update (only create), and no data retrieval beyond schema, but these are not critical dead-ends. The core workflow is well-supported.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Conversational access to advertising performance data, creative analysis, and campaign insights
Conversational access to advertising performance data, creative analysis, and campaign insights
AI marketing agent for Google Ads, Meta, GA4, TikTok, LinkedIn, Shopify, HubSpot and more.
- AdCrunchOAuthdev.adcrunch
Ask AI about your ads — query Meta, TikTok, and Google Ads performance in natural language.
Related MCP Servers
- -licenseNot gradedqualityBmaintenanceConnects AI assistants to marketing mix models, enabling natural language data upload, performance modeling, budget optimization, and scenario testing.-
- AlicenseAqualityBmaintenanceEnables AI assistants to manage Meta Ads (Facebook, Instagram) end-to-end through natural conversation, including launching campaigns, uploading creatives, updating budgets, and analyzing performance.42Business Source 1.1
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to create, analyze, and optimize ad campaigns across Google Ads, Meta Ads, TikTok Ads, LinkedIn Ads, Amazon Ads, and ChatGPT Ads through natural language using 400+ tools.87MIT
- FlicenseNot gradedqualityCmaintenanceEnables marketing optimization tasks such as copywriting, campaign analysis, social media planning, audience segmentation, and KPI tracking through natural language.113-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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