Skip to content

fix: render MCP tools via ToolExecutionComponent prototype patch (Pi 0.80.6+) - #31

Open
jeremynikolic wants to merge 2 commits into
MasuRii:mainfrom
jeremynikolic:fix/mcp-render-via-tool-execution-prototype
Open

fix: render MCP tools via ToolExecutionComponent prototype patch (Pi 0.80.6+)#31
jeremynikolic wants to merge 2 commits into
MasuRii:mainfrom
jeremynikolic:fix/mcp-render-via-tool-execution-prototype

Conversation

@jeremynikolic

@jeremynikolic jeremynikolic commented Jul 14, 2026

Copy link
Copy Markdown

On Pi 0.80.6+, MCP tools (pi-mcp-adapter direct tools and the mcp proxy) stopped picking up pi-tool-display's rendering — they kept their original verbose renderers and mcpOutputMode had no effect on them. Built-in tools were fine.

Why: two Pi API changes both broke the existing decoration paths.

  • pi.registerTool is now per-extension, so the registerTool interceptor on our own API never sees tools that other extensions register.
  • pi.getAllTools() now returns shallow clones without renderCall / renderResult / label, so the session-start sweep mutates throwaway objects and never reaches the live definitions.

Built-ins still worked because they're re-registered (a fresh tool object goes through the registry), not mutated.

Fix: patch ToolExecutionComponent.prototype.getCallRenderer / getResultRenderer to render MCP-candidate tools with our compact MCP renderers at render time. The component reads the live this.toolDefinition (which still carries label), so detection works regardless of how the tool was registered. Same prototype-patch technique we already use for UserMessageComponent, and it resolves to the same Pi instance via jiti's @earendil-works/* aliases. Built-ins are left to the original resolver (guarded by builtInToolDefinition being undefined for MCP-only tools).

Tested on Pi 0.80.6 with pi-mcp-adapter (solo, linear) and the mcp proxy: calls render as MCP <tool> <n>args, results follow mcpOutputMode (hidden / summary / preview) with Ctrl+O expansion. typecheck clean; npm test is 716 pass / 5 fail, with the 5 failures pre-existing on main and unchanged here.

Out of scope: customToolOverrides for non-MCP extension tools has the same getAllTools-clone issue and could use the same render-time approach later.

MCP tool rendering broke on Pi 0.80.6+ for two independent reasons:

1. `pi.registerTool` is now a per-extension API object, so intercepting it
   on this extension's API no longer captures tools registered by other
   extensions (e.g. pi-mcp-adapter's direct tools). The interceptor only
   ever saw this extension's own registrations.
2. `pi.getAllTools()` returns shallow clones that omit `renderCall`,
   `renderResult`, and `label`, so the session_start/before_agent_start
   decoration sweep (`registerMcpToolOverrides`) mutated throwaway objects
   and never reached the live tool definitions in `_toolDefinitions`.

As a result, MCP direct tools (and the `mcp` proxy tool) kept their original
verbose renderers and `mcpOutputMode` had no effect on them. Built-in tools
were unaffected because they are re-registered (not mutated).

`ToolExecutionComponent` resolves the renderer per call via
`getCallRenderer()` / `getResultRenderer()`, reading the LIVE
`this.toolDefinition` (which still carries `label`). Patching those
prototype methods lets pi-tool-display render MCP-candidate tools with its
compact MCP renderers at render time, regardless of how the tool was
registered or whether `getAllTools()` exposes renderers. This mirrors the
existing `UserMessageComponent` prototype patch, and resolves against the
same Pi instance via jiti's `@earendil-works/*` aliases.

Built-in tools are left to the original resolver (guarded by
`builtInToolDefinition` being undefined for MCP-only tools), so per-tool
ownership and the diff/thinking renderers are unaffected.

Tested on Pi 0.80.6 with pi-mcp-adapter direct tools (solo, linear) and the
`mcp` proxy: call lines render as `MCP <tool> <n>args`, and results honor
`mcpOutputMode` (hidden/summary/preview) with Ctrl+O expansion.
@jeremynikolic
jeremynikolic marked this pull request as draft July 14, 2026 20:42
@jeremynikolic
jeremynikolic marked this pull request as ready for review July 21, 2026 11:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant