lsd-mcp
Provides an alternative backend in which the server runs on the host but forwards every tool call into a running LSD Docker container (from the Docker_LSD_setup project), copying its own code in with docker cp and using the container's C++ compiler, LSD installation and R. This lets an agent inspect, edit, compile, run and analyse LSD models without installing anything on the host besides Docker, with models living in the container's Work folder shared with the host.
Click on "Deploy 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., "@lsd-mcp compile and run my model, then show the results"
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.
lsd-mcp
An MCP server that lets an agent work with LSD
(Laboratory for Simulation Development, Valente and Pereira): inspect and edit
models, compile and run them headless, and run sensitivity analyses
(meta-models with Sobol indices, elementary effects). It uses LSD's own engine,
command-line utilities (lsd_confgen, lsd_getsaved, ...), design code
and R package LSDsensitivity; it does not re-implement them. Built against release tag 8.1-stable-5.
It runs LSD either on the host or, with the Docker backend below, inside the container of Docker_LSD_setup.
Install
Needs Python 3.10+, uv, a C++ compiler (c++, g++ or clang++), zlib,
and git (to fetch the LSD source on first use). Rscript with the R package
LSDsensitivity is only needed for sa_analyze.
uv sync
uv run pytest -qRelated MCP server: COMSOL MCP Verifier
Environment variables (all optional)
Variable | Default | Meaning |
| unset | An LSD folder containing |
|
| Tag to fetch. |
|
| Fetched source and all build output. |
|
| Your models. The only place the edit and run tools write. |
|
| R interpreter for |
Tools
Inspect: lsd_status, list_models, read_equations, describe_configuration.
Edit: copy_model, create_model, write_equations, edit_structure, set_values, set_run_settings, set_saved.
Compile and run: compile_model, run_configuration, read_results.
Sensitivity analysis: sa_create_design, sa_run_design, sa_analyze.
set_values and the factors of sa_create_design take "Name -k" for the k-th lag of a variable.
create_model makes a new model folder as LSD's model manager (LMM) does: the
equation file fun_<name>.cpp from LSD's template, model_options.txt,
modelinfo.txt, description.txt and a Sim1.lsd holding only Root.
edit_structure applies a list of operations (add object, parameter, variable
or function, rename, delete, set the number of instances, set the value of each
instance, set a description) to a configuration with LSD's own functions,
through lsd_edit (src/lsd_mcp/structure.cpp), and saves with LSD's
save_configuration; if one operation fails nothing is written. With these, a
model can be built from nothing: create_model, edit_structure,
write_equations, run_configuration.
sa_create_design makes one of four designs. lhs and random are sampled in
Python and written through lsd_confgen. nolh (near-orthogonal Latin
hypercube, LSD's own tables, optionally extended) and ee (elementary effects,
Morris; trajectories, levels, jump, pool) are made by LSD's own design code
(design and sensitivity_doe in set_all.cpp) through lsd_doe, a small
program of ours (src/lsd_mcp/doe.cpp) that includes LSD's file unmodified and
makes the calls the interface makes. A nolh design gets an out-of-sample set
from LSD's Monte Carlo range sampling, as the interface offers after NOLH; an
ee design has none. Every design also gets <config>_design.json (method and
parameters). sa_analyze fits a Kriging or polynomial meta-model with Sobol
indices, or, for an ee design, runs LSD's elementary effects analysis and
returns mu, mu_star, sigma, se and p_value per factor. For an ee design made in
LSD's interface (no design file) pass metamodel="ee" with its levels and
jump.
Register with Claude Code
claude mcp add lsd -- uv run --project /path/to/lsd-mcp lsd-mcpAdd -e LSD_MODELS=/path/to/models to change the models folder.
Docker backend
With LSD_MCP_BACKEND=docker the server still runs on the host, but every tool
call is executed inside a running LSD container by the same standard-library
code, which lsd-mcp copies into the container (docker cp, re-copied when the
source changes). It never starts, stops or removes a container.
The container comes from Docker_LSD_setup,
a separate repository that runs LSD in Docker with a browser desktop, R and
LSD's R packages. This backend needs nothing installed on the host besides
Docker and uv: the compiler, LSD and R are the container's.
Variable | Default | Meaning |
|
|
|
|
| Name of the running container. |
|
| LSD folder inside the container. |
|
| Models folder inside the container. |
claude mcp add lsd-docker -e LSD_MCP_BACKEND=docker -- uv run --project /path/to/lsd-mcp lsd-mcpStart the container with ./run.sh in your Docker_LSD_setup folder first. Two
things to know: models live in the container's Work folder, which is shared
with the host and shown in LMM as "Work in Progress" (copy_model adds a
modelinfo.txt so LMM lists the copy); and the build cache inside the
container is lost when the container is recreated, so the next call rebuilds
it.
Limits
Kriging can fail with "the leading minor ... is not positive" (covariance matrix not positive definite), typically when design points nearly coincide, for example integer factors with few levels.
sa_analyzeexplains this; try the polynomial meta-model or more spread-out points.sa_create_designwarns about integer factors with fewer levels than samples / 4.LSD's polynomial meta-model weights design points by mean/SD of the response and fails when a point has a negative mean (a bug in LSDsensitivity, not worked around here).
sa_analyzesays so; usemetamodel="kriging".LSD's polynomial meta-model also needs at least two factors (its package builds a broken formula for one);
sa_analyzerefuses it for a single factor.LSD cannot load a configuration with
SEEDbelow 1 (27 shipped examples haveSEED 0); the tools say so andset_run_settings(seed=1)fixes it.Totals files (
.tot.gz) have no header and one row per run;read_resultsdoes not read them and names the.res.gzfiles instead.Sensitivity analysis covers Latin hypercube, uniform random and NOLH designs with a Kriging or polynomial meta-model, and elementary effects designs.
Factors are parameters or the initial values of variables (
"X"is the first lag,"X -2"the second). One element can be one factor only: LSD's design table names a factor by its label alone. Inlsd_confgen's own files a negative lag always means the first lag (confgen.cpp,change_configuration), so the tools send it the positive number it does honour.An elementary effects design made on macOS differs from one made on Linux (including in Docker) for the same seed, because LSD shuffles trajectories with the C++ standard library's
shuffle, which differs between libc++ and libstdc++. Both are valid designs. On Linux the design is byte-identical to what LSD's interface writes for the same settings and seed; NOLH and Monte Carlo range designs are identical on both platforms (tests/data/doe_guiholds the interface's files,tests/test_doe.pyand the Docker tests compare them).edit_structuresaves with LSD'ssave_configuration, so the file takes LSD's current layout. Of the 151 shipped example configurations LSD can load, 32 come back byte-identical from an empty edit. The rest differ only in layout (no data): descriptions without text were written as "(no description available)" in older files and are now empty,MODELREPORTlost a leading space, an emptyEQ_FILEsection is added, and the note LSD generates about the initial values of a variable with no lags is dropped (LSD'ssave_description). If the equation file is not in the model folder LSD would blank theEQUATIONname; the tool puts it back. New instances copy the object's first instance. Objects always keep at least one instance.Models made by
create_modeluse LMM's compiler options (SWITCH_CC=-O0 -ggdb3), so they compile without optimisation; editmodel_options.txtfor speed.NOLH tables cover 1 to 100 factors (17 to 512 points);
samplesdoes not apply.Without the Docker backend the compiler and utilities run on the host.
Models are compiled headless (
-D_NW_). Eight of the 45 example models use GUI-only features (Tcl calls, the debugger variables) and do not compile this way.lsd_confgenin 8.1-stable-5 generates at most as many configurations per call as the CSV has rows;sa_create_designsplits the work accordingly.lsd_confgendrops everything afterMODELREPORT(descriptions, embedded equations).set_valuesappends it again from the original file; the numbered design configurations are left as LSD writes them.sa_analyzeis tested on Linux with R 4.3.3 and LSDsensitivity 1.2.3 (the tests are skipped where R is missing).
Available Tools
17 toolscompile_modelB
Compile the model's equation file into a headless LSD program (built into the cache, not the model folder). Returns ok and build time, or the first compiler errors as file:line: message. Nothing is rebuilt if the equation file is unchanged.
Inputs: model (required), group.
copy_modelB
Copy a model folder (source files only: no binaries, results, backups,
numbered design configurations, design tables or _sa folders) into
the models folder as name, so it can be edited. Fails if name exists.
Inputs: name (required), source (required), source_group.
create_modelA
Create a new, empty model folder in the models folder, as LSD's model
manager (LMM) does: equation file fun_.cpp from LSD's template,
model_options.txt, modelinfo.txt (LMM lists a folder only with it),
description.txt, and a configuration Sim1.lsd holding only Root. name is
the folder (letters, digits, underscores; it must not exist or lie inside
another model). Then use edit_structure to add objects, parameters and
variables, write_equations for the equations, set_saved if needed, and
run_configuration. An empty model compiles and runs (it computes nothing
and saves nothing).
Inputs: name (required), title, description.
describe_configurationA
Describe a .lsd configuration: the object tree with instance counts,
and for each element (variable, parameter or function) its type, number of
lags, whether it is saved to the result files, and its value (a single
value if all instances are equal, otherwise min, max and count), plus the
run settings SIM_NUM, SEED, MAX_STEP and EQUATION. config is the file name
with or without .lsd. Set only when they apply: computed=false on objects
(not computed), and debug, plot, parallel, saved_separately on elements.
For big models pass object='Name' to describe one object, or
detail='names' for the tree with instance counts and just the element
names grouped by type.
Inputs: model (required), config (required), group, detail, +1 more.
edit_structureA
Change a configuration's structure (objects, parameters, variables,
functions, instance counts) with LSD's own code. operations is a list of
objects applied in order; if any fails (the message names it) nothing is
written. Writes new_config.lsd, or replaces config.lsd (old file kept as
.bak). Names must be valid LSD labels (letter or '' first, then letters,
digits, '') and unique across the whole model, objects and elements alike.
Operations, one example each:
{"op": "add_object", "parent": "Root", "name": "Firm", "instances": 10}
{"op": "add_parameter", "object": "Firm", "name": "alpha", "value": 0.5}
{"op": "add_variable", "object": "Firm", "name": "K", "lags": 1,
"initial": 1.0, "saved": true} (initial: a number, or one per lag)
{"op": "add_function", "object": "Firm", "name": "f"}
{"op": "rename", "name": "old", "new_name": "new"} (object or element)
{"op": "delete", "name": "K"} (element; an object with elements or child
objects needs "force": true and goes with all of it)
{"op": "set_instances", "object": "Firm", "instances": 50}
{"op": "set_instance_values", "name": "alpha", "values": [0.1, 0.2],
"lag": 2} (one value per instance in file order; lag only for variables)
{"op": "describe", "name": "alpha", "text": "adjustment speed"}
Parameters and variables are added to every instance of the object, with
the value (default 0) in each. set_instances gives the object that number
under every parent instance; new instances are copies of the object's
first instance (its values and its child objects), extra ones are removed
from the end; at least 1. Equations are not touched: add or change them
with write_equations. LSD's save rewrites the file in its own layout, so
old files may change in layout (empty descriptions, the notes LSD
generates for initial values of variables with no lags are dropped), never
in values.
Inputs: model (required), config (required), operations (required), new_config.
list_modelsA
List models. group='models' is the user's LSD_MODELS folder; group='examples' is the Example folder of the LSD distribution (read-only). A model is a folder with an equation file (fun_*.cpp) and at least one .lsd configuration. Returns relative path, title, equation file, source files (*.cpp, *.h, *.hpp in the folder) and configuration names for each.
Inputs: group. Returns: result
lsd_statusA
Show the setup: LSD source root and tag, models folder, whether a C++ compiler was found, whether LSD's command-line utilities are built yet (they are built automatically on first use), and whether Rscript and the R package LSDsensitivity are available.
Inputs: no named parameters.
read_equationsA
Return the text of the model's equation file (the C++ source with the
EQUATION(...) blocks). Models whose equations are spread over several files
list them as source_files in list_models; pass such a plain file name
(.cpp, .h or .hpp, no path) as file to read it instead.
Inputs: model (required), file, group. Returns: result
read_resultsA
Read time series from one result file (.res.gz) in the model folder. variables filters by name ('Mean') or name with instance ('Mean 1'); start/end select time steps (the row number in the file is the time step; row 0 holds initial values; start must not exceed end; max_points >= 1); the series are thinned evenly to max_points. At most 50 series are returned.
Inputs: model (required), results_file (required), end, start, +2 more.
run_configurationA
Compile if needed and run a configuration of a model in the models folder. seed and runs override SEED and SIM_NUM of the file. threads: with runs > 1, the number of runs executed in parallel; otherwise threads for models that use parallel objects. Results are written next to the configuration as .res.gz. Returns the files written and, for the first run, the last value and mean of each saved series (at most 50 series, those whose name has few instances first; the rest are counted). With runs > 1 (sequential) LSD also writes _.tot.gz; with threads set the runs are parallel and no totals file is written. Row 0 of a result file holds initial values. On failure returns the tail of LSD's output.
Inputs: model (required), config (required), runs, seed, +2 more.
sa_analyzeA
Analyse the design results for one saved variable with LSD's R package LSDsensitivity. metamodel 'kriging' (default for lhs, random and nolh designs) or 'polynomial' fits a meta-model and computes its Sobol decomposition: returns the fit quality (Q2 for kriging, R2 for polynomial) and a table with direct effects and interactions per factor. For a design made with method 'ee' the analysis is elementary effects (metamodel 'ee', chosen automatically): returns per factor mu, mu_star, sigma, se and p_value (parameters scaled to [0, 1]; mu_star is the overall effect, sigma non-linear or interaction effects, p_value tests mu_star = 0), sorted by mu_star. Kriging or polynomial on an ee design, or ee on another design, is an error. For an ee design made in LSD's own interface (no design file) pass metamodel='ee' with its levels and jump. ini_drop drops initial time steps, n_keep keeps that many (-1 = all). The response is the mean of the variable over the kept steps, averaged over runs. Variables whose name starts with '_' work; with several instances only the first instance is analysed. ini_drop must be below MAX_STEP and ini_drop + n_keep at most MAX_STEP. r_seed seeds R's random numbers, so identical calls give identical results. A warning is added when a meta-model fit is below 0.5. The polynomial meta-model fails when a design point has a negative mean response (LSD weights points by mean/SD) and needs at least two factors; use kriging then. Kriging can fail numerically when design points nearly coincide (the message says so; try polynomial). Needs Rscript and LSDsensitivity; says so if they are missing.
Inputs: model (required), config (required), variable (required), jump, +5 more.
sa_create_designA
Create a design of experiments for a sensitivity analysis and write it in
LSD's own file layout in the model folder: .sa, the design table
_1_N.csv (and for meta-model designs the out-of-sample table
_N+1_N+V.csv), numbered configurations _1.lsd ..., and
_design.json (our file: method and parameters).
factors maps an element to [min, max], or [min, max, "int"] for integers.
An element is a parameter name, or a variable name for the variable's
initial value at its first lag, or "Name -2", "Name -3" ... (name, space,
negative lag) for the initial value at that lag. Functions, variables with
no lags and lags beyond the variable's lags are refused, and an element can
be a factor only once (LSD's design table names a factor by its label, so
the result files and the analysis tables show the plain name, for example
"X"; the design file _design.json records each factor's lag, 0 for
a parameter). method:
'lhs' (Latin hypercube) or 'random': samples points (required, at least 2)
plus validation_samples uniform out-of-sample points, for a Kriging or
polynomial meta-model.
'nolh': near-orthogonal Latin hypercube made by LSD's own NOLH tables. LSD
chooses the table from the number of factors (17 points for 1-7 factors,
33 for 8-11, 65 for 12-16, 129 for 17-22, 257 for 23-29, 512 for 30-100;
extended=True uses LSD's extended size for the table: 33, 65, 129, 257,
257, 512), so samples is not used; the result says how
many points LSD produced. Plus validation_samples out-of-sample points by
LSD's Monte Carlo range sampling. For meta-model analysis.
'ee': elementary effects (Morris) design made by LSD's own code:
trajectories (default 10) each of factors + 1 points, chosen from a pool of
pool random trajectories (default 100) on levels levels (even, default
4) with jump (default 2). No out-of-sample set; validation_samples and
samples are ignored. An ee design made on macOS differs from one made on
Linux for the same seed (the C++ library's shuffle differs); both are valid
designs. Analyse it with sa_analyze (metamodel 'ee').
Each point runs runs_per_point times (at least 2) with its own seeds.
seed seeds the sampling. Refuses to replace an existing design unless
overwrite=True. A warning is returned for integer factors with few levels
(a hypercube collapses onto them). Variables whose results will be analysed
must be saved (set_saved).
Inputs: model (required), config (required), factors (required), jump, +10 more.
sa_run_designB
Run every numbered configuration of the design in parallel processes (default: one per CPU). Points whose result files already exist are skipped. Returns counts of points done, run, failed and not started.
Inputs: model (required), config (required), threads, timeout_s.
set_run_settingsC
Edit SIM_NUM (runs), SEED and MAX_STEP (time steps) of a configuration.
Inputs: model (required), config (required), runs, seed, +1 more.
set_savedB
Mark the named variables or parameters as saved (or not saved) to the result files. Only saved elements appear in results.
Inputs: model (required), names (required), config (required), saved.
set_valuesA
Set element values in a configuration, using LSD's own lsd_confgen.
values maps element name to a number; every instance of the element gets
the value. A variable's name sets its initial value at the first lag;
"Name -2", "Name -3" ... (name, space, negative lag) set the second, third
... lag ("Name -1" is the first); a lag beyond the variable's lags, or on a
parameter, is an error, and one element can appear once per call.
Writes new_config.lsd, or
replaces config.lsd (the old file is kept as .bak). The result says
whether an existing file was replaced (replaced, backup).
Inputs: model (required), config (required), values (required), new_config.
write_equationsA
Replace the model's equation file with content (complete C++ source),
or the source file named by file (plain name, .cpp, .h or .hpp; a new
file is created if it does not exist). The version before the latest write
is kept as .bak and the one before the first write as .orig.
Only models in the models folder can be written.
Inputs: model (required), content (required), file.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 17 tools
Most tools have clearly distinct scopes (model management, configuration editing, execution, and sensitivity analysis). Slight overlap exists between set_values and edit_structure's set_instance_values operation, and between set_run_settings and run_configuration's seed/runs overrides, but descriptions distinguish them well.
Predominantly snake_case verb_noun names such as list_models, read_equations, and create_model. Deviations are the sa_ prefix for sensitivity-analysis tools and lsd_status, but these are readable and consistent within their subgroups.
With 17 tools, the set is slightly above the ideal 3-15 range but the domain is broad and each tool covers a distinct workflow step. The count is reasonable, though a couple of configuration-editing tools could potentially be merged.
Coverage is strong across the model lifecycle (create, copy, read/write equations, edit structure, compile, run) and sensitivity analysis (design, run, analyze). Minor gaps include no delete_model/delete_configuration and no explicit list_results, which agents can partially work around.
Related MCP Connectors
Create and evaluate versioned decision models with reproducible results and declared assumptions.
Manage SysML2 projects; check, evaluate, verify, query, document and diagram models.
Build, run and analyse block-diagram simulations: PID, Bode, FFT, optimisation and code export.
Start and manage Reason cloud coding agents, projects and sessions from any MCP client.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI hosts to design and simulate complex adaptive systems, including managing agent types, running simulations, and analyzing emergent behavior, feedback loops, and sensitivities.1MIT
- AlicenseNot gradedqualityCmaintenanceEnables coding agents to run bounded COMSOL simulations with contract validation, model inspection, provenance tracking, and deterministic verifier feedback.2MIT
- AlicenseNot gradedqualityBmaintenanceEnables agents to build, validate, calibrate, and export versioned scientific models with mandatory units, dimensional and numerical checks, and uncertainty analysis over stdio. Models can be simulated and exported to portable formats such as SBML, CellML, and Modelica.65 npm9MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to read, write, and patch game economy and mechanic-map models stored as YAML, then run static analysis, simulation, and balance search on them so agent-driven work stays in sync with models edited in the browser.9 npm1MIT