{
  "protocolVersion": "2025-11-25",
  "serverInfo": {
    "name": "agent-as-a-service",
    "version": "1.1.0",
    "title": "Sandbox as a Service",
    "websiteUrl": "https://sandbox-as-a-service.com"
  },
  "capabilities": {
    "tools": {}
  },
  "transport": {
    "type": "streamable-http",
    "url": "https://sandbox-as-a-service.com/v1/mcp"
  },
  "authentication": {
    "required": true,
    "schemes": [
      "bearer",
      "x-api-key"
    ],
    "description": "Per-user API key, created by the account holder at https://sandbox-as-a-service.com/dashboard/keys and sent as \"Authorization: Bearer aas_sk_...\" or \"x-api-key: aas_sk_...\". There is no shared secret and no service-wide credential. initialize, tools/list and get_service_info answer without a key so the server can be scanned; every other tool acts on an account and requires one."
  },
  "configSchema": {
    "type": "object",
    "properties": {
      "apiKey": {
        "type": "string",
        "title": "API key",
        "description": "Your own API key from https://sandbox-as-a-service.com/dashboard/keys. Sandboxes created through this server are billed to the account it belongs to.",
        "x-from": {
          "header": "x-api-key"
        },
        "x-to": {
          "header": "x-api-key"
        }
      }
    },
    "required": [
      "apiKey"
    ]
  },
  "tools": [
    {
      "name": "create_sandbox",
      "description": "Create an isolated cloud sandbox — a dedicated virtual machine you can run commands in. Returns once the sandbox is ready. Python 3, Node.js 22, git and a build toolchain are pre-installed. The sandbox is destroyed automatically after timeout_minutes; nothing inside it survives that. Use this before running any code you would not want to run on the local machine.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "size": {
            "type": "string",
            "enum": [
              "small",
              "medium",
              "large"
            ],
            "description": "small = 2 vCPU/4 GB, medium = 4 vCPU/8 GB, large = 8 vCPU/16 GB. Default: small."
          },
          "name": {
            "type": "string",
            "description": "Optional label to identify this sandbox later."
          },
          "timeout_minutes": {
            "type": "integer",
            "description": "Destroy the sandbox automatically after this many minutes (default 15, max 1440 — 24 hours).",
            "minimum": 1,
            "maximum": 1440
          }
        }
      }
    },
    {
      "name": "run_command",
      "description": "Run a shell command inside a sandbox and wait for it to finish. Returns stdout, stderr and the exit code. The command runs as an unprivileged user in /workspace. A non-zero exit code is returned normally, not as an error. Use this to execute code, install packages, clone repositories or inspect the filesystem. To start something that keeps running (a web server), background it with `&` AND pass `cwd` instead of writing `cd ... &&` — a `&` after a `&&` list backgrounds a subshell that holds the output stream open, so the call waits out the whole timeout and returns exit_code 124. The process survives either way; only the waiting is wasted.",
      "inputSchema": {
        "type": "object",
        "required": [
          "sandbox_id",
          "command"
        ],
        "properties": {
          "sandbox_id": {
            "type": "string",
            "description": "The id returned by create_sandbox."
          },
          "command": {
            "type": "string",
            "description": "Shell command, e.g. `python3 script.py`. Runs unprivileged with no sudo, so package installs need a user-space form: `pip install --user --break-system-packages requests` (the system Python is externally managed, PEP 668), `python3 -m venv`, or `npm install`. `apt-get` cannot work."
          },
          "env": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Environment variables for this command. They are exported, so they survive chaining with && or ;."
          },
          "timeout_ms": {
            "type": "integer",
            "description": "How long to wait before killing the command (default 60000, max 600000)."
          },
          "cwd": {
            "type": "string",
            "description": "Working directory. Default /workspace. Prefer this over a `cd ... &&` prefix, which breaks backgrounding with `&`."
          }
        }
      }
    },
    {
      "name": "write_file",
      "description": "Write a file inside a sandbox. Use this to place a script or input data before running it. Paths are relative to /workspace unless absolute. Content of any kind is safe — it is transferred verbatim, not interpreted by a shell.",
      "inputSchema": {
        "type": "object",
        "required": [
          "sandbox_id",
          "path",
          "content"
        ],
        "properties": {
          "sandbox_id": {
            "type": "string"
          },
          "path": {
            "type": "string",
            "description": "e.g. `analysis.py` or `/workspace/data/input.json`."
          },
          "content": {
            "type": "string",
            "description": "File contents."
          },
          "encoding": {
            "type": "string",
            "enum": [
              "utf8",
              "base64"
            ],
            "description": "Use 'base64' to write binary content. Default 'utf8'."
          }
        }
      }
    },
    {
      "name": "read_file",
      "description": "Read a file back out of a sandbox — an artifact your code produced, a log, a generated report. Use encoding \"base64\" for binary files such as images.",
      "inputSchema": {
        "type": "object",
        "required": [
          "sandbox_id",
          "path"
        ],
        "properties": {
          "sandbox_id": {
            "type": "string"
          },
          "path": {
            "type": "string"
          },
          "encoding": {
            "type": "string",
            "enum": [
              "utf8",
              "base64"
            ]
          }
        }
      }
    },
    {
      "name": "list_files",
      "description": "List the contents of a directory in a sandbox, with the type and size of each entry. Defaults to /workspace. Use this to find what your code produced before reading it.",
      "inputSchema": {
        "type": "object",
        "required": [
          "sandbox_id"
        ],
        "properties": {
          "sandbox_id": {
            "type": "string"
          },
          "path": {
            "type": "string",
            "description": "Directory to list. Default /workspace."
          }
        }
      }
    },
    {
      "name": "expose_port",
      "description": "Give a server running inside the sandbox a public https URL, so a person can open it in a browser. Use this after starting a web server or dev server in the background with run_command (background it with `&` and pass `cwd` rather than `cd ... &&`). The server only needs to listen on localhost. Returns a URL that works until the sandbox is destroyed.",
      "inputSchema": {
        "type": "object",
        "required": [
          "sandbox_id",
          "port"
        ],
        "properties": {
          "sandbox_id": {
            "type": "string",
            "description": "The id returned by create_sandbox."
          },
          "port": {
            "type": "integer",
            "minimum": 1,
            "maximum": 65535,
            "description": "The port the server listens on, e.g. 3000."
          }
        }
      }
    },
    {
      "name": "get_sandbox",
      "description": "Get the current status and details of one sandbox, including when it expires.",
      "inputSchema": {
        "type": "object",
        "required": [
          "sandbox_id"
        ],
        "properties": {
          "sandbox_id": {
            "type": "string"
          }
        }
      }
    },
    {
      "name": "list_sandboxes",
      "description": "List the sandboxes on this account, newest first. Use it to find sandboxes you created earlier.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "integer",
            "description": "How many to return (default 20, max 100)."
          },
          "include_deleted": {
            "type": "boolean",
            "description": "Include sandboxes that have already been destroyed. Useful for auditing what a run created."
          }
        }
      }
    },
    {
      "name": "extend_sandbox",
      "description": "Push a sandbox’s expiry further out so long-running work is not cut off. Total lifetime is still capped at 24 hours from creation.",
      "inputSchema": {
        "type": "object",
        "required": [
          "sandbox_id"
        ],
        "properties": {
          "sandbox_id": {
            "type": "string"
          },
          "additional_minutes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1440,
            "description": "Default 15. Total lifetime is still capped at 24 hours from creation."
          }
        }
      }
    },
    {
      "name": "destroy_sandbox",
      "description": "Destroy a sandbox and stop billing for it. Everything inside is lost. Call this as soon as you are finished — do not leave sandboxes running.",
      "inputSchema": {
        "type": "object",
        "required": [
          "sandbox_id"
        ],
        "properties": {
          "sandbox_id": {
            "type": "string"
          }
        }
      }
    },
    {
      "name": "get_usage",
      "description": "Show the account’s remaining credit balance and recent sandbox usage.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      }
    },
    {
      "name": "get_service_info",
      "description": "Describe this service: what a sandbox costs, which machine sizes exist, the account limits, and where to get an API key. Free — it never provisions anything and is not charged for. Every other tool here needs an API key and acts on the account that key belongs to.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
  ],
  "resources": [],
  "prompts": []
}