opp_repl can expose an MCP (Model Context Protocol) server that
allows AI assistants to execute Python code in the live REPL session.
Start it with --mcp-port 9966 (disabled by default).
- Transport: Streamable HTTP (stateless)
- Endpoint:
http://127.0.0.1:{port}/mcp - Authentication: Bearer token (SHA-256 hash passed via
--mcp-token-hash) - Requires the
mcpextra:pip install -e ".[mcp]"
The MCP server requires bearer token authentication. The AI client generates a random token, computes its SHA-256 hash, and passes the hash on the command line. The raw token never appears in process arguments or shell history.
# Example: AI client generates a token, hashes it, and launches opp_repl
TOKEN=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
HASH=$(echo -n "$TOKEN" | sha256sum | cut -d' ' -f1)
opp_repl --mcp-port 9966 --mcp-token-hash "$HASH"The client then sends Authorization: Bearer <TOKEN> with every HTTP
request. opp_repl hashes the incoming token and compares it to the
stored hash (timing-safe). Requests without a valid token are rejected.
Outside opp_sandbox, authentication is mandatory by default — opp_repl
refuses to start the MCP server without either --mcp-token-hash or
the sandbox sentinel. Pass --mcp-bypass-token-hash-check to skip
authentication on purpose, e.g. for local development behind another
firewall:
opp_repl --mcp-port 9966 --mcp-bypass-token-hash-checkThis flag is intended for trusted, isolated environments only — any process that can connect to the port can execute arbitrary Python in the REPL.
When opp_repl is launched inside opp_sandbox (the bubblewrap-based
sandbox shipped with OMNeT++), the sandbox already provides
filesystem-level isolation: the process can only write to the working
directory and explicitly mounted paths, capabilities are dropped, and
namespaces are isolated.
In this case --mcp-token-hash can be omitted — opp_repl detects
the sandbox environment and starts the MCP server without
authentication:
opp_sandbox -w ~/workspace -- opp_repl --load "opp/*.opp" --mcp-port 9966Use -w / --writable to grant the sandbox write access to
additional directories (e.g. ~/workspace). Use -m / --mount for
read-only mounts.
Sandbox detection works by checking for the /.opp_sandbox sentinel
file that opp_sandbox bind-mounts (read-only) into the container,
and verifying that the file is actually read-only.
Execute Python code in the live IPython session. The code runs in the same namespace as the interactive REPL user — all public opp_repl packages, functions and classes are pre-loaded.
Returns captured stdout/stderr output. If the code is a single expression, its repr is returned.
A cell launched through execute_python can be interrupted from either
side without losing the REPL session:
Ctrl-Cin the REPL terminal — exactly as if you had typed the cell yourself.- The agent's Stop / cancel control — sends an MCP cancellation that the server turns into the same kind of interrupt.
Both paths trigger opp_repl's normal cancellation handling. Long-running
operations (task pipelines, simulation runs, etc.) see their cooperative
cancel flag set and report a CANCEL (Cancel by user) result rather
than crashing partway. Output produced before the interrupt is
preserved both in the REPL terminal and in the agent's response, and
the cell stays in IPython's history (In [N]: / Out[N]:) like any
other.
| URI | Description |
|---|---|
opp-repl://guides |
List available guide topics with first-paragraph summaries |
opp-repl://guide/{topic} |
Read a specific guide topic (e.g. fingerprint_tests, concepts) |
| URI | Description |
|---|---|
opp-repl://packages |
List all opp_repl sub-packages with first-paragraph summaries |
opp-repl://package/{package_name} |
Full package docstring, first paragraph per class, one-line summary per method, signature + one-line per function |
opp-repl://class/{class_name} |
Full class docstring, method signatures with first-paragraph summaries |
opp-repl://method/{class_name}/{method_name} |
Complete method documentation |
opp-repl://function/{function_name} |
Complete function documentation |
Class and function names can be fully qualified (e.g.
opp_repl.simulation.workspace.SimulationWorkspace) or short public
names (e.g. SimulationWorkspace).
- Read
opp-repl://guidesto find the relevant guide topic - Read
opp-repl://guide/{topic}for usage examples - Read
opp-repl://packagesto find the relevant sub-package - Read
opp-repl://package/{package_name}for a compact API overview - Drill into
opp-repl://class/…,opp-repl://method/…, oropp-repl://function/…for full details
Start opp_repl with --mcp-socket to listen on a Unix domain socket
instead of a TCP port:
opp_repl --mcp-socket # uses stable per-user default path
opp_repl --mcp-socket /custom/path # explicit pathThe default socket path is $XDG_RUNTIME_DIR/opp_repl/mcp.sock (falling
back to /tmp/opp_repl-<uid>/mcp.sock). The socket is created with
permissions 0600 (owner-only), so no bearer token is required — the
filesystem enforces access control.
--mcp-socket and --mcp-port are mutually exclusive.
Since most AI coding tools speak MCP over stdio rather than HTTP, a small bridge command is provided:
opp_repl_mcp_bridge # connects to the default socket path
opp_repl_mcp_bridge --mcp-socket PATH # connects to a custom pathRun opp_repl_mcp_bridge --help to see the resolved default path and
ready-to-paste configuration snippets for all supported clients.
The simplest config — no arguments needed when using the default path:
Windsurf (~/.codeium/windsurf/mcp_config.json):
{
"mcpServers": {
"opp_repl": {
"command": "opp_repl_mcp_bridge"
}
}
}Claude Code (~/.claude.json or .mcp.json for project scope):
{
"mcpServers": {
"opp_repl": {
"type": "stdio",
"command": "opp_repl_mcp_bridge"
}
}
}Or via the claude CLI:
claude mcp add --transport stdio opp_repl -- opp_repl_mcp_bridgeVS Code / Cursor (.vscode/mcp.json):
{
"servers": {
"opp_repl": {
"type": "stdio",
"command": "opp_repl_mcp_bridge"
}
}
}Add the following to your MCP configuration file
(~/.codeium/windsurf/mcp_config.json):
{
"mcpServers": {
"opp_repl": {
"disabled": false,
"headers": {
"Authorization": "Bearer <your_token>"
},
"url": "http://localhost:9966/mcp"
}
}
}Replace <your_token> with the raw bearer token whose SHA-256 hash was
passed to --mcp-token-hash when launching opp_repl. If running inside
opp_sandbox (no authentication), you can omit the headers field or
use any placeholder value.