feat: implement dynamic tool discovery via MCP notifications/tools/li…#8276
feat: implement dynamic tool discovery via MCP notifications/tools/li…#8276makanilani wants to merge 1 commit intoblock:mainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58ef3c786c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| let invalidator: Option<Arc<dyn ToolCacheInvalidator>> = | ||
| Some(Arc::clone(self) as Arc<dyn ToolCacheInvalidator>); |
There was a problem hiding this comment.
Break strong reference cycle when wiring tool invalidator
Passing Arc::clone(self) as the ToolCacheInvalidator creates a retain cycle: ExtensionManager holds each client in extensions, and each McpClient now holds a GooseClient that keeps this strong Arc<ExtensionManager> in tool_cache_invalidator (mcp_client.rs). When a session/agent is removed, this cycle prevents ExtensionManager and its clients from dropping, so child MCP processes and temp resources can leak across sessions. Please switch this back-reference to a Weak-based invalidator (or an explicit teardown path) so session cleanup can actually release clients.
Useful? React with 👍 / 👎.
|
Thanks for the PR — handling A few things to address before we can move forward:
/cc @alexhancock |
…st_changed
When MCP servers send notifications/tools/list_changed (e.g., Google Colab
servers that register tools dynamically), Goose now invalidates its tool
cache so the next agent turn sees the updated tool set.
Changes:
- Add ToolCacheInvalidator trait in mcp_client.rs
- Implement ToolCacheInvalidator for ExtensionManager
- Add tool_cache_invalidator field to GooseClient
- Implement on_tool_list_changed handler in GooseClient's ClientHandler impl
(overrides rmcp's default no-op)
- Thread invalidator reference through all MCP client construction paths
(StreamableHttp, Stdio, Builtin, InlinePython)
- Add unit tests for invalidator wiring
Architecture:
MCP Server → notifications/tools/list_changed
→ GooseClient::on_tool_list_changed() (new)
→ ExtensionManager::invalidate_tools_cache_and_bump_version() (existing)
→ Agent reads fresh tools on next turn via get_prefixed_tools()
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Signed-off-by: Yasu Sakakibara <ysakakibara@gmail.com>
58ef3c7 to
be77571
Compare
Pull Request
Title
feat: implement dynamic tool discovery via MCP notifications/tools/list_changed
URL
main...makanilani:goose:dynamic-tool-discovery
Description
Summary
When MCP servers send
notifications/tools/list_changed(e.g., Google Colab servers that register tools dynamically), Goose now invalidates its tool cache so the next agent turn sees the updated tool set.Problem
Currently, Goose calls
tools/listonce during initialization and never checks for updates. Thermcpcrate'sClientHandlertrait provideson_tool_list_changed()with a default no-op implementation, andGooseClientdoes not override it — so the notification is silently dropped.Changes
ToolCacheInvalidatortrait inmcp_client.rsToolCacheInvalidatorforExtensionManagertool_cache_invalidatorfield toGooseClienton_tool_list_changedhandler inGooseClient'sClientHandlerimpl (overrides rmcp's default no-op)Architecture
Files Changed
Cargo.lockcrates/goose/src/agents/mcp_client.rscrates/goose/src/agents/extension_manager.rsTesting
Observed Google colab mcp server works after the change.
Co-authored-by: Qwen-Coder qwen-coder@alibabacloud.com