MCP server: soup mcp serve (v0.71.28)
v0.71.28 ships a Model Context Protocol server, so you can drive Soup from any MCP client — Claude Code, Cursor, Cline, Continue — without leaving the chat. Your agent inspects a dataset, searches recipes, reads runs and gives a ship verdict as tool calls.
No other fine-tuning CLI ships an MCP server.
Start it
pip install 'soup-cli[mcp]' # official mcp SDK (mcp>=1.2.0), lazy-imported
soup mcp serve # stdio; read-only tools
soup mcp serve --allow-mutating # also list the 2 plan-only mutating toolsThere is exactly one flag: --allow-mutating. Transport is stdio only — no network listener, no HTTP, no SSE. That is a deliberate security property, not a limitation to work around.
Connect a client
Add Soup to your client's MCP config (.mcp.json for Claude Code, claude_desktop_config.json for Claude Desktop):
{
"mcpServers": {
"soup": { "command": "soup", "args": ["mcp", "serve"] }
}
}To expose the plan-only mutating tools, add the flag:
{
"mcpServers": {
"soup": { "command": "soup", "args": ["mcp", "serve", "--allow-mutating"] }
}
}The tools
The server exposes 16 tools total: 14 read-only + 2 plan-only mutating. It exposes MCP Tools only — no Resources, no Prompts. Every tool maps to a Soup command and returns JSON.
14 read-only tools (always available)
| Tool | Backing command | Returns |
|---|---|---|
advise | soup advise | PROMPT_ENG / RAG / SFT / DPO / GRPO verdict for a dataset |
data_inspect | soup data inspect | Row count, columns, length distribution, duplicates |
data_validate | soup data validate | Format-compliance report (issues + valid-row count) |
data_score | soup data score | Quality scorecard: PII, toxicity, language mix, educational value |
data_doctor | soup data doctor | Chat-template compatibility vs a tokenizer (needs [train]) |
recipes_search | soup recipes search | Search the catalog by keyword / task / size (no YAML body) |
recipes_show | soup recipes show | A full recipe including the ready-to-use soup.yaml |
runs_list | soup runs | Recent experiment runs from the local tracker |
runs_show | soup runs show | One run's full record (accepts an id prefix) |
registry_list | soup registry list | Registry entries, filterable by name/tag/base/task |
registry_show | soup registry show | One entry by id / prefix / name:tag / registry:// ref |
profile | soup profile | Memory / speed / GPU-fit estimate from a soup.yaml (no model load) |
diagnose_evidence | soup diagnose --evidence | Failure-mode report card from a pre-computed evidence JSON |
ship_evidence | soup ship --evidence | SHIP / DON'T-SHIP verdict from a pre-computed evidence JSON |
2 plan-only mutating tools (behind --allow-mutating)
| Tool | Backing command | Behaviour |
|---|---|---|
train_start | soup train | Validates a soup.yaml, returns {config_valid, task, base, would_run, note}. Never executes. |
export | soup export | Validates the format, returns {format, would_run, note}. Never executes. |
Both are always listed but refuse to run unless you started the server with --allow-mutating, and even then they only render the exact command that would run — live execution is a filed follow-up, not v1 behaviour. Calling them while disabled returns a clean isError telling you to restart with the flag.
Security model
Every point below is implemented and tested:
- stdio only — no network listener at all. stdout is reserved for the JSON-RPC channel; all human-facing text goes to stderr, and handler stdout is redirected so a stray
print()can't corrupt the stream. - Path containment — every path argument re-enters cwd-containment + symlink rejection (
O_NOFOLLOW+ fstat TOCTOU defence on reads). - Output sanitization — C0/ESC/DEL bytes are recursively stripped from every returned string (tab/newline/CR kept), so a malicious dataset string can't smuggle ANSI/OSC terminal escapes into your client.
- Path-free errors — a failing handler becomes a clean
isErrorresult; no filesystem path or stack trace leaks, and the server survives. - Bounds — string args ≤ 4096 chars, JSON args ≤ 16 MiB, dataset loads ≤ 1 GiB, int args range-checked (rejected, not silently clamped).
Install note
The [mcp] extra pulls one dependency, mcp>=1.2.0 (the official MCP Python SDK), and is lazy-imported — only the server module touches it, so the core CLI and the tool registry stay PyTorch-free and SDK-free. If you run soup mcp serve without the extra, you get a friendly one-line install hint and exit 1. The extra is also folded into [all] and [dev].
SSE/HTTP transport is a filed follow-up; v1 is stdio only.
See also
- Fine-tune Doctor —
data_doctoris one of the read-only tools here. - soup ship —
ship_evidencegives the SHIP / DON'T-SHIP verdict as a tool call. - advise / diagnose — the decide-and-report tools your agent can call directly.