itasca-mcp-bridge
Runtime bridge that runs inside an ITASCA product process (PFC, FLAC3D, 3DEC, MPoint, MassFlow) and exposes the product's Python SDK as an HTTP API, enabling execution tools for MCP servers such as itasca-mcp.
The bridge is product-neutral: it drives the host through the shared ITASCA command language / Python SDK rather than any product-specific API.
Features
- Async tasks with progress polling. Submit a long simulation script
(
execute_taskmessage) and poll its status and paginated output while it runs (check_task_status). - Live REPL during a run. Send
execute_codeagainst the running task's namespace at any time to inspect state or tune parameters mid-cycle — no need to bake probes into the script up front. - Graceful interrupt. Stop a long cycling task on request
(
interrupt_task) without killing the product. - Unified output capture. Python
printand product console output (itasca.command()tables, list dumps, summaries) are interleaved in execution order in the task log. - User console history. What the person types into the product GUI —
cells in the IPython pane and lines at the command prompt — is recorded
with its output and handed to the client on request (
console_history), so an agent sees what happened in the GUI between its own calls.
Architecture
ITASCA's Python SDK is main-thread-only, so the bridge keeps the simulation on the main thread and serves remote requests around it with three parts:
flowchart TD
C[MCP client] -->|HTTP + SSE| S[HTTP server<br/>thread-per-request]
S -->|submit → Future| Q[MainThreadExecutor<br/>queue]
Q -->|Qt timer / blocking poll| M[product main thread<br/>itasca SDK + solver]
M -.->|callback at cycle| CB[interrupt check<br/>+ snippet executor]
CB -.-> M
- HTTP server (thread-per-request). A stdlib
http.server(no asyncio, no third-party dependency) serves each request on its own thread, hands the work to the main thread, and awaits aFuture. It never touches the SDK directly, so lightweight calls (status, interrupt) stay responsive even while a long task runs. Request/response is plainPOST /<command>; the one server→client doorbell (task_status_changed) is pushed over a single long-livedGET /eventsServer-Sent Events stream. - Main-thread queue.
MainThreadExecutorholds a thread-safe queue that the main thread drains — via a Qt timer in GUI mode, or a blocking poll in console mode. Submitted task scripts (execute_task) run here. - Cycle-gap callbacks. A cycling task holds the main thread, so two
itasca.set_callbackhooks keep it reachable: an interrupt check that stops the run (interrupt_task), and a snippet executor that runsexecute_codeREPL calls in the gaps between cycles — sharing the task's__main__namespace for live inspection and tuning.
HTTP protocol
The bridge is the source of truth for the wire contract — MCP servers such
as itasca-mcp are clients of it. Each request is a POST /<command> whose
body is a JSON object carrying a request_id; the JSON response echoes the
request_id. The server→client doorbells ride a single long-lived
GET /events SSE stream (payload-free task_status_changed and
console_entry events that prompt the client to re-poll), and
GET /health is a liveness probe. The commands are product-neutral:
POST /<command> |
Purpose | Key body fields |
|---|---|---|
execute_task |
Submit a file-backed script as a tracked async task | task_id, script_path, description |
check_task_status |
Poll a task's status and paginated log | task_id, skip_newest, limit, filter_text |
list_tasks |
List known tasks | offset, limit |
interrupt_task |
Request a graceful interrupt of a running task | task_id |
execute_code |
Run a snippet in the running task's __main__ (sync REPL) |
code, timeout_ms |
console_history |
Read what the person typed in the GUI since the last call | limit |
Quick Start
Run inside the product's Python (GUI IPython console or console CLI):
Install from PyPI
In the product's IPython console:
from pip._internal.cli.main import main as pip_main
pip_main(["install", "--user", "itasca-mcp-bridge"])
import itasca_mcp_bridge
itasca_mcp_bridge.start()
Headless, agent-launched
A console build runs the data file passed as its first argument, so an agent can bring the stack up itself — no GUI, nobody at the keyboard:
model new
python import itasca_mcp_bridge
python itasca_mcp_bridge.start(mode="console")
$ <product>_console.exe start_bridge.dat # e.g. pfc3d900_console.exe, flac3d900_console.exe
start() does not return, so nothing after that line runs; everything else
goes through the MCP tools.
The bridge is stdlib-only (http.server + Server-Sent Events), so there is
no third-party dependency to install or version-match — it lands cleanly in
any ITASCA embedded Python (3.6+) with no pins.
On every start() the bridge checks PyPI for a newer release (5-second
timeout; the Tsinghua mirror is tried when pypi.org is unreachable) and
self-upgrades before starting. The check is best-effort -- offline
machines and failed installs fall back to the installed version. To pin
the installed version, call start(auto_upgrade=False) or set the
environment variable ITASCA_MCP_BRIDGE_AUTO_UPGRADE=0. Corporate
mirrors can be configured with ITASCA_MCP_PIP_INDEX_URL.
After a self-upgrade the banner is followed by a short "What's new" list
of the release highlights you just received; call
itasca_mcp_bridge.whats_new() to reprint it anytime.
Run from a source checkout
%run C:/path/to/itasca-mcp-bridge/start_bridge.py
Use forward slashes in the path. Do not wrap it in quotes.
Code changes take effect on the next %run, so this is the preferred
workflow during development.
The bridge auto-detects the runtime: a Qt timer when the host is a GUI
application, a blocking loop otherwise. The banner reports which pump won,
so Mode is the first thing to check if a console start looks unreachable.
Expected output:
============================================================
Itasca MCP Bridge Server
============================================================
Version: 0.6.2
URL: http://localhost:9001
Log: /your-working-dir/.itasca-mcp-bridge/bridge.log
Mode: Qt timer
============================================================
Requirements
- An ITASCA product with an embedded Python interpreter. Verified on PFC, FLAC3D, 3DEC, MPoint and MassFlow, GUI and console builds, across the 6.0, 7.0 and 9.x product generations.
- Python >= 3.6 (6.0/7.0 products embed Python 3.6; 9.x products embed Python 3.10).
- No third-party runtime dependency: the transport is stdlib-only
(
http.server+ Server-Sent Events).
Troubleshooting
| Symptom | Fix |
|---|---|
| Server won't start | Re-run the install/start steps in the product's IPython console; check .itasca-mcp-bridge/bridge.log |
| Port in use | itasca_mcp_bridge.start(port=9002), then point your MCP client's bridge URL at http://localhost:9002 |
| Connection failed | Confirm the bridge is running and the port is reachable; see .itasca-mcp-bridge/bridge.log |
| No task execution / MCP cannot connect | If execution tools return ok=false, error.code=bridge_unavailable, error.details.reason=cannot connect to bridge service, confirm itasca_mcp_bridge.start() is running and your MCP client's bridge URL matches |
Relationship to MCP servers
This package is the in-process runtime only. Pair it with an MCP server that speaks its HTTP protocol — for example itasca-mcp — for full client setup.
License: MIT.
Release files for itasca-mcp-bridge 0.6.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| itasca_mcp_bridge-0.6.2.tar.gz | 157.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| itasca_mcp_bridge-0.6.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 265.9 kB
Release files / itasca_mcp_bridge-0.6.2.tar.gz
| Download URL | itasca_mcp_bridge-0.6.2.tar.gz |
|---|---|
| Size | 157.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5666721c36bcecf13f565065cdee8e9f0db5d1f479d10a277ed821bf7c309e59
|
|
BLAKE2b-256 checksum How to use checksums |
9b8bbc29a70013e23e993b23932fc26446544fa4a36af759aa3428cbc58289bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency logRelease files / itasca_mcp_bridge-0.6.2-py3-none-any.whl
| Download URL | itasca_mcp_bridge-0.6.2-py3-none-any.whl |
|---|---|
| Size | 109.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
79f5ece59d733b63d04feb69e702f697acb1b39ece29ebed05bf130b8b9f2892
|
|
BLAKE2b-256 checksum How to use checksums |
800b4da1076ea051b0f15435bd2ba0c5b5e11e508e8db46431dd2f58b853b588
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency log