mcp-async-repl
Async Python REPL + Shell execution for MCP. Provides persistent state, background jobs, interactive input() bridging, and crash isolation in a single server.
README
mcp-async-repl
Async Python REPL + Shell execution for MCP. Persistent state, background jobs, and interactive input() bridging — in a single server.
The only MCP server that combines a crash-isolated persistent Python worker, true async shell execution, stdin interaction, and job lifecycle management in one package.
What makes this different
Every other Python REPL MCP server runs exec() in the server process and blocks on long-running code. This one doesn't.
- Crash-isolated Python worker — runs in a separate subprocess with a JSON protocol over stdin/stdout. If your code segfaults, the MCP server stays alive.
- True async from the start — both shell and Python execution return job IDs immediately if they take >2s. Poll with status tools. Never blocks the server.
input()bridging — user code can callinput("prompt")and the server surfaces awaiting_inputstatus. Feed text viasend_python_input()to unblock it. No other REPL MCP has this.- Persistent state — variables survive across
execute_python()calls until you restart the worker. - Shell + REPL in one server — async shell commands with stdin support alongside the persistent Python worker. No need for two separate MCP servers.
- Auto venv via uv — creates and manages a
.venvautomatically. No Docker required.
Install
# Run directly with uvx (no install needed)
uvx mcp-async-repl
# Or install from PyPI
pip install mcp-async-repl
Configuration
Add to your MCP client config:
{
"mcpServers": {
"async-repl": {
"command": "uvx",
"args": ["mcp-async-repl"]
}
}
}
With a custom venv path:
{
"mcpServers": {
"async-repl": {
"command": "uvx",
"args": ["mcp-async-repl"],
"env": {
"REPL_VENV_DIR": "/path/to/your/venv"
}
}
}
}
Claude Desktop
Add to claude_desktop_config.json:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Claude Code
claude mcp add async-repl uvx mcp-async-repl
Cursor
Add to .cursor/mcp.json or ~/.cursor/mcp.json.
Tools (9 total)
Python REPL
| Tool | Description |
|---|---|
execute_python |
Execute code in a persistent worker. Returns immediately if >2s. Supports input(). |
send_python_input |
Feed text to a pending input() call in the worker. |
check_python_status |
Poll status, stdout, stderr, and input prompts for the current job. |
list_variables |
Inspect all variables in the persistent session. |
restart_python_worker |
Kill and restart the worker. Clears all state. |
Async Shell
| Tool | Description |
|---|---|
execute_command_async |
Run any shell command in the background. Returns a job ID. |
send_command_input |
Send stdin text to a running shell job (e.g. y\n, passwords). |
check_job_status |
Poll status and output of a background shell job. |
Package Management
| Tool | Description |
|---|---|
install_package_async |
Install a pip package via uv in the background. |
Example session
Full 8-step test run, executed by an LLM agent via Mux-Swarm:
> Test the Python REPL MCP by running these steps in order:
>
> 1. Execute: x = 42; print(f"x is {x}")
> 2. Execute: y = x * 2; print(f"y is {y}")
> 3. List variables
> 4. Execute: name = input("Enter your name: ")
> 5. Send python input: Jonathan
> 6. Execute: print(f"Hello {name}, x={x}")
> 7. Execute: import time; [print(f"tick {i}") for i in range(5) if not time.sleep(1)]
> 8. Restart the python worker, then list variables
── MuxAgent ────────────────────────────────────────────────────────────
## Step 1: Execute initial code with state and stdout
✅ Step 1 passed — State persisted, stdout captured: `x is 42`
## Step 2: Verify x persisted from step 1
✅ Step 2 passed — `x` persisted correctly: `y is 84`
## Step 3: List variables
✅ Step 3 passed — Variables `x` and `y` are present
## Step 4: Execute code with input() — should return waiting_input status
✅ Step 4 passed — Correctly returned `waiting_input` status with prompt: `'Enter your name: '`
## Step 5: Send python input to unblock
✅ Step 5 passed — Input delivered, status changed to `completed`
## Step 6: Verify name persisted alongside x and y
✅ Step 6 passed — All variables persisted: `Hello Jonathan, x=42`
## Step 7: Execute long-running code — should timeout to background
✅ Step 7a passed — Timed out to background as expected.
✅ Step 7b passed — Background job completed with all ticks: `tick 0` through `tick 4`
## Step 8: Restart python worker, then list variables
✅ Step 8 passed — Worker restarted, variables cleared (empty list returned)
───────────────────────────────────────────────────────────────────────
Summary: All Tests Passed ✅
| Step | Test | Result |
|------|-------------------------------------------|-----------------------------------|
| 1 | State persistence + stdout capture | ✅ `x is 42` |
| 2 | Variable persistence across calls | ✅ `y is 84` (x=42 persisted) |
| 3 | List variables | ✅ `x`, `y` found |
| 4 | input() returns waiting_input | ✅ Status: `waiting_input` |
| 5 | Send input unblocks | ✅ Status: `completed` |
| 6 | All variables persist together | ✅ `Hello Jonathan, x=42` |
| 7 | Long-running → background + status check | ✅ All ticks captured |
| 8 | Restart clears state | ✅ Empty variable list |
Architecture
┌─────────────────────────────────────────────────────┐
│ MCP Server │
│ (mcp-async-repl) │
│ │
│ ┌─────────────────┐ ┌────────────────────────┐ │
│ │ Shell Jobs │ │ Python Worker Manager │ │
│ │ │ │ │ │
│ │ execute_command │ │ ┌──────────────────┐ │ │
│ │ send_input │ │ │ Worker Subprocess│ │ │
│ │ check_status │ │ │ │ │ │
│ │ │ │ │ Main Thread: │ │ │
│ │ Each command │ │ │ stdin loop │ │ │
│ │ runs as an │ │ │ (never blocks) │ │ │
│ │ async subprocess│ │ │ │ │ │
│ │ with job ID │ │ │ Exec Thread: │ │ │
│ │ │ │ │ runs exec() │ │ │
│ │ │ │ │ in daemon │ │ │
│ │ │ │ │ thread │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ Input Queue: │ │ │
│ │ │ │ │ bridges input()│ │ │
│ │ │ │ │ calls to host │ │ │
│ └─────────────────┘ │ └──────────────────┘ │ │
│ └────────────────────────┘ │
└─────────────────────────────────────────────────────┘
The Python worker runs in a separate subprocess communicating via JSON over stdin/stdout. Inside the worker:
- Main thread reads commands from stdin and dispatches them. Never blocks.
- Exec thread runs
exec()in a daemon thread soinput()calls don't starve the command loop. - Input queue bridges
send_python_input()from the host tobuiltins.input()inside user code. When code callsinput("prompt"), the worker emits aninput_requestmessage and blocks on the queue. The host pushes text onto the queue to unblock it.
This means:
- Long-running code doesn't block the MCP server
input()works without a PTY- A crash in user code kills the worker, not the server
- The worker can be restarted cleanly at any time
Environment variables
| Variable | Default | Description |
|---|---|---|
REPL_VENV_DIR |
.venv |
Path to the virtual environment. Created automatically via uv if it doesn't exist. |
How it compares
| Feature | mcp-async-repl | mcp-python (hdresearch) | mcp-python-repl (soufiane-aazizi) | mcp-background-job (dylan-gluck) |
|---|---|---|---|---|
| Persistent Python state | ✅ | ✅ | ✅ | ❌ |
| Async (non-blocking) execution | ✅ | ❌ | ❌ | ✅ |
| Background job polling | ✅ | ❌ | ❌ | ✅ |
input() bridging |
✅ | ❌ | ❌ | ❌ |
| Shell command execution | ✅ | ❌ | ❌ | ✅ |
| Shell stdin interaction | ✅ | ❌ | ❌ | ✅ |
| Crash-isolated worker | ✅ | ❌ | ❌ | N/A |
| Variable introspection | ✅ | ✅ | ✅ | ❌ |
| Package install tool | ✅ | ✅ | ❌ | ❌ |
| Auto venv (no Docker) | ✅ | ❌ | ✅ | ✅ |
Requirements
License
Apache License 2.0
Author
Jonathan Bankston (@jnotsknab)
Built for Mux-Swarm — a CLI-native multi-agent runtime.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。