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:
- Arguments:
api_url,api_key,access_token,usernameandpassword,project(camelCase in TypeScript). - Environment:
TRITON_URL,TRITON_API_KEY,TRITON_ACCESS_TOKEN,TRITON_USERNAMEandTRITON_PASSWORD,TRITON_PROJECT. - The
tritonctlsession, 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 anytritonctlcommand 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 Sandbox | from triton_sandbox import Sandbox |
E2B_API_KEY | TRITON_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, remove | Same |
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, press | desktop.type, desktop.key |
Desktop stream | tritonctl sandbox rdp |
| No equivalent | sbx.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 unlessrecursive=True.- Every refusal is a typed exception under
SandboxException.NotImplementedException.reasonsays 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:
{
"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.