Skip to content

fix: let subagents see asynchronously-registered extension tools (MCP)#141

Open
philipmw wants to merge 1 commit into
tintinweb:masterfrom
philipmw:subagents-mcp-tools
Open

fix: let subagents see asynchronously-registered extension tools (MCP)#141
philipmw wants to merge 1 commit into
tintinweb:masterfrom
philipmw:subagents-mcp-tools

Conversation

@philipmw

Copy link
Copy Markdown

Subagents could not use tools provided by MCP extensions (e.g. pi-mcp-extension), even though those tools work in the main agent. pi-mcp registers its tools asynchronously from its session_start handler, after connecting to MCP servers — never during synchronous extension load. runAgent, however, snapshotted extension.tools.keys() into a static tools: allowlist right after loader.reload() and before bindExtensions() fires session_start. In pi-mono that allowlist (allowedToolNames) is frozen at construction and gates the tool registry itself, so MCP tools — registered later — were dropped permanently, not just deactivated.

Scope extension tools via the session's live denylist instead of a frozen allowlist, matching how the main agent stays in sync. When extensions load and there is no ext: narrowing, pass tools: undefined (allowlist unset, so the live isAllowedTool gate admits tools whenever they register) and express scope as excludeTools = this extension's own orchestration tools + built-ins the agent didn't ask for + disallowedTools. Because an unset allowlist only activates pi's four default built-ins at turn 1, repair the active set post-bind via setActiveToolsByName(getAllTools()); tools registered later (lazy MCP servers) auto-activate through pi's refresh path. The static-allowlist path is retained unchanged for noExtensions/isolated and for ext: narrowing, where the exact set is known up front.

May solve issue #125.

I (the human) tested this manually by setting my local checkout of pi-subagents as the extension, then asking the LLM to spawn a subagent and use a search tool. Previously, it couldn't -- and now it can.

Subagents could not use tools provided by MCP extensions (e.g. pi-mcp-extension),
even though those tools work in the main agent. pi-mcp registers its tools
asynchronously from its session_start handler, after connecting to MCP servers —
never during synchronous extension load. runAgent, however, snapshotted
extension.tools.keys() into a static `tools:` allowlist right after loader.reload()
and before bindExtensions() fires session_start. In pi-mono that allowlist
(allowedToolNames) is frozen at construction and gates the tool *registry* itself,
so MCP tools — registered later — were dropped permanently, not just deactivated.

Scope extension tools via the session's live denylist instead of a frozen
allowlist, matching how the main agent stays in sync. When extensions load and
there is no `ext:` narrowing, pass `tools: undefined` (allowlist unset, so the
live isAllowedTool gate admits tools whenever they register) and express scope as
`excludeTools` = this extension's own orchestration tools + built-ins the agent
didn't ask for + disallowedTools. Because an unset allowlist only activates pi's
four default built-ins at turn 1, repair the active set post-bind via
setActiveToolsByName(getAllTools()); tools registered later (lazy MCP servers)
auto-activate through pi's refresh path. The static-allowlist path is retained
unchanged for noExtensions/isolated and for `ext:` narrowing, where the exact set
is known up front.

May solve issue tintinweb#125.

I (the human) tested this manually by setting my local checkout of pi-subagents
as the extension, then asking the LLM to spawn a subagent and use a search tool.
Previously, it couldn't -- and now it can.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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