Doramagic Project Pack · Human Manual

yade-mcp

MCP server connecting AI agents to YADE — run DEM simulations through natural conversation

Overview and Architecture

Related topics: MCP Tools Reference, YADE Bridge Internals

Section Related Pages

Continue reading this section for the full explanation and source context.

Section MCP Server (yade-mcp)

Continue reading this section for the full explanation and source context.

Section Bridge (yade-mcp-bridge)

Continue reading this section for the full explanation and source context.

Related topics: MCP Tools Reference, YADE Bridge Internals

Overview and Architecture

Purpose and Scope

yade-mcp is an MCP (Model Context Protocol) integration that lets AI agents drive YADE — an open-source discrete element method (DEM) simulator — directly from a chat client. The repository tagline captures the spirit: O.engines += [LLM()] # yet another engine. Source: README.md.

The project solves a recurring problem in agentic DEM workflows: LLMs need a live, callable interface to YADE for code execution, simulation control, and API discovery. The repository is therefore split into two Python packages that share a wire protocol but live in different processes:

PackageRoleWhere it runs
yade-mcpMCP server. Registers FastMCP tools (yade_query_api, yade_browse_api, yade_execute_code, yade_execute_task, yade_list_tasks, …).Inside the agent runtime (e.g., Claude Desktop).
yade-mcp-bridgeWebSocket/HTTP server embedded in YADE. Owns the task pump, script execution, console capture, and cancellation.Inside the YADE Python console / Qt process.

Sources: README.md, yade-mcp-bridge/README.md.

System Architecture

The two packages are intentionally decoupled. The MCP server never imports YADE; the bridge never imports fastmcp. They meet on a JSON-over-WebSocket boundary exposed by the bridge, and a knowledge base of pre-scraped API JSONs sits beside the MCP server so agents can grep YADE's class hierarchy without a live round-trip.

