runloop-mcp
An MCP server that exposes Runloop Devbox operations as tools, enabling AI agents to create and manage Linux sandboxes, execute commands, edit files, snapshot disks, and drive interactive PTY sessions.
README
runloop-mcp
A FastMCP server that exposes Runloop Devbox operations as Model Context Protocol (MCP) tools. It uses the official runloop-api-client Python SDK and lets AI agents (Claude, Cursor, etc.) create and manage isolated Linux sandboxes, run code in multiple languages, drive browsers with Playwright, and execute shell commands.
Features
| Category | Tools |
|---|---|
| Code execution | run_python, run_nodejs, run_deno, run_go, run_rust, run_java, run_cpp, run_c, run_ruby, run_php, run_bash |
| Browser automation | run_browser (Playwright) |
| Shell execution | run_shell |
| Devbox lifecycle | create_devbox, list_devboxes, get_devbox, update_devbox, suspend_devbox, resume_devbox, shutdown_devbox |
| Execution & files | execute_command, execute_command_async, get_execution, wait_for_execution, get_execution_logs, kill_execution, send_execution_stdin, upload_file, download_file, write_file, read_file |
| Snapshots | create_snapshot, list_snapshots, delete_snapshot, get_snapshot_status |
| Interactive PTY & tunnels | pty_connect, pty_send_command, pty_control, create_pty_tunnel, enable_tunnel, get_tunnel_url, remove_tunnel |
Code Execution Tools
Each language has a dedicated tool that automatically manages devbox lifecycle:
- Auto-create/resume: Finds existing devbox for the language or creates a new one
- Auto-suspend: Suspends devbox immediately after code execution (except browser)
- Latest images: Uses Docker Hub
latesttags for all language images - Pull detection: Returns
image_pullingstatus if image is being pulled; retry after 5 seconds
Available language tools
| Tool | Docker Image | Description |
|---|---|---|
run_python |
python:latest |
Run Python code |
run_nodejs |
node:latest |
Run Node.js/JavaScript code |
run_deno |
denoland/deno:latest |
Run Deno code |
run_go |
golang:latest |
Run Go code |
run_rust |
rust:latest |
Run Rust code |
run_java |
eclipse-temurin:latest |
Run Java code |
run_cpp |
gcc:latest |
Compile and run C++ code |
run_c |
gcc:latest |
Compile and run C code |
run_ruby |
ruby:latest |
Run Ruby code |
run_php |
php:latest |
Run PHP code |
run_bash |
ubuntu:latest |
Run Bash scripts |
Blueprints: Runloop does not accept a Docker Hub image name as a blueprint, so every devbox is created from a real blueprint id (
UNIVERSAL_BLUEPRINT_ID/BROWSER_BLUEPRINT_IDinrunloop_mcp/server.py). The account uses two prebuilt blueprints: one universal image containing all language runtimes (python, node, deno, go, rust, java, gcc/g++, ruby, php) and one browser (Playwright) image. They are managed separately byscripts/create_blueprints.py(not part of the MCP server).
All language tools accept:
code(required): The source code to executefile_path(optional): Path to save the code file (default:/home/user/code.<ext>)
Browser automation: run_browser
Uses Playwright (mcr.microsoft.com/playwright:latest) for browser automation.
Parameters:
action(required): One ofnavigate,click,type,fill,screenshot,get_text,get_attribute,wait_for_selector,wait_for_navigation,press,hover,scroll,check,uncheck,select_option,closevalue(optional): Action-specific value (URL, selector, text, etc.)session_id(optional): Browser session ID for multi-step workflows
Lifecycle:
- Does not suspend after most actions (keeps browser alive for session continuity)
- Only suspends when
actionisclose
Shell execution: run_shell
Execute arbitrary shell commands on a devbox.
Parameters:
devbox_id(required): Target devbox IDcommand(required): Shell command to executeshell_name(optional): Named shell for stateful sessions
Requirements
- Python 3.10+
- A Runloop API key — get one at app.runloop.ai
Installation
# Clone
git clone https://github.com/contributory/runloop-mcp.git
cd runloop-mcp
# (Optional) virtual environment
python -m venv .venv && source .venv/bin/activate
# Install
pip install -e .
# The API key is supplied in the MCP URL query parameter; see below.
Usage
HTTP/SSE transport (default)
# Starts an HTTP/SSE MCP server on http://127.0.0.1:8000
runloop-mcp
# or
python -m runloop_mcp
# Bind to all interfaces / custom port
runloop-mcp --host 0.0.0.0 --port 8000
stdio transport (for local MCP clients)
runloop-mcp --transport stdio
Running from Python
from runloop_mcp import mcp
if __name__ == "__main__":
mcp.run(transport="http", host="127.0.0.1", port=8000)
Deployment
main.py is a thin FastAPI app that only hosts the MCP server at
/mcp — all Runloop interaction happens through the MCP tools defined in
runloop_mcp/server.py, not through REST routers. The MCP handler is
registered as a first-class FastAPI route (via app.add_route, no sub-app
Mount), so /mcp is an exact, redirect-free path that FastAPI Cloud serves
reliably.
# FastAPI Cloud / any ASGI host: MCP server at /mcp
uvicorn main:app --reload
# MCP: http://127.0.0.1:8000/mcp (streamable HTTP, exact path - no redirect)
# Health: /health Info: /
# Or run the MCP server standalone (HTTP/SSE by default)
python main.py
# python main.py --transport stdio
Tools available at /mcp (from runloop_mcp/server.py):
| Category | Tools |
|---|---|
| Code execution | run_python, run_nodejs, run_deno, run_go, run_rust, run_java, run_cpp, run_c, run_ruby, run_php, run_bash |
| Browser automation | run_browser |
| Shell execution | run_shell |
| Devbox lifecycle | create_devbox, list_devboxes, get_devbox, update_devbox, suspend_devbox, resume_devbox, shutdown_devbox |
| Execution & files | execute_command, execute_command_async, get_execution, wait_for_execution, get_execution_logs, kill_execution, send_execution_stdin, upload_file, download_file, write_file, read_file |
| Snapshots | create_snapshot, list_snapshots, delete_snapshot, get_snapshot_status |
| Interactive PTY & tunnels | pty_connect, pty_send_command, pty_control, create_pty_tunnel, enable_tunnel, get_tunnel_url, remove_tunnel |
The same wiring is used by main.py — register the StreamableHTTP handler as a
direct route instead of mounting a sub-app:
from fastapi import FastAPI
from runloop_mcp.server import mcp
app = FastAPI(title="Runloop MCP")
mcp_app = mcp.http_app(path="/mcp")
route = next(r for r in mcp_app.routes if getattr(r, "path", None) == "/mcp")
app.add_route(route.path, route.endpoint, methods=["GET", "POST", "DELETE"])
app.router.lifespan_context = mcp_app.lifespan # required for MCP session mgmt
Connecting from an MCP client
For HTTP clients, put the API key in the MCP URL query parameter. It is not part of any tool schema:
https://runloop.fastapicloud.dev/mcp?api_key=YOUR_RUNLOOP_API_KEY
Example client configuration:
{
"mcpServers": {
"runloop": {
"url": "https://runloop.fastapicloud.dev/mcp?api_key=YOUR_RUNLOOP_API_KEY"
}
}
}
The server reads api_key from the HTTP request URL for every HTTP tool call. For stdio transport, set RUNLOOP_API_KEY in the environment. Do
not log or share URLs containing the key; query parameters may appear in proxy
or access logs.
Examples
Code execution
# Run Python code
run_python(code="print('Hello from Python!')")
# Run Node.js code
run_nodejs(code="console.log('Hello from Node.js!')")
# Run Go code with custom file path
run_go(
code='package main; import "fmt"; func main() { fmt.Println("Hello from Go!") }',
file_path="/home/user/main.go"
)
# Run browser automation (multi-step workflow)
session = run_browser(action="navigate", value="https://example.com")
run_browser(session_id=session["session_id"], action="screenshot", value="/tmp/screenshot.png")
run_browser(session_id=session["session_id"], action="close") # This suspends the devbox
Shell execution
# Run shell command on existing devbox
run_shell(devbox_id="dev_...", command="ls -la")
# Run in a stateful named shell
run_shell(devbox_id="dev_...", command="cd /app && python3 server.py", shell_name="server")
Devbox lifecycle
# Create a devbox
create_devbox(
name="my-agent-box",
blueprint_name="runloop/universal-ubuntu-24.04-x86_64",
resource_size="SMALL",
)
# List running devboxes
list_devboxes(status="running")
# Execute a command (blocking)
execute_command(devbox_id="dev_...", command="python3 --version")
# Write a file
write_file(devbox_id="dev_...", file_path="/home/user/app.py", contents="print('hi')")
# Snapshot the disk
create_snapshot(devbox_id="dev_...", name="before-refactor")
# Suspend / resume
suspend_devbox(devbox_id="dev_...")
resume_devbox(devbox_id="dev_...")
# Interactive PTY
pty_send_command(session_name="repl", command="python3 -i", max_wait=30.0)
See examples/example.py for a complete walkthrough.
Tools reference
Code execution tools
run_python— run Python code; auto-manages devbox lifecycle (create/resume/suspend)run_nodejs— run Node.js/JavaScript code; auto-manages devbox lifecyclerun_deno— run Deno code; auto-manages devbox lifecyclerun_go— run Go code; auto-manages devbox lifecyclerun_rust— run Rust code; auto-manages devbox lifecyclerun_java— run Java code; auto-manages devbox lifecyclerun_cpp— compile and run C++ code; auto-manages devbox lifecyclerun_c— compile and run C code; auto-manages devbox lifecyclerun_ruby— run Ruby code; auto-manages devbox lifecyclerun_php— run PHP code; auto-manages devbox lifecyclerun_bash— run Bash scripts; auto-manages devbox lifecycle
All code execution tools accept:
code(required): Source code to executefile_path(optional): Path to save the code file (default:/home/user/code.<ext>)
Note: If image is being pulled, tools return image_pulling status; retry after 5 seconds.
Browser automation
run_browser— browser automation using Playwright (mcr.microsoft.com/playwright:latest)action(required):navigate,click,type,fill,screenshot,get_text,get_attribute,wait_for_selector,wait_for_navigation,press,hover,scroll,check,uncheck,select_option,closevalue(optional): Action-specific value (URL, selector, text, etc.)session_id(optional): Session ID for multi-step workflows- Lifecycle: Does not suspend after most actions; only suspends when
action="close"
Shell execution
run_shell— execute arbitrary shell commands on a devboxdevbox_id(required): Target devbox IDcommand(required): Shell command to executeshell_name(optional): Named shell for stateful sessions
Devbox lifecycle
create_devbox— create a devbox with optional blueprint, snapshot, env vars, file mounts, launch commands, instance size, architecture, TTL, and idle lifecycle policy.list_devboxes— list devboxes, optionally filtered bystatus.get_devbox— retrieve a single devbox by id.update_devbox— update a devbox'snameand/ormetadata.suspend_devbox— suspend a devbox (disk state preserved).resume_devbox— resume a suspended devbox.shutdown_devbox— shut down / delete a devbox.
Execution & files
execute_command— run a command and block until completion, returningstdout,stderr,exit_status. Optionalshell_namegives you a stateful named shell.execute_command_async— start a command and return immediately with anexecution_id(use for long-running servers/watchers).write_file— create or overwrite a file on a devbox.read_file— read a file's contents from a devbox.
Snapshots
create_snapshot— snapshot a devbox's disk (synchronous).list_snapshots— list disk snapshots, optionally filtered by devbox.delete_snapshot/get_snapshot_status— manage snapshot lifecycle.
Execution lifecycle, files, and tunnels
get_execution,wait_for_execution,get_execution_logs— inspect async commands.kill_execution/send_execution_stdin— stop or interact with async commands.upload_file/download_file— transfer binary data using Base64.keep_devbox_alive/get_resource_usage— keep a devbox active and inspect usage.create_pty_tunnel— create an ephemeral authenticated PTY tunnel.enable_tunnel,get_tunnel_url,remove_tunnel— expose devbox HTTP/WebSocket services.
MCP Hub and secrets
list_mcp_configs,create_mcp_config,update_mcp_config,delete_mcp_config— manage MCP Hub endpoints and tool allow-lists.list_secrets,create_secret,update_secret,delete_secret— manage account secret metadata and values.
PTY sessions
pty_connect— create or reconnect to an interactive PTY session; returns the WebSocketconnect_url.pty_send_command— send a command through the PTY WebSocket and capture output (for TTY-aware programs, REPLs, TUIs).pty_control— resize the terminal, deliver a POSIXsignal, orclosethe session.
Deploy to FastAPI Cloud
fastapi, fastapi-cli (the fastapi executable) and uvicorn are core
dependencies, so FastAPI Cloud's fastapi run main.py works out of the box.
Just connect your repo and deploy; main.py exposes app = FastAPI(...).
# local check that the CLI is present
fastapi run main.py --port 8000
A Dockerfile is also included (serves with
uvicorn main:app --host 0.0.0.0 --port 8000) for Docker-based platforms.
Troubleshooting: if you previously deployed when
fastapiwas only an optional dependency, you may have hitsh: 1: exec: fastapi: not found. Redeploy after this fix — the dependency is now installed by default.
Notes & gotchas
- Prefer
execute_commandfor normal, non-interactive commands; PTY is heavier and intended for true interactive use. - Each
execute_commandspawns an isolated shell unless you reuse ashell_name. - Background processes started in
launch_commandsmust redirect output (> /tmp/out.log 2>&1 &) or the devbox will never become active. - Only one WebSocket client may attach to a PTY session at a time.
- Snapshots and suspended devboxes accrue storage charges until deleted/shut down.
License
推荐服务器
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 模型以安全和受控的方式获取实时的网络信息。