Files
Itamar Zand cba2c722fe refactor(mcp): run each tool call as a subprocess instead of in-process
The MCP adapter ran every tools/call via CliRunner in the long-lived
server process, so module-level state (the REPL skin, cached auth/session,
clients) was shared across calls — state bleed and resource leaks that the
one-shot CLI path never hits. Each call now spawns a fresh `cli-web-<app>`
subprocess (installed binary, or `python -m cli_web.<pkg>` fallback) with
`--json` forced, giving every tool the same clean-process isolation as a
normal CLI invocation, plus a per-call timeout so a wedged command can't
hang the server. Behavior is otherwise identical: stdout carries the
success/error envelope, stderr is the fallback for hard failures.

- mcp_server.py: McpServer gains pkg/timeout and an injectable executor
  (subprocess by default); resynced to all 20 vendored copies. Entry-point
  template passes pkg for the python -m fallback.
- unit tests: existing protocol/argv/shaping tests run the in-memory demo
  CLI via an injected CliRunner executor; new tests cover the subprocess
  path (binary vs python -m resolution, nonzero-exit/stderr, timeout).
- contract test: drives a real mcp-serve and calls the offline `doctor`
  tool, asserting the full subprocess-per-call path end to end (plus an
  unknown-tool JSON-RPC error).
2026-06-10 15:06:18 +03:00
..