fix: render MCP tools via ToolExecutionComponent prototype patch (Pi 0.80.6+) - #31
Open
jeremynikolic wants to merge 2 commits into
Open
Conversation
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
marked this pull request as draft
July 14, 2026 20:42
jeremynikolic
marked this pull request as ready for review
July 21, 2026 11:20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On Pi 0.80.6+, MCP tools (pi-mcp-adapter direct tools and the
mcpproxy) stopped picking up pi-tool-display's rendering — they kept their original verbose renderers andmcpOutputModehad no effect on them. Built-in tools were fine.Why: two Pi API changes both broke the existing decoration paths.
pi.registerToolis now per-extension, so theregisterToolinterceptor on our own API never sees tools that other extensions register.pi.getAllTools()now returns shallow clones withoutrenderCall/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/getResultRendererto render MCP-candidate tools with our compact MCP renderers at render time. The component reads the livethis.toolDefinition(which still carrieslabel), so detection works regardless of how the tool was registered. Same prototype-patch technique we already use forUserMessageComponent, and it resolves to the same Pi instance via jiti's@earendil-works/*aliases. Built-ins are left to the original resolver (guarded bybuiltInToolDefinitionbeing undefined for MCP-only tools).Tested on Pi 0.80.6 with pi-mcp-adapter (solo, linear) and the
mcpproxy: calls render asMCP <tool> <n>args, results followmcpOutputMode(hidden / summary / preview) with Ctrl+O expansion. typecheck clean;npm testis 716 pass / 5 fail, with the 5 failures pre-existing onmainand unchanged here.Out of scope:
customToolOverridesfor non-MCP extension tools has the samegetAllTools-clone issue and could use the same render-time approach later.