HTTP servers without an Authorization header use OAuth. Connections send the stored token and refresh it after a 401; /mcp login runs the browser authorization code flow (PKCE, dynamic client registration) with a loopback callback or a pasted redirect URL, and /mcp logout removes the credentials. Tokens are stored per server URL in mcp-auth.json. Pre-registered clients are configured with the oauth block.
Adds a built-in mcp extension that reads mcp.json (agent dir, and .pi/mcp.json for trusted projects) in the common mcpServers format, connects stdio and streamable HTTP servers at session start, and registers their tools as mcp__<server>__<tool>. Calls go through the regular tool pipeline, so hooks and permission extensions apply. /mcp shows server status.
By default a server's tools are codemode-only: the new nestedOnly tool flag keeps them executable for other tools but out of the model's tool declarations, and pi activates the codemode tool for them. "exposure": "direct" declares them to the model as well. structuredContent from tools with an outputSchema reaches codemode scripts as data.
Single definitions of isObject, toError, and isJsonRpcId in protocol/jsonrpc.
TransportEvents now coerces errors and fires close once, so the stdio,
HTTP, and in-memory transports drop their private copies. McpFetch lives
in auth-provider, removing the type cycle with the HTTP transport.
McpClient: one idempotent markClosed() shared by close(), transport close,
and connect() failure; requestInternal builds the pending entry inside the
promise executor; requireTransport() returns the transport; progress and
cancel notifications split out of handleNotification.
OAuth: compact() replaces validate-then-recast in the metadata parsers;
shared TokenRequestOptions and a single error path in tokenRequest;
discovery, provider, and callback helpers factored out of repeated code.
Tests share an HTTP server helper; the SSE parser test moves into the
HTTP transport test file.
One file per transport: stdio, streamable-http (SSE parser folded in),
and in-memory. The McpTransport interface and TransportEvents base class
are merged into transports/transport.ts. InMemoryTransport now extends
TransportEvents instead of duplicating the listener sets.
Public exports from the root and ./testing entry points are unchanged.
Adds a built-in, opt-in codemode tool that runs model-written JavaScript in the codemode sandbox. Scripts call the other active tools as tools.<name>(args), including concurrently with Promise.all; only the return value, console output, and images attached with image() reach the model.
Nested calls run through the agent loop via a new AgentToolContext (5th execute argument, ctx.executeTool for extension tools), so argument validation and the beforeToolCall/afterToolCall hooks apply. Hooks and tool_call/tool_result events carry the parent call id.
Tools can declare outputSchema and return structuredContent; codemode passes that to scripts and falls back to text content otherwise. The codemode package gains globals, declaration rendering from JSON Schema, and optional deadlines.
Successful RPC prompt, steer, and follow_up responses include
data.disposition ("handled", "queued", or "started" for prompt), so clients
know whether to wait for agent_settled.
fixes#9098
Closing the last overlay hid the terminal cursor. If an extension closed
an overlay during session shutdown, this ran after stop() had restored
the cursor, leaving the shell with an invisible cursor.
closes#10026
Replace the tsgo native preview with typescript@7.0.2 and port the check scripts to the TS 7 API. Target ES2024, drop useDefineForClassFields: false and unused decorator options, and enable verbatimModuleSyntax. Replace tsx with node plus the source resolver hook, passed to --import as a file URL.
closes#9965
Strict tool schemas make models send null for omitted optional fields.
The read renderer only treated undefined as missing, so full-file reads
rendered as "path:1".
fixes#9996
Temporary git extensions (-e git:...@ref) were cached in a folder keyed
only by host and repo path. After changing the pinned ref, pi reused the
old checkout without refreshing it and kept loading the first downloaded
commit. Include the ref in the temporary folder hash so each ref gets
its own checkout. Unpinned sources keep their existing folder.
closes#9982
Replace the alternate tracker implementations with the optimized immutable overlay, validate draft placements as strict JSON, and document the ownership contract. Consolidate tracker tests and benchmarks around the canonical implementation.
Expose theme colors as values and add theme.style() for combined styling.
- @earendil-works/pi-tui gains a Color type (palette index, sRGB, OKLCH) with parseColor(), mixColors(), colorToHex(), colorToRgb(), styleText() and related helpers.
- Theme JSON accepts #rgb and oklch(...) values and an optional appearance ("dark" or "light"), detected from the theme colors when omitted.
- theme.style() combines tokens or concrete colors with text attributes; theme.colors exposes concrete colors, including the terminal's reported default colors (OSC 10/11) for tokens set to "".
- Terminals with TERM=*-direct are detected as truecolor.
Name the Astra-immutable-optimized Chord Delta tracker as the Packages 6-7
prerequisite, include the minimal generic Tx table surface in that
milestone, and revoke drafts at callback settlement. Drop the Chord
prerequisite from Package 11 because the existing replicated-state source
contract already matches. Specify that tool stream() never spills; tools
spill through their execution environment.
Port and extend the agent environment tests for NodeExecutionEnv, output
capture, adaptive publishing, and truncation, including exact-byte
truncation, flushing, line-reader cancellation, spill backpressure, and
Buffer-free UTF-8 counting.
Fix truncation reporting when bytes and lines are both exceeded, when only
bytes are exceeded at the line cap, and when small limits trim multi-byte
edge characters. Report the full size of oversized newline-terminated tail
lines. Resolve durable test imports from source so tests run unbuilt.
Set Pico tool output defaults to 50 KiB and 2,000 lines.
OpenRouter decision models use its TypeSafe-compatible /api/v1/systemone endpoint. Cloudflare Workers AI gets a cloudflare-workers-ai-system-one classifier API for the /ai/run envelope. Request and answer parsing is shared in system-one-shared.ts.
Move catalog layout, index validation, version selection, and request
negotiation into scripts/model-catalog-protocol.ts. pi.dev keeps an
identical copy, so the publisher and a test running the current client
exercise the same selection pi.dev performs. Replaces the cross-repository
compatibility dispatch.
Related to #9099.