MCP tools make agents useful by connecting them to browsers, shells, issue trackers, log files, databases, and cloud CLIs. The same tools can also destroy a context window. A single browser snapshot, issue list, log dump, or CSV can inject tens of kilobytes of raw text into the conversation, even when the model only needs three lines of evidence.
MCP tool output sandboxing is a boundary pattern for long-running agents. Instead of returning raw tool output directly to the model, the tool call runs in a subprocess or local execution environment. The sandbox captures the full output, indexes or filters it locally, and returns only the answer, excerpt, metric, or ranked snippets needed for the current intent. The raw artifact remains inspectable, but it does not become permanent conversation history by default.
This is different from reducing tool definitions. Static tool catalogs and compressed schemas shrink the input side of an agent run. Output sandboxing attacks the other side: uncontrolled observations. It is most valuable for coding agents, operations agents, and research agents whose tools regularly produce large, noisy, semi-structured responses.
Every tool result is an observation the model must carry forward. If an agent reads a 60 KB log to find one stack trace, the other 59 KB still competes with requirements, plans, file paths, and user corrections. Treating observations as budgeted artifacts forces the system to decide what deserves to enter the model context.
The sandbox runs code near the data, not inside the model context. It can parse JSON, grep logs, compute aggregates, extract errors, run BM25 search over indexed text, or summarize a file into structured fields. Only stdout or an explicit return object crosses the boundary back to the agent.
Large tool results often need follow-up queries. Instead of dumping the whole result, the system can chunk and index it in a local full-text database, then expose a search tool that returns ranked sections. SQLite FTS5 with BM25 ranking is a practical default because it is local, cheap, deterministic, and good enough for many code, log, and documentation corpora.
The model should receive the smallest faithful observation needed for the next decision. Store raw tool output outside the conversation, make it queryable, and return targeted evidence rather than entire files or command results.
The host, plugin, or MCP server identifies tools likely to produce bulky output: shell commands, file reads, repository searches, web fetches, browser snapshots, cloud CLI calls, and issue tracker queries. Lightweight calls can pass through normally, while risky calls are routed through sandboxed execution and filtering.
type ToolRequest = {
name: string;
args: Record<string, unknown>;
intent?: string;
};
const DATA_HEAVY = new Set([
"shell",
"read_file",
"web_fetch",
"browser_snapshot",
"issue_list",
"log_query"
]);
async function dispatchTool(req: ToolRequest) {
if (!DATA_HEAVY.has(req.name)) {
return callRawTool(req);
}
return runThroughOutputSandbox(req);
}
The sandbox can run a short script or command that reads the raw artifact, extracts the signal, and emits a compact result. For example, a test triage command might keep the full log on disk but return only failing test names, the first stack trace, and the command exit code.
import re
from pathlib import Path
log = Path("run.log").read_text(errors="replace")
failures = re.findall(r"FAILED ([^\\s]+)", log)
trace = log.split("Traceback", 1)
print({
"failed_tests": failures[:20],
"first_traceback": "Traceback" + trace[1][:1800] if len(trace) == 2 else None,
"raw_log_path": "run.log"
})
If the agent needs to explore a document, issue list, or API response, the sandbox can chunk the artifact and store it in a local index. A follow-up search then retrieves exact sections rather than lossy summaries. Heading-aware chunking is useful for Markdown and documentation because it preserves code blocks and section hierarchy.
Test suites and build tools often emit thousands of lines. A sandboxed command can return the failing targets, stack traces, changed-file hints, and reproduction command while keeping the raw log available for explicit follow-up. This prevents one failed CI run from dominating the next several turns.
Browser snapshots can be large because they include every visible element. A sandbox can query the snapshot for buttons, forms, accessibility labels, or changed regions and return a focused map. The agent still acts on real page state but does not need to reason over the complete DOM-like dump each turn.
Cloud CLIs, Kubernetes, and log platforms produce bulky JSON and tabular output. Sandboxing lets an operations agent compute rates, error clusters, pod restarts, or unusual fields locally before returning a compact incident observation. The pattern also reduces accidental exposure of secrets embedded in logs.
Large-output tools should ask the model what it is trying to learn. The intent controls extraction and ranking. Without an intent, the safest behavior is to return metadata, size, schema, and suggested searches rather than dumping the artifact.
async function filterLargeOutput(raw: string, intent?: string) {
if (raw.length < 5000) return raw;
if (!intent) {
return {
kind: "large_output",
bytes: raw.length,
preview: raw.slice(0, 500),
next_step: "Provide an intent to search or extract specific evidence."
};
}
const indexId = await indexChunks(raw);
return searchIndex(indexId, intent, { limit: 5 });
}
The compact observation should include a stable reference such as a cache key, file path, trace ID, or command ID. This lets the agent ask for more evidence without re-running expensive commands or losing provenance. Raw artifacts should have retention limits and redaction policies.
Output sandboxing controls context volume; it is not a complete security boundary. The underlying tool still needs authentication, authorization, network egress controls, and secret redaction. A sandbox that inherits cloud credentials must be treated as privileged code execution.