Skip to main content

Use the sandbox SDKs and the MCP server

This guide installs the Python or TypeScript sandbox SDK, sets its credentials, and runs a first call. It also sets up the MCP server, which gives a model sandboxes as tools. The SDK surface follows E2B, so most E2B code moves over with a change of import.

The SDKs are not on PyPI or npm yet. You install them from the source repository, which your operator gives you access to.

Install the Python SDK​

Python 3.10 or later:

pip install "git+https://github.com/TritonDataCenter/mariana-trench.git@main#subdirectory=sdks/python"

Put a commit SHA in place of main to pin a version. The dependencies are httpx and websockets.

Install the TypeScript SDK​

Node 18 or later, or Bun. From a checkout of the source repository, make a tarball, then install it in your project:

cd sdks/typescript && npm ci && npm pack
cd /path/to/your/project && npm install /path/to/triton-sandbox-0.1.0.tgz

Set credentials​

The SDKs look for credentials in this order, highest first:

  1. Arguments: api_url, api_key, access_token, username and password, project (camelCase in TypeScript).
  2. Environment: TRITON_URL, TRITON_API_KEY, TRITON_ACCESS_TOKEN, TRITON_USERNAME and TRITON_PASSWORD, TRITON_PROJECT.
  3. The tritonctl session, read only, from $TRITONCTL_CONFIG_DIR/config.json. Without that variable the SDKs read $XDG_CONFIG_HOME/triton/tritonctl/config.json, else ~/.config/triton/tritonctl/config.json. If its access token has expired, run any tritonctl command to refresh it.

The SDKs ignore tritonctl profiles and read only the default profile's file. On macOS, tritonctl keeps its session under ~/Library/Application Support/triton/tritonctl/, which the SDKs do not look in. Point the SDKs at the session with TRITONCTL_CONFIG_DIR. On macOS, for the default profile:

export TRITONCTL_CONFIG_DIR="$HOME/Library/Application Support/triton/tritonctl"

For another profile, append /profiles/<PROFILE> to the directory, and set the variable only for the program that uses the SDK. tritonctl reads the same variable as the root of all its profiles.

Or skip the session and set TRITON_URL and TRITON_API_KEY. Make a key with tritonctl api-key create.

If your cloud's API uses a private certificate authority, set TRITON_DC_ANCHORS to the path of the CA's PEM file. tritonctl reads the same variable.

The SDKs, the MCP server, and the code interpreter cannot name a subnet when they create a sandbox. In a project with more than one subnet, the create returns 400 MissingScope. Create the sandbox with tritonctl sandbox create --subnet and connect to it with Sandbox.connect.

Run a first call​

from triton_sandbox import Sandbox

sbx = Sandbox.create(package="sandbox-2g", timeout=3600)
print(sbx.commands.run("uname -a").stdout)
sbx.kill()
import { Sandbox } from '@triton/sandbox'

const sbx = await Sandbox.create({ package: 'sandbox-2g', timeoutMs: 3_600_000 })
console.log((await sbx.commands.run('uname -a')).stdout)
await sbx.kill()

AsyncSandbox in Python has the same methods, each one awaited. A command that exits non-zero raises CommandExitException with the result.

Move code over from E2B​

Change the import and the credential variable. The calls map one to one.

E2B (Python)Triton (Python)
from e2b_code_interpreter import Sandboxfrom triton_sandbox import Sandbox
E2B_API_KEYTRITON_URL and TRITON_API_KEY, or the tritonctl session
Sandbox.create(template=, timeout=)Sandbox.create(template=, timeout=)
sbx.commands.run(cmd, background=, on_stdout=)sbx.commands.run(cmd, background=, on_stdout=)
sbx.files.read, write, list, removeSame
sbx.run_code(code)sbx.run_code(code)
sbx.set_timeout(s)sbx.set_timeout(s)
sbx.pause()sbx.pause()
Sandbox.resume(id)Sandbox.connect(id), which starts or resumes it
Desktop write, pressdesktop.type, desktop.key
Desktop streamtritonctl sandbox rdp
No equivalentsbx.snapshot(), sbx.fork(n), sbx.stop(), sbx.start()

Differences that matter:

  • Network egress is denied unless network= allows it.
  • files.remove() refuses a non-empty directory unless recursive=True.
  • Every refusal is a typed exception under SandboxException. NotImplementedException.reason says what the cloud leaves out on purpose.
  • File watches poll every 250 ms.
  • Sandbox.capabilities() lists what your cloud offers.

Reach a port from the SDK​

sbx.ports.forward(8000)

ports.forward opens a local TCP listener over the same authenticated tunnel as tritonctl sandbox port-forward.

Preview URLs are not enabled on Triton Cloud yet. While previews are off, get_host, get_url, and ports.open raise PreviewsDisabledException in Python and throw PreviewsDisabledError in TypeScript. Use ports.forward instead.

Set up the MCP server​

The MCP server is a stdio server built on the TypeScript SDK. Its tools are create_sandbox, run_command, read_file, write_file, list_files, get_preview_url, run_code, screenshot, click, type_text, and kill_sandbox.

Build it from a checkout of the source repository:

cd sdks/typescript && npm install && npm run build
cd ../mcp && npm install && npm run build

Add it to your MCP client's configuration, for example Claude Desktop or Claude Code:

MCP client configuration
{
"mcpServers": {
"triton-sandbox": {
"command": "node",
"args": ["/path/to/sdks/mcp/dist/index.js"],
"env": { "TRITON_URL": "<API_ENDPOINT>", "TRITON_API_KEY": "<API_KEY>" }
}
}
}

A model can be steered by text it reads. By default, the tools reach only the sandboxes this server created. Set TRITON_MCP_ALLOW_ANY=1 to let them reach any sandbox the credential can see.

create_sandbox refuses a 33rd sandbox in one server session. Sandboxes reached through TRITON_MCP_ALLOW_ANY do not count toward that limit. create_sandbox gives each one a lifetime of 300 seconds unless the model passes timeout_s. Tool output is cut at 102,400 characters per field. get_preview_url calls ports.open, so it fails while previews are off.

Give a coding agent the CLI guide​

tritonctl llms.txt prints a guide for coding agents and an index of every command. tritonctl llms-full.txt adds every flag. Neither needs a session.

See also​