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
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 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.83MIT
- FlicenseNot gradedqualityCmaintenanceEnables marketing optimization tasks such as copywriting, campaign analysis, social media planning, audience segmentation, and KPI tracking through natural language.113
Related MCP Connectors
AI marketing agent for Google Ads, Meta, GA4, TikTok, LinkedIn, Shopify, HubSpot and more.
Ask AI about your ads — query Meta, TikTok, and Google Ads performance in natural language.
Connect e-commerce and marketing data to AI assistants via MCP.
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