From 217940dfdcac3ee0c535ec4df369fd175b014a0d Mon Sep 17 00:00:00 2001 From: pandadev66 Date: Sat, 9 May 2026 09:19:26 +0200 Subject: [PATCH] test(agents/bundle-mcp): assert live splitSdkTools customTools boundary in Docker e2e harness Extend the existing Pi bundle-MCP Docker e2e harness so the live stdio MCP probe also exercises `splitSdkTools` and asserts the configured server tool reaches `customTools` for coding/messaging and is filtered out for minimal and `tools.deny: ["bundle-mcp"]`. The harness already had real materialize plus profile-filter coverage against a real stdio MCP child, but did not assert the splitSdkTools().customTools boundary, which is the value the SDK serializes to the outbound provider request body and the disputed boundary on #76063. Refs #76063. --- .../e2e/pi-bundle-mcp-tools-docker-client.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/scripts/e2e/pi-bundle-mcp-tools-docker-client.ts b/scripts/e2e/pi-bundle-mcp-tools-docker-client.ts index 8a845b3438f..dce1f96cd95 100644 --- a/scripts/e2e/pi-bundle-mcp-tools-docker-client.ts +++ b/scripts/e2e/pi-bundle-mcp-tools-docker-client.ts @@ -12,6 +12,7 @@ import { getOrCreateSessionMcpRuntime, } from "../../dist/agents/pi-bundle-mcp-runtime.js"; import { applyFinalEffectiveToolPolicy } from "../../dist/agents/pi-embedded-runner/effective-tool-policy.js"; +import { splitSdkTools } from "../../dist/agents/pi-embedded-runner/tool-split.js"; import type { OpenClawConfig } from "../../dist/config/types.openclaw.js"; import { getPluginToolMeta } from "../../dist/plugins/tools.js"; @@ -136,6 +137,37 @@ async function main() { }); assert(denied.tools.length === 0, "expected tools.deny bundle-mcp to filter MCP tools"); + // The disputed boundary on #76063 is what reaches the SDK as `customTools`, + // since that is the exact value serialized to the outbound provider request. + // Prove the live stdio probe survives the materialize -> filter -> split chain + // through `splitSdkTools` for the same four profiles already asserted above. + const codingCustom = splitSdkTools({ tools: coding.tools, sandboxEnabled: false }).customTools; + const messagingCustom = splitSdkTools({ + tools: messaging.tools, + sandboxEnabled: false, + }).customTools; + const minimalCustom = splitSdkTools({ + tools: minimal.tools, + sandboxEnabled: false, + }).customTools; + const deniedCustom = splitSdkTools({ tools: denied.tools, sandboxEnabled: false }).customTools; + assert( + codingCustom.some((tool) => tool.name === probeTool.name), + "expected coding profile customTools to include bundle MCP tools", + ); + assert( + messagingCustom.some((tool) => tool.name === probeTool.name), + "expected messaging profile customTools to include bundle MCP tools", + ); + assert( + minimalCustom.length === 0, + "expected minimal profile customTools to exclude bundle MCP tools", + ); + assert( + deniedCustom.length === 0, + "expected tools.deny bundle-mcp customTools to exclude bundle MCP tools", + ); + process.stdout.write( JSON.stringify( { @@ -147,6 +179,18 @@ async function main() { minimal: minimal.tools.length, denied: denied.tools.length, }, + customToolsCounts: { + coding: codingCustom.length, + messaging: messagingCustom.length, + minimal: minimalCustom.length, + denied: deniedCustom.length, + }, + customToolNames: { + coding: codingCustom.map((tool) => tool.name), + messaging: messagingCustom.map((tool) => tool.name), + minimal: minimalCustom.map((tool) => tool.name), + denied: deniedCustom.map((tool) => tool.name), + }, }, null, 2,