openclaw - ✅(Solved) Fix Claude CLI runner ignores user-configured `mcp.servers` from openclaw.json [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#70909Fetched 2026-04-24 10:37:59
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Participants
Timeline (top)
cross-referenced ×1

Claude CLI runner silently drops user-registered mcp.servers from openclaw.json. Servers registered via openclaw mcp set appear in openclaw mcp list, and Pi-embedded runs pick them up, but Claude CLI sessions never see their tools — the generated /tmp/openclaw-cli-mcp-*/mcp.json only contains bundled-plugin MCPs plus the openclaw loopback bridge.

Because Claude CLI is invoked with --strict-mcp-config --mcp-config /tmp/openclaw-cli-mcp-*/mcp.json, fallback channels (project-local .mcp.json, user-scope claude mcp add) are also ignored. Net effect: any MCP integration that isn't packaged as a bundled plugin is silently unusable under Claude CLI.

Hit this while building a local BG3 MCP server registered as bg3openclaw mcp list showed it; inside a Claude CLI session, none of its tools surfaced via ToolSearch.

Root Cause

prepareCliBundleMcpConfig in dist/prepare.runtime-*.js (source: src/agents/cli-runner/bundle-mcp.ts) only merges:

  1. loadEnabledBundleMcpConfig(...) — bundled plugin MCPs
  2. params.additionalConfig — the openclaw loopback bridge

It never reads cfg.mcp.servers.

Contrast with the Pi runtime, which does handle it (dist/pi-bundle-mcp-runtime-*.js around line 97):

const configuredMcp = normalizeConfiguredMcpServers(params.cfg?.mcp?.servers);
return {
  mcpServers: {
    ...bundleMcp.config.mcpServers,
    ...configuredMcp
  },

Fix Action

Fixed

PR fix notes

PR #70916: fix: merge configured mcp.servers into Claude CLI bundle config

Description (problem / solution / changelog)

Summary

Fixes #70909 — Claude CLI runner silently drops user-registered mcp.servers from openclaw.json.

prepareCliBundleMcpConfig (src/agents/cli-runner/bundle-mcp.ts) only merged bundled-plugin MCP configs and the OpenClaw loopback bridge into the generated --mcp-config overlay — it never read cfg.mcp.servers. Since Claude CLI is launched with --strict-mcp-config, servers added via openclaw mcp set never surfaced inside CLI sessions (even though Pi-embedded runs include them via normalizeConfiguredMcpServers in src/agents/embedded-pi-mcp.ts).

Change

  • Import normalizeConfiguredMcpServers and merge the normalized config.mcp.servers into the overlay after the bundled-plugin merge and before additionalConfig. The loopback bridge (additionalConfig) stays last, so the system loopback still overrides.
  • Added two test cases:
    • user-configured bg3 server appears alongside a bundled probe plugin
    • empty mcp.servers config is a no-op (covered by existing tests, no regression)

Test plan

  • pnpm tsgo:core (clean)
  • pnpm tsgo:core:test (clean)
  • node scripts/run-vitest.mjs run --config test/vitest/vitest.agents.config.ts src/agents/cli-runner/bundle-mcp.test.ts → 11 passed (1 new)
  • pnpm exec oxfmt --check on changed files
  • pnpm exec oxlint on changed files (0 warnings, 0 errors)
  • Manual: register server via openclaw mcp set → confirm tools surface inside a Claude CLI session via ToolSearch

Notes

Happy to adjust merge priority (e.g. let user config override bundled plugins, matching Pi-embedded's spread semantics) if that's preferred; left the current deep-merge order unchanged to minimize behavioral drift for bundled-plugin users.

Changed files

  • src/agents/cli-runner/bundle-mcp.test.ts (modified, +44/-0)
  • src/agents/cli-runner/bundle-mcp.ts (modified, +7/-0)

Code Example

const configuredMcp = normalizeConfiguredMcpServers(params.cfg?.mcp?.servers);
return {
  mcpServers: {
    ...bundleMcp.config.mcpServers,
    ...configuredMcp
  },
RAW_BUFFERClick to expand / collapse

Summary

Claude CLI runner silently drops user-registered mcp.servers from openclaw.json. Servers registered via openclaw mcp set appear in openclaw mcp list, and Pi-embedded runs pick them up, but Claude CLI sessions never see their tools — the generated /tmp/openclaw-cli-mcp-*/mcp.json only contains bundled-plugin MCPs plus the openclaw loopback bridge.

Because Claude CLI is invoked with --strict-mcp-config --mcp-config /tmp/openclaw-cli-mcp-*/mcp.json, fallback channels (project-local .mcp.json, user-scope claude mcp add) are also ignored. Net effect: any MCP integration that isn't packaged as a bundled plugin is silently unusable under Claude CLI.

Hit this while building a local BG3 MCP server registered as bg3openclaw mcp list showed it; inside a Claude CLI session, none of its tools surfaced via ToolSearch.

Root cause

prepareCliBundleMcpConfig in dist/prepare.runtime-*.js (source: src/agents/cli-runner/bundle-mcp.ts) only merges:

  1. loadEnabledBundleMcpConfig(...) — bundled plugin MCPs
  2. params.additionalConfig — the openclaw loopback bridge

It never reads cfg.mcp.servers.

Contrast with the Pi runtime, which does handle it (dist/pi-bundle-mcp-runtime-*.js around line 97):

const configuredMcp = normalizeConfiguredMcpServers(params.cfg?.mcp?.servers);
return {
  mcpServers: {
    ...bundleMcp.config.mcpServers,
    ...configuredMcp
  },

Suggested fix

One-liner in prepareCliBundleMcpConfig: merge normalizeConfiguredMcpServers(params.config?.mcp?.servers) into mergedConfig before additionalConfig is applied, so bundled plugins + user-configured servers both show up, and the loopback bridge retains override priority.

Happy to open a PR.

Repro

  1. openclaw mcp set foo <stdio-command> (any local MCP server)
  2. openclaw mcp listfoo is listed
  3. Start a Claude CLI session via OpenClaw gateway
  4. foo's tools never surface via ToolSearch
  5. Same server registered and invoked under a Pi-embedded run works fine

Environment

  • openclaw v2026.4.22 (npm global install)
  • Claude CLI backend (claude-cli/claude-opus-4-7)
  • Linux x64

extent analysis

TL;DR

The issue can be fixed by modifying the prepareCliBundleMcpConfig function to merge user-registered MCP servers into the mergedConfig before applying the additionalConfig.

Guidance

  • The root cause of the issue is that the prepareCliBundleMcpConfig function only merges bundled plugin MCPs and the openclaw loopback bridge, but not user-registered MCP servers.
  • To fix this, the normalizeConfiguredMcpServers function should be called with params.config?.mcp?.servers as an argument and the result merged into mergedConfig.
  • The suggested fix is to add a line to the prepareCliBundleMcpConfig function to merge the user-registered MCP servers into mergedConfig before applying additionalConfig.
  • The fix can be verified by registering a local MCP server using openclaw mcp set, starting a Claude CLI session, and checking if the server's tools surface via ToolSearch.

Example

const mergedConfig = {
  ...loadEnabledBundleMcpConfig(...),
  ...normalizeConfiguredMcpServers(params.config?.mcp?.servers),
  ...params.additionalConfig
};

Notes

The issue only affects Claude CLI sessions and not Pi-embedded runs. The fix should be applied to the prepareCliBundleMcpConfig function in the src/agents/cli-runner/bundle-mcp.ts file.

Recommendation

Apply the suggested workaround by modifying the prepareCliBundleMcpConfig function to merge user-registered MCP servers into mergedConfig. This will allow user-registered MCP servers to be visible in Claude CLI sessions.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Claude CLI runner ignores user-configured `mcp.servers` from openclaw.json [2 pull requests, 1 participants]