Monte Carlo decision-intelligence over MCP: simulate, optimize, and decide under uncertainty.
A domain-agnostic Monte Carlo simulation and decision intelligence system.
Zero dependencies. Pure Python stdlib. Local web UI. Runs anywhere Python runs.
SimEngine turns uncertainty into numbers you can act on. Define your variables, your logic, and your risk tolerances in a JSON config. The engine runs thousands of simulated futures, scores them, and — if you ask — evolves toward the best strategy that still respects your safety constraints.
Think of it as a calculator for uncertainty.
# 1. Clone the repository
git clone <repo-url> ~/projects/simengine
cd ~/projects/simengine
# 2. Start the web UI
cd v3 && python3 server.py
# 3. Open your browser
# http://localhost:8420
That is it. No pip install, no Docker, no Node, no build step. Python 3.8+ is the only requirement.
uvx simengine-mcp
Listed on the official MCP registry. Hosted, no-install endpoint: join the waitlist.
The default engine remains pure Python. A Rust workspace now lives at the repo root for optional acceleration of metric reducers, trajectory bands, risk evaluation, histograms, and native pre-sampling of simple numeric variable distributions.
This is opt-in and does not change the baseline workflow above.
Cargo.toml
crates/
├── simengine-core/ # pure Rust numeric kernels
└── simengine-py/ # PyO3 extension module: simengine_native
v3/native.py # optional loader + Python fallback glue
cd crates/simengine-py
python3 -m venv ../../.venv
source ../../.venv/bin/activate
pip install maturin
maturin develop --release
After that, the existing Python engine will automatically use the native
reducers and the native batch sampler when simengine_native is importable.
If the module is missing or fails, SimEngine falls back to the existing
Python implementation.
The batch sampler is conservative:
SIMENGINE_DISABLE_NATIVE_SAMPLING=1This keeps the expression engine, accumulators, and metrics in Python while moving a larger chunk of the Monte Carlo loop into Rust.
There is also a narrower native fast path for stochastic expressions:
binomial(n, p) can be delegated to Rust when the extension is installedSIMENGINE_DISABLE_NATIVE_EXPR_SAMPLING=1This helps domains whose step_logic relies heavily on binomial(...) while
still leaving general expression evaluation in Python.
On the Python side, repeated expressions are now compiled once and reused
across Monte Carlo runs. That cache can be disabled explicitly with
SIMENGINE_DISABLE_EXPR_CACHE=1 for benchmarking or troubleshooting.
The diagnostics module applies the same idea to its AST-only safe evaluator:
parsed trees are reused across calls, and that cache can be disabled with
SIMENGINE_DISABLE_SAFE_EXPR_CACHE=1.
/api/simulate and get structured results back. No files needed. LLMs can use SimEngine as a tool (llms.txt at the repo root and GET /llms.txt orient them).cd v3 && python3 backtest.py (offline, from committed snapshots). Results: docs/backtests/.All production code lives in v3/.
v3/
├── kernel.py Monte Carlo engine, distributions, safety evaluation,
│ fitness scoring, genetic optimizer, experiment manifests
├── server.py HTTP server (port 8420), all API endpoints, report generation
├── bayesian.py Conjugate prior updates for calibrating parameters from data
├── diagnostics.py Convergence, sensitivity (OAT), baseline comparison, AST evaluator
├── static/
│ └── index.html Single-page web UI (vanilla HTML/JS/CSS, no framework)
└── domains/
├── _template.json Annotated starter config
├── business_pipeline_v3.json B2B sales pipeline
├── investment_portfolio.json Portfolio allocation
├── investment_portfolio_v2.json Fat-tailed returns (Student's t)
├── job_search.json Job search decision model
├── project_timeline.json Software project estimation
├── real_estate_rental.json Rental property analysis
└── saas_startup.json SaaS MRR growth and runway
A domain config is a single JSON file that fully describes the simulation. The v3 schema separates variables into three semantic categories, which matters for Bayesian updating and optimization.
Published contract: the machine-readable JSON Schema (Draft 2020-12) is served live at GET /api/schema — hand it to any AI to author a valid config in one shot. A plain-language field reference is in docs/schema-reference.md. The schema is verified against every shipped domain in the test suite.
| Field | Type | Description |
|---|---|---|
name | string | Human-readable domain name |
description | string | What this simulation models |
n_simulations | int | Number of Monte Carlo runs (default: 5000) |
n_steps | int | Time steps per simulation (e.g., 12 months) |
step_label | string | Label for time axis: "month", "week", "sprint" |
seed | int or null | Random seed for reproducibility |
parameters | object | Uncertain variables, updatable with evidence |
controls | object | Operator decisions (pricing, budget, effort) |
exogenous | object | External factors outside your control |
initial_state | object | Starting values for accumulators |
step_logic | array | Computations executed each time step |
accumulators | object | Running totals updated each step |
metrics | object | Final output measurements |
safety | object | Chance constraints and CVaR constraints |
fitness | object | Weighted scoring components for the optimizer |
tunable | array | Parameters the optimizer is allowed to adjust |
context | object | Optional metadata: decision question, key levers |
calibration | object | Per-variable data source and update method |
All three variable categories (parameters, controls, exogenous) share the same structure:
{
"monthly_churn_rate": {
"distribution": "triangular",
"params": {"low": 0.02, "mode": 0.05, "high": 0.12},
"calibration": {
"source": "Baremetrics Open Benchmarks: median monthly churn 5-8%",
"updatable": true,
"update_method": "Beta-Binomial conjugate from observed monthly cancellations"
}
}
}
| Distribution | Params | Use Case |
|---|---|---|
fixed | value | Known constants |
uniform | low, high | Equal probability across a range |
triangular | low, mode, high | Expert estimates (pessimistic / likely / optimistic) |
normal | mean, std, min?, max? | Bell curve, optionally clamped |
lognormal | median, spread, min?, max? | Always positive, right-skewed (prices, durations) |
bernoulli | p | Binary yes/no events |
poisson | lambda | Counts of rare events |
student_t | mean, scale, df, min?, max? | Fat-tailed returns (use df=5 for equities) |
correlated_normal | mean, std | Normal with correlation support (via step_logic) |
An ordered list of computations executed each time step. Each entry has a target name and either an expr (expression string) or a sample (inline distribution):
"step_logic": [
{"target": "new_leads", "expr": "binomial(round(demand), conversion_rate)"},
{"target": "revenue", "expr": "new_leads * price_per_unit"},
{"target": "costs", "expr": "fixed_cost + variable_cost * new_leads"},
{"target": "net_income", "expr": "revenue - costs"},
{"target": "shock_event", "sample": {"distribution": "bernoulli", "params": {"p": 0.02}}}
]
Available expression functions: min, max, abs, round, sum, len, int, float, sqrt, log, exp, ceil, floor, pow, random(), gauss(mu, sigma), binomial(n, p), clamp(val, lo, hi), range(). Ternary expressions work: 100 if x > 0 else 0.
Running state that persists across time steps:
"accumulators": {
"cumulative_revenue": "cumulative_revenue + revenue",
"cash": "cash + net_income",
"peak_subscribers": "max(peak_subscribers, subscribers)"
}
Final measurements computed after all steps complete:
"metrics": {
"total_revenue": {"expr": "cumulative_revenue", "format": "dollar"},
"roi": {"expr": "cumulative_revenue / cumulative_costs", "format": "percent"},
"final_subs": {"expr": "subscribers", "format": "number"}
}
"safety": {
"chance_constraints": [
{
"metric": "ending_cash",
"condition": "below",
"threshold": 0,
"max_prob": 0.15,
"rationale": "No more than 15% chance of running out of cash"
}
],
"cvar_constraints": [
{
"metric": "ending_cash",
"alpha": 0.10,
"min_cvar": -15000,
"rationale": "Average of the worst 10% of outcomes must not exceed $15k loss"
}
]
}
The optimizer maximizes a weighted sum of fitness components while respecting safety constraints. Each component is an expression evaluated against the metric statistics (e.g., total_revenue_median, ending_cash_p10):
"fitness": {
"components": [
{"expr": "min(100, final_mrr_median / 100)", "weight": 0.30, "name": "mrr_growth"},
{"expr": "max(0, 100 - months_negative_median * 5)", "weight": 0.25, "name": "time_to_profit"}
]
},
"tunable": [
{"path": "controls.price_per_seat.params.value", "range": [9, 99]},
{"path": "parameters.monthly_churn_rate.params.mode", "range": [0.01, 0.10]}
]
Fitness expressions can reference any metric stat in the form {metric_name}_{stat} where stat is one of: mean, median, std, p10, p25, p75, p90.
Safety violations apply a 30% penalty per violated constraint. The optimizer learns to avoid them.
The server runs at http://localhost:8420. All POST endpoints accept and return JSON. CORS headers are included on all responses.
List all available domain configs.
Response:
[
{
"file": "saas_startup.json",
"name": "Indie SaaS -- MRR Growth & Runway",
"description": "Models a bootstrapped SaaS product over 24 months...",
"n_simulations": 5000,
"n_steps": 24,
"step_label": "month"
}
]
Load a specific domain config by filename.
Response: The full JSON domain config object.
Run a Monte Carlo simulation.
Request (file-based):
{
"domain": "saas_startup.json",
"n_simulations": 5000,
"seed": 42,
"overrides": {
"controls.price_per_seat.params.value": 49
}
}
Request (inline config -- for AI agents):
{
"config": { ... full domain config object ... },
"n_simulations": 5000,
"seed": 42
}
Response:
{
"domain": "Indie SaaS -- MRR Growth & Runway",
"n_simulations": 5000,
"elapsed": 1.23,
"stats": {
"final_mrr": {
"mean": 4250.00,
"median": 3915.00,
"std": 2100.50,
"p10": 1740.00,
"p25": 2610.00,
"p75": 5220.00,
"p90": 7105.00,
"format": "dollar"
}
},
"trajectories": {
"cash": {
"p10": [24500, 23800, ...],
"p50": [25100, 25300, ...],
"p90": [25800, 26900, ...]
}
},
"histograms": {
"final_mrr": {
"bins": [0.0, 250.0, ...],
"counts": [12, 45, ...],
"bin_width": 250.0,
"lo": 0.0,
"hi": 10000.0
}
},
"safety": {
"chance": [
{"metric": "ending_cash", "condition": "below", "threshold": 0,
"max_prob": 0.15, "actual_prob": 0.082, "passed": true}
],
"cvar": [
{"metric": "ending_cash", "alpha": 0.10, "min_cvar": -15000,
"actual_cvar": -8500.00, "passed": true}
],
"all_passed": true
},
"fitness": 72.5,
"narrative": "**Final Mrr** is most likely $3,915 (range: $1,740 to $7,105 in 80% of scenarios)...",
"context": {"decision": "Should I go full-time on this SaaS?"}
}
Run the genetic optimizer to find optimal control settings.
Request:
{
"domain": "saas_startup.json",
"generations": 15,
"population": 20
}
Response:
{
"domain": "Indie SaaS -- MRR Growth & Runway",
"best_fitness": 85.3,
"best_stats": { ... same format as simulate stats ... },
"best_safety": { "all_passed": true, "chance": [...], "cvar": [...] },
"history": [
{"gen": 0, "best_fit": 62.1, "avg_fit": 45.3, "safe_pct": 60.0, "elapsed": 2.1},
{"gen": 1, "best_fit": 68.5, "avg_fit": 52.1, "safe_pct": 75.0, "elapsed": 2.0}
],
"elapsed": 31.5
}
Validate a domain config without running a full simulation. Runs a 10-iteration test to catch expression errors.
Request:
{
"config": { ... domain config object ... }
}
Response:
{
"valid": true,
"errors": []
}
Or on failure:
{
"valid": false,
"errors": [
"Variable 'close_rate': unknown distribution 'beta'",
"step_logic[2]: missing 'target'"
]
}
Validate and save a domain config to the domains/ directory.
Request:
{
"config": { ... domain config object ... },
"filename": "my_new_domain"
}
Response:
{
"saved": true,
"file": "my_new_domain.json"
}
Bayesian update: feed observed data into a domain config and get updated parameter distributions plus a preview simulation.
Request:
{
"domain": "saas_startup.json",
"observations": {
"monthly_churn_rate": [0.04, 0.06, 0.03, 0.05],
"organic_signup_rate": [18, 22, 15, 25, 20]
}
}
Response:
{
"updated_config": { ... full config with tightened distributions ... },
"update_report": {
"monthly_churn_rate": {
"method": "beta_binomial",
"prior_mean": 0.05,
"posterior_mean": 0.045,
"posterior_std": 0.012,
"observations_used": 4,
"credible_interval_90": [0.025, 0.065]
}
},
"preview_stats": { ... simulation results with updated params ... },
"preview_safety": { ... }
}
Generate a standalone HTML report from simulation results.
Request:
{
"results": { ... simulate response object ... },
"config": { ... domain config ... }
}
Response: HTML document (Content-Type: text/html). Self-contained, no external dependencies. Save it, email it, print it.
cd ~/projects/simengine/v3
# Run a Monte Carlo simulation
python3 kernel.py domains/saas_startup.json
# Set a random seed for reproducibility
python3 kernel.py domains/saas_startup.json --seed 42
# Save results to a specific file
python3 kernel.py domains/saas_startup.json --output results.json
# Run evolutionary optimization
python3 kernel.py domains/saas_startup.json --evolve
# Customize optimizer parameters
python3 kernel.py domains/saas_startup.json --evolve \
--generations 25 \
--population 30 \
--workers 8 \
--output best_strategy.json
Short flags: -g (generations), -p (population), -w (workers), -o (output).
cd ~/projects/simengine/v3
# Convergence analysis -- proves sample size is sufficient
# Runs at N=100, 250, 500, ..., 20000 and measures estimator stability.
python3 diagnostics.py domains/saas_startup.json --convergence
# Sensitivity analysis -- ranks which inputs drive the output
# One-at-a-time perturbation with normalized impact scores.
python3 diagnostics.py domains/saas_startup.json --sensitivity
# Baseline comparison -- Monte Carlo vs deterministic spreadsheet
# Shows the risk that point-estimate forecasting hides.
python3 diagnostics.py domains/saas_startup.json --baseline
# Target a specific metric (default: first metric defined)
python3 diagnostics.py domains/saas_startup.json --convergence --metric ending_cash
# Save results to JSON
python3 diagnostics.py domains/saas_startup.json --convergence --output conv.json
You can combine flags: --convergence --sensitivity --baseline runs all three.
There are three ways to create a domain config.
Open http://localhost:8420, click the domain wizard, and fill in the form. The wizard generates a valid config, validates it, and saves it to the domains/ directory.
cp ~/projects/simengine/v3/domains/_template.json ~/projects/simengine/v3/domains/my_problem.json
Edit my_problem.json. The template includes inline documentation in the _guide field and a working example structure. Replace the placeholder variables, logic, and metrics with your own.
Describe your problem to an LLM and ask it to produce a SimEngine v3 domain config. Validate it before use:
# Validate from the command line via the API
curl -X POST http://localhost:8420/api/validate \
-H 'Content-Type: application/json' \
-d '{"config": <paste your JSON>}'
Or POST the config directly to /api/simulate with {"config": {...}} -- it will either run or return an error.
The smallest config that will run:
{
"name": "Coin Flip",
"n_simulations": 1000,
"n_steps": 10,
"parameters": {
"heads": {
"distribution": "bernoulli",
"params": {"p": 0.5}
}
},
"step_logic": [
{"target": "payout", "expr": "1 if heads > 0.5 else -1"}
],
"accumulators": {
"bankroll": "bankroll + payout"
},
"metrics": {
"final_bankroll": {"expr": "bankroll", "format": "number"}
},
"initial_state": {"bankroll": 0}
}
SimEngine supports conjugate Bayesian updates that tighten your parameter distributions as real-world data arrives.
triangular(0.02, 0.05, 0.12) for churn rate).[0.04, 0.06, 0.03, 0.05]).| Method | Conjugate Pair | Use For |
|---|---|---|
beta_binomial | Beta-Binomial | Rates and probabilities: close rate, churn rate, conversion rate |
gamma_poisson | Gamma-Poisson | Counts: leads per month, bugs per sprint, signups per week |
normal_normal | Normal-Normal | Continuous means: project value, salary, deal size |
The method is chosen in this order:
calibration.update_method in the variable definition.curl -X POST http://localhost:8420/api/update \
-H 'Content-Type: application/json' \
-d '{
"domain": "saas_startup.json",
"observations": {
"monthly_churn_rate": [0.04, 0.06, 0.03, 0.05]
}
}'
The response includes the updated config, a diagnostic report showing prior vs. posterior, and a preview simulation with the updated parameters.
from bayesian import update_parameter
updated_params, diagnostics = update_parameter(
variable_def={
"distribution": "triangular",
"params": {"low": 0.02, "mode": 0.05, "high": 0.12}
},
observations=[0.04, 0.06, 0.03, 0.05],
method="beta_binomial"
)
print(diagnostics["posterior_mean"]) # 0.0459
print(diagnostics["credible_interval_90"]) # [0.0312, 0.0606]
SimEngine is designed to be used as a tool by LLMs and AI agents. The key feature is inline config support: POST a full domain config directly to /api/simulate without saving any files.
{"config": {...}, "n_simulations": 5000, "seed": 42} to /api/simulate.import json, urllib.request
config = {
"name": "Should I take this contract?",
"n_simulations": 3000,
"n_steps": 6,
"step_label": "month",
"parameters": {
"hours_per_week": {
"distribution": "triangular",
"params": {"low": 15, "mode": 25, "high": 45}
},
"scope_creep": {
"distribution": "bernoulli",
"params": {"p": 0.3}
}
},
"controls": {
"hourly_rate": {
"distribution": "fixed",
"params": {"value": 150}
}
},
"exogenous": {},
"initial_state": {"total_hours": 0, "total_revenue": 0},
"step_logic": [
{"target": "weekly_hours", "expr": "hours_per_week * (1.4 if scope_creep > 0.5 else 1.0)"},
{"target": "monthly_hours", "expr": "weekly_hours * 4.33"},
{"target": "monthly_rev", "expr": "min(monthly_hours, 160) * hourly_rate"}
],
"accumulators": {
"total_hours": "total_hours + monthly_hours",
"total_revenue": "total_revenue + monthly_rev"
},
"metrics": {
"total_revenue": {"expr": "total_revenue", "format": "dollar"},
"effective_rate": {"expr": "total_revenue / total_hours if total_hours > 0 else 0", "format": "dollar"},
"total_hours": {"expr": "total_hours", "format": "number"}
}
}
req = urllib.request.Request(
"http://localhost:8420/api/simulate",
data=json.dumps({"config": config, "seed": 42}).encode(),
headers={"Content-Type": "application/json"},
method="POST"
)
resp = json.loads(urllib.request.urlopen(req).read())
print(f"Revenue (median): ${resp['stats']['total_revenue']['median']:,.0f}")
print(f"Revenue (P10-P90): ${resp['stats']['total_revenue']['p10']:,.0f} - ${resp['stats']['total_revenue']['p90']:,.0f}")
print(f"Effective rate (median): ${resp['stats']['effective_rate']['median']:,.0f}/hr")
The /api/simulate response includes everything an agent needs to reason about the outcome:
stats -- Full distribution statistics for every metric (mean, median, std, p10/p25/p75/p90).safety -- Pass/fail on every constraint with actual probabilities.fitness -- Single scalar score for comparing scenarios.narrative -- Human-readable summary text.trajectories -- Time-series percentile bands for trend analysis.histograms -- Binned data for distribution shape analysis.To compare alternatives, an agent can POST multiple configs (varying the controls) and compare fitness scores, safety evaluations, or specific metric percentiles across the responses.
decide_under_uncertainty (MCP)Multi-step agents compound overconfident point answers. The decide_under_uncertainty MCP tool turns a simulation into a proceed / escalate verdict: it runs the Monte Carlo, measures how much of the outcome distribution lands inside a range you accept, and returns the flag plus the full distribution and a plain-English reason.
It models outcome risk -- the spread of results given uncertain inputs -- not the language model's own token confidence. The two are complementary; do not conflate them.
Arguments: metric (required), acceptable ({"min": ..., "max": ...}, at least one bound), min_confidence (probability mass that must land in range to proceed, default 0.8), plus domain or inline config, and optional seed / n_simulations.
{
"metric": "annual_gross_income",
"decision": "proceed",
"proceed": true,
"probability_within_bounds": 0.92,
"min_confidence": 0.8,
"acceptable": {"min": 40000, "max": null},
"distribution": {"median": 68000, "p10": 44000, "p90": 95000, "format": "dollar"},
"n_simulations": 5000,
"reason": "92% of 5,000 simulated outcomes for 'annual_gross_income' fall within the acceptable range (>= 40,000) -- at or above the 80% confidence required to proceed."
}
See docs/decision-gate.md for the full agent pattern.
A Monte Carlo engine will always emit a confident-looking distribution. The only thing that separates "a calculator that produces plausible numbers" from "a forecasting instrument with a demonstrated hit rate" is a track record scored against reality. v3/calibration.py is that spine -- pure stdlib, zero dependencies.
Proper scoring rules: brier_score, log_loss, crps_sample.
Forecast ledger: record a forecast now, resolve it against the real outcome later, score how well-calibrated you have been over time.
from calibration import CalibrationLedger
ledger = CalibrationLedger("forecasts.db")
fid = ledger.record("Annual gross >= $40k?", 0.82, metric="annual_gross_income")
# ... the year resolves ...
ledger.resolve(fid, 1)
print(ledger.score()) # {"n": 1, "brier": 0.0324, "log_loss": 0.198}
Brier 0.0 is perfect; 0.25 is the score of always guessing 50/50; 1.0 is worst. Log-loss punishes confident-and-wrong forecasts harder. Lower is better for both. Time is the moat: the track record only accumulates if logging starts now.
The core engine is offline and pure-stdlib. The v3/feeds/ package is the optional bridge to live data — the only part of SimEngine that touches the network, still using only urllib (no new dependencies), and never imported by the core.
The first adapter, feeds/polymarket.py, turns a live Polymarket prediction-market price into a calibrated prior: a market-implied probability becomes a SimEngine variable you can drop into a domain config and then tighten with the Beta-Binomial updater as your own evidence arrives. Price in → prior → posterior, not price in → price out.
from feeds import polymarket
markets = polymarket.fetch_markets(query="fed rate", limit=5)
prior = polymarket.market_prior(markets[0], strength=20) # -> a triangular variable_def
See docs/feeds.md. Market prices are treated as internal simulation inputs, never a rebroadcast feed or trade signal.
Don't want to write a config? Describe your decision in plain words and let an LLM build the model for you. SimEngine drafts a config, validates it against the engine, repairs any errors, runs the simulation, and explains the result — so even small local models stay reliable, because the engine grounds whatever the model produces.
This is opt-in and stdlib-only. It defaults to a local model via Ollama — free, private, no API key. Set an environment variable to use a hosted model instead.
# With Ollama running (e.g. `ollama pull qwen2.5`):
python3 v3/sim_ask.py "Should I take an $8k/mo, 6-month contract if there's a 30% chance it overruns?"
Flags: --n (simulations), --seed, --save NAME (persist the config to domains/), --show-config, --json, --model NAME, --backend.
Open http://localhost:8420, click Ask anything, type your question, and run. You get a plain-language answer, the key numbers, the safety verdict, and the generated model — which you can save as a reusable domain.
POST /api/ask with {"question": "...", "n_simulations": 3000, "seed": 42} returns {config, results, explanation, attempts, valid}.
| Variable | Default | Purpose |
|---|---|---|
SIMENGINE_LLM_BACKEND | ollama | ollama | openai | anthropic |
SIMENGINE_LLM_MODEL | qwen2.5 | model name |
SIMENGINE_LLM_TIMEOUT | 120 | per-request seconds (raise for slow local models) |
OPENAI_API_KEY / OPENAI_BASE_URL | — | OpenAI-compatible (also covers llama.cpp / LM Studio / vLLM) |
ANTHROPIC_API_KEY | — | Anthropic |
Decision support and scenario analysis only — never financial advice or a trade signal.
When you run a simulation, each metric reports:
Safety constraints translate directly to decision language:
New to SimEngine? Start with the plain-language guide. It explains what SimEngine is, how to read results, who it is for, how to explain it to others, and how to model your own decision — no background required.
Peer review reports and the system design paper are available on request. Contact the maintainer for access.
SimEngine uses an open-core model.
Self-hosting the open-source engine is and will remain free. The commercial license applies only to the hosted service and managed features that are not part of the open-source distribution.
SimEngine is an OtrovertLabs product, published by Venture Horizon LLC.
For commercial licensing, enterprise inquiries, or partnerships: https://otrovertlabs.com/contact
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
uvx simengine-mcpMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-cogswellspacely8-star-simengine": {
"command": "uvx",
"args": [
"simengine-mcp"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceio.github.cogswellspacely8-star/simengine works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.