The usual MCP failure mode is a tool that returns a large value: the agent
either floods its context window or has to re-run the command with | head
to claw it back. Both options cost turns and lose information.
nu-mcp sidesteps this by storing every evaluation's full result in a ring buffer the agent can refer to by index on subsequent calls.
Every tool call's full Value is pushed into a $history: list<any> ring
buffer (default 100 entries, NU_MCP_HISTORY_LIMIT). The response the agent
actually sees is truncated to NU_MCP_OUTPUT_LIMIT (default 10kb), but every
response carries a stable history_index. The next turn the agent can
re-slice the full untruncated value:
# turn N: run something big
ls **/*.rs | get name | path expand
# response: { history_index: 7, note: "truncated; see $history.7", ... }
# turn N+1: slice the saved value -- no re-run, no context flood
$history.7 | where $it =~ 'mcp' | first 5history_index is the agent's handle. $history | last is the wrong reflex
because every new evaluation pushes its own entry, so it refers to itself on
the next call.
The ring buffer itself is small and worth a read --
crates/nu-mcp/src/history.rs
(~90 lines). The agent-facing contract lives in
crates/nu-mcp/src/instructions.md
and is served to the model on connect, so the truncation + index protocol
isn't something the agent has to discover empirically.
Added by @andrewgazelka in nushell/nushell#17132 ("feat(mcp): add $history variable and structured response format", merged 2025-12-10).