How to Use Soup’s MCP Server for Programmatic Model Interactions
Use soup mcp serve to start a JSON-RPC server over stdio that exposes read-only and plan-execution tools, enabling any MCP-compatible client to drive Soup programmatically.
Soup's Model Context Protocol (MCP) server turns the CLI into a programmatic service that coding agents, IDEs, and automation scripts can control. This guide covers installation, configuration, security boundaries, and practical code examples based on the MakazhanAlpamys/Soup source code.
What the MCP Server Provides
The MCP server implements four architectural layers defined in src/soup_cli/mcp_server/:
| Component | Source File | Responsibility |
|---|---|---|
| Server Launcher | server.py |
Parses CLI flags, creates the Server instance, runs the JSON-RPC loop over stdin/stdout |
| Tool Registry | registry.py |
Declares read-only tools (advise, data_inspect) and plan-only mutating tools (train_start, export) |
| Execution Manager | execution.py |
Generates confirmation tokens, tracks subprocess lifecycles, enforces single-run concurrency |
| Configuration Snapshotting | execution.py |
Copies soup.yaml to .soup/mcp-runs/<run_id>/config.yaml and validates input hashes before execution |
By default, the server only exposes read-only tools. Mutating operations require explicit flags that enable planning and, separately, execution.
Installation and Server Startup
Install the MCP-enabled distribution of Soup:
pip install "soup-cli[mcp]"
Start the server in one of three modes:
# Read-only mode (default): safe for any environment
soup mcp serve
# Plan-only mode: mutating tools visible but never execute subprocesses
soup mcp serve --allow-mutating
# Full execution mode: enables background training and export runs
soup mcp serve --allow-execute
The --allow-execute flag implies --allow-mutating. Without it, tools like train_start return only execution plans and never spawn subprocesses.
Client Interaction Pattern
MCP clients communicate via JSON-RPC over the server's stdin/stdout. The protocol distinguishes three tool categories:
- Read-only tools — Immediate responses, zero side effects
- Plan-only tools — Return a token and execution plan; subprocess deferred
- Execution tools — Consume the token to trigger the actual subprocess
Example Client Implementation
from mcp import Client # Provided by `pip install "soup-cli[mcp]"`
# Connect to a local server with execution enabled
client = Client(command=["soup", "mcp", "serve", "--allow-execute"])
# 1️⃣ Call a read-only advisory tool
result = client.call("advise", {
"data": "Explain back-propagation in transformers"
})
print(result) # → {"response": "...", "tool": "advise"}
# 2️⃣ Plan a training run (does NOT start training yet)
plan = client.call("train_start", {"config": "/path/to/soup.yaml"})
token = plan["token"] # Required for next step
run_id = plan["run_id"]
print(f"Planned run {run_id}, token: {token[:8]}...")
# 3️⃣ Confirm and execute with the token
exec_result = client.call("train_execute", {"token": token})
print(exec_result) # → {"run_id": "...", "status": "started"}
The two-step plan-then-execute flow ensures human or automated review before any resource-intensive operation begins.
Security Architecture
The src/soup_cli/mcp_server/execution.py module implements four safety mechanisms:
1. Flag-Driven Capability Gates
| Flag | Effect |
|---|---|
| (none) | Read-only tools only |
--allow-mutating |
Adds train_start, export as plan-only tools |
--allow-execute |
Enables train_execute, export_execute with full subprocess spawning |
Accidental execution is impossible without --allow-execute.
2. One-Time Confirmation Tokens
When train_start or export is called, execution.py generates a cryptographically random token with a ~5-minute TTL. The token must be returned verbatim in the subsequent execution call. This prevents replay attacks and ensures the client explicitly intends to proceed.
Token generation and validation logic resides in execution.py with TTL enforcement via timestamp comparison.
3. Process Isolation
Subprocesses launch with these constraints:
shell=False— No shell interpretation of argumentsstdin=subprocess.DEVNULL— Isolated input stream- Locked working directory prevents concurrent directory mutations
- All child stdout/stderr redirect to
.soup/mcp-runs/<run_id>.log, keeping the JSON-RPC channel clean
4. Concurrency Control
Only one active execution is permitted system-wide. The server:
- Persists run records including PID to
.soup/mcp-runs/ - Verifies child process existence before accepting new execution requests
- Survives server restarts without orphaning or duplicating runs
This guarantees that a restarted soup mcp serve will not launch a second training job while the first remains active.
Debugging and Monitoring
Inspect execution logs for any active or completed run:
# Real-time log tail
tail -f .soup/mcp-runs/<run_id>.log
# Full log review
cat .soup/mcp-runs/<run_id>/config.yaml # Snapshot of config at plan time
ls .soup/mcp-runs/ # All runs with metadata
The configuration snapshot in .soup/mcp-runs/<run_id>/config.yaml ensures reproducibility: even if soup.yaml changes on disk, the executed run uses the exact configuration from planning time.
Key Source Files Reference
| Path | Purpose |
|---|---|
src/soup_cli/commands/mcp.py |
CLI entry point, argument parsing for soup mcp serve |
src/soup_cli/mcp_server/server.py |
Core Server class, JSON-RPC message handling |
src/soup_cli/mcp_server/registry.py |
ToolEntry definitions and static tool table |
src/soup_cli/mcp_server/execution.py |
Token lifecycle, subprocess management, safety checks |
docs/commands.md |
User-facing MCP documentation and security model |
tests/test_mcp_execute.py |
Automated verification of execution flow and concurrency |
Summary
- Install with
pip install "soup-cli[mcp]"to get the MCP SDK dependency - Start read-only with
soup mcp serveor enable execution via--allow-execute - Interact via JSON-RPC: call tools immediately, plan mutating operations, confirm with tokens
- Trust the security model: flags gate capabilities, tokens prevent replays, and process isolation protects the host
Frequently Asked Questions
What MCP clients work with Soup's server?
Any MCP-compatible client can connect. Verified options include Claude Code, Cursor, Cline, and Continue. All communicate over stdin/stdout using the JSON-RPC protocol defined in the MCP specification.
Why does training require a two-step plan-and-execute flow?
The design prevents accidental resource consumption and enables audit trails. The train_start tool snapshots the configuration, computes resource estimates, and returns a token. Only train_execute with that specific token spawns the actual training subprocess, allowing human review or automated policy checks between stages.
How does the server handle crashes or restarts during a training run?
The execution manager in src/soup_cli/mcp_server/execution.py persists run metadata including the subprocess PID. On restart, the server checks whether the recorded PID is still alive. If a run is active, new execution requests are rejected until the current run completes, preventing duplicate training jobs.
Can I use the MCP server without installing the full Soup package?
No. The soup-cli package with the [mcp] extra is required. This installs both the server implementation and the MCP SDK client libraries. The server depends on internal Soup modules for configuration parsing and subprocess management that are not available separately.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →