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 arguments
  • stdin=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:

  1. Persists run records including PID to .soup/mcp-runs/
  2. Verifies child process existence before accepting new execution requests
  3. 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 serve or 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →