Reference / Connect an AI tool with MCP

Connect an AI tool with MCP

Connect Claude, ChatGPT or another MCP client to Rootsy, then create and manage computers, run commands, read files back, and manage schedules and domains through its 29 tools.

Updated 2026-10-21 · View as Markdown

This page covers Rootsy’s MCP server: how to connect a client, the access it gets, every tool, and the limits and errors. An AI tool outside your computer can use it to create, restart, reset and delete computers, run shell commands on them, move files in and out, and manage schedules and custom domains. Any client that supports remote MCP servers with OAuth can connect.

The server

Server URLhttps://app.rootsy.io/mcp
TransportStreamable HTTP, stateless
AuthOAuth 2.1 with a bearer token in the Authorization header
Resource metadatahttps://app.rootsy.io/.well-known/oauth-protected-resource/mcp
Scoperootsy:access
Largest request524,288 bytes (512 KiB)

What a connection can do

There is one permission, rootsy:access. It lets the client act as you, with your current Rootsy permissions. Every tool needs it. There is no read-only mode.

A connection reaches every computer in your personal account and in every organization you belong to. It follows your memberships as they change. Leave an organization and the connection loses its computers on the next call. Rootsy checks your identity, your memberships and whether MCP access is paused on every call.

A connected client can read and change any file on those computers, and it can delete them. Connect only clients you trust.

A token without rootsy:access gets HTTP 403 with insufficient_scope. Reconnect the client and approve the access it asks for.

Connect a client

  1. Add a custom MCP server (some clients call it a connector or an app) with the URL https://app.rootsy.io/mcp.
  2. When the client opens the Rootsy sign-in page, sign in with your Rootsy account.
  3. On the consent screen, approve the access the client asks for.

In Claude, add it as a custom connector. Give it a name and paste the server URL. In ChatGPT, turn on Developer mode before adding a custom MCP server. Rootsy doesn’t issue client IDs or secrets. The URL is all you need.

Pause every connection

To cut off all of your MCP connections at once, open Account in the app. Choose Manage account in the account menu, or Settings in the sidebar while you’re in your personal account. Then choose Pause MCP access under MCP access. Every connection is refused from the next request on. That includes ones you’ve forgotten about and ones that refresh their token later. A call already in progress may finish. Paused calls fail with this message:

Access is paused. Resume in Rootsy personal settings > MCP access. Reconnecting does not resume access.

Choose Resume MCP access to allow connections again. Resuming lets old connections work again too. If you think a token has leaked, keep access paused.

Pausing stops new calls. It doesn’t stop schedules, scheduled requests already sent, or work Rootsy already accepted, such as a deletion in progress.

The tools

Every tool except get_identity and list_accounts takes an explicit account_id. Tools that act on a computer also take its computer_id. Get both from list_accounts and list_computers.

GroupToolsCovered in
Accounts and computersget_identity, list_accounts, list_computers, get_computerThis page
Computer lifecyclecreate_computer, restart_computer, reset_computer, delete_computer, get_computer_operationThis page
Commandsrun_command, read_command, cancel_commandThis page
Filesimport_file, read_file_import, export_fileThis page
Scheduleslist_schedules, get_schedule, preview_schedule, create_schedule, update_schedule, set_schedule_enabled, delete_schedule, run_schedule, list_schedule_requestsScheduled tasks
Domainslist_domains, get_domain, connect_domain, verify_domain, remove_domainDomains

run_command, the lifecycle tools, import_file, create_schedule and run_schedule take a request_id, a UUID you generate for each action you mean to take. If you don’t know whether a call went through, repeat it with the same request_id and the same input. Rootsy returns the original result and doesn’t act twice. The same request_id with different input fails with request_conflict. Never pick a new request_id to retry an action whose outcome is unknown.

Read accounts and computers

These tools only read. They don’t wake a computer or spend Runtime Credits.

ToolInputReturns
get_identitynothinguser_id, display_name
list_accountsoptional limit (1–100, default 50), optional cursoraccounts[], next_cursor
list_computersaccount_id, optional limit (1–100, default 50), optional cursoraccount, computers[], next_cursor
get_computeraccount_id, computer_idOne computer’s details

Each account has id, type (personal or organization), name, slug, and lifecycle with deleting and suspended booleans. Each computer in list_computers has id, name, slug, status, public_url (its address) and created_at. status is one of provisioning, active, stopped, resetting, restoring, failed, deleting. When next_cursor isn’t null, pass it back as cursor to get the next page.

get_computer adds workspace_url, provisioning_step, observed_at, unreachable_since, reachability_checked_at, site_fault_at, hosting, capabilities, actions and simulated. hosting.platform_request_body_limit_bytes is the request body limit for your apps, 1,048,576 bytes. It can be null. The limit is the same either way. See Serve an app. capabilities has booleans for commands, files, file_transfer, schedules and reset. files means the workspace Files window. file_transfer means the MCP file tools below. actions says whether restart, reset and delete are available now, with a reason when they aren’t. status: "active" doesn’t mean the computer is awake. awake is always null.

Create, restart, reset and delete computers

ToolInputs besides account_id and request_idWhat it does
create_computernameCreates a computer in the account. The slug comes from the name.
restart_computercomputer_idRestarts the computer. Files stay. Running processes stop.
reset_computercomputer_id, confirm_reset: trueResets the computer. It keeps /home, /root and /srv, stops running processes and pauses every schedule. See Backups and Reset.
delete_computercomputer_id, confirm_slugDeletes the computer, its files and its backups, and removes its domains from Rootsy. confirm_slug must equal the computer’s slug exactly.
get_computer_operationnothing elseReads the receipt for a lifecycle request_id

Each change tool returns a receipt. Call get_computer_operation with the same account_id and request_id until state is final, waiting poll_after_ms between calls. Receipts last as long as the account, so you can read one after the computer is deleted.

stateMeaning
accepted, runningIn progress. Not finished.
succeededDone. For a create, the computer is ready. For a delete, the computer is gone. cleanup_pending: true means Rootsy is still finishing the remaining external cleanup.
failedDidn’t happen. reason says why.
unknownRootsy can’t prove the outcome. Read the receipt again. Don’t send a new request.

needs_review: true means the operation has been unresolved for 15 minutes and Rootsy has been alerted. For a restart, acknowledged: false means Rootsy can’t confirm the restart happened.

Creating a computer follows the account’s plan and Runtime Credits. An organization without a plan gets org_subscription_required. A personal account without a plan or credits gets runtime_exhausted. Pick a plan with Create computer in the app first. A full account gets box_limit_reached with the plan’s limit in error.details. Too many creations in 24 hours gets creation_rate_limited with retry_after_seconds and retry_at. A name that makes a bad slug fails with too_short, too_long, invalid_format or reserved, and a slug in use fails with slug_unavailable. Limits lists the slug rules.

Deleting never edits DNS at your domain provider. Remove the CNAME records yourself.

run_command

run_command runs a non-interactive bash script on one computer. The command keeps running after the call returns and after your client disconnects.

FieldRequiredLimits
account_idyesUUID of the account that owns the computer
computer_idyesUUID from list_computers
request_idyesa UUID you generate, new for each command you mean to run
commandyes1 to 16,384 bytes of UTF-8 bash, counted after JSON decoding. No NUL bytes.
cwdnoabsolute path, up to 4,096 bytes. Default /home/dev.
timeout_secondsno1 to 900. Default 300.
completion_modenodetached (default) or check_once

With detached, the call returns as soon as the command starts. With check_once, Rootsy checks once more before answering, so a quick command can come back finished in the same call. If it’s still running, the call returns running and the command carries on. The check never stops the command or extends its time limit. If the check itself fails, the result has state: "unknown" and an observation_error.code. The command was still accepted. Read it with read_command and the same command_id.

A command that’s too long or has a bad cwd is refused before anything runs. To run a larger script, upload it with import_file or the workspace Files window, then run it with a short command.

The command runs as the dev user with bash, with no terminal and no stdin. Its environment is empty apart from:

HOME=/home/dev
USER=dev
LOGNAME=dev
PATH=/usr/local/bin:/usr/bin:/bin
LANG=C.UTF-8

Your shell profile and ~/.bashrc don’t load. If a tool lives somewhere else, use its full path or set PATH at the top of the command, for example export PATH="$HOME/.local/bin:$PATH".

Save the returned command_id. read_command and cancel_command need it.

read_command and cancel_command

Both take account_id, computer_id and command_id, and return the same fields as run_command.

read_command returns the command’s current state and output. Reading again never restarts it. cancel_command stops the command and every process it started. Canceling a finished command changes nothing and returns its result.

Command results

Every command tool returns account_id, computer_id, command_id, request_id, state, exit_code, output, truncated, output_info, submitted_at, finished_at and simulated.

stateMeaning
runningStill running. Call read_command later.
completedFinished. exit_code holds the real exit code, including non-zero failures.
timed_outHit its time limit and was stopped. exit_code is null.
cancelledStopped by cancel_command. exit_code is null.
unknownRootsy couldn’t confirm what happened, usually because the computer didn’t answer in time. Call read_command with the same command_id, or run_command with the same request_id. Don’t start it again under a new request_id unless it then reads lost.
lostThe computer no longer has a result for this command. On its own it doesn’t tell you whether the command ran or succeeded.

Check state and exit_code together. Empty output doesn’t mean success.

output is stdout and stderr together, as text. It holds the last 1,000 journal records, then the last 65,536 bytes of those. A long line can be split across records, and a newline can appear where your program wrote none. Output written faster than 200 lines a second can be dropped. truncated doesn’t tell you whether anything is missing either way. output_info states the same limits: max_journal_records: 1000, max_bytes: 65536, clipping: "unknown" and byte_preserving: false.

Never pass JSON payloads, base64 or binary files through output. Use export_file. For a full log, write it to a file and read the end of it:

npm test > /home/dev/test.log 2>&1; result=$?; tail -n 40 /home/dev/test.log; exit "$result"

Command limits

LimitValue
Commands running at once on one computer4
Time limitdefault 300 seconds, at most 900
How long a finished result stays readable24 hours, unless a reset or restore removes it first
Results kept per computer1,000, running ones included

Up to 4 commands run at once on one computer. Cancel or wait for a running command before starting another. A computer keeps at most 1,000 command results and takes new commands again once older results expire.

When a command’s time limit runs out, Rootsy stops it and every process it started, background processes included, after a 2-second grace period. Work that needs more than 900 seconds can’t run through run_command directly. Jobs shows how to start it as a separate unit.

Edit files with run_command

Only ChatGPT can send a file in with import_file. From other clients, write text files with shell commands through run_command. To read a file:

cat -n /home/dev/notes.md

To create or replace a file, use a quoted heredoc. The quotes in <<'EOF' stop the shell from expanding $ and backticks:

cat > /home/dev/notes.md <<'EOF'
# Notes
Price is $5.
EOF

The whole command, file text included, must fit in 16,384 bytes. Files you write this way belong to the dev user.

Move files in and out

import_file writes one file onto a computer. export_file reads one back. Each moves one regular file of 1 to 262,144 bytes, with its exact bytes. To move a folder, pack it into an archive with a command first. Importing an archive doesn’t unpack it. The tools work only when get_computer reports capabilities.file_transfer: true. Files are read and written as the dev user, with its permissions.

ToolInputs besides the computerWhat it does
import_filerequest_id, destination, expected_bytes, expected_sha256, fileWrites an attached file to destination
read_file_importrequest_idReads the import’s receipt
export_filepath, expected_bytes, expected_sha256, optional representationReturns the file’s bytes

Import a file

file is the client’s attachment, with download_url and file_id, and optionally mime_type and name. Rootsy accepts only download URLs on ChatGPT’s file host (*.oaiusercontent.com), so import works from ChatGPT. Other clients can’t attach a file this way. Use run_command or the workspace Files window instead.

destination is an absolute path of up to 4,096 bytes, and its folder must already exist. Import never overwrites. If a file is already there, the import fails with failure_reason: "destination_exists" and the existing file stays. Import never creates folders, so create them with a command first. The attachment’s name never chooses where the file goes.

