runloop-mcp

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.

Category
Visit Server

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 latest tags for all language images
  • Pull detection: Returns image_pulling status 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_ID in runloop_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 by scripts/create_blueprints.py (not part of the MCP server).

All language tools accept:

  • code (required): The source code to execute
  • file_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 of navigate, click, type, fill, screenshot, get_text, get_attribute, wait_for_selector, wait_for_navigation, press, hover, scroll, check, uncheck, select_option, close
  • value (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 action is close

Shell execution: run_shell

Execute arbitrary shell commands on a devbox.

Parameters:

  • devbox_id (required): Target devbox ID
  • command (required): Shell command to execute
  • shell_name (optional): Named shell for stateful sessions

Requirements

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 lifecycle
  • run_deno — run Deno code; auto-manages devbox lifecycle
  • run_go — run Go code; auto-manages devbox lifecycle
  • run_rust — run Rust code; auto-manages devbox lifecycle
  • run_java — run Java code; auto-manages devbox lifecycle
  • run_cpp — compile and run C++ code; auto-manages devbox lifecycle
  • run_c — compile and run C code; auto-manages devbox lifecycle
  • run_ruby — run Ruby code; auto-manages devbox lifecycle
  • run_php — run PHP code; auto-manages devbox lifecycle
  • run_bash — run Bash scripts; auto-manages devbox lifecycle

All code execution tools accept:

  • code (required): Source code to execute
  • file_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, close
    • value (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 devbox
    • devbox_id (required): Target devbox ID
    • command (required): Shell command to execute
    • shell_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 by status.
  • get_devbox — retrieve a single devbox by id.
  • update_devbox — update a devbox's name and/or metadata.
  • 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, returning stdout, stderr, exit_status. Optional shell_name gives you a stateful named shell.
  • execute_command_async — start a command and return immediately with an execution_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 WebSocket connect_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 POSIX signal, or close the 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 fastapi was only an optional dependency, you may have hit sh: 1: exec: fastapi: not found. Redeploy after this fix — the dependency is now installed by default.

Notes & gotchas

  • Prefer execute_command for normal, non-interactive commands; PTY is heavier and intended for true interactive use.
  • Each execute_command spawns an isolated shell unless you reuse a shell_name.
  • Background processes started in launch_commands must 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

MIT

Recommended Servers

playwright-mcp

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured