Skip to main content

Simba MCP Server

PyPI License: MIT Python 3.11+

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-mcp

Or run directly without installing:

uvx simba-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_data_schema Get the canonical CSV schema for MMM input files
upload_data Upload a CSV dataset to Simba
list_models List all models with their status
create_model Configure and start fitting a new MMM model
get_model_status Poll fitting progress for a model
get_model_results Get results (ROI, contributions, response curves, diagnostics, and more)
run_optimizer Run budget optimization on a completed model
get_optimizer_results Get optimizer status and results
get_scenario_template Generate a forward-period template for scenario planning
run_scenario Run a "what-if" scenario prediction
get_scenario_results Get scenario prediction results

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

Gotchas & Tips

Things that commonly trip up both AI agents and humans:

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] = 0

Three endpoints are async

These return 202 and require polling:

Action Start Poll
Fit model create_model get_model_status
Optimize run_optimizer get_optimizer_results
Scenario run_scenario get_scenario_results

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_schemax-simba-constraints.min_rows; the upload response's warnings field is authoritative. More rows = tighter posteriors (104+ weekly rows recommended).
  • Media columns: {channel}_activity and {channel}_spend per channel.
  • Use 0 for inactive periods, not blank or NA.
  • Large file? Pass csv_path (a local file path) instead of csv_content — the server reads it directly instead of the CSV going through the conversation. Local (stdio) servers only; disabled on HTTP/SSE deployments unless SIMBA_MCP_ALLOW_LOCAL_FILES=1.

Common Errors

Error Cause Fix
Authentication required No API key or expired key Check SIMBA_API_KEY env var
API key missing required scope: <scope> Key doesn't have the needed scope Create a key with all scopes
Missing required fields: [...] Payload missing required keys Check the tool's parameter list
Model status is '<status>'. Optimization requires a 'complete' model. Model still fitting or failed Poll get_model_status until complete
laydown_weights['TV'] must be an array of length 12 Scalar instead of array, or wrong length Use arrays matching num_periods
period_cpm['TV'] values must all be positive Zero or negative CPM All CPM values must be > 0
Channels in bounds missing from period_cpm: [...] Mismatched channel names Same keys in bounds, laydown_weights, and period_cpm
Columns not found in data: [...] Column name typo Check CSV headers match exactly
File exceeds 10 MB limit 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:

  1. Go to Profile > API Keys in the Simba UI
  2. Click Create Key
  3. Set scopes: ingest, read:models, read:results, create:models, optimize, scenario
  4. Copy the key (shown only once)

Set the key as the SIMBA_API_KEY environment variable in your MCP config.

Configuration

Environment Variable Description Default
SIMBA_API_URL Simba API base URL http://localhost:5005
SIMBA_API_KEY Your Simba API key (required)

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 8100

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simba_mcp-0.2.0.tar.gz (51.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

simba_mcp-0.2.0-py3-none-any.whl (30.8 kB view details)

Uploaded Python 3

File details

Details for the file simba_mcp-0.2.0.tar.gz.

File metadata

  • Download URL: simba_mcp-0.2.0.tar.gz
  • Upload date:
  • Size: 51.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for simba_mcp-0.2.0.tar.gz
Algorithm Hash digest
SHA256 d53883baf2dd8c5edad01534ec7ba755678ddbe6bd4eabdd6a6e4500b9543224
MD5 63012d1ef60f15c237760934fb7d7d8e
BLAKE2b-256 9231c0dd957fbc895cdfc426df155538bc3e9ca7922511a1bdfa840edc55ab0c

See more details on using hashes here.

Provenance

The following attestation bundles were made for simba_mcp-0.2.0.tar.gz:

Publisher: publish.yml on getsimba-ai/simba-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file simba_mcp-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: simba_mcp-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 30.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for simba_mcp-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 719b432dd4ea65d33e57a111f20c274424572d7b2f0dc742b19d1881b969b07f
MD5 9715a3905afd67fa1190fe1bd6af5867
BLAKE2b-256 1753d5007493c1eaa5241a011f1ded5205c6c4f22fdda81e0f6861b7305325ea

See more details on using hashes here.

Provenance

The following attestation bundles were made for simba_mcp-0.2.0-py3-none-any.whl:

Publisher: publish.yml on getsimba-ai/simba-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.2

2 files

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page