loommux
It is an MCP server that provides a persistent, inspectable IPython kernel session with tools to run Python code, observe/manage executions, and read/search their output.
Run raw Python cells in a persistent IPython kernel; variables, imports, and definitions survive across cells in the same resource.
Control per-cell behavior with
# loommux:directives such as--wait 120and--full-output.Pass valid Apply Patch literals through Python cells as ordinary strings.
View server/kernel status: workspace, interpreter, kernel PID, busy state, and current or recent execution.
Inspect execution status and metadata by execution number or the auto-selected current/recent record.
Read output streams (
combined,stdout,stderr,result,traceback) with inclusive line ranges and per-line character clipping.Search retained output using literal, regex, or auto matching, with case control and context lines.
Wait for an execution to finish with a timeout, without interrupting the running cell.
Interrupt the currently running execution.
Restart/reset the IPython kernel while preserving execution history and the resource-local execution sequence.
Use private or named shared kernel resources, with lease-based lifecycle management.
Run over stdio or Streamable HTTP, with content-only results by default or optional structured results.
Provides tools to run and manage persistent IPython kernel sessions, enabling code execution, output inspection, and kernel lifecycle management similar to a Jupyter notebook environment.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@loommuxrun Python code to sum numbers from 1 to 10"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
loommux
loommux is a Model Context Protocol (MCP)
server for persistent, inspectable IPython work. A loommux server owns logical
kernel resources on behalf of MCP sessions. Each resource has an independent
namespace, execution history, client lease set, and replaceable kernel process.
Python variables, imports, and definitions survive from one submitted cell to
the next inside that selected resource.
The project is for MCP clients and agents that need more than a one-shot subprocess. It makes a running cell observable without losing it: callers can wait later, inspect its state, read a selected output stream by line range, search retained output, interrupt the active cell, or restart the kernel.
What It Provides
Session-private kernel resources by default and explicitly named shared resources when clients need one collaborative namespace.
One persistent IPython session, execution sequence, and retained history per logical resource.
Activity or standard MCP-ping leases with automatic orphan reclamation.
A strictly increasing positive integer
executioncoordinate for every accepted cell during its logical resource's lifetime.In-memory output retained separately as
combined,stdout,stderr,result, andtracebackstreams.IOPub-order
combinedoutput, including IPython-styleOut[execution]:labels for display results.Terminal-formatted IOPub text normalized into ordinary append-only text transcripts before it reaches public output.
A non-blocking execution model: a tool-call timeout ends only that MCP call; it does not terminate the Python cell.
Explicit interrupt and kernel-reset operations, with preserved historical execution records after a reset.
A single MCP entrypoint with content-only defaults and an explicit structured result mode.
loommux is intentionally not a multi-user notebook service, a durable job
queue, or a sandbox. Kernel state and execution records are memory-only and
belong to their logical resource; server shutdown retires every resource.
Related MCP server: LLM Python Code Sandbox
Requirements And Installation
loommux requires Python 3.13 or newer. The installed package brings the runtime dependencies needed to launch an IPython kernel.
python -m pip install loommuxWindows
Native Windows support covers Windows 10 and Windows 11 with CPython 3.13 or newer. Install into the interpreter that the MCP host will use:
py -m pip install loommuxThe installed command is loommux.exe. Point an MCP host directly at that
executable rather than through a shell wrapper, and use an absolute Windows
workspace path for cwd:
{
"mcpServers": {
"loommux": {
"command": "C:\\workspace\\.venv\\Scripts\\loommux.exe",
"args": ["--result-mode", "structured"],
"cwd": "C:\\workspace"
}
}
}loommux launches the kernel with the same interpreter as loommux.exe, keeps
its IPython and Jupyter state in a private temporary directory, and uses a
Windows Job Object so restart and server shutdown also end child
processes launched by the kernel. A submitted cell remains arbitrary Python:
commands inside that cell must target the operating system on which the kernel
is running. WSL is a separate Linux deployment, not a substitute for native
Windows coverage. Because IPython kernels do not accept Ctrl+C through this
entry point on Windows, interrupt replaces the private kernel after
marking the active cell interrupted; later cells use the fresh kernel.
The package installs one console command:
loommux content-only results over Studio stdio
loommux --server content-only results over Streamable HTTPloommux uses an MCP Studio or host's child-process stdio connection by
default. --server starts a Streamable HTTP service with configurable --host,
--port, and --path. Both forms return only content by default.
--result-mode structured is the explicit opt-in that additionally returns
structuredContent.
For development, use uv:
git clone https://github.com/MichengLiang/loommux.git
cd loommux
uv sync --locked --group devDefault Studio Connection
loommux defaults to MCP stdio transport and returns model-oriented content
only. This is the Studio-compatible default and prevents a client from
preferring raw structuredContent over the presentation intended for the
model.
The server process's working directory is the default kernel workspace. A
generic MCP configuration therefore assigns the desired project directory as
the command's cwd:
{
"mcpServers": {
"loommux": {
"command": "loommux",
"cwd": "/absolute/path/to/your/workspace"
}
}
}The exact enclosing configuration shape depends on the MCP host. The material
facts are that the host starts loommux, the process runs in the intended
workspace, and the Python environment running loommux can import
ipykernel.
On startup, loommux resolves its workspace, builds a kernel launch from the server interpreter, and starts the kernel before accepting MCP tools. Server startup fails rather than exposing a partially configured execution service.
HTTP Server And Structured Opt-In
loommux --server exposes the same tools, input schemas, execution behavior,
and model-readable text over Streamable HTTP. It remains content-only unless
--result-mode structured is explicitly supplied.
Start a loopback-only content-only HTTP service from the workspace you want the kernel to use:
cd /absolute/path/to/your/workspace
loommux --server --host 127.0.0.1 --port 8801 --path /mcpIts MCP endpoint is http://127.0.0.1:8801/mcp. --result-mode structured is
available only when a client genuinely needs the raw status object:
loommux --server --result-mode structured --host 127.0.0.1 --port 8801 --path /mcpMCP Studio, Inspector, and other Streamable HTTP clients use the same endpoint URL. There is no separate Studio protocol. The complete matrix, subprocess configuration examples, and security guidance are in MCP Connection Guide.
HTTP is a deployment boundary, not a different execution model: the
tools, resource-local execution sequences, output streams, workspace
resolution, and presentation rules are the same as the stdio server. The HTTP
application also serves a resource console at / and operational JSON APIs
under /api. Binding it beyond the local machine exposes arbitrary Python
execution and requires network controls and authentication outside loommux.
Kernel Resources And Client Leases
An ordinary MCP connection selects a resource without changing the eight-tool
surface. Without an additional header, its MCP Session ID addresses a private
workbench. X-Loommux-Resource selects a named shared workbench; every
participating MCP session still holds an independent lease.
The server publishes the current lease policy at /api/lease-policy. The
included loommux.client.LeaseAwareClient discovers and pins that policy
generation before initialization and sends standard MCP ping while a
heartbeat lease is active:
from loommux.client import LeaseAwareClient
async with LeaseAwareClient(
"http://127.0.0.1:8801/mcp",
"analysis-agent",
resource_name="shared-analysis",
) as client:
result = await client.call_tool(
"run_cell",
{"freeform": "value = 1\nprint(value)"},
)The operator label is optional. Omitting it or passing None leaves the
X-Loommux-Operator header absent, so the server uses its session-derived
fallback display name.
The complete runnable client-cooperation example is in examples/lease-aware-client.
The complete identity, lifecycle, policy, orphan-execution, control API, and source-ownership contract is documented in Kernel Resource Daemon Design.
Workspace And Interpreter
Workspace selection occurs when the server process starts. loommux does not provide a runtime tool that changes the workspace or Python interpreter.
By default, the server's current working directory is the workspace and the
interpreter that launched loommux launches the kernel. This preserves the
same virtual environment that imported loommux and avoids an ambiguous second
Python-selection mechanism.
LOOMMUX_WORKSPACE_CONFIG is the only optional workspace configuration
entrance for the Python/IPython loommux server. Set it to the absolute path of
a trusted Python resolver defining resolve_workspace(launch_cwd: Path) -> Path | str. loommux never searches or executes loommux_workspace.py, .codex, or
any other workspace-tree file or marker. Resolver failures prevent startup
before tools are available.
The generic and Codex resolver examples are inert until explicitly selected through that environment variable. See workspace configuration and the canonical Coding Agent Control Plane Design for the complete contract.
Execution Model
Each accepted run_cell submission creates an execution record with one
public identity:
execution: positive integerThe sequence begins at 1 for a newly provisioned logical resource and
increases only when a cell is accepted. Loommux accepts one running cell at a
time inside each resource; separate resources may execute concurrently. A
second run_cell call against the same busy resource is rejected with
status="busy"; it is not queued.
An execution can be running, completed, error, interrupted, or
killed. Python errors are recorded execution states, not MCP transport
failures. The error summary identifies the exception while the collected
traceback remains available from the execution's traceback stream.
The integer is owned by loommux rather than copied from IPython's kernel-local
execution counter. It stays stable for the logical resource, including across
restart. When a cell yields a text/plain display result, loommux
authors the combined log with its own stable coordinate:
Out[5]: 42After a reset, the replacement IPython kernel may have restarted its internal counter, but the next loommux execution number remains consecutive and prior records remain readable.
MCP Tools
All tools below are exposed by the single loommux entrypoint. Calls that take an
optional execution share one selection rule: an explicitly supplied positive
integer selects that record; otherwise loommux selects the current running
record, then the most recently accepted record. With neither, the tool returns
execution_not_found.
Tool | Purpose |
| Submit one loommux IPython cell to the persistent kernel and wait for its initial result. |
| Inspect the workspace, its authored source category, interpreter, kernel PID, busy state, and current or recent execution. |
| Inspect lifecycle and diagnostic metadata without returning the full output body. |
| Read a selected execution stream, optionally by line range and with per-line clipping. |
| Search a selected output stream using literal text or regular expressions. |
| Wait for an execution without interrupting it. |
| Send an interrupt signal to the current running execution. |
| Restart the kernel while preserving execution records and the resource-local sequence. |
Submitting A Cell
run_cell accepts one freeform loommux IPython cell. Ordinary source and
the resulting Python values of validated Apply Patch literals are available to
later cells in the same selected logical resource.
import math
radius = 3
math.pi * radius**2Apply Patch Literals
Use an outer triple-double-quoted literal containing a valid Apply Patch
program to pass patch text through a Python cell. The exact *** Begin Patch
and *** End Patch markers, valid file-operation controls, and hunk lines are
validated before loommux converts the literal into an equivalent Python str.
The patch text remains part of the resulting value, including embedded triple
quotes, backslashes, and braces.
patch = f"""
*** Begin Patch
*** Update File: example.py
@@
+message = r"""
+hello
+"""
*** End Patch
"""patch contains the complete Apply Patch program. The outer r and f
prefixes do not apply raw-string or f-string interpretation to the converted
patch text. Marker-shaped text with invalid patch grammar is ordinary Python
source and is not converted. See Apply Patch Literal Transform Design
for the full contract and acceptance rules.
The default initial wait for one MCP call is 10 seconds. A cell can make its complete submission policy explicit with a Loommux control directive:
# loommux: --wait 120
build_report()--wait only changes how long that run_cell call waits. It does not limit
Python runtime, interrupt the cell when time expires, modify later calls, or
add a variable to the kernel. A malformed or duplicated option returns
invalid_loommux_directive before an execution is allocated or source is
submitted. Valid directive lines are transport-only metadata: Loommux consumes
them before IPython receives the cell, so they do not appear in IPython history
or execution records. A directive may therefore precede a %% cell magic.
When the call returns while the cell is still running, use wait,
execution_status, read_output, search_output,
interrupt, or restart to continue observing or controlling the
same execution.
Output Streams And Long Output
Each execution retains five append-only text projections:
Stream | Contents |
| stdout, stderr, display results, and tracebacks in IOPub arrival order. |
| Python stdout stream events. |
| Python stderr stream events. |
|
|
| Traceback text from Python error events. |
Completed combined output of at most 5,000 o200k_base tokens is returned by
run_cell and wait beneath an In [execution]: header. A display result then
keeps its IPython-style Out[execution]: line; a silent cell returns only the
input header, and stdout or traceback remains in its original combined order.
For an execution that is still running, or for an unmarked terminal execution
whose combined output exceeds 5,000 tokens, the response retains the record but
omits the full body. Its omission notice reports the combined output's total
lines, Unicode code point characters, and UTF-8 size using one binary unit (B,
KiB, MiB, and so on). The structured run_cell, wait, and
execution_status surfaces expose the corresponding exact counts as
output_total_lines, output_total_characters, and
output_total_utf8_bytes. The output is not discarded; the notice itself names
the recovery paths, and the caller reads or searches the retained text through
read_output and search_output, or requests the complete body with the
# loommux: --full-output directive. Token counting is required for this
automatic delivery policy; if the o200k_base tokenizer cannot be loaded, the
call fails instead of silently changing to another limit.
read_output uses start:stop inclusive line coordinates. Positive
endpoints are 1-indexed, endpoints may be omitted, and negative endpoints
count from the end of the selected stream:
:10 first 10 lines
-10: final 10 lines
20:40 lines 20 through 40
3:3 only line 3When the caller has determined that the selected stream must be consumed in
full, omit line_range. read_output returns all of its lines in one
response, so there is no need to divide the read into consecutive small ranges.
max_chars clips each returned line without changing stored text or line
coordinates. search_output supports literal, regex, and auto
matching. In auto mode, loommux treats the query as a regular expression
when it compiles and falls back to literal matching when it does not. Search
results preserve original line numbers, mark matching lines with M, and
mark selected context lines with C.
Requesting Complete Output
When a cell's entire terminal combined output is the intended result, include
--full-output in a Loommux control directive:
# loommux: --full-output
build_report()The option applies only to that execution. Once the execution is terminal, it
bypasses the normal 5,000-token delivery threshold and makes run_cell or a
later wait return the complete collected combined output. It does not cause
partial running output to be returned and does not alter the input or behavior
of read_output and search_output.
The full-output and wait options are independent and may appear in the same directive:
# loommux: --wait 120 --full-output
build_report()They may also be split across two directives:
# loommux: --wait 120
# loommux: --full-output
build_report()Interrupting And Resetting
interrupt requests an interrupt for the current running cell. An
interrupt_sent response only confirms signal delivery; the execution reaches
its final state after the kernel reports IOPub idle.
restart is stronger: it stops the existing kernel and starts a
replacement in the same workspace with the same interpreter. A running record
is marked killed. Reset does not erase stored executions, their output, or
the sequence counter, so historical records can still be read by their
integer execution value and the next accepted cell receives the next number.
Stopping the loommux server retires all resources. Their kernels, namespaces,
execution-record tables, output streams, and sequences are not persisted to
disk. Recycling one resource has the same persistence boundary for that
resource; a subsequently provisioned resource begins a fresh sequence at 1.
Security
Arbitrary Python execution is loommux's central capability. Treat the MCP client, its process account, installed packages, the selected workspace, and any reachable network endpoint as parts of the same security boundary. Give the server access only to files, environments, and network resources the MCP client is authorized to use.
The stdio server is generally the least exposed deployment mode. The HTTP server must never be placed directly on an untrusted network. For a vulnerability in loommux itself, use the private reporting process in SECURITY.md, not a public issue.
Architecture And Documentation
The runtime is deliberately divided into narrow responsibilities:
loommux/
session.py
Owns one persistent IPython namespace, execution identity, selection,
waiting, control operations, and historical execution records.
kernel/
launch.py
Builds the interpreter command, child environment, and private root.
runtime.py
Owns Jupyter kernel process lifecycle and platform containment.
session.py
Correlates IOPub messages with the active execution record.
execution/
record.py
Stores one execution's lifecycle facts and normalized projections.
events.py
Names visible text, image, and delivery-failure events.
logs.py
Provides append-only streams, line ranges, clipping, and search.
terminal.py
Removes terminal controls while preserving chunk boundaries.
submission/
cell.py
Combines directive consumption and source transformation into one
prepared cell passed to the session.
directives.py
Parses and consumes submission-owned control directives.
apply_patch_literals.py
Converts valid Apply Patch literals before kernel submission.
mcp/
factory.py
Registers MCP tools that consume the protocol-neutral session.
result.py
Projects session facts into MCP text, structured, and image content.
presentation.py
Renders MCP-facing model-readable text.
entrypoints.py and server.py
Select MCP transport and expose the installed command.The workspace authorization and resolution modules remain at the package boundary until their independent configuration work is complete. They are deliberately not mixed into this structural change.
The top-level loommux package imports only the protocol-neutral Python
session API. FastMCP is entered explicitly through loommux.mcp; the runtime
does not depend on its transport consumer.
The current public contract is documented in Coding Agent Control Plane Design. Focused references cover freeform cell control, complete-output control, workspace configuration, and the changelog.
Development And Release Checks
Run the Python checks from the repository root:
uv run pytest
uv run ruff check src tests examples
uv run basedpyright src
uv build --out-dir dist
uv run twine check dist/*The project metadata declares this README as the package readme:
[project]
readme = "README.md"Consequently, the same document is rendered on PyPI when a new release is built and uploaded. The explicit source-distribution allowlist includes this file, the runtime package, tests, and public documentation while excluding workspace-only material.
See CONTRIBUTING.md for contribution expectations.
License
Copyright 2026 MichengLiang.
loommux is licensed under the Apache License, Version 2.0.
Available Tools
8 toolsexecution_statusA
返回一个 execution 的状态与元数据,不返回完整输出正文。
选择规则
提供 execution 时,只选择该正整数记录。省略时,先选择当前
running 记录;不存在 running 记录时,选择最近一次被接受的记录;
两者都不存在时返回 execution_not_found。
| Name | Required | Description | Default |
|---|---|---|---|
| execution | No | 要查看的正整数执行编号。省略时使用当前记录,随后 使用最近记录。 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of disclosing behavior. It does disclose the return type (status/metadata, not full output) and a specific error condition, but it does not explicitly state whether the operation is read-only, whether it has side effects, or any other behavioral constraints such as rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-organized, using a short introductory sentence followed by a clear '选择规则' section. Every statement serves a useful purpose, and there is no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description explains what the tool returns at a high level and gives the selection rules and error condition, which is enough to call it. However, there is no output schema and the description does not enumerate the specific status values or metadata fields returned, leaving the response shape somewhat underspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already fully documents the single parameter, including its type, nullability, default, and meaning. The description reinforces this by explaining the exact fallback resolution order when the parameter is omitted, adding clear value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool returns execution status and metadata and explicitly excludes the full output body, which distinguishes it from output-reading tools. However, it does not explicitly differentiate itself from the sibling tool named 'status', so some ambiguity remains.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit selection rules for the 'execution' parameter: use the provided ID, fall back to the current running execution, then to the most recent accepted execution, and return 'execution_not_found' if none exist. It gives clear operational guidance for the parameter, though it does not discuss when to prefer this tool over sibling tools other than implying that full output is obtained elsewhere.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
interruptA
向当前正在运行的 execution 发送 kernel 中断信号。
中断语义
该工具只作用于当前 running 记录。信号已发送不等同于记录已终态:
kernel 到达 IOPub idle 后,记录才会报告 interrupted、
error 或其他最终状态。kernel 空闲时返回 idle。
Returns:
已发送信号时返回目标 execution;kernel 空闲时返回 idle。
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full responsibility for transparency. It explains the interrupt semantics, including that sending the signal does not immediately finalize the record, and describes the return behavior in different states. This gives a complete picture of the tool's side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured, starting with the primary action and then providing semantic details. It is not overly verbose and conveys necessary information efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity and lack of output schema, the description is sufficiently complete. It covers the action, side effects, and return values. No critical information appears to be missing for an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has no parameters, so there is nothing to explain. According to the rubric, a baseline of 4 is appropriate for zero parameters, and the description does not need to add any parameter-related meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action: sending a kernel interrupt signal to the currently running execution. It also explains the intended effect, leaving no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides guidance by specifying that the tool only affects the current running record. This implies it should be used when there is an active execution, and it clarifies the expected behavior when the kernel is idle, helping the agent decide when to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_outputB
读取一个 execution 的指定输出流。
选择与流
execution 的选择规则与 execution_status 相同。stream
只能为 combined、stdout、stderr、result 或
traceback。
行坐标
line_range 使用 start:stop。正数端点是从 1 开始的流行号,
stop 包含在范围内;端点可省略,负数端点从所选流尾部计数。:10
读取前十行,-10: 读取后十行,3:3 只读取第三行。
完整读取
调用者已确定需要完整消费所选流时,省略 line_range。工具会在一次响应
中返回全部行,无需把阅读拆成连续小范围。
| Name | Required | Description | Default |
|---|---|---|---|
| stream | No | 输出流;默认 ``combined``,其余值为 ``stdout``、``stderr``、 ``result`` 与 ``traceback``。 | combined |
| execution | No | 要读取的正整数执行编号。省略时使用当前记录,随后 使用最近记录。 | |
| max_chars | No | 每个返回行允许显示的最大字符数;必须为正数。超出 部分只在响应中裁切,不改变已保存文本或行坐标。 | |
| line_range | No | ``start:stop`` 行范围;已确定需要完整消费所选流时省略, 工具会一次返回全部行,无需拆分为多个小范围。 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the truncation behavior of max_chars (only in response, does not alter saved text or line coordinates). It does not mention any other side effects, permissions, or that it is a read-only operation, so transparency is partial.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured into sections (选择与流, 行坐标, 完整读取) which aids readability. However, some repetition occurs (e.g., line_range explanation appears both in the main text and in the parameter schema). It is not overly verbose but could be more concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description conveys that the tool returns lines of output (via '返回行' and truncation context) and explains how to request subsets. Since there is no output schema, this explanation is sufficient for basic usage, but it does not detail the exact return structure (e.g., whether it returns a list, the format of each line). Overall, it is complete enough for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers all 4 parameters with descriptions, achieving 100% coverage. The tool description repeats some parameter details but does not add significant new meaning beyond the schema. Baseline 3 is appropriate given the high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: reading a specified output stream of an execution. The verb '读取' (read) is specific and the resource 'execution 的输出流' is unambiguous. It does not explicitly differentiate from sibling tools like search_output, but the core purpose is clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides some usage guidance, such as how to select the execution (rules same as execution_status) and when to omit line_range for full consumption. However, it does not explicitly mention when to use this tool over alternatives like search_output, leaving some ambiguity for an agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
restartA
重启 IPython kernel,并保留当前持久 IPython 会话的 execution 历史。
重置边界
若存在 running execution,它会先标记为 killed;随后旧 kernel
停止并创建替代 kernel。已存在的记录及其输出流仍可按原整数
execution 读取,下一次接受的 cell 使用连续的下一个编号。
Returns: 新 kernel 的状态与 PID;重启失败时返回 workspace 或 kernel 启动错误。
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description outlines the behavioral sequence (killing running executions, stopping old kernel, creating new kernel) and explicitly notes that execution history is preserved. It also addresses the edge case of a running execution. However, it does not mention potential side effects on non-persistent state or any error handling beyond return values.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, well-structured with a clear purpose and a separate section for the reset boundary. It avoids unnecessary verbosity while covering key behavioral aspects.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description includes explicit return values (new kernel status and PID, or error on failure) and covers the main execution conditions. It is complete for an agent to understand the tool's output without additional information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has no parameters, and the schema coverage is 100%, so the baseline is 3. The description does not need to explain parameters, and it correctly omits them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: restart the IPython kernel while preserving execution history. It specifies the verb (restart) and the resource (IPython kernel), and it is distinct from sibling tools like run_cell or interrupt.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly mention when to use this tool versus alternatives. It implies usage for restarting the kernel but lacks guidance on scenarios where this is preferable to other tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_cellA
向持久 IPython kernel 提交一个原始 IPython cell。
请你使用 IPython 的思想来优雅使用本系列工具。
输入
接受一段 loommux IPython cell 源码。普通 Python 文本使用默认策略;若作者
需要声明本次 cell 的观察策略,使用位于物理行首的 # loommux: 控制
注释。Loommux 在提交前验证并完全消费有效控制注释,因此它们不会进入
IPython history 或下游 cell-magic body。变量、导入和其他 namespace 状态会
与当前持久 IPython 会话中的后续 cell 共享。
等待上限
本次调用默认最多等待 10 秒。# loommux: 的 --wait 正有限十进制
值只覆盖本次调用的等待上限::
# loommux: --wait 120
build_report()# loommux: --wait 120 与 # loommux: --full-output 可写在同一条
或不同的控制注释中。重复选项、未知选项、缺少值或非正值会返回
invalid_loommux_directive,不会分配 execution 或提交 kernel。等待
到期不会中断仍在运行的 cell;directive 不改变 Python runtime 或后续
调用的等待上限。
完整输出
若任一有效 # loommux: 控制注释包含 --full-output,该 execution
在终态时直接交付完整 combined 正文,不受默认 5,000-token 交付阈值限制::
# loommux: --full-output
print("\n".join(generate_manifest()))--wait 与 --full-output 可以组合为
# loommux: --wait 120 --full-output。这些选项只作用于本次
execution。有效控制注释在提交前被 Loommux 完全消费,不会进入 IPython
history、cell magic body 或 execution 响应。在明确需要完整阅读某些信息,
例如阅读某些文件、资料时,使用该选项避免无意义的反复阅读开销。
图像展示
IPython display() 产生的 PNG、JPEG、WEBP 或单帧 GIF 图像会按输出
顺序直接交付给agent。普通 display(image) 使用高视觉细节;本次展示
需要整体确认或密集文字时,分别书写 display(image, metadata={"detail": "low"}) 或 display(image, metadata={"detail": "original"})。detail 只作用于这一处 display() 调用。
执行编号与后续操作
每个已接受的提交都会获得一个连续递增的正整数 execution。后续工具
使用它定位当前持久 IPython 会话中的这次执行。若执行仍在运行,或未标记
--full-output 的 combined 输出超过 5,000 token,响应不携带完整输出
正文;行数、Unicode code point 字符数和 UTF-8 字节数描述同一份
normalized combined 文本。使用 wait 等待,使用 execution_status
查看状态,使用 read_output 或 search_output 读取或搜索保留的输出。
| Name | Required | Description | Default |
|---|---|---|---|
| freeform | Yes | 原始 IPython cell 源码文本。 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure, and it does so thoroughly. It discloses the default 10-second wait, how '--wait' overrides it, that control comments are fully consumed and do not enter history or cell-magic bodies, that waiting expiry does not interrupt a running cell, the 5,000-token output truncation threshold, the effect of '--full-output', image display behavior with detail metadata, and the execution numbering scheme. This is comprehensive transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections (输入, 等待上限, 完整输出, 图像展示, 执行编号与后续操作). Every section adds essential information, and the main purpose is front-loaded in the first sentence. It could be slightly more concise, but the organization makes it easy to navigate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one parameter and no output schema, the description is exceptionally complete. It covers input format, control directives, wait behavior, output truncation and the full-output override, image display options, execution numbering, and explicitly mentions the sibling tools for subsequent operations. An agent has all the information needed to invoke run_cell correctly and understand its effects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only describes 'freeform' as '原始 IPython cell 源码文本' (raw IPython cell source text). The description adds significant meaning by explaining the 'loommux:' control comment syntax, including '--wait' and '--full-output' options, their combinations, validation behavior, and how they affect the execution. This goes far beyond the schema's minimal description, giving the agent actionable details for constructing valid input.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action: '向持久 IPython kernel 提交一个原始 IPython cell' (submit a raw IPython cell to a persistent kernel). It distinguishes itself from sibling tools by positioning itself as the submission entry point, with siblings like wait, execution_status, read_output, and search_output described as subsequent operations for handling the execution.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for using the tool, including when to use the '--full-output' option (when full reading of information like files or materials is needed to avoid repeated reading overhead) and how to combine options. It also implies that for checking status or reading output, one should use the sibling tools (wait, execution_status, read_output, search_output), but it doesn't explicitly state when not to use run_cell itself. The guidance is implicit but effective.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_outputA
在一个 execution 的指定输出流中搜索文本或正则表达式。
选择与匹配
execution 的选择规则与 execution_status 相同;可选的
stream 值与 read_output 相同。query_mode="literal"
按字面文本匹配,query_mode="regex" 要求 query 是有效正则,
query_mode="auto" 先按正则解释,仅在编译失败时回退到字面匹配。
命中上下文
每条命中保留原始所选流行号,并以 M 标记;前后上下文行以
C 标记。
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | 要匹配的字面文本或正则表达式。 | |
| stream | No | 输出流;默认 ``combined``,其余值为 ``stdout``、``stderr``、 ``result`` 与 ``traceback``。 | combined |
| execution | No | 要搜索的正整数执行编号。省略时使用当前记录,随后 使用最近记录。 | |
| max_chars | No | 每个返回行允许显示的最大字符数;必须为正数,且只 裁切响应文本。 | |
| query_mode | No | 匹配解释方式:``literal``、``regex`` 或 ``auto``; 默认 ``auto``。 | auto |
| ignore_case | No | 为 true 时忽略大小写。 | |
| context_after | No | 每个命中之后附加的相邻行数;必须大于或等于 0。 | |
| context_before | No | 每个命中之前附加的相邻行数;必须大于或等于 0。 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description does not include any annotations, so it carries the full burden of disclosing behavioral traits. It explains how the tool selects executions (current or most recent when omitted), how matching modes work, and how context lines are added. However, it does not disclose potential side effects (e.g., it is read-only), whether it modifies any state, or any error conditions. The description is mostly about operation mechanics, not behavioral caveats, so it partially covers transparency but leaves gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear section headers for '选择与匹配' and '命中上下文', and the prose is concise. Each sentence provides useful information without redundancy. The description is appropriately sized for the complexity of the tool, covering key aspects without unnecessary verbosity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of this tool (search with modes, context lines, stream selection) and no output schema, the description is quite complete. It provides enough information for an agent to understand how to use it correctly. It references sibling tools for parameter selection, which reduces the need for repeating those rules. However, it could mention that this tool is read-only (non-destructive) and what the return format looks like (a list of matches with context), but the absence of an output schema is somewhat compensated by the description. Minor gaps exist but overall it's sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers 100% of the parameters with descriptions. The description adds further semantics by explaining the selection rules for 'execution' (same as execution_status) and 'stream' (same as read_output), which are not fully apparent from the schema alone. It also clarifies the behavior of query_mode with examples (literal vs regex vs auto fallback). However, some parameters like max_chars have a schema description already, and the additional description of truncation is consistent but not substantially new. Overall, the description adds meaningful context beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: searching text or regex in specified output streams of an execution. It names the resource ('execution'), the action ('search'), and the target (output stream), which distinguishes it from sibling tools like read_output (which reads without searching) and execution_status (which retrieves status). However, it does not explicitly name a sibling tool for contrast, though the references to read_output and execution_status in the description imply differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: it explains how to select the 'execution' parameter (same rules as execution_status), how to choose the 'stream' parameter (same values as read_output), and how query_mode behaves with literal vs regex vs auto. It also explains context lines and max_chars truncation. However, it does not explicitly state when to use this tool instead of alternatives like read_output, though the contrast is implied by describing search-specific features.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statusB
返回 workspace、kernel 与最近执行记录的观察状态。
状态范围
返回当前 IPython 工作台启动时解析的 workspace、其
workspace_resolution 来源
类别、Python 解释器、kernel PID、kernel 是否已启动,以及 kernel 是否
正忙。workspace_resolution 只能是 launch_cwd 或
explicit_config;它不公开 resolver 的路径或内容,也不公开 kernel
session 的 private runtime root。忙碌时 current_execution 是正在
运行的正整数执行编号;空闲时 recent_execution 是最近一次被接受的
执行编号。kernel-local execution count 只用于诊断,不能用来选择
loommux execution。
.. code-block:: text
可见标签 In [N]
=
loommux execution N
!=
IPython kernel-local execution_countIPython 通过原生 ZMQ 协议连接,拥有完整能力。
Returns: 当前 IPython 工作台与 kernel 的状态快照。
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the transparency burden. It is unusually explicit about what the tool does not expose (resolver path/content, private runtime root) and that execution counts are diagnostic-only, which gives users a clear behavioral boundary.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized with headings and a code block, but it repeats the same summary sentence ('Returns workspace, kernel, and recent execution status') multiple times. Some redundancy makes it slightly less concise than necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description supplies substantial detail about return fields, including enum values for workspace_resolution, busy/idle semantics, and the meaning of execution IDs. It is not perfectly precise about JSON structure but is sufficiently complete for a status tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema coverage is 100%, so the baseline score applies. There are no parameter semantics to explain beyond the empty schema, and the description does not need to add more.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns workspace, kernel, and recent execution status, using a specific verb and resource. It does not explicitly distinguish itself from the sibling execution_status tool, but the detailed field list makes its purpose evident.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not say when to prefer this tool over alternatives such as execution_status or read_output. It provides no usage context, prerequisites, or when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
waitA
等待一个 execution 结束,或在指定时限到达时返回其当前状态。
选择与等待
execution 的选择规则与 execution_status 相同。等待
到期只结束本次工具调用,不中断 Python cell。后续可再次调用本工具,
或用 read_output 查看已到达的输出。
完整输出交付
当所选 execution 的原始 run_cell 请求含有效 --full-output 且已达到
终态时,本工具直接返回完整 combined 正文,不应用默认 5,000-token
省略。该策略仅保留为 private runtime state;仍在运行的 execution 继续
返回 running,而非不完整正文。
| Name | Required | Description | Default |
|---|---|---|---|
| execution | No | 要等待的正整数执行编号。省略时使用当前记录,随后 使用最近记录。 | |
| timeout_seconds | No | 本次调用最多等待的正数秒数;默认 30 秒。 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behavioral traits: it waits for completion or timeout, does not interrupt the cell, can be called again, and returns full output under certain conditions. Without annotations, this is good transparency, though it could mention potential side effects or error cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections, but it contains some redundancy, particularly the 'full output delivery' section which repeats similar wording about full-output and 5,000-token omission. Still, it's relatively concise and organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple tool with two parameters, the description covers the main aspects: what it does, selection rules, timeout behavior, and output handling. No output schema exists, so return value details are not required. It's complete enough for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Both parameters (execution and timeout_seconds) are described in the schema with default values and meanings. The description adds context about selection rules and timeout behavior, fully complementing the schema's 100% coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool waits for an execution to finish or returns its current status after a timeout. It names the specific resource (execution) and the action (wait/return status), though it doesn't explicitly contrast with sibling tools like execution_status, which is a minor gap.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explains when to use the tool: to wait for an execution, and mentions that timeout doesn't interrupt the Python cell. It also references read_output as an alternative for viewing output later. However, it doesn't explicitly say when to prefer this over execution_status or other siblings, though the context is implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
16 tool updates
v0.1.13- Added
execution_status - Added
interrupt - Removed
interrupt_python - Removed
python_execution_status - Removed
python_status - Added
read_output - Removed
read_python_output - Removed
reset_python - Added
restart - Added
run_cell - Removed
run_python - Added
search_output - Removed
search_python_output - Added
status - Added
wait - Removed
wait_python
8 tool updates
v0.1.11- First observed
interrupt_python - First observed
python_execution_status - First observed
python_status - First observed
read_python_output - First observed
reset_python - First observed
run_python - First observed
search_python_output - First observed
wait_python
TDQS
Scored across 8 tools
Each tool has a distinct role in the IPython execution lifecycle: submit, wait, interrupt, restart, global status, per-execution status, read, and search. The only real ambiguity is between status and execution_status, which are easy to confuse by name even though one is a workspace/kernel snapshot and the other is per-execution.
Names are all lowercase snake_case and group logically: action tools are imperative verbs (run_cell, wait, interrupt, restart) and retrieval/query tools are noun or verb_noun forms (status, execution_status, read_output, search_output). The mix of bare verbs and noun-only status names is a minor deviation from a strict verb_noun pattern but remains predictable.
Eight tools is well-scoped for a persistent IPython kernel server: submission, lifecycle control, and output retrieval each have dedicated tools without redundancy. No tool feels superfluous.
The core lifecycle is covered: run, wait, interrupt, restart, status, and output reading/searching. A minor gap is the lack of a way to list or enumerate past executions beyond the most recent one, which agents must track themselves.
Maintenance
Related MCP Connectors
Persistent memory and cross-session learning for AI coding assistants (hosted remote MCP).
System-of-record notebook for AI coding agents: pages, datastores, tasks, skills over MCP.
Your org's AI agents, tasks, runs, search, and brain files as MCP tools and resources.
Agent Replay Debugger MCP — record every agent step + deterministic replay. Step-debugger for
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides persistent IPython shell sessions per conversation with DataFrame-centric architecture, enabling stateful data analysis, CLI tool execution, and integration of external MCP servers within the same workspace context.23Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables LLMs to execute Python code in isolated sandboxes with file operations and MCP integration, supporting multi-round execution and plot capture.1-
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to execute Jupyter notebook cells with persistent kernel state, output persistence, and structured JSON control surface.2-
- FlicenseNot gradedqualityBmaintenanceProvides a persistent Jupyter kernel for executing code, inspecting variables and dataframes, and checking SQL query plans, enabling agents to work with stateful Python sessions.-