flowchart LR
    subgraph Agent["Agent runtime"]
        A[LLM / Claude Desktop]
    end
    subgraph MCP["yade-mcp (MCP server)"]
        T1[yade_query_api]
        T2[yade_browse_api]
        T3[yade_execute_code]
        T4[yade_execute_task]
        KB[(python_api_docs/*.json)]
    end
    subgraph Bridge["yade-mcp-bridge (inside YADE)"]
        WS[WebSocket / HTTP server]
        Pump[Background pump thread]
        PR[PyRunner self-heal]
        SR[ScriptTask runner]
        CC[Console capture]
    end
    YADE[(YADE __main__ + O.engines)]

    A -->|MCP tool call| T1
    A --> T2
    A --> T3
    A --> T4
    T1 --> KB
    T2 --> KB
    T3 -->|JSON-RPC| WS
    T4 -->|JSON-RPC| WS
    WS --> Pump
    Pump --> SR
    Pump --> PR
    PR --> YADE
    SR --> YADE
    CC --> Pump
    Pump -->|SSE events| A

The bridge auto-detects whether it is loaded inside the YADE Qt GUI or a headless Python console and switches its pump between a QTimer tick and a blocking daemon-thread poll, so start() never freezes the user's REPL (a behavior introduced in bridge-v0.2.0). Source: yade-mcp-bridge/README.md.

Component Responsibilities

MCP Server (`yade-mcp`)

Tools are registered through FastMCP. Each tool wraps a thin domain call into a uniform response envelope (build_ok / build_error from yade_mcp.contracts). Examples:

  • yade_query_api(query, limit=10) performs keyword search across the bundled knowledge base and returns ranked matches. Source: src/yade_mcp/tools/query_api.py.
  • yade_browse_api(path) walks YADE's native class tree (e.g., engine.GlobalEngine.NewtonIntegrator) and returns the full class JSON for a leaf. Source: src/yade_mcp/tools/browse_api.py.
  • yade_execute_code(code, timeout_ms) is fire-and-return; it documents three distinct failure shapes — interrupted, terminated, and timeout — that the agent must handle differently (added in v0.3.0). Source: src/yade_mcp/tools/execute_code.py.

The knowledge base lives under src/yade_mcp/knowledge/resources/python_api_docs/runtime/ and contains 371 runtime-introspected class JSONs (last fully refreshed in v0.2.2). Each JSON describes a class's category, parent, attributes, and methods — e.g., MaterialContainer exposes append/index for material lookup, and FileGenerator is the base for SimpleShear and TriaxialTest. Sources: MaterialContainer.json, FileGenerator.json.

Bridge (`yade-mcp-bridge`)

The bridge owns three runtime concerns:

  1. Task pump — a daemon thread (console mode) or Qt timer (GUI mode) that polls the task queue and dispatches ScriptTask instances. bridge-v0.2.4 aligned task lifetime with cycling lifetime so that O.run(N, wait=False) no longer leaves orphan cycling after the task "completes". Source: yade-mcp-bridge/README.md.
  2. PyRunner self-heal — injects and re-injects a _mcp_pyrunner_tick engine at O.engines[0] so user scripts that mutate O.engines cannot silently disable interrupt/observation. bridge-v0.2.2 fixed the case where IPython's %run script.py re-resolves sys.modules['__main__'] and breaks the name lookup. Source: yade-mcp-bridge/src/yade_mcp_bridge/runtime/pyrunner.py.
  3. Response shapingTaskDataBuilder constructs a uniform data block (task_id, task_type, script_path, status, start_time, elapsed_time, …) shared with the MCP server's data.task_status field, keeping lifecycle metadata on the subject rather than the envelope. Source: yade-mcp-bridge/src/yade_mcp_bridge/utils/response.py.

Communication Protocol and Lifecycle

The bridge exposes:

  • POST /execute_task / check_task_status / list_tasks / interrupt_task / execute_code / console_history (JSON-RPC over HTTP)
  • GET /events — Server-Sent Events stream emitting task_status_changed and console_entry
  • GET /health — liveness probe and runtime-mode report

The MCP server fans these out as MCP tools. v0.2.1 / bridge-v0.2.1 moved pagination (skip_newest, limit, filter_text) from the server to the bridge so check_task_status returns an explicit {total_lines, line_range, has_older, has_older} envelope against the complete log file rather than a moving window. Sources: yade-mcp-bridge/README.md, yade-mcp-bridge/src/yade_mcp_bridge/execution/script_runner.py.

The latest bridge-v0.3.1 simplifies startup to a single banner line (YADE MCP Bridge on ws://<host>:<port>, log: <path>) and quiets stdout to WARNING so initialization INFO only lands in bridge.log, leaving the YADE prompt clean. It also fixes a spurious "Console capture not installed" warning. Source: bridge-v0.3.1 release notes.

See Also

  • Tools Reference — per-tool argument and response shapes
  • Bridge Internals — PyRunner, task pump, cancellation
  • Knowledge Base — how the API JSON corpus is generated and refreshed

Sources: README.md, yade-mcp-bridge/README.md.

MCP Tools Reference

Related topics: YADE Bridge Internals, Knowledge Base, Search, and Deployment

Section Related Pages

Continue reading this section for the full explanation and source context.

Section yadebrowseapi

Continue reading this section for the full explanation and source context.

Section yadequeryapi

Continue reading this section for the full explanation and source context.

Section yadeexecutecode

Continue reading this section for the full explanation and source context.

Related topics: YADE Bridge Internals, Knowledge Base, Search, and Deployment

MCP Tools Reference

Overview

The yade-mcp server exposes seven tools to AI agents via the Model Context Protocol (MCP). They are organized into two functional groups: knowledge/discovery tools for navigating the YADE Python API, and runtime tools that drive the YADE process through the companion yade-mcp-bridge WebSocket service.

Source: src/yade_mcp/tools/__init__.py

Every tool returns a uniform response envelope produced by build_ok() / build_error(). Since v0.2.0, build_ok() is async and injects _context.user_console so agents can see what the human user just typed in the YADE IPython console, providing live context for multi-user workflows.

Knowledge & API Discovery

These two tools operate on locally bundled JSON documents under knowledge/resources/python_api_docs/runtime/ (371 classes scraped from a live YADE runtime in v0.2.2). They do not require a live bridge connection.

yade_browse_api

Walks the YADE-native class tree using a dot-separated path argument. Navigation is strictly tree-driven: there are no class-name shortcuts, and every leaf must be reached through its parent chain.

Path ExampleResult
None / ""Top-level categories (engine, functor, material, shape, …)
"engine"Sub-trees of Engine (Dispatcher, GlobalEngine, PartialEngine, …)
"engine.GlobalEngine"Sub-trees plus leaf classes (NewtonIntegrator, InteractionLoop, …)
"engine.GlobalEngine.NewtonIntegrator"Full documentation with attributes, methods, default values

Source: src/yade_mcp/tools/browse_api.py

yade_query_api

Performs keyword search (similar to grep) across the bundled docs via APISearch.search(). Useful when the agent knows what it wants — for example "friction material", "gravity engine", "contact force", "triaxial stress", "sphere create" — but not the exact class name. The limit parameter defaults to 10 matches and results are ranked by relevance.

Source: src/yade_mcp/tools/query_api.py

Runtime Execution

These tools call into the yade-mcp-bridge WebSocket service and require it to be running inside the target YADE process. Both follow the same envelope pattern:

  • client = await get_bridge_client() then await client.<method>(...)
  • Connection failures return build_bridge_error(exc)
  • Logic failures return build_operation_error(code, message, action)

Source: src/yade_mcp/tools/execute_code.py, src/yade_mcp/tools/execute_task.py

yade_execute_code

Synchronous, fire-and-return execution. Code runs in the YADE __main__ namespace; side effects persist and the tool is not tracked by yade_list_tasks.

The tool remains responsive even while a long simulation is running in another task, making it ideal as a live REPL for inspecting O.bodies, energy balance, stress tensor, viewport screenshots, etc.

The timeout parameter (default 10 seconds) drives cancellation. As of v0.3.0, the response distinguishes three failure codes:

error.codeMeaning
interruptedCode was inside an O.run cycle and was paused cleanly at an iteration boundary. Use yade_execute_task for long cycles.
terminatedAsync-exception abort succeeded; pump is free but YADE state may be partially modified.
timeoutAbort failed (stuck in C extension or inside a running task's PyRunner tick). Bridge may still be blocked; consider restart.

Source: src/yade_mcp/tools/execute_code.py

yade_execute_task

Asynchronous execution backed by ScriptRunner.run(). The tool generates a 6-character task_id immediately and returns it; the script proceeds in the background. Use this for production simulation runs and any operation expected to take minutes or longer.

Source: src/yade_mcp/tools/execute_task.py

Task Lifecycle Management

Once a task has been submitted, three companion tools manage its lifecycle. They all wrap the bridge handlers handle_execute_task, handle_check_task_status, handle_list_tasks, and handle_interrupt_task.

Source: yade-mcp-bridge/src/yade_mcp_bridge/handlers/__init__.py

flowchart LR
    A[yade_execute_task] -->|returns task_id| B[(ScriptTask log)]
    B --> C[yade_check_task_status]
    B --> D[yade_list_tasks]
    B --> E[yade_interrupt_task]
    C -->|status / output| F[Agent]
    D -->|history| F
    E -->|terminated flag| B

yade_check_task_status

Polls a task by task_id. Pagination has been moved to the bridge side since v0.2.1 (released in bridge-v0.2.1):

  • skip_newest — skip the most recent N output lines
  • limit — bounded page size (default 64); the bridge returns pagination.total_count so the caller knows how much remains
  • filter — substring filter against the complete log file

A separate wait_seconds parameter (default 1) lets the caller block briefly for new output before returning.

The lifecycle status is read with _lifecycle_status(), which prefers data.status and falls back to the envelope top-level for cross-version compatibility with older bridges.

Source: src/yade_mcp/tools/check_task_status.py, yade-mcp-bridge/src/yade_mcp_bridge/handlers/tasks.py

yade_list_tasks

Browses the task history with skip_newest (offset) and limit (default 32) pagination. The tool tolerates legacy bridges that signal success via status:"success" instead of ok:true.

Source: src/yade_mcp/tools/list_tasks.py

yade_interrupt_task

Requests cancellation of a running task. The bridge applies two cancellation paths together (bridge-v0.3.0):

  1. flag_only — sets an interrupt flag that YADE's PyRunner tick observes between iterations (graceful path for O.run tasks).
  2. flag_and_async_exc — additionally injects a TaskInterrupt exception into the script thread so pure-Python deadloops with no O.run on the stack can also be force-aborted.

The response method field reports which path actually ran. When async-exc is refused (e.g. target thread is a Dummy-N boost::python frame), async_exc_skipped_reason explains why. After an interrupt, the YADE __main__ namespace is preserved — variables defined by the interrupted script (including O state) survive.

Source: src/yade_mcp/tools/interrupt_task.py

Common Failure Modes

  • Bridge unreachable — every runtime tool returns build_bridge_error(exc); no task_id is generated, so there is nothing to poll.
  • Long simulation in yade_execute_codeO.run inside the synchronous tool will not be tracked; switch to yade_execute_task.
  • Pure-Python deadloop — submit it via yade_execute_task, then call yade_interrupt_task. The async-exc path (bridge-v0.3.0) terminates the loop without a bridge restart.
  • wait=False O.run — fixed in bridge-v0.2.4; previously caused silent-success bugs or orphan cycling because the task could complete in milliseconds while cycling continued.
  • Stale %run script.py NameError — fixed in bridge-v0.2.2; caused by IPython's %run reassigning sys.modules['__main__'] and YADE's PyRunner re-resolving it on every tick.

See Also

  • Bridge Architecture & WebSocket Protocol
  • YADE Python API Knowledge Base
  • Task Lifecycle & Cancellation Semantics

Source: https://github.com/yusong652/yade-mcp / Human Manual

YADE Bridge Internals

Related topics: MCP Tools Reference, Overview and Architecture

Section Related Pages

Continue reading this section for the full explanation and source context.

Related topics: MCP Tools Reference, Overview and Architecture

YADE Bridge Internals

The yade-mcp-bridge is the in-process runtime that lets a remote MCP client drive a live YADE discrete-element simulation. It exposes two execution surfaces — yade_execute_code for a live REPL and yade_execute_task for long-running scripts — over an HTTP + Server-Sent-Events (SSE) protocol that the yade-mcp MCP server consumes. Source: yade-mcp-bridge/src/yade_mcp_bridge/__init__.py:1-23

This page documents the internals that the public tools depend on: bootstrap and module surface, runtime coordination around YADE's Qt-bound main thread, task lifecycle, and transport.

Bootstrap and Module Surface

The package root re-exports a single start() function so both interactive and batch users hit the same code path. Source: yade-mcp-bridge/src/yade_mcp_bridge/__init__.py:18-23

import yade_mcp_bridge
yade_mcp_bridge.start()                # interactive / GUI mode
yade_mcp_bridge.start(mode="console")  # batch mode

Running the package as a module (python -m yade_mcp_bridge) dispatches to the same start() via __main__.main. Source: yade-mcp-bridge/src/yade_mcp_bridge/__main__.py:7-12

bootstrap.start() selects a transport, installs runtime hooks, and starts the request handler. Since bridge-v0.2.0 it has run the task pump in a background daemon thread, so the YADE IPython prompt stays usable while the bridge is active (community release notes: "Non-Blocking Console Mode"). A non-blocking startup is essential because the bridge is normally started from inside the YADE console and must not freeze it.

Runtime Coordination: Pump, PyRunner, Signals

YADE's Qt GUI objects are main-thread-only. The bridge keeps execute_code on the main thread while running each task on its own thread, so a long O.run() never blocks the server or live code. Source: yade-mcp-bridge/README.md:18-28

The runtime package exposes two coordination primitives plus an installer:

  • start_background_pump — drains the execute_code queue from a daemon thread; used in non-GUI / batch mode.
  • start_qt_pump — drains the queue from the Qt event loop; used in interactive GUI mode.
  • install_pyrunner — injects _mcp_pyrunner_tick into O.run() so the bridge can observe iterations and apply graceful interrupts.

Source: yade-mcp-bridge/src/yade_mcp_bridge/runtime/__init__.py:11-21

The _mcp_pyrunner_tick symbol is the bridge's only foothold inside O.run(). Community release notes for bridge-v0.2.2 call out that YADE's PyRunner re-resolves sys.modules['__main__'] on every tick, so the symbol must be installed on the __main__ namespace that IPython's %run uses; otherwise a NameError: name '_mcp_pyrunner_tick' is not defined fires when a user %runs a script after the bridge has started.

flowchart LR
    Client[MCP client<br/>yade-mcp] -->|POST /command| Server[HTTP + SSE server<br/>background thread]
    Client -.->|GET /events| Server
    Server -->|execute_code| Pump[Runtime pump<br/>main thread]
    Server -->|execute_task| Tasks[ScriptTask<br/>own thread]
    Pump --> YADE[(YADE simulation<br/>__main__ namespace)]
    Tasks --> YADE
    Pump -. interrupt / pause .-> PyRunner
    Tasks -. log lines .-> Logs[".yade-mcp/logs"]

Cancellation uses two complementary paths described by the yade_interrupt_task tool:

  • flag_only — sets an interrupt flag that the PyRunner tick observes between iterations; the graceful path for O.run tasks.
  • flag_and_async_exc — additionally injects a TaskInterrupt exception into the script thread, terminating pure-Python deadloops.

When async-exc is refused (for example the target thread is a Dummy-N boost::python frame), async_exc_skipped_reason is returned so the agent can tell why the deadloop may still be alive. Source: src/yade_mcp/tools/interrupt_task.py:14-32

Since bridge-v0.3.0, execute_code timeouts distinguish terminated (async-exc abort succeeded, the pump is free) from timeout (async-exc refused, the bridge may still be blocked). The split was promoted so agents can tell a graceful cancellation apart from a force-kill, and so they know that the YADE __main__ namespace survives the interrupt. Before this split, agents could not tell whether a stuck execute_code would ever return and had no clean way to recover.

Task Lifecycle

Tasks are managed by ScriptTask in the bridge's tasks package. The class tracks lifecycle states — pending, running, completed, failed, and interrupted — recorded on _status and surfaced through check_task_status. Source: yade-mcp-bridge/src/yade_mcp_bridge/tasks/task.py:14-21

ScriptTask carries an error_details field that captures structured failure information (user-frame traceback, exception type, overflow log path) and surfaces it through check_task_status so the agent has full debugging context without chasing log files. Source: yade-mcp-bridge/src/yade_mcp_bridge/tasks/task.py:39-42

Since bridge-v0.2.4, task lifetime is aligned with cycling lifetime: a script that calls O.run(N, wait=False) no longer creates "silent success" bugs or orphan cycling. Previously the task could complete in milliseconds while cycling continued in the background, masking real failures and leaving a runaway O.run() behind. This is a common failure mode for any agent that scripts a non-blocking run and immediately polls for status — the fix is the kind of detail that only becomes visible in production.

Since bridge-v0.2.1, output pagination (skip_newest / limit / filter_text) is handled on the bridge side via ScriptTask.get_paginated_output, which reads the full log file and returns an explicit pagination dict with total_lines, line_range, has_older, and has_newer. The MCP layer no longer paginates a possibly truncated window, which had been a long-standing source of off-by-one bugs. Source: src/yade_mcp/tools/check_task_status.py:1-13

Transport and On-Disk Paths

The transport is a pure-stdlib HTTP + SSE server. Request/response flows over POST /command; server push flows over GET /events. Source: yade-mcp-bridge/README.md:24-29

On disk, all bridge artifacts live under a single dot-directory in the YADE process CWD: DATA_DIR = ".yade-mcp" and LOGS_DIR = ".yade-mcp/logs". These constants are defined once in paths.py so every module refers to the same location. Source: yade-mcp-bridge/src/yade_mcp_bridge/paths.py:13-19

As of bridge-v0.3.1, the startup banner is reduced to a single line — YADE MCP Bridge on ws://<host>:<port>, log: <path> — and stdout is quieted to WARNING. Initialization INFO logs are routed to bridge.log only, keeping the interactive YADE prompt clean. The release also fixes a spurious "Console capture not installed" warning that previously fired even when console capture was wired correctly.

See Also

  • MCP Tool Reference — the public surface area (yade_execute_code, yade_execute_task, yade_check_task_status, yade_interrupt_task, yade_list_tasks, yade_query_api, yade_browse_api).
  • YADE Bridge Quickstart — installing and launching the bridge inside YADE.
  • Bridge Cancellation Protocol — full semantics of terminated vs timeout and the two interrupt paths.

Source: https://github.com/yusong652/yade-mcp / Human Manual

Knowledge Base, Search, and Deployment

Related topics: MCP Tools Reference, Overview and Architecture

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Layout and schema

Continue reading this section for the full explanation and source context.

Section Why runtime introspection

Continue reading this section for the full explanation and source context.

Section Architecture

Continue reading this section for the full explanation and source context.

Related topics: MCP Tools Reference, Overview and Architecture

Knowledge Base, Search, and Deployment

Overview

yade-mcp is a Model Context Protocol server that lets AI agents drive the YADE discrete-element-method simulator. The system is split across two deliverables: the MCP server package (yade-mcp) and the in-process bridge (yade-mcp-bridge) that the user launches from inside YADE's Python console. This page covers three pillars that make the integration work end-to-end: the offline runtime-generated knowledge base of YADE classes, the search and browse tools that surface that knowledge to the agent, and the deployment model that wires an MCP client to a live YADE process.

The knowledge base is the static half of the system: 371 class JSON files produced by introspecting a live YADE runtime and frozen under src/yade_mcp/knowledge/resources/python_api_docs/runtime/. The bridge is the dynamic half: a WebSocket server embedded inside YADE's Python interpreter that pumps task output back to MCP clients.

Knowledge Base

Layout and schema

The knowledge base lives at src/yade_mcp/knowledge/resources/python_api_docs/runtime/, with one JSON file per introspectable YADE class. The v0.2.2 release notes describe this as a "complete refresh of the 371 class JSONs ... against a live YADE runtime". Every file follows the same shape: name, category (the top-level bucket such as engines, functor, material, shape), parent (the immediate superclass — the field that drives tree navigation), description, an attributes list of {name, type, default, description} records, and a methods list of {name, args, returns, description, inherited_from?} records.

For example, MaterialContainer.json declares parent: "instance" and exposes append(Material) -> int plus index(str) -> int Source: src/yade_mcp/knowledge/resources/python_api_docs/runtime/MaterialContainer.json:1-31. FileGenerator.json declares parent: "Serializable" and exports generate(out) and load() Source: src/yade_mcp/knowledge/resources/python_api_docs/runtime/FileGenerator.json:1-30. Concrete preprocessors such as TriaxialTest extend FileGenerator and pull in dozens of typed attributes (sigmaIsoCompaction, sphereYoungModulus, compactionFrictionDeg, boxYoungModulus, maxWallVelocity, ...) Source: src/yade_mcp/knowledge/resources/python_api_docs/runtime/TriaxialTest.json:1-40.

Why runtime introspection

YADE is a hybrid C++/Boost.Python project whose API surface evolves between commits. Scraping from a live runtime is preferred over scraping reStructuredText docs because the docstrings are pinned to the actual method signatures. The scraper and the JSONs travel together, so a future bump of YADE re-runs introspection and replaces the bundle in a single commit (per v0.2.2 release notes).

Search and Browse Tools

The MCP server exposes two complementary tools over the knowledge base, both registered through the tools package Source: src/yade_mcp/tools/__init__.py:1-18.

yade_query_api is a keyword search. It takes a free-text query and a limit (default 10) and delegates to APISearch.search(query, top_k=limit). The docstring tells agents to use it when they have keywords but not the exact class name — examples include "friction material", "gravity engine", "triaxial stress", "sphere create", "hertz mindlin" Source: src/yade_mcp/tools/query_api.py:1-42. Results are wrapped with build_docs_data(source="python_api", action="query", ...) and emitted through build_ok(...), the canonical success envelope.

yade_browse_api walks the YADE-native class tree by path. The path argument is dot-separated: None or '' lists top-level categories, engine lists Engine sub-trees, engine.GlobalEngine.NewtonIntegrator resolves a leaf Source: src/yade_mcp/tools/browse_api.py:1-49. Navigation therefore goes through parent-class chains (GlobalEngine → PeriodicEngine → ...) rather than arbitrary class-name shortcuts. Unknown leaves yield build_error("class_not_found", ...) with a details block containing the requested category, tree_path, and class_name, which lets the agent self-correct without round-tripping.

The two tools are intentionally paired: yade_query_api for discovery, yade_browse_api for full documentation of a known class. Both call into the same APILoader / APISearch layer, so any future knowledge source (for example tutorial transcripts) can plug in behind the same source field.

Deployment and Bridge

Architecture

flowchart LR
    A[MCP client<br/>agent] -- stdio MCP --> B[yade-mcp server]
    B -- WebSocket<br/>ws://host:port --> C[yade-mcp-bridge]
    C -- py::exec / PyRunner --> D[YADE runtime]
    D -- O.engines[0] --> E[PyRunner tick]
    E -- async exception --> D

The MCP server is a normal Python package installed via pip install yade-mcp and registered with the model client (the README advertises io.github.yusong652/yade-mcp as the canonical server name) Source: README.md:1-15. The bridge is a separate package, yade-mcp-bridge, installed inside the YADE Python interpreter so it can reach yade C-extension bindings Source: yade-mcp-bridge/README.md:25-45.

Startup and runtime modes

yade_mcp_bridge.start() is called from the YADE IPython console. It auto-detects the runtime: a Qt timer drives the task pump in GUI mode, while console mode spawns a background daemon thread so the user can keep typing Source: yade-mcp-bridge/README.md:45-60. The bridge startup banner was collapsed to a single line — YADE MCP Bridge on ws://<host>:<port>, log: <path> — and stdout is quieted to WARNING, with initialization INFO logs going to bridge.log only (per bridge-v0.3.1 release notes).

Task pump and PyRunner integration

Long-running work (yade_execute_task) is driven by a PyRunner engine injected at O.engines[0] whose command is the literal string _mcp_pyrunner_tick() # yade-mcp-bridge: DO NOT MODIFY. The marker comment makes the engine self-identifying when users print O.engines. The bridge calls _normalize_pyrunner() on every tick, self-healing against user scripts that reassign O.engines, mutate iterPeriod, or move the engine out of slot 0, and logs a warning on tamper so the cause of any interrupt-latency bug is visible Source: yade-mcp-bridge/src/yade_mcp_bridge/runtime/pyrunner.py:1-60. The same path was also where %run script.py triggered a NameError: name '_mcp_pyrunner_tick' is not defined, fixed in bridge-v0.2.2 by avoiding __builtins__ re-resolution under IPython.

Response envelope

The bridge emits a typed JSON envelope on every WebSocket response. TaskDataBuilder is the constructor: it carries task_id, task_type, script_path, and description, then layers in status (one of pending, running, completed, failed, interrupted) via .with_status(...) Source: yade-mcp-bridge/src/yade_mcp_bridge/utils/response.py:1-35. status intentionally rides inside data alongside task_id rather than parallel to the request-level ok, mirroring how the MCP server already nests it as data.task_status.

Cancellation semantics

bridge-v0.3.0 introduced abort-aware cancellation. The execute_code tool now distinguishes terminated (async-exc abort succeeded, pump free, YADE state may be partially modified) from timeout (abort failed, bridge may still be blocked). yade_execute_code mirrors this by exposing interrupted, terminated, and timeout as separate error.code values Source: src/yade_mcp/tools/execute_code.py:1-50. For long simulations, agents are steered toward yade_execute_task plus yade_interrupt_task rather than yade_execute_code, because task interrupts are cooperative and the __main__ namespace survives the interrupt (per v0.3.0 release notes).

See Also

  • Tools reference (yade_execute_code, yade_execute_task, yade_list_tasks, yade_interrupt_task, yade_check_task_status)
  • Bridge runtime internals — task pump, PyRunner tick loop, websocket protocol
  • Bootstrap guide for PEP 668 externally-managed environments

Source: https://github.com/yusong652/yade-mcp / Human Manual

Doramagic Pitfall Log

Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.

medium Configuration risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Capability evidence risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Maintenance risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Security or permission risk requires verification

May increase setup, validation, or first-run risk for the user.

Doramagic Pitfall Log

Found 7 structured pitfall item(s), including 0 high/blocking item(s). Top priority: Configuration risk - Configuration risk requires verification.

1. Configuration risk: Configuration risk requires verification

  • Severity: medium
  • Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: capability.host_targets | https://github.com/yusong652/yade-mcp

2. Capability evidence risk: Capability evidence risk requires verification

  • Severity: medium
  • Finding: README/documentation is current enough for a first validation pass.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: capability.assumptions | https://github.com/yusong652/yade-mcp

3. Maintenance risk: Maintenance risk requires verification

  • Severity: medium
  • Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: evidence.maintainer_signals | https://github.com/yusong652/yade-mcp

4. Security or permission risk: Security or permission risk requires verification

  • Severity: medium
  • Finding: no_demo
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: downstream_validation.risk_items | https://github.com/yusong652/yade-mcp

5. Security or permission risk: Security or permission risk requires verification

  • Severity: medium
  • Finding: no_demo
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: risks.scoring_risks | https://github.com/yusong652/yade-mcp

6. Maintenance risk: Maintenance risk requires verification

  • Severity: low
  • Finding: issue_or_pr_quality=unknown。
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: evidence.maintainer_signals | https://github.com/yusong652/yade-mcp

7. Maintenance risk: Maintenance risk requires verification

  • Severity: low
  • Finding: release_recency=unknown。
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: evidence.maintainer_signals | https://github.com/yusong652/yade-mcp

Source: Doramagic discovery, validation, and Project Pack records

Community Discussion Evidence

These external discussion links are review inputs, not standalone proof that the project is production-ready.

Sources 11

Count of project-level external discussion links exposed on this manual page.

Use Review before install

Open the linked issues or discussions before treating the pack as ready for your environment.

Community Discussion Evidence

Doramagic exposes project-level community discussion separately from official documentation. Review these links before using yade-mcp with real data or production workflows.

Source: Project Pack community evidence and pitfall evidence