Bug
tool_blocklist in agent.toml does not prevent MCP tools from being presented to the LLM or executed. The agent can still call blocked tools successfully.
Steps to Reproduce
- Configure the ops agent with a
tool_blocklist for Notion write tools:
# agents/ops/agent.toml
tool_blocklist = [
"mcp_notion_api_patch_block_children",
"mcp_notion_api_patch_page",
"mcp_notion_api_post_page",
"mcp_notion_api_delete_block",
]
[capabilities]
tools = ["*"]
- Restart the daemon
- Ask the ops agent to write to a Notion page
- The agent successfully calls
mcp_notion_api_patch_block_children — the blocklist is ignored
Expected Behavior
- Blocked tools should be removed from the tool definitions sent to the LLM (so it doesn't even know they exist)
- If somehow called, blocked tools should return a permission denied error
Actual Behavior
- The LLM still sees all Notion tools including write tools
- The agent successfully executes
mcp_notion_api_patch_block_children
Investigation
The filtering logic in kernel.rs available_tools() (line ~4891) looks correct:
if !tool_blocklist.is_empty() {
all_tools.retain(|t| !tool_blocklist.iter().any(|b| b == &t.name));
}
Possible causes:
- TOML parsing issue:
tool_blocklist placed after [capabilities] gets parsed as capabilities.tool_blocklist (swallowed by serde #[serde(default)]). Moving it before [capabilities] didn't help either — the field may not be loading from agent.toml at all.
- Agent manifest loading: The
tool_blocklist field may not be deserialized from the on-disk agent.toml during agent registration/spawn. Need to verify the manifest loading path actually reads this field.
- MCP tool name mismatch: The actual MCP tool names at runtime may differ from what's in the blocklist. Need a way to inspect the exact tool names the MCP server registers.
Suggested Fix
- Add debug logging in
available_tools() to log the blocklist and which tools get filtered
- Verify
tool_blocklist round-trips through agent.toml → manifest deserialization
- Consider adding
GET /api/agents/{id}/available-tools endpoint that returns the post-filtered tool list (not just the config)
Environment
- Branch:
fix/all-tools-integration
- Notion MCP:
@notionhq/notion-mcp-server@2.2.1
Bug
tool_blocklistinagent.tomldoes not prevent MCP tools from being presented to the LLM or executed. The agent can still call blocked tools successfully.Steps to Reproduce
tool_blocklistfor Notion write tools:mcp_notion_api_patch_block_children— the blocklist is ignoredExpected Behavior
Actual Behavior
mcp_notion_api_patch_block_childrenInvestigation
The filtering logic in
kernel.rsavailable_tools()(line ~4891) looks correct:Possible causes:
tool_blocklistplaced after[capabilities]gets parsed ascapabilities.tool_blocklist(swallowed by serde#[serde(default)]). Moving it before[capabilities]didn't help either — the field may not be loading fromagent.tomlat all.tool_blocklistfield may not be deserialized from the on-diskagent.tomlduring agent registration/spawn. Need to verify the manifest loading path actually reads this field.Suggested Fix
available_tools()to log the blocklist and which tools get filteredtool_blocklistround-trips through agent.toml → manifest deserializationGET /api/agents/{id}/available-toolsendpoint that returns the post-filtered tool list (not just the config)Environment
fix/all-tools-integration@notionhq/notion-mcp-server@2.2.1