Skip to content

Feature request: Multi-MATLAB workflow - allow per-tool-call instance selection to avoid silent session swaps after MCP server respawn #72

@henrik7o

Description

@henrik7o

Context
I run multiple MATLAB instances side-by-side, one per git work tree each driving its own Claude Code session (several projects in parallel). I use the session mode "existing" and the MCP server reads %APPDATA%\MathWorks\MATLAB MCP Core Server\v1\sessionDetails.json at startup to pick which MATLAB to attach to. Each mcpShareSession call from any MATLAB overwrites this file, so the last writer wins.

I built a workaround on top of this:
Per-worktree session-pin file at .matlab-session.json.
A Claude Code PreToolUse hook matching mcp__MATLAB__.* that copies the per-worktree file over the canonical one before every MATLAB MCP tool call.
That works while tool calls are flowing — every call resets the canonical file to the right worktree's session before the server reads it.

The hole
Today I hit a case the workaround can't catch. The MCP server itself crashed (or was killed) and a watchdog (or the host) respawned it. The respawn happens outside the tool-call lifecycle — no PreToolUse hook fires. The new server reads whatever the canonical file currently contains, which was the other worktree's MATLAB (whichever ran mcpShareSession most recently).
End result: a Claude session in worktree A silently became attached to worktree B's MATLAB. No errors, just wrong workspace, wrong path, wrong everything. Discovered only when commands started failing for unexplained reasons.

Proposal
Make the target MATLAB instance selectable at the tool-call level, not just via the global session file. Two shapes I see working:

Option A — optional pid (or sessionFile) parameter on every tool
Each mcp__MATLAB__* tool gains an optional input naming which MATLAB to target. Server keeps a small connection pool keyed by PID and routes the call accordingly. Backwards-compatible: omit the parameter and the server falls back to today's canonical-file behavior.

Jsonc
{ "code": "...", "pid": 12345 }

This eliminates the race entirely — there's no shared mutable state to corrupt.

Option B — separate list_sessions + select_session tools, server-side stateful

Jsonc
list_sessions() -> [{pid: 12345, branch: "barcode", root: "C:\..."} , ...]
select_session(pid: 12345)

Stateful from then on. Slightly worse — still has a shared selection, just held in the MCP server's memory instead of a file — but more discoverable and the LLM can pick from the visible list rather than needing the PID baked in. Could combine with Option A as a convenience.

Why I think this belongs in the MCP server, not the Claude harness
The harness only sees the tool surface the server exposes. If the server's tool inputs only carry "execute this code" with no instance context, no harness-level configuration can recover from a wrong attach — by the time the call is dispatched, the server has already picked its target. Per-tool selection (Option A) shifts the contract so the caller can be authoritative about which MATLAB it means.

What I'd like to discuss

Is there appetite for adding a pid/sessionFile parameter to the existing tools? It's going towards more and more parallel operations of agents and handling this seems important.

If yes, what's the right behavior when the requested PID isn't in the connection pool (auto-attach vs. error)?

Are there security or platform constraints I'm missing that would push this toward Option B instead?

Other approaches I haven't considered? One constraint worth flagging: keeping the existing session-attach model is essential — please don't let the MCP spawn its own MATLAB on demand. Each project has substantial pre-loaded context (annotation datasets, calibration states, models, configurations etc) that takes minutes to rebuild, and in my experience the MCP server already falls out periodically and takes its MATLAB with it. A spawn-on-demand model would mean re-paying that load cost on every restart, which is impractical. The instance-selection proposal above only makes sense in the attach-to-existing model.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementA request for new functionality or an improvement

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions