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
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Neon Database
MCP server for interacting with Neon Management API and databases
E2B
Using MCP to run code via e2b.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.