Summary
Over stdio the server holds one session per client process. In Claude Code, subagents run inside that same process, so a main agent and any number of parallel subagents share one Python namespace and one current_shape. export(), validate(), measure() and analyze_printability() all default to current_shape, so a concurrent show() from another agent silently retargets them.
I want to be upfront that this is a consequence of a stateful stdio server rather than a defect, and that you clearly know about it — list_sessions says "over stdio there is always exactly one session". This issue is only about one very cheap mitigation.
What happened
While building a part, two subagents I had not realised were still running independently called import_cad_file and show(..., "p8pcase") against the same session. session_state afterwards showed their objects and about a dozen of their locals interleaved with mine:
objects : p8pcase (Solid, 156 faces) <- not mine
variables: mycase (Solid, vol 16381.2433) rows2 (len 156) idx 155
zfaces (len 23) xf/yf (len 12) ks (len 228) ff, cc, nn, bbx, q
Nothing was corrupted, because I happened to pass object_name= explicitly on every export / validate / analyze_printability call. The default path is the hazard: had I built a part and called export("out.stl") with no object_name, I would have written out a different agent's model and there is nothing in the result that would have told me.
Note this is not persistence — the server process was verifiably fresh (spawned by the client, ~90 min old). It is concurrent access.
Suggested fix (small)
Have export() name the object it wrote. Today:
Exported to /Users/paul/testb123dmcp/pixel8pro-case.stl
volume 2.692e+04 mm3, bbox 81.1x167.2x11.95 mm, 94 faces
The volume/bbox/face echo is already a good sanity check — but it does not say which named object was written, which is exactly the fact needed to notice a wrong-object export. Something like Exported 'case' to ... (and '<unnamed current_shape>' when there is no name) would make it obvious at a glance. Same argument for validate().
Optionally, a line in the server instructions telling agent callers to pass object_name explicitly whenever parallel subagents may be active would be worth more than it costs.
Version
build123d-mcp 0.3.82.dev372, build123d 0.11.1, macOS.
🤖 Generated with Claude Code
Summary
Over stdio the server holds one session per client process. In Claude Code, subagents run inside that same process, so a main agent and any number of parallel subagents share one Python namespace and one
current_shape.export(),validate(),measure()andanalyze_printability()all default tocurrent_shape, so a concurrentshow()from another agent silently retargets them.I want to be upfront that this is a consequence of a stateful stdio server rather than a defect, and that you clearly know about it —
list_sessionssays "over stdio there is always exactly one session". This issue is only about one very cheap mitigation.What happened
While building a part, two subagents I had not realised were still running independently called
import_cad_fileandshow(..., "p8pcase")against the same session.session_stateafterwards showed their objects and about a dozen of their locals interleaved with mine:Nothing was corrupted, because I happened to pass
object_name=explicitly on everyexport/validate/analyze_printabilitycall. The default path is the hazard: had I built a part and calledexport("out.stl")with noobject_name, I would have written out a different agent's model and there is nothing in the result that would have told me.Note this is not persistence — the server process was verifiably fresh (spawned by the client, ~90 min old). It is concurrent access.
Suggested fix (small)
Have
export()name the object it wrote. Today:The volume/bbox/face echo is already a good sanity check — but it does not say which named object was written, which is exactly the fact needed to notice a wrong-object export. Something like
Exported 'case' to ...(and'<unnamed current_shape>'when there is no name) would make it obvious at a glance. Same argument forvalidate().Optionally, a line in the server instructions telling agent callers to pass
object_nameexplicitly whenever parallel subagents may be active would be worth more than it costs.Version
build123d-mcp 0.3.82.dev372, build123d 0.11.1, macOS.
🤖 Generated with Claude Code