What's New
soup mcp serve — drive Soup from any MCP client. A Model Context Protocol server so Claude Code / Cursor / Cline / Continue can run Soup conversationally. No other fine-tuning CLI ships one.
- 14 read-only tools, JSON out —
advise,data_inspect/data_validate/data_score/data_doctor,recipes_search/recipes_show,runs_list/runs_show,registry_list/registry_show,profile,diagnose_evidence,ship_evidence. Your agent can inspect data, search recipes, read runs, and get a ship verdict without leaving the chat. - Plan-only by default, safe by design — stdio transport only (no network listener). The two mutating tools (
train_start,export) are gated behind--allow-mutatingand only ever render the exact command that would run — they never execute. Every path argument re-enters cwd containment + symlink rejection; tool output is control-char sanitized; error messages are path-free; string / size / int bounds enforced. - Light install — the official
mcpSDK lives behind a new[mcp]extra, lazy-imported so the core CLI stays torch-free and fast. - Live-validated on Windows — a real stdio MCP client drove
initialize → list_tools → callend-to-end on Windows + RTX 3050: read tools return real JSON, the mutating tools refuse without the flag, and a path-traversal argument is rejected.
Wire it into your client (.mcp.json for Claude Code, or claude_desktop_config.json):
{ "mcpServers": { "soup": { "command": "soup", "args": ["mcp", "serve"] } } }Also in this release: the DPO / IPO / KTO / BCO and ORPO / SimPO / GRPO trainers now honor configured vocabulary expansion (data.add_new_tokens / data.new_special_tokens), completing consistent behavior across every SFT / preference / RL trainer (thanks @CODING-DARSH, #293 / #295).
Install / Upgrade
pip install --upgrade 'soup-cli[mcp]' # MCP server
# or, everything:
pip install --upgrade 'soup-cli[all]'Security
- stdio-only — the MCP server has no network listener.
- Path safety — every path argument (
data,config,evidence) stays under the working directory and rejects symlinks; JSON/config reads useO_NOFOLLOW+ a size cap; dataset loads are size-capped. - No leaks / no injection — tool output is recursively control-char (C0/ESC/DEL) sanitized before it reaches the client, and so is every error message; error messages never echo a filesystem path or raw user input.
- Bounds — string arguments are length-capped, integer arguments are range-checked (rejected, not silently clamped), and the SDK JSON-Schema-validates each tool's input before dispatch.
- No execution — the mutating tools are plan-only; there is no
subprocess/evalanywhere in the server.
Known Limitations
- Mutating tools are plan-only in v1 — even with
--allow-mutating,train_start/exportrender the command that would run; they never execute. Live execution from an MCP client is a deliberate future enhancement (agent-initiated GPU jobs need a human-in-the-loop design). - stdio transport only — SSE / HTTP transports are deferred.
data-argument reads use plainopen()(noO_NOFOLLOWre-check) — inherited from the shared dataset loader used by everysoup datacommand; the symlink is still rejected at check time, and the residual TOCTOU window requires an attacker who can already race-write files in your working directory.data_doctor'smodelargument can trigger outbound Hugging Face Hub fetches — mirrors the existingsoup data doctor --modelCLI;trust_remote_code=Falseis hard-coded so remote code execution is blocked.
Full notes: CHANGELOG.md.