Repository navigation
v1.0.0
First stable release. The server is feature-complete for conversational
agent-based modeling: 25 tools covering model creation with declarative
widgets, simulation and data collection, BehaviorSpace parameter sweeps,
CoMSES Net library access, and view/world export — now published on PyPI
as netlogo-mcp.
Packaging
- Published to PyPI:
pip install netlogo-mcp. - Package renamed
NetLogo_MCP→netlogo-mcp(PyPI-normalized name);
version is now single-sourced fromnetlogo_mcp.__version__. - Added release automation: pushing a
v*tag builds, publishes to PyPI
via trusted publishing, and creates a GitHub Release with these notes. - Added
CITATION.cff, issue/PR templates, and Dependabot config.
Changed — lazy JVM startup
- The JVM (and the NetLogo GUI window) now starts lazily on the first
tool call that needs the workspace, instead of the moment an MCP client
connects. Connecting Claude/Cursor/etc. no longer pops a NetLogo window
you didn't ask for. Startup runs on a worker thread under the workspace
lock, so the event loop and MCP heartbeats stay responsive during the
30-60s boot. SetNETLOGO_EAGER_START=trueto restore the old
boot-at-launch behavior. server_infonow reportsjvm_startedso clients can check workspace
state without triggering a boot.
Fixed — JVM startup deadlock on Windows
- The stdio transport keeps a pending blocking read on the stdin pipe from
a worker thread; Windows serializes operations on a synchronous pipe's
file object, so the JVM's std-handle probes duringCreateJavaVMblocked
behind that read — JVM startup hung until the client happened to send
another byte. The server now hands the transport a private duplicate of
stdin and points fd 0 (and the Win32STD_INPUT_HANDLE) at devnull, so
the JVM never touches the protocol pipe. This was the real reason an
earlier lazy-startup attempt was abandoned for eager startup.
Fixed — protocol corruption on NetLogo errors
- pynetlogo
print()s Java stack traces to stdout whenever a NetLogo
command/reporter/load fails — and stdout is the MCP JSON-RPC channel.
One compile error in generated model code could corrupt the protocol
stream and leave the session flaky. The server now duplicates fd 1 for
the transport's private use, points fd 1 at stderr (covering the JVM's
directSystem.outwrites, which bypass Python entirely), and parks
Python'ssys.stdouton stderr for the whole serving phase.
Fixed — widget generation
create_model/save_modelno longer emit Setup/Go buttons for
procedures that don't exist in the code — a button pointing at a missing
procedure made the whole model fail to load.to setup-patchesno longer falsely counts as definingsetup.
Changed — multi-column widget layout
- Declarative widgets now wrap into additional columns when they'd
overflow the column height, and the world view shifts right to sit
beside the last column — widget-heavy models no longer pile into one
endless strip that runs off the bottom of the window.
Added — GUI polish
- The NetLogo window is retitled to the model name and brought to the
front whenever a model is loaded (create_model/open_model/
update_model/open_comses_model). Best-effort via the Swing event
thread; silent no-op in headless mode. - New
watch_simulation(ticks, delay_ms)tool — runsgostep-by-step
with a pause between steps so a human can actually watch the dynamics
unfold in the GUI. Capped at 120s per call;run_simulationremains the
full-speed data-collection path.
Added — plot widgets
- The
widgetsschema now supports{"type": "plot", "pens": [...]}—
live population-dynamics plots in the NetLogo window, the main reason to
watch a GUI run. Pens take NetLogo plot code, palette color names (or raw
AWT ints), line/bar/point modes, and intervals; axes auto-scale.
Verified live: NetLogo 7.0.3 loads the generated XML and pens plot every
tick.
Added — update_model
- New
update_model(code, widgets?)tool: rewrites the currently loaded
.nlogoxin place and reloads it. Existing widgets are preserved when
widgetsis omitted, so iterating on procedures keeps the interface the
user already has. Ends the one-_created_*.nlogox-file-per-iteration
clutter in the models directory.
Added — declarative interface widgets
create_modelandsave_modelaccept an optionalwidgetslist:
sliders, switches, buttons, and monitors with validated names, escaped
code, and automatic column layout (NetLogo 7.nlogoxwidget schema).
Slider/switch widgets define their variable, so generated models can use
interface globals exactly like hand-built ones — andset_parameter
works against them out of the box.
Docs
- README slimmed to the essentials; full tool reference moved to
docs/TOOLS.md, environment variables and GUI/headless guidance to
docs/CONFIGURATION.md, and the security model todocs/SECURITY.md. docs/DEVELOPMENT.mdarchitecture notes rewritten to match the lazy
startup and fd-level stdout discipline (the old notes contradicted the
code on threading).
Security & validation
set_parameternow validates thenameargument against a NetLogo
identifier regex before interpolating it into aset <name> <value>
command. Closes a command-injection vector where a name like
"x setup -- "would have appended an arbitrary NetLogo command past
theset. Legitimate kebab-case + predicate names (show-energy?,
initial-number-sheep) are unaffected.run_simulationrejects empty / non-string entries inreporters,
andget_patch_datarejects blankattributes — these formerly
produced confusing NetLogo compile errors deep in the call.- 25 new tests cover the validation surface (injection-shape names,
blank reporters, blank attributes).
Added — workspace control & introspection
- New
close_modeltool — issuesclear-alland forgets the current
model path so AI clients can drop pending state without bouncing the
JVM (which costs 30-60s on the next startup). - New
server_infotool — pure config / filesystem inspection that
returns server version, GUI mode, configured paths, and whether the
BehaviorSpace headless launcher is reachable. Useful as a pre-flight
check before launching long sweeps; does not require the JVM to be
warm.
Removed
- Dead
get_or_create_netlogolazy-init helper inserver.py— the
eagerlifespan()startup is the only path now, and the duplicated
init was an attractive nuisance for future contributors.
Added — BehaviorSpace integration & NetLogo 7 transition guide
- 3 new tools for running NetLogo BehaviorSpace experiments:
list_experiments(read saved experiments from.nlogox),
preview_experiment(show run plan without executing),
run_experiment(drive the headless launcher in a separate JVM and
return parsed table-CSV results). - Drives BehaviorSpace via the canonical
NetLogo_Console/
netlogo-headlesslauncher — no dependency on the unbundledbspace
extension, works with NetLogo 6.x and 7.x. - Hard run cap (
max_total_runs, default 200) and wall-clock timeout
(timeout_seconds, default 600). Partial table CSV is preserved on
timeout; the runner reportstimed_outseparately fromfailed. - New prompt:
behaviorspace_experiment— enforces preview-before-run. - New resource:
netlogo://docs/transition— focused 6→7 porting guide
for AI clients hitting old CoMSES models. Covers.nlogo→
.nlogoxauto-conversion,ifelse-valueprecedence shift,task→
anonymous procedures, movie-prim →vidextension, bundled vs
non-bundled extensions in 7.0.3. - Tracks
current_model_pathin the lifespan context so BehaviorSpace
can target the model the AI most recently loaded without an extra arg.
Changed — token efficiency
run_simulationacceptssummary_only=True(returns
min/mean/max/std/final per reporter as one row each) andmax_rows=N
(evenly-spaced decimation that always keeps the final tick).get_patch_dataacceptssummary_only=True(returns shape + numeric
stats + unique-count instead of the full 2D grid).- Defaults are unchanged; existing prompts keep working.
Added — CoMSES Net integration
- 5 new tools for exploring the CoMSES Net computational model library:
search_comses,get_comses_model,download_comses_model,
open_comses_model,read_comses_files. - 1 new prompt:
explore_comses— NetLogo-first, source-introspection,
never fabricates commands, stops-and-asks on runtime errors. - Safe download pipeline: HEAD screen + mid-stream byte cap
(COMSES_MAX_DOWNLOAD_MB, default 50), zip-member path-traversal
validation, zip-bomb guard, atomic temp-to-final extract with
.comses_completemarker, race reconciliation. "latest"version resolution with snapshot semantics — resolved to
a concrete version before any cache path is computed; the resolved
version is returned so follow-up reads stay pinned.read_comses_filesreturns a precise contract with per-file
{content, full_size, returned_size, truncated}, priority ordering
(ODD → NetLogo → other code → md/txt), byte cap with line-boundary
truncation, UTF-8 decoding witherrors="replace", zero-match case
handled explicitly.httpx>=0.27dependency.- 44 new tests covering retry matrix, zip-slip, zip-bomb, marker,
race-orphan, NetLogo-file selection rule, ODD discovery, cache
reuse, latest resolution, truncation, extension filters, prompt rules.