MCP server tools never reach outbound tools[] across 4.26 → 5.7 (cluster previously closed + locked as "resolved")
Summary
Configured mcp.servers entries do not appear in the agent's outbound LLM request body's tools[] array, on every stable release tested from 2026.4.26 through 2026.5.7 (latest at filing). The MCP servers themselves are healthy — they spawn, register, and respond to direct stdio tools/list and tools/call cleanly with real results. Only the path from "openclaw materializes the catalog" to "OpenAI-format chat-completions request body" fails.
This issue exists because the predecessor cluster (#74387, #74726, #74844) was closed three times — twice as "already implemented" by automated review, then locked as resolved — despite wire-level evidence to the contrary posted by two independent users including at least one additional environment beyond a single-machine repro.
Why a fresh issue
All three predecessor issues are now closed + locked with lock_reason: "resolved":
Each was auto-closed by clawsweeper after static-analysis review citing the same code paths that ship with the bug intact. Locking eliminated the only feedback channel into the cluster. The bug is still present; opening a fresh canonical issue is the only available path.
Environment
- OpenClaw:
2026.5.7 (eeef486)
- Node.js:
v22.22.2
- macOS:
26.4.1
- Install method:
npm i -g openclaw@2026.5.7
- Agent runtime: embedded (Pi)
- MCP servers configured: two stdio servers, both verified healthy
tools.profile: coding
plugins.allow: contains explicit plugin ids; allow list verified loaded via openclaw plugins list
Reproduction
- Configure two stdio MCP servers under
mcp.servers.
- Verify each starts and responds:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize",...}' | <command from mcp.servers.<id>.command>
Returns full tools/list (50+ tools across the two servers in our case).
openclaw mcp list confirms both servers configured.
openclaw plugins inspect <pluginId> shows Status: loaded for each configured MCP server.
- Start the gateway and trigger one agent turn (any normal channel — iMessage/BlueBubbles in our case).
- Capture the outbound
https://openrouter.ai/api/v1/chat/completions request body via the built-in debug proxy (OPENCLAW_DEBUG_PROXY_ENABLED=1 + OPENCLAW_DEBUG_PROXY_URL=...).
- Inspect
body.tools[] — no server__* entries, only bundled openclaw tools (read, write, exec, sessions_*, web_search, web_fetch, etc.).
Longitudinal data (7 stable releases)
Each row is an independently verified test run, configuration unchanged, MCP servers verified healthy each time:
| Version |
Tested |
tools[] contains server__* |
Agent behavior |
| 2026.4.26 |
yes |
❌ |
"I don't have access to outlook tools" (honest failure) |
| 2026.4.27 (cited as "fixed", cbc2ba0) |
yes |
❌ |
Silent confabulation — fabricates plausible-sounding email lists with no overlap to reality |
| 2026.5.2 (cited as "fixed", 8b2a6e5) |
yes |
❌ |
Silent confabulation |
| 2026.5.7 (current, eeef486) |
yes |
❌ |
Reverts to honest admission — tries shell exec workaround, hits "openclaw: not found" |
Cost-tracker confirms one LLM call per agent turn in every test (no tool round-trip occurred). Input token count stable at ~48–72k across versions — consistent with no MCP tool definitions in the prompt (which would add ~20–30k for the configured server count).
Wire evidence
The captured outbound request body from 2026.4.26 (redacted, messages[] stripped) is inlined in #74844 (it's locked but still readable). The tools[] array contains exactly 15 entries — all bundled OpenClaw tools. Zero server__* entries.
I can re-capture on 5.7 if it would help maintainers — we observed event-loop stalls with the debug proxy attached on some recent releases, so we've been using cost-tracker telemetry as the cleaner signal in subsequent tests. Same evidence shape either way.
What works at every layer
Every layer between config and provider serialization passes its own test:
mcp.servers populated, valid JSON, dmPolicy and credential resolution working
openclaw mcp list lists both servers
- MCP server child processes spawn (visible in
ps aux)
- Direct stdio probe of each server returns full
tools/list (verified each test)
- Direct stdio probe of
tools/call outlook_list_inbox returns real inbox data (verified each test)
openclaw plugins inspect <id> reports Status: loaded for every configured MCP plugin
- Built-in OpenClaw tools (
read/write/exec/sessions_*/web_search/web_fetch) DO appear in outbound tools[] — so the serializer works, just not for MCP tools
- Gateway log shows
BlueBubbles (or whichever channel) catchup, webhook, and inbound delivery all working
The failure is silent: no warning in gateway.log, no error in gateway.err.log, openclaw doctor reports the system clean.
Code paths cited by previous closures
The clawsweeper static review of each predecessor cited these as the implementation:
src/agents/bundle-mcp-config.ts:49 — loadMergedBundleMcpConfig
src/agents/command/attempt-execution.ts:457 — runEmbeddedPiAgent
src/agents/pi-embedded-runner/run/attempt.ts:908 — embedded attempt materializing bundle-MCP tools and appending to effectiveTools
src/agents/pi-embedded-runner/run/attempt.ts:1358 — converting effectiveTools into Pi customTools and session allowlist
src/agents/pi-bundle-mcp-materialize.ts:64 — materializeBundleMcpToolsForRun
src/agents/tool-catalog.ts:316 — coding/messaging profile includes bundle-mcp
These code paths likely exist and run, but something between materialization and the final OpenAI-format serialization drops the MCP tools. The cost-tracker single-LLM-call-per-turn pattern across 7 versions rules out "tool was attempted but execution failed."
Things I have ruled out (tested each)
tools.profile — tried coding, messaging, full. Same result on all.
tools.alsoAllow: ["outlook__*","gmail__*"] at root and under tools.sandbox.tools. No effect.
plugins.allow containing outlook, gmail, mcp — flagged as stale-not-a-plugin and ignored.
mcp.sessionIdleTtlMs: 0 (prevent idle eviction). MCP processes stay resident; tools still missing.
- Multiple gateway restarts.
openclaw doctor, openclaw doctor --fix. No MCP-related findings.
- Bundled vs external plugin: the BlueBubbles plugin moved from bundled to npm in 5.x; reinstalling and reconnecting did not affect MCP tool exposure.
Ask
@steipete @vincentkoc — clawsweeper named both of you as the owners of the embedded Pi MCP exposure path across the closure comments on #74387 and #74844. This bug has now persisted through seven stable releases with two automated "already implemented" closures and a lock as "resolved" despite consistent wire-level falsifying evidence from at least two independent users (myself and @luuq2026).
A human pair of eyes on this would be valuable. Concrete options:
- Quick check: add an integration test that asserts
body.tools[] includes configured server__* entries when mcp.servers is populated. If such a test already exists and is passing, the test does not exercise the same code path users hit.
- Diagnostic ask: what specific config shape or environment is the existing integration coverage exercising? My setup uses iMessage/BlueBubbles inbound, Gemini 2.5 Pro via OpenRouter,
tools.profile: coding, two stdio MCP servers. If yours uses something different, that's the clue.
- Reproduce: I'm happy to capture a fresh debug-proxy wire capture on 5.7, or any other artifact you'd like. Just say what's most useful.
The three locked predecessors should ideally be unlocked and linked back to this issue once a human triage decision is made — but that's an optional cleanup.
MCP server tools never reach outbound
tools[]across 4.26 → 5.7 (cluster previously closed + locked as "resolved")Summary
Configured
mcp.serversentries do not appear in the agent's outbound LLM request body'stools[]array, on every stable release tested from 2026.4.26 through 2026.5.7 (latest at filing). The MCP servers themselves are healthy — they spawn, register, and respond to direct stdiotools/listandtools/callcleanly with real results. Only the path from "openclaw materializes the catalog" to "OpenAI-format chat-completions request body" fails.This issue exists because the predecessor cluster (#74387, #74726, #74844) was closed three times — twice as "already implemented" by automated review, then locked as
resolved— despite wire-level evidence to the contrary posted by two independent users including at least one additional environment beyond a single-machine repro.Why a fresh issue
All three predecessor issues are now
closed + lockedwithlock_reason: "resolved":Each was auto-closed by
clawsweeperafter static-analysis review citing the same code paths that ship with the bug intact. Locking eliminated the only feedback channel into the cluster. The bug is still present; opening a fresh canonical issue is the only available path.Environment
2026.5.7 (eeef486)v22.22.226.4.1npm i -g openclaw@2026.5.7tools.profile:codingplugins.allow: contains explicit plugin ids; allow list verified loaded viaopenclaw plugins listReproduction
mcp.servers.tools/list(50+ tools across the two servers in our case).openclaw mcp listconfirms both servers configured.openclaw plugins inspect <pluginId>showsStatus: loadedfor each configured MCP server.https://openrouter.ai/api/v1/chat/completionsrequest body via the built-in debug proxy (OPENCLAW_DEBUG_PROXY_ENABLED=1 + OPENCLAW_DEBUG_PROXY_URL=...).body.tools[]— noserver__*entries, only bundled openclaw tools (read, write, exec, sessions_*, web_search, web_fetch, etc.).Longitudinal data (7 stable releases)
Each row is an independently verified test run, configuration unchanged, MCP servers verified healthy each time:
tools[]containsserver__*Cost-tracker confirms one LLM call per agent turn in every test (no tool round-trip occurred). Input token count stable at ~48–72k across versions — consistent with no MCP tool definitions in the prompt (which would add ~20–30k for the configured server count).
Wire evidence
The captured outbound request body from 2026.4.26 (redacted,
messages[]stripped) is inlined in #74844 (it's locked but still readable). Thetools[]array contains exactly 15 entries — all bundled OpenClaw tools. Zeroserver__*entries.I can re-capture on 5.7 if it would help maintainers — we observed event-loop stalls with the debug proxy attached on some recent releases, so we've been using cost-tracker telemetry as the cleaner signal in subsequent tests. Same evidence shape either way.
What works at every layer
Every layer between config and provider serialization passes its own test:
mcp.serverspopulated, valid JSON,dmPolicyand credential resolution workingopenclaw mcp listlists both serversps aux)tools/list(verified each test)tools/call outlook_list_inboxreturns real inbox data (verified each test)openclaw plugins inspect <id>reportsStatus: loadedfor every configured MCP pluginread/write/exec/sessions_*/web_search/web_fetch) DO appear in outboundtools[]— so the serializer works, just not for MCP toolsBlueBubbles(or whichever channel) catchup, webhook, and inbound delivery all workingThe failure is silent: no warning in
gateway.log, no error ingateway.err.log,openclaw doctorreports the system clean.Code paths cited by previous closures
The
clawsweeperstatic review of each predecessor cited these as the implementation:src/agents/bundle-mcp-config.ts:49—loadMergedBundleMcpConfigsrc/agents/command/attempt-execution.ts:457—runEmbeddedPiAgentsrc/agents/pi-embedded-runner/run/attempt.ts:908— embedded attempt materializing bundle-MCP tools and appending toeffectiveToolssrc/agents/pi-embedded-runner/run/attempt.ts:1358— convertingeffectiveToolsinto PicustomToolsand session allowlistsrc/agents/pi-bundle-mcp-materialize.ts:64—materializeBundleMcpToolsForRunsrc/agents/tool-catalog.ts:316—coding/messagingprofile includesbundle-mcpThese code paths likely exist and run, but something between materialization and the final OpenAI-format serialization drops the MCP tools. The cost-tracker single-LLM-call-per-turn pattern across 7 versions rules out "tool was attempted but execution failed."
Things I have ruled out (tested each)
tools.profile— triedcoding,messaging,full. Same result on all.tools.alsoAllow: ["outlook__*","gmail__*"]at root and undertools.sandbox.tools. No effect.plugins.allowcontainingoutlook,gmail,mcp— flagged as stale-not-a-plugin and ignored.mcp.sessionIdleTtlMs: 0(prevent idle eviction). MCP processes stay resident; tools still missing.openclaw doctor,openclaw doctor --fix. No MCP-related findings.Ask
@steipete @vincentkoc —
clawsweepernamed both of you as the owners of the embedded Pi MCP exposure path across the closure comments on #74387 and #74844. This bug has now persisted through seven stable releases with two automated "already implemented" closures and a lock as "resolved" despite consistent wire-level falsifying evidence from at least two independent users (myself and @luuq2026).A human pair of eyes on this would be valuable. Concrete options:
body.tools[]includes configuredserver__*entries whenmcp.serversis populated. If such a test already exists and is passing, the test does not exercise the same code path users hit.tools.profile: coding, two stdio MCP servers. If yours uses something different, that's the clue.The three locked predecessors should ideally be unlocked and linked back to this issue once a human triage decision is made — but that's an optional cleanup.