expected_bytes and expected_sha256 (lowercase hex) must match the attachment exactly. Compute them from the real bytes in the client. If the client can’t read the bytes, say so. Don’t guess a hash.

request_id here must be a UUIDv7 generated now. It can be at most 5 minutes in the future, and it expires 24 hours after its timestamp. After any error, disconnect or uncertain answer, call read_file_import with the same request_id before you try again. A retry needs the same request_id, destination, size and hash. Rootsy allows 3 attempts per request_id.

The receipt’s phase says where the import stands:

phaseMeaning
reserved, staging, finalizingIn progress
completedThe file is in place with the expected bytes
failedIt didn’t happen. failure_reason says why when Rootsy knows.
expiredThe request_id expired before the import finished
unknownRootsy can’t prove whether the file was written. Check the destination with a command. Don’t import again under a new request_id.

Export a file

export_file reads path once and checks it against expected_bytes and expected_sha256. Get those with ordinary commands:

wc -c < /home/dev/site.tar.gz; sha256sum /home/dev/site.tar.gz

With representation: "resource" (the default), the result holds the original bytes as one embedded resource. With "image", it returns a PNG as an image, for PNGs up to 4,096 pixels a side and 16,777,216 pixels in all. A file that changes while it’s read fails the check and isn’t returned. Create screenshots or archives with a command first, then export them.

File limits

LimitValue
File size1 to 262,144 bytes
Pathabsolute, up to 4,096 bytes
Time for one call60 seconds
Imports in progress per computer4
Import receipts kept256 per computer, 2,048 per account

Sleep and Runtime Credits

A sleeping computer wakes when a command, a file call or a restart reaches it. A command holds it awake until the command ends or hits its time limit. Commands fail with computer_unavailable while a computer is resetting, restoring or being deleted.

Time awake spends Runtime Credits, whatever woke the computer. run_command and read_command check the account’s credits first. If the account can’t fund the full time limit, Rootsy shortens the limit to what it can fund. If it can fund nothing, the call fails with runtime_exhausted. On a computer that’s parked because the account ran out, calls fail with box_parked_runtime. cancel_command works without credits. See Billing.

Errors

A failed tool call returns isError: true and a JSON body with error.code, error.message and error.retryable. Lifecycle errors can add error.details. Import errors carry the request_id to read back with read_file_import. These are the codes you’re most likely to see. Schedule and domain tools have their own codes, explained in their messages.

error.codeWhat to do
invalid_argumentsFix the input: a missing field, a non-UUID ID, or a value out of range.
not_foundThe account or computer doesn’t exist, isn’t yours, or the computer_id belongs to a different account_id.
insufficient_scopeReconnect the client and approve the access it asks for.
access_pausedResume MCP access in the app.
request_conflictThis request_id was used with different input. Read the original instead.
computer_unavailableThe computer isn’t active. Check status with get_computer, and wait for a create, reset, restore or deletion to finish. If its actions show restart as available, use restart_computer.
unsupported_runtimeThis computer can’t run the tool. Check capabilities in get_computer.
runtime_exhausted, runtime_dustThe account has no usable Runtime Credits, and the computer isn’t parked. Calls work again when credits arrive.
box_parked_runtimeThe computer is parked because the account ran out of Runtime Credits. Calls work again once credits arrive and Rootsy unparks it. See Billing.
box_dormantThe computer is dormant because the plan has fewer computers than the account holds. See Billing.
storage_over_limitThe computer is over its plan’s storage. Delete files with the workspace Files window, then try again.
account_suspended, account_deletingThe account can’t run anything. Write to support@rootsy.io if you don’t know why.
temporarily_unavailableRootsy couldn’t complete the call. Try again after a few seconds with the same request_id. For an import, call read_file_import first.

What the MCP server doesn’t do

It doesn’t create, restore or pin backups. It doesn’t change plans or billing, or manage organizations and members. It has no interactive terminal and no stdin, and it doesn’t stream output while a command runs. Do those things in the app. It never edits DNS at your domain provider. Create and remove those records yourself.