Add --disable-builtin-tools flag to disable built-in MCP tools#374
Conversation
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
There was a problem hiding this comment.
Pull Request Overview
This PR adds a --disable-builtin-tools flag to the serve command, allowing users to disable all built-in MCP management tools while keeping only loaded WebAssembly component tools available.
Key changes:
- Added new command-line flag to disable 12 built-in management tools (load-component, unload-component, permissions management, etc.)
- Modified server logic to conditionally exclude builtin tools from listings and reject their invocation when disabled
- Added comprehensive integration test to verify the feature works correctly
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/commands.rs | Added disable_builtin_tools boolean field to the Serve struct |
| src/main.rs | Updated McpServer to track the flag state and pass it to tool handlers |
| src/config.rs | Added default false value for the new flag in test configurations |
| crates/mcp-server/src/tools.rs | Implemented core logic to filter builtin tools from listings and reject their calls |
| tests/transport_integration_test.rs | Added integration test verifying builtin tools are properly disabled |
| CHANGELOG.md | Documented the new feature addition |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| let result = if disable_builtin_tools && is_builtin_tool(req.name.as_ref()) { | ||
| // When builtin tools are disabled, reject calls to builtin tools | ||
| Err(anyhow::anyhow!("Built-in tools are disabled")) | ||
| } else { | ||
| // Handle builtin tools (if enabled) or component calls | ||
| match req.name.as_ref() { | ||
| "load-component" if !disable_builtin_tools => { | ||
| handle_load_component(&req, lifecycle_manager, server_peer).await | ||
| } | ||
| "unload-component" if !disable_builtin_tools => { | ||
| handle_unload_component(&req, lifecycle_manager, server_peer).await | ||
| } | ||
| "list-components" if !disable_builtin_tools => { | ||
| handle_list_components(lifecycle_manager).await | ||
| } | ||
| "get-policy" if !disable_builtin_tools => { | ||
| handle_get_policy(&req, lifecycle_manager).await | ||
| } | ||
| "grant-storage-permission" if !disable_builtin_tools => { | ||
| handle_grant_storage_permission(&req, lifecycle_manager).await | ||
| } | ||
| "grant-network-permission" if !disable_builtin_tools => { | ||
| handle_grant_network_permission(&req, lifecycle_manager).await | ||
| } | ||
| "grant-environment-variable-permission" if !disable_builtin_tools => { | ||
| handle_grant_environment_variable_permission(&req, lifecycle_manager).await | ||
| } | ||
| "revoke-storage-permission" if !disable_builtin_tools => { | ||
| handle_revoke_storage_permission(&req, lifecycle_manager).await | ||
| } | ||
| "revoke-network-permission" if !disable_builtin_tools => { | ||
| handle_revoke_network_permission(&req, lifecycle_manager).await | ||
| } | ||
| "revoke-environment-variable-permission" if !disable_builtin_tools => { | ||
| handle_revoke_environment_variable_permission(&req, lifecycle_manager).await | ||
| } | ||
| "search-components" if !disable_builtin_tools => { | ||
| handle_search_component(&req, lifecycle_manager).await | ||
| } | ||
| "reset-permission" if !disable_builtin_tools => { | ||
| handle_reset_permission(&req, lifecycle_manager).await | ||
| } | ||
| _ => handle_component_call(&req, lifecycle_manager).await, | ||
| } |
There was a problem hiding this comment.
The logic is duplicated - builtin tools are checked twice (first in the if condition, then in each match arm guard). Consider simplifying by removing the guards from the match arms since builtin tools are already handled in the outer if condition.
| Ok(()) | ||
| } | ||
|
|
||
| #[test(tokio::test)] |
There was a problem hiding this comment.
The test attribute should be #[tokio::test] not #[test(tokio::test)]. The current syntax is incorrect and may not work as expected.
Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>
|
@copilot please resolve all the comments |
I've verified that the PR is in good shape:
Could you clarify which specific comments need to be resolved? I don't see any review comments or change requests in the current context. If there are specific issues or suggestions from code review, please point me to them so I can address them. |
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>
…soft#374) * Initial plan * Add --disable-builtin-tools flag to serve command Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com> * Refactor builtin tool checking to reduce code duplication Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com> * Simplify conditional logic in handle_tools_call Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com> * Addressing PR comments Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com> --------- Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com> Co-authored-by: Jiaxiao Zhou <duibao55328@gmail.com>
Overview
This PR addresses issue #XXX by adding a
--disable-builtin-toolsflag to theservecommand, allowing users to disable all built-in tools and only expose loaded WebAssembly component tools through the MCP server.Motivation
Some use cases require running Wassette with only custom component tools, without exposing the built-in management tools (load-component, unload-component, list-components, get-policy, permission management tools, etc.). This flag provides users with control over which tools are available through the MCP interface.
Changes
New Flag
--disable-builtin-toolsboolean flag to theservecommandImplementation Details
McpServerstruct to track the flag statehandle_tools_list()to conditionally exclude builtin tools from the responsehandle_tools_call()to reject builtin tool invocations with a clear error messageis_builtin_tool()helper function to centralize builtin tool name checkingBuilt-in Tools Affected
When
--disable-builtin-toolsis set, the following tools are disabled:load-componentunload-componentlist-componentsget-policygrant-storage-permissiongrant-network-permissiongrant-environment-variable-permissionrevoke-storage-permissionrevoke-network-permissionrevoke-environment-variable-permissionreset-permissionsearch-componentsTesting
Added comprehensive integration test
test_disable_builtin_toolsthat verifies:Example Usage
Backward Compatibility
This change is fully backward compatible. The flag defaults to
false, preserving existing behavior when not specified.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
example.com/home/REDACTED/work/wassette/wassette/target/debug/deps/transport_integration_test-e0a05ef8810ed925(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.