mirror of
https://github.com/sredevopsorg/deepseek-kubernetes-sandbox.git
synced 2026-11-03 09:23:25 +00:00
Update AGENT_SANDBOX_VERSION to v1.0.8 and the docs that quote the control-plane pin (example prerequisites, architecture, versioning table, minimal-single-tenant template comment, platform skill). The v1.0.8 release adds only one CRD field, spec.failedPodPolicy (Sandbox and SandboxTemplate, enum Retain|Recreate, default Retain), so the existing manifests keep their behavior: Retain is the default and neither the API version (v1beta1) nor any field we set changed. All five custom resources still validate against the v1.0.8 CRD schemas. Behavior changes in the controller itself (bounded MCP output, router kustomization, creation-latency metric timing) do not affect the platform because it uses neither the sandbox-router nor the MCP server. Co-authored-by: SREDevOpsAgents <agents@sredevops.org>
108 lines
6.2 KiB
Markdown
108 lines
6.2 KiB
Markdown
# agent-sandbox MCP server reference
|
|
|
|
Upstream: [clients/integrations/mcp-server](https://github.com/kubernetes-sigs/agent-sandbox/tree/main/clients/integrations/mcp-server).
|
|
It is a Python/FastAPI + FastMCP service (streamable HTTP on `:8000`, MCP
|
|
endpoint `/mcp`) that provisions sandboxes from a warm pool and runs commands or
|
|
file operations through a sandbox runtime. It ships with **no authentication**.
|
|
|
|
Build the server from the same tag as the cluster: read `AGENT_SANDBOX_VERSION`
|
|
in `versions.env`, and check the installed controller image. Do not build from
|
|
`main` against an older cluster; tool schemas and connection types differ.
|
|
|
|
## Tool surface
|
|
|
|
| Tool | Arguments (defaults) | Returns / notes |
|
|
| --- | --- | --- |
|
|
| `create_sandbox` | `warmpool`, `namespace`, `sandbox_ready_timeout=180`, `labels`, `shutdown_after_seconds=300` (`null` disables), `pod_labels`, `pod_annotations` | `sandbox_claim_name`; adds the MCP session label |
|
|
| `delete_sandbox` | `sandbox_claim_name`, `namespace` | Deletes the session-owned claim; PVC cascades |
|
|
| `execute_command` | `sandbox_claim_name`, `namespace`, `command`, `timeout=60` (max 600), `max_output_chars` only on v1.0.8+ (128-300,000, default 30,000) | `exit_code`, `stdout`, `stderr`; v1.0.8 adds `*_total_chars` and `*_truncated` |
|
|
| `upload_file` | `sandbox_claim_name`, `namespace`, `path`, `content`, `binary=false`, `timeout=60` | Bytes written; base64 when `binary=true` |
|
|
| `download_file` | `sandbox_claim_name`, `namespace`, `path`, `binary=false`, `timeout=60` | Content + bytes read |
|
|
| `list_files` | `sandbox_claim_name`, `namespace`, `path`, `timeout=60`, `max_entries=1000` (max 10,000) | Entries (`name`, `size`, `type`, `mod_time`), `total_entries`, `truncated` |
|
|
| `file_exists` | `sandbox_claim_name`, `namespace`, `path`, `timeout=60` | `exists`; a missing path is not an error |
|
|
| `get_sandbox_status` | `sandbox_claim_name`, `namespace` | `SandboxReady` / `SandboxNotReady` / `SandboxNotFound`, `ready`, `message` |
|
|
|
|
Resource: `sandboxes://{namespace}` lists sandboxes for the current MCP session.
|
|
|
|
## Session scoping is the most important behavior
|
|
|
|
Every tool, including `get_sandbox_status`, calls `get_sandbox()` ->
|
|
`ensure_session_owns()`, which lists sandboxes with the label selector
|
|
`<K8S_SANDBOX_SESSION_ID_LABEL_KEY>=<MCP session id>`. The resource uses the same
|
|
selector. Consequences:
|
|
|
|
- The server can only see/exec/delete claims **it created in the same MCP
|
|
session**. It cannot inspect or manage DSH platform claims created by the
|
|
gateway or `kubectl`, or claims from another session.
|
|
- On a DSH MCP reconnect, the MCP session changes; earlier claims become
|
|
invisible to the tools. They keep running until `shutdown_after_seconds`
|
|
expires, or until you remove them by label with a confirmed `kubectl delete`.
|
|
- A "Sandbox claim '<name>' is not found in namespace '<ns>'" error usually
|
|
means wrong namespace **or** the claim belongs to a different session.
|
|
- Use `kubectl` for global inventory; use the MCP only for sandboxes it created
|
|
in this task.
|
|
|
|
Session identity requires a session-providing transport. With stdio,
|
|
`ctx.session_id` is `None` and creation fails. Connect DSH over
|
|
`streamable-http`.
|
|
|
|
## Runtime prerequisite
|
|
|
|
The server talks to a sandbox runtime, not to arbitrary pods:
|
|
|
|
- `gateway`, `direct`, `in-cluster`: runtime HTTP on `SERVER_PORT=8888`
|
|
(sandbox-router API or direct pod runtime).
|
|
- `sandboxd-in-cluster` (v1.0.8+): sandboxd REST `8080`, gRPC `9090`.
|
|
|
|
The shipped DSH template runs only DSH Web on `3080`, so no connection type can
|
|
exec into it. A sandboxd **sidecar** executes commands in the sidecar's own
|
|
container, not in the DSH container; shared volumes share files, not binaries or
|
|
processes. To exec inside DSH, build a combined image (sandboxd injected into the
|
|
DSH image) or use `kubectl exec` with explicit RBAC and confirmation. For
|
|
untrusted code, deploy a separate runtime warm pool rather than modifying the
|
|
DSH template.
|
|
|
|
## Version differences
|
|
|
|
| Area | Before v1.0.8 | v1.0.8+ |
|
|
| --- | --- | --- |
|
|
| Connection types | `gateway`, `direct`, `in-cluster` | Adds `sandboxd-in-cluster` |
|
|
| `execute_command` output | Unbounded | Bounded by `max_output_chars`; four metadata fields |
|
|
| Failed pod recovery | `Retain` only | `spec.failedPodPolicy: Recreate` |
|
|
| Router install | `kubectl apply -f sandbox-router/deploy/` | `kubectl apply -k sandbox-router/deploy/`; projected token |
|
|
|
|
Never pass `max_output_chars` to a pre-v1.0.8 server. On older servers, redirect
|
|
verbose output to a file and `download_file` it, or pipe through `tail`/`head`.
|
|
|
|
The repository pins `AGENT_SANDBOX_VERSION=v1.0.8`, so the right-hand column is
|
|
what the documented platform and a same-tag MCP build provide; keep the
|
|
before-column for clusters still on v1.0.7.
|
|
|
|
## Safety and cleanup
|
|
|
|
- No auth: anyone reaching `:8000` gets every tool and the service account's
|
|
access. Keep it ClusterIP, authenticated, and namespace-scoped.
|
|
- Treat commands as untrusted code: they can read files and environment
|
|
variables inside the sandbox, including provider keys in a combined image.
|
|
- `delete_sandbox` cascades the claim, sandbox, and PVC: confirm the target and
|
|
namespace. Never delete a namespace or PVC as cleanup.
|
|
- Clean up in the same session that created the sandbox. If the session is gone,
|
|
list claims by the session label and delete them explicitly (requires write
|
|
RBAC); otherwise rely on the shutdown timeout.
|
|
|
|
## Troubleshooting
|
|
|
|
| Symptom | Cause / fix |
|
|
| --- | --- |
|
|
| Tools missing | Row not enabled, wrong URL, connection failed; check logs and `/readyz` |
|
|
| 404 on connect | URL is missing `/mcp` or points at the wrong port |
|
|
| `ctx.session_id is None` | Connected over stdio; use streamable HTTP |
|
|
| `Sandbox claim ... is not found` | Wrong namespace, or claim created by another MCP session |
|
|
| Creation times out at ~60 s | MCP session alive but DSH cancelled the call; raise `toolCallTimeoutMs` |
|
|
| `execute_command` connection error | No runtime on 8888/8080/9090, or wrong connection type; the DSH template is unsupported |
|
|
| Output flood | Pre-v1.0.8 server; bound the command output yourself |
|
|
| Empty sandbox list | The resource is session-scoped; use `kubectl` for global inventory |
|
|
|
|
Deployment, connection matrix, RBAC, and the DSH row:
|
|
[MCP deployment](mcp-deployment.md).
|