Commit graph

3862 commits

Author SHA1 Message Date
Christian Klotz
e3c9214d4b
docs(coding-agent): improve MCP server guide 2026-09-30 00:40:41 +01:00
Armin Ronacher
f4c7624c40 fix(coding-agent): mark current MCP exposure with a check like other pickers 2026-09-29 08:12:41 +02:00
Armin Ronacher
83f0c5033b Merge remote-tracking branch 'origin/main' into codemode-and-mcp 2026-09-29 08:12:12 +02:00
Armin Ronacher
28fd590868 fix(ai,coding-agent): replace removed Together Kimi K2.6 with Kimi K3
Together no longer lists Kimi K2.6, which broke type checks against the hydrated catalog. Tests use Kimi K3 and the Together default model now points at it.
2026-09-29 08:11:56 +02:00
Armin Ronacher
1ef250772e feat(coding-agent): split MCP deferred exposure into tool_search and codemode modes
deferred MCP servers now activate tool_search instead of codemode, so their tools load as declared tools without codemode. The previous behavior is available as codemode-deferred. The unreachable-tools warning now accepts an active tool_search as reaching undeclared MCP tools.
2026-09-29 08:03:12 +02:00
Armin Ronacher
a1fa315f8f feat(coding-agent): add MCP resources, per-tool exposure, and output limits
Servers with resources are reached through Codex's list_mcp_resources, list_mcp_resource_templates, and read_mcp_resource tools; MCP App resources and icons are left out. toolExposure sets the exposure of single tools by name or pattern. Tool annotations are passed on to ToolDefinition and ToolInfo for permission extensions. MCP text over 20KB is cut in the middle like in Codex and saved to a temp file. OAuth takes scope and a Codex-style callbackUrl, and stdio servers expand ~ in command, args, and cwd. Also fixes the !command header example in the MCP docs.
2026-09-29 07:49:19 +02:00
Armin Ronacher
715f2eccac feat(coding-agent): use -l/--local for project servers in pi mcp add/remove
Replaces --project to match pi install and pi remove.
2026-09-29 01:24:27 +02:00
Armin Ronacher
e78aece136 feat(coding-agent): add pi mcp add/remove and log server messages to mcp.log
pi mcp add writes stdio or HTTP server entries to the global or project mcp.json, pi mcp remove deletes them. Log messages servers send with notifications/message are appended to mcp.log in the agent directory, rotated at 5 MB.
2026-09-29 01:03:19 +02:00
Armin Ronacher
0cc77a1c10 Merge branch 'main' into codemode-and-mcp
# Conflicts:
#	packages/coding-agent/docs/extensions.md
#	packages/coding-agent/src/core/agent-session.ts
#	packages/coding-agent/src/core/extensions/loader.ts
#	packages/coding-agent/src/core/extensions/types.ts
#	packages/coding-agent/src/core/model-registry.ts
#	packages/coding-agent/src/index.ts
2026-09-28 23:54:27 +02:00
Armin Ronacher
540e174c72
feat(coding-agent): Virtual models (#10035)
This adds experimental support for virtual models. A virtual model is a catalog entry that an extension registers with pi.registerVirtualModel(). It does not talk to a provider itself; for every request it picks a physical model and thinking level. The motivation is to make routing policies pluggable: plan on a strong model and implement on a cheap one, pick a model with a classifier, or move to a larger window when the context grows. Today this needs model switching by hand or hacks in prepareRequest.

The selection stays virtual: model_change records it, resume restores it, and each response records the physical model and thinking level that produced it. Router state can be stored on the session branch, so it follows /tree and forks and survives compaction. Context limits, compaction and image sizing use the physical model a request was routed to. examples/extensions/jev-router.ts shows a full router that uses the Jev classifier to pick Sol or Terra for planning and hands off to Luna after the first edit. docs/virtual-models.md describes the API.
2026-09-28 23:30:45 +02:00
Christian Klotz
fd889a2741
fix(coding-agent,tui): paste Finder file paths instead of icons (#10136)
Read Finder file URLs before icon image data on macOS. Quote paths in
bash mode and reject terminal control characters before rendering.

Fixes #9999

Co-authored-by: 1dustycy <onedustycy@gmail.com>
2026-09-28 20:59:29 +01:00
Armin Ronacher
c90d9ea586 feat(ai,coding-agent): add Claude Sonnet 5.5 support 2026-09-28 20:46:38 +02:00
Armin Ronacher
04efdfc380
feat(ai): Discount jev (#10119)
Add the llama-cpp-classify classifier API. Each question becomes one chat prompt with single-token answer labels; llama-server's pre-sampling next-token log-probabilities give the softmax over those labels. Missing labels are retried with deeper readouts and then reported as errors.
2026-09-28 14:19:07 +02:00
Armin Ronacher
2e0ca71816 Merge remote-tracking branch 'origin/main' into codemode-and-mcp 2026-09-28 12:09:06 +02:00
Armin Ronacher
e1787702d3 fix(coding-agent): default OpenCode Go to Kimi K3 after Kimi K2.6 removal 2026-09-28 12:08:56 +02:00
Armin Ronacher
c95a4cc282 test(codemode,coding-agent): trim duplicated codemode and MCP tests
Test each behavior at one layer, share the UI context and tool result helpers in the suite harness, loosen assertions on prompt text, and drop the /mcp manager UI test.
2026-09-28 01:17:22 +02:00
Armin Ronacher
fd7798bae2 Merge branch 'main' into codemode-and-mcp 2026-09-28 00:22:58 +02:00
Armin Ronacher
6f7551516b fix(ai,coding-agent): update Fireworks tests and default for removed models
models.dev dropped Kimi K2.6, GLM 5.2, and the dated DeepSeek V4 Fireworks
models, which broke type checks against the regenerated catalog.
2026-09-28 00:22:39 +02:00
Armin Ronacher
237a4e80f1 feat(mcp,agent,codemode): expose toLlmContent and document agent-core usage
pi-mcp exports toLlmContent(), which converts a CallToolResult to pi-ai-shaped text and image content. The coding agent's MCP adapter uses it.

A typechecked example in packages/agent/examples/mcp-codemode shows a plain Agent with MCP tools and a codemode tool whose nested calls go through runToolCall() and the agent's hooks. The pi-mcp, pi-codemode, and pi-agent-core READMEs describe the same wiring.
2026-09-28 00:10:50 +02:00
Armin Ronacher
a6bc4036d7 feat(coding-agent): let extensions register MCP servers
pi.registerMcpServer(name, config) adds a server for the session with the mcp.json config shape; pi.unregisterMcpServer() removes it and pi.getMcpServers() lists registrations. Servers registered while loading connect on session_start, later ones right away. A server in mcp.json with the same name takes precedence and /mcp shows the override. Changes to registered servers in /mcp apply to the session only.

The mcp_servers_change event lets any MCP extension connect registered servers; when none handles it, registrations are reported as extension errors.
2026-09-27 23:50:53 +02:00
Armin Ronacher
e94c9763db feat(codemode,coding-agent): rename the exec tool back to codemode
The tool is named codemode again and scripts configure it with a first-line // @options: {...} instead of the // @exec: pragma. yield_time_ms is gone; max_output_tokens and timeout_ms remain. Comments, docs, and tests no longer describe the tool in terms of another agent.
2026-09-27 23:22:48 +02:00
Armin Ronacher
74393661e9 fix(coding-agent): let extensions replace built-in MCP, codemode, and tool search
Built-in extensions marked replaceable are left out when another extension registers the same tool, command, or flag name, so third-party MCP extensions such as pi-mcp-adapter take over /mcp instead of both connecting the same servers.

MCP only activates the codemode exec tool, not another extension's tool named exec, and the first prompt waits at most 10 seconds for startup connections.
2026-09-27 22:41:51 +02:00
Armin Ronacher
779f67895c feat(coding-agent): add pi mcp list, login, and logout commands
pi mcp list connects to every enabled server and reports its state, tools, and errors, exiting with 1 when anything fails, so agents can verify an mcp.json they wrote. pi mcp login runs the OAuth sign-in through the browser, and pi mcp logout deletes stored credentials. Running sessions reconnect servers waiting for a sign-in at the next turn when their credentials changed.

The system prompt points MCP questions to docs/mcp.md, which now covers setting up servers: which file to edit, rules that are easy to get wrong, converting entries from other clients, and verifying with pi mcp list.
2026-09-27 22:01:25 +02:00
Armin Ronacher
4951dcc376 feat(coding-agent): open an MCP server manager from /mcp
/mcp in the TUI lists every configured server with its state, tool count, exposure, and scope, servers that need attention first, and updates while they connect. Selecting a server shows its command or URL, config file, and full error, and offers the actions for its state: sign in (with a paste field for the redirect URL), tools, reconnect, sign out, exposure, and enable or disable. Exposure and enabled are saved to the mcp.json that defines the server.

Startup problems are reported once in the transcript, pointing to /mcp. Outside the TUI, /mcp prints the status, and /mcp login, logout, and the new reconnect subcommand stay available.
2026-09-27 21:40:00 +02:00
Armin Ronacher
2498ca492e refactor(agent,coding-agent): isolate codemode, tool search, and MCP from the core
The agent loop is back to main's tool execution: it only exports runToolCall(), honors isError results, and passes structuredContent through afterToolCall. Nested calls (ctx.executeTool, ids, events with parentToolCallId, the nestedCalls record) live in coding-agent and start on the first call.

AgentSession no longer knows exec or tool_search. Tools adjust the declared loadout through a generic prepareLoadout hook, and codemode and tool_search use it like any other tool.

exec and tool_search move to built-in extensions under src/extensions/ and register inactive (defaultActive: false). The CLI loads them with MCP; SDK sessions add createCodemodeExtension(), createToolSearchExtension(), and createMcpExtension(). Extensions gain pi.getSettings() and model catalog and classifier access on ModelRegistry.
2026-09-27 21:15:56 +02:00
Armin Ronacher
377cef09de fix(agent,coding-agent): simplify tool result contracts from the codemode review
- structuredContent after tool_result/afterToolCall: providing it replaces it; replacing content without it drops it. No more key-presence checks.
- Tools run outside a session get a ToolContext (loop services plus optional extension fields) instead of a context typed as a full ExtensionToolContext.
- Document that nested calls get synthesized <parent>/<n> tool call ids that never appear in the transcript.
- The exec description no longer mentions yield_time_ms, which is accepted and ignored.
- The sandbox abort test waits for the tool call instead of a fixed delay.
2026-09-27 19:31:57 +02:00
Armin Ronacher
42933fdb50 feat(ai,agent,coding-agent): emit events for nested tool calls and record them
Calls a tool makes through executeTool (for example from exec scripts) now emit tool_execution_start/update/end with parentToolCallId, for extensions and telemetry. Interactive mode keeps showing them inside the parent's row, and Agent.pendingToolCalls only tracks model-issued calls.

The model-issued call's tool result message carries nestedCalls, a bounded record like Codex's ExecutedToolCalls: name, arguments, status, duration, and error, never results. Arguments over 8 KiB per call or 32 KiB in total are omitted, at most 256 calls are kept, and complete is false when anything was lost or still running. Compaction and branch summaries count files touched by nested read/edit/write calls, and HTML exports list nested calls.
2026-09-27 19:14:50 +02:00
Armin Ronacher
188d3a4bd0 feat(coding-agent): add codemode.mode to present tools like Codex's tool modes
While exec is active, codemode.mode on (default) appends the exec declaration to declared tools that scripts can call and lists only non-direct tools in the exec description. codemode.mode only lists every callable tool in the exec description and hides active direct tools from requests. The hiding is a request projection, so the transcript still declares the active set and /tree and resume keep it.

The exec listing depends on exposure, not on the active set, so tool_search loads do not redeclare exec.
2026-09-27 19:07:25 +02:00
Armin Ronacher
fe07d21dde feat(coding-agent): add tool discovery for exec and a tool_search tool
- The exec description spends at most codemode.inlineBudget (default 3000) estimated tokens on tool declarations, filled round-robin across namespaces, cheapest first. Every namespace is listed with its tool count, and the listing says COMPLETE or PARTIAL.
- Scripts find omitted and deferred tools with searchTools(query, { limit, namespace }) and describeTool(name).
- tool_search, an optional built-in modeled on Codex, searches codemode and deferred tools and declares the matches for the next model call through the active tool set, so loads are recorded on the branch.
- Both use a BM25 ranker over Codex's search text (name, description, schema properties, namespace) behind a ToolRanker interface.
2026-09-27 18:48:47 +02:00
Armin Ronacher
3de4babe50 feat(codemode,coding-agent): make codemode a Codex-compatible exec tool
The codemode tool is now exec and follows the exec tool of OpenAI Codex, so scripts written for Codex run unchanged:

- // @exec: pragma with yield_time_ms, max_output_tokens (default 10000 tokens) and the pi addition timeout_ms; Codex's grammar and error messages
- text(), image() (data URLs, { image_url }, MCP ImageContent), exit(), ALL_TOOLS, tools under normalized identifiers; console and return values append text
- Results start with Script completed/failed and the wall time; failed scripts return an error result that keeps partial output and appends Script error
- Output over the token budget keeps its start and end like Codex; the full text is spilled to a temp file
- MCP tools resolve to their CallToolResult (isError resolves) and are declared as CallToolResult<T>; bash resolves to { output, exit_code, wall_time_seconds }, also for non-zero exits
- The description uses Codex's layout: helper list, deferred-tool guidance, shared MCP types, one section per tool grouped by namespace (MCP servers, with their instructions)
2026-09-27 18:00:33 +02:00
Armin Ronacher
4ccdc212e7 feat(agent,coding-agent): replace nestedOnly with tool exposure
AgentTool.nestedOnly is replaced by AgentContext.nestedTools, the tools callable through executeTool. Tool definitions declare an exposure (direct, model-only, codemode, deferred, hidden). The active set is now the declared set; codemode and deferred tools are callable from codemode whenever registered, so tree navigation, resume and fork cannot drop them.

MCP servers accept deferred and hidden exposure, withdraw tools by re-registering them as hidden, and mcp.json gains autoEnableCodemode.
2026-09-27 17:38:48 +02:00
Armin Ronacher
be49a2509d fix(mcp,coding-agent): bound SSE event data and report codemode spill errors
The SSE parser only limited the partial line, so a stream of short data: lines without a blank line could grow without bound. The event data size is now checked as lines arrive.

When saving a truncated codemode return value to a temp file fails, the truncation notice now names the error.
2026-09-27 17:38:40 +02:00
Armin Ronacher
d20d3ada42 fix(coding-agent): keep codemode MCP tools on tree navigation, cap codemode memory
Restoring tools from the transcript dropped nestedOnly tools because they are never declared to the model, so /tree navigation turned off codemode-exposed MCP tools. Active nestedOnly tools are now kept.

Codemode scripts now run with a 256 MiB QuickJS memory limit instead of growing up to the 4 GiB wasm32 ceiling inside pi's process.
2026-09-27 13:59:40 +02:00
Armin Ronacher
423b99797e fix(coding-agent): validate MCP server URLs and re-prompt sign-in on repeated 401
An invalid url made the OAuth store throw while creating connections, which
failed MCP startup for every server. OAuth servers that still answer 401
after a refresh now show as needing sign-in instead of failing each call.
2026-09-27 12:44:42 +02:00
Armin Ronacher
b9bbc35844 fix(coding-agent): make MCP connections and OAuth refresh reliable
- Share one OAuth refresh between concurrent requests and skip it when the
  token was already replaced, so rotating refresh tokens do not sign the
  user out; refresh tokens before they expire
- Treat insufficient_scope as needs-sign-in and request the new scope on
  /mcp login instead of refreshing
- Only list tools for servers that declare the tools capability
- Retry HTTP connects that fail transiently; show dropped connections as
  disconnected
- Deactivate tools a server withdraws on list_changed and restore them
- Keep sanitized tool names unique; default missing input properties
2026-09-27 12:41:07 +02:00
Armin Ronacher
6e6c5a9fe3 Merge branch 'main' into codemode-and-mcp
# Conflicts:
#	packages/coding-agent/install-lock/package-lock.json
#	packages/coding-agent/npm-shrinkwrap.json
2026-09-27 12:26:43 +02:00
Armin Ronacher
2b0a123de9 feat(coding-agent): remove themes section from startup banner 2026-09-26 14:37:30 +02:00
Armin Ronacher
bf8e4b9531
feat(coding-agent,tui): System theme (#10067)
* feat(coding-agent,tui): add system theme derived from terminal colors

The new default system theme builds pi's colors from the terminal's reported foreground, background, and ANSI palette. Tokens take their hue and relative saturation from a palette slot; lightness is placed by OKLab lightness difference and WCAG 2 contrast minimums. Terminals that report only a background get built-in hues, and terminals that report nothing get ANSI indices with faint secondary text.

The TUI queries OSC 10, 11, and 4 in one burst ended by DA1, so replies complete in one round trip, and reports replies that arrive after the timeout. Startup never waits: the system theme starts in grayscale and updates when colors arrive. Light/dark detection now uses the reported colors instead of the ?996 query; mode 2031 notifications trigger a new query.

* fix(coding-agent): wait for terminal colors before building the startup header

The header and startup notices bake theme colors into their text. When the color replies arrived after they were built, as in Windows Terminal, they stayed grayscale. Startup now waits for the first color query, which ends at the DA1 reply or after 100 ms.

* fix(coding-agent): rebuild header and notices on theme changes

The startup header, loaded resources, and chat notices baked theme colors into their text, so they kept the old colors after a theme switch or when the system theme received the terminal's colors. They now use ThemedText, which rebuilds its text from a function whenever the UI is invalidated.

* fix(tui): keep focus on components that forward mouse events to children

A component that forwards a mouse event to a child it hosts, such as SettingsList with an open submenu, left keyboard focus on the child. When the host removed the child, focus stayed on a detached component and all keys were lost. The forwarding component now keeps focus, like delegating containers do.

* feat(coding-agent): describe the system theme in the theme selector

* feat(coding-agent): list the system theme above automatic in the theme selector

* refactor(coding-agent,tui): remove leftovers of the light/dark startup detection

Theme detection only reports dark or light now; the source and confidence fields only served saving the detected theme. The first-time setup no longer shows the detected appearance. Removes the TUI's unused queryTerminalColorScheme(), queryTerminalBackgroundColor(), queryTerminalForegroundColor(), and parseOsc11BackgroundColor(); queryTerminalColors() covers them.

* feat(coding-agent): match the reviewed system and light/dark theme design

The system theme now follows the reviewed design: color families with OKHSL saturation curves, palette slots per family, contrast rules per token and panel, relaxation for mid-gray backgrounds, and the terminal foreground for body text. Each contrast level is a target-lightness curve fitted to the reviewed output. The built-in dark and light themes use the reviewed Pi dark and light colors.

* feat(coding-agent): show the pi logo in the startup header

A two-line pixel logo replaces the app name. Its first line carries the version, its second line the first line of key hints.

* feat(tui,coding-agent): support OKHSL colors in themes

parseColor() accepts okhsl(H S L), and okhslColor() and colorToOkhsl() construct and read OKHSL colors. OKHSL saturation is relative to the sRGB gamut, so every value is in gamut. Theme files accept okhsl() values; HTML exports convert them to hex. The OKHSL code moves from coding-agent into pi-tui, where colors.ts now shares its Oklab conversion instead of keeping a second copy.

* refactor(coding-agent): write the built-in themes in OKHSL

The built-in dark and light themes use okhsl() values, with variables for colors that several roles share, so they read as color families and serve as editable templates. Near-identical values collapsed into one; no color changes visibly.

* refactor(coding-agent,tui): simplify terminal color and theme code

Share the terminal color query between startup and the theme controller, merge the query's resolve/late-reply state into one callback, keep a single global for terminal colors, use oklab.ts arrays directly in colors.ts, and drop leftover helpers and exports.

* fix(coding-agent): use one terminal light/dark decision everywhere

Theme pairs, the system theme, and Theme.appearance now share getTerminalTheme(): the reported background decides, then the terminal's light/dark report, then COLORFGBG, then dark.

COLORFGBG is classified by palette index like Vim (0-6 and 8 dark) and only reads the last field, so rxvt's "default" no longer picks up the foreground index.

Simplify the tests added on this branch.

* fix(ai): use an OpenRouter model that still exists in beta test

OpenRouter removed anthropic/claude-3-haiku, which broke type checking in CI after model regeneration.
2026-09-26 13:33:47 +02:00
Armin Ronacher
7799d796df fix: harden nested tool calls, codemode, and MCP connections
- Serialize nested calls to sequential tools (or all nested calls in sequential mode) per tool batch.
- Let codemode run without a session manager, starting from an empty store.
- Resolve the MCP OAuth client secret only on token refresh, so one bad secret no longer blocks all servers.
- Report MCP transport errors without failing pending requests; a broken POST SSE stream fails only its request.
- Start a new MCP session and retry once when the server reports the session expired.
2026-09-25 17:42:07 +02:00
David Brailovsky
ab30693d64
fix(ai): upgrade openai SDK to 7.19.0 (#10044)
* fix(ai): upgrade openai SDK to 7.19.0

Adds the "fast" service tier to the SDK types, needed to price
GPT-6 Fast mode requests correctly. Drops the local
prompt_cache_options type, which the SDK now defines.

* fix(coding-agent): check Cloudflare compat request via fetch instead of SDK mock

pi-ai now resolves its own nested openai 7.x while evals keeps 6.x at the
root, so vi.mock("openai") in coding-agent no longer reached pi-ai's client.
Capture the outgoing request with a fake fetch and assert the URL and headers.

* fix(ai): drop any casts for stream_options and max_tokens in openai-completions

stream_options is typed by the SDK, so assign it directly. max_tokens is
deprecated by OpenAI but still needed for OpenAI-compatible providers
that reject max_completion_tokens; use a narrow cast instead of any to
avoid the deprecation warning.
2026-09-25 17:27:12 +02:00
David Brailovsky
ff72faba28 fix(coding-agent): save new session file at the first user message
A new session was only written to disk once the first assistant message
existed. If pi exited during the first turn (Ctrl+C twice while streaming,
or the process was killed), the user's prompt was lost and the session
never appeared in /resume.

The file is now created as soon as the session has a user or assistant
message. A session with only setup entries (model, thinking level) still
stays in memory, so starting pi and quitting without chatting leaves no
file. Forking uses the same rule through a shared helper, so the two paths
cannot drift apart and write the header twice (#1672).

closes #10000
2026-09-25 16:27:51 +02:00
Christian Klotz
ddba596187
fix(coding-agent): honor truecolor in custom themes (fixes #9973) (#10039) 2026-09-25 14:44:41 +01:00
Armin Ronacher
362e2bdc80 feat(coding-agent): spill truncated codemode results to a JSON temp file
Like bash output, a codemode result over 50KB or 2000 lines keeps its head in the tool result and writes the full return value as JSON to a pi-codemode-<id>.json temp file, referenced in the output and in details.fullOutputPath.
2026-09-25 15:02:51 +02:00
Armin Ronacher
350aa4674d feat(coding-agent): expose the model catalog and classifiers to codemode
Scripts get models.getModelsOfType/getAvailableOfType/getModelOfType/classify, mirroring ModelRuntime. The host resolves models by provider and id so scripts cannot redirect credentials, strips headers from listed models, and runs at most four classifications per script at once. pi-codemode gains namespaced globals, spread arguments, and explicit signatures.
2026-09-25 15:02:51 +02:00
Armin Ronacher
9163a000f2 feat(coding-agent): add @options source format and session store to codemode
Codemode input is now the script itself, optionally starting with a // @options {"timeout": N} line, and the tool declares a Lark grammar so capable models write raw JavaScript. Scripts can keep JSON values with store()/load(); successful writes are appended as codemode-store custom entries and read back from the current branch.
2026-09-25 15:02:51 +02:00
Armin Ronacher
de3491ff12 perf(coding-agent): load MCP and codemode runtimes on first use
The MCP client, transports, and OAuth code load only when mcp.json lists a server, and connecting starts after the first render. The codemode sandbox loads on the first script; the tool description only needs the new pi-codemode/declarations entry. TUI startup matches main again.
2026-09-25 15:02:51 +02:00
Armin Ronacher
b16d985d42 feat(codemode): run scripts in a QuickJS wasm VM inside the worker
Replaces the node:vm context with quickjs-wasi, so the sandbox is a separate wasm instance instead of a same-process V8 context. The worker stays to keep the host thread responsive; a shared interrupt flag stops spinning scripts on Bun, where worker.terminate() cannot interrupt wasm.

The Node bundle and the Bun binary build the worker as a separate entrypoint, and the Bun binary embeds quickjs.wasm.
2026-09-25 15:02:51 +02:00
Armin Ronacher
8cd0ed48de feat(coding-agent): add OAuth sign-in for remote MCP servers
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.
2026-09-25 15:02:51 +02:00
Armin Ronacher
e5a252c102 feat(coding-agent): highlight JSON return values in codemode output 2026-09-25 15:02:51 +02:00
Armin Ronacher
27d2914457 feat(coding-agent): connect MCP servers and expose them through codemode
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.
2026-09-25 15:02:51 +02:00