openclaw - ✅(Solved) Fix Bug: MCP stdio server processes orphaned on session end — 2.4GB RAM leak from context7-mcp [1 pull requests]

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…

MCP stdio servers using npx are spawned per-session but never cleaned up when sessions end. Over time, orphaned processes accumulate and consume significant RAM.

Error Message

The gateway should track child MCP server PIDs and send SIGTERM when the parent session/subagent exits, regardless of exit reason (completion, error, timeout, cancellation).

Root Cause

  1. MCP stdio protocol requires each client to spawn its own server process
  2. OpenClaw gateway spawns a new MCP server per session/subagent invocation
  3. When the session/subagent ends, the MCP server process is not terminated (no SIGTERM/SIGKILL sent)
  4. npx exacerbates this by spawning a parent npm process + child node process (double the overhead)

Fix Action

Workaround

Installing the MCP server globally (npm install -g @upstash/context7-mcp) and changing the config from:

"context7": {
  "command": "npx",
  "args": ["-y", "@upstash/context7-mcp", "--api-key", "..."] 
}

to:

"context7": {
  "command": "context7-mcp",
  "args": ["--api-key", "..."] 
}

This reduces per-process overhead (~40MB vs ~100MB) but does not fix the orphaning issue. Processes still accumulate; they just use less RAM each.

PR fix notes

PR #21: fix: dispose bundled MCP servers after every embedded run end

Description (problem / solution / changelog)

Root cause

MCP stdio servers spawned per session via npx were never cleaned up when sessions end because cleanupBundleMcpOnRunEnd was gated behind a flag that defaulted to false/unset. Orphaned processes accumulated unboundedly (reported 2.4GB RAM from a single context7-mcp instance, gateway OOM kill over time).

Fix

Always call disposeSessionMcpRuntime() in the run finally block, removing the conditional cleanupBundleMcpOnRunEnd flag. This makes session cleanup unconditional for all embedded runs.

Changes

  • run.ts: remove flag guard, always call disposeSessionMcpRuntime
  • params.ts: remove cleanupBundleMcpOnRunEnd from RunEmbeddedPiAgentParams
  • attempt-execution.ts / types.ts / agent-via-gateway.ts: remove flag propagation
  • e2e.test.ts / agent.test.ts: remove test references to the flag

Test coverage

Existing tests updated to remove the now-unnecessary cleanupBundleMcpOnRunEnd param; all other tests remain unchanged (cleanup is now unconditional, tests still pass).

Fixes #69465

Changed files

  • .agents/maintainers.md (removed, +0/-1)
  • .agents/skills/openclaw-parallels-smoke/SKILL.md (modified, +15/-0)
  • .agents/skills/openclaw-qa-testing/SKILL.md (modified, +10/-10)
  • .agents/skills/openclaw-release-maintainer/SKILL.md (modified, +12/-0)
  • .agents/skills/openclaw-secret-scanning-maintainer/SKILL.md (modified, +31/-12)
  • .agents/skills/openclaw-secret-scanning-maintainer/scripts/secret-scanning.mjs (modified, +274/-15)
  • .agents/skills/openclaw-test-performance/SKILL.md (added, +134/-0)
  • .agents/skills/openclaw-test-performance/agents/openai.yaml (added, +6/-0)
  • .github/actionlint.yaml (modified, +2/-0)
  • .github/actions/setup-node-env/action.yml (modified, +6/-6)
  • .github/actions/setup-pnpm-store-cache/action.yml (modified, +3/-16)
  • .github/instructions/copilot.instructions.md (modified, +3/-3)
  • .github/workflows/ci.yml (modified, +1247/-353)
  • .github/workflows/codeql.yml (modified, +8/-7)
  • .github/workflows/control-ui-locale-refresh.yml (modified, +2/-2)
  • .github/workflows/docker-release.yml (modified, +23/-15)
  • .github/workflows/docs-sync-publish.yml (modified, +2/-2)
  • .github/workflows/install-smoke.yml (modified, +14/-11)
  • .github/workflows/macos-release.yml (modified, +0/-1)
  • .github/workflows/openclaw-cross-os-release-checks-reusable.yml (added, +472/-0)
  • .github/workflows/openclaw-live-and-e2e-checks-reusable.yml (added, +658/-0)
  • .github/workflows/openclaw-npm-release.yml (modified, +12/-3)
  • .github/workflows/openclaw-release-checks.yml (modified, +113/-37)
  • .github/workflows/openclaw-scheduled-live-checks.yml (added, +74/-0)
  • .github/workflows/parity-gate.yml (modified, +11/-2)
  • .github/workflows/plugin-clawhub-release.yml (modified, +0/-3)
  • .github/workflows/plugin-npm-release.yml (modified, +0/-3)
  • .github/workflows/sandbox-common-smoke.yml (modified, +4/-1)
  • .github/workflows/workflow-sanity.yml (modified, +3/-1)
  • .oxlintrc.json (modified, +29/-2)
  • .pre-commit-config.yaml (modified, +2/-2)
  • .vscode/settings.json (modified, +2/-1)
  • AGENTS.md (modified, +199/-318)
  • CHANGELOG.md (modified, +257/-1)
  • CONTRIBUTING.md (modified, +5/-2)
  • Dockerfile (modified, +7/-1)
  • Dockerfile.sandbox (modified, +1/-1)
  • Dockerfile.sandbox-browser (modified, +1/-1)
  • README.md (modified, +252/-384)
  • SECURITY.md (modified, +5/-0)
  • appcast.xml (modified, +116/-0)
  • apps/android/app/build.gradle.kts (modified, +2/-2)
  • apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewayDiscovery.kt (modified, +36/-35)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/CanvasScreen.kt (modified, +2/-8)
  • apps/ios/CHANGELOG.md (modified, +16/-0)
  • apps/ios/Config/Version.xcconfig (modified, +2/-2)
  • apps/ios/Sources/Gateway/GatewayConnectionController.swift (modified, +2/-1)
  • apps/ios/Sources/Gateway/GatewaySettingsStore.swift (modified, +3/-1)
  • apps/ios/Sources/HomeToolbar.swift (modified, +4/-1)
  • apps/ios/Sources/Model/NodeAppModel.swift (modified, +79/-48)
  • apps/ios/Sources/Onboarding/OnboardingWizardView.swift (modified, +3/-1)
  • apps/ios/Sources/Services/WatchConnectivityTransport.swift (modified, +7/-4)
  • apps/ios/Sources/Services/WatchMessagingService.swift (modified, +11/-3)
  • apps/ios/Sources/Voice/TalkModeManager.swift (modified, +6/-2)
  • apps/ios/fastlane/metadata/en-US/release_notes.txt (modified, +1/-1)
  • apps/ios/version.json (modified, +1/-1)
  • apps/macos/Sources/OpenClaw/AppState.swift (modified, +52/-66)
  • apps/macos/Sources/OpenClaw/ChannelsStore+Lifecycle.swift (modified, +2/-1)
  • apps/macos/Sources/OpenClaw/CommandResolver.swift (modified, +7/-3)
  • apps/macos/Sources/OpenClaw/ExecApprovalCommandDisplaySanitizer.swift (modified, +15/-1)
  • apps/macos/Sources/OpenClaw/ExecApprovalsSocket.swift (modified, +2/-4)
  • apps/macos/Sources/OpenClaw/GeneralSettings.swift (modified, +3/-1)
  • apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift (modified, +1/-0)
  • apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntime.swift (modified, +32/-4)
  • apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntimeMainActorServices.swift (modified, +22/-0)
  • apps/macos/Sources/OpenClaw/NodeMode/MacNodeScreenCommands.swift (modified, +9/-0)
  • apps/macos/Sources/OpenClaw/NodePairingApprovalPrompter.swift (modified, +1/-2)
  • apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift (modified, +3/-1)
  • apps/macos/Sources/OpenClaw/RemoteGatewayProbe.swift (modified, +21/-12)
  • apps/macos/Sources/OpenClaw/RemotePortTunnel.swift (modified, +1/-3)
  • apps/macos/Sources/OpenClaw/Resources/Info.plist (modified, +2/-2)
  • apps/macos/Sources/OpenClaw/ScreenSnapshotService.swift (added, +109/-0)
  • apps/macos/Sources/OpenClawProtocol/GatewayModels.swift (modified, +18/-0)
  • apps/macos/Tests/OpenClawIPCTests/AppStateRemoteConfigTests.swift (modified, +56/-49)
  • apps/macos/Tests/OpenClawIPCTests/CommandResolverTests.swift (modified, +3/-0)
  • apps/macos/Tests/OpenClawIPCTests/ExecApprovalCommandDisplaySanitizerTests.swift (modified, +33/-0)
  • apps/macos/Tests/OpenClawIPCTests/MacNodeRuntimeTests.swift (modified, +101/-0)
  • apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift (modified, +37/-25)
  • apps/shared/OpenClawKit/Sources/OpenClawKit/ScreenCommands.swift (modified, +25/-0)
  • apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift (modified, +18/-0)
  • apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatComposerTextViewTests.swift (added, +15/-0)
  • docs/.generated/config-baseline.sha256 (modified, +4/-4)
  • docs/.generated/plugin-sdk-api-baseline.sha256 (modified, +2/-2)
  • docs/.i18n/glossary.zh-CN.json (modified, +24/-0)
  • docs/automation/cron-jobs.md (modified, +7/-1)
  • docs/automation/hooks.md (modified, +3/-1)
  • docs/automation/tasks.md (modified, +1/-1)
  • docs/channels/bluebubbles.md (modified, +1/-0)
  • docs/channels/groups.md (modified, +2/-2)
  • docs/channels/index.md (modified, +1/-1)
  • docs/channels/matrix.md (modified, +5/-3)
  • docs/channels/pairing.md (modified, +6/-0)
  • docs/channels/telegram.md (modified, +1/-1)
  • docs/channels/troubleshooting.md (modified, +2/-1)
  • docs/channels/wechat.md (added, +168/-0)
  • docs/ci.md (modified, +42/-28)
  • docs/cli/config.md (modified, +28/-0)
  • docs/cli/devices.md (modified, +9/-2)
  • docs/cli/gateway.md (modified, +21/-7)
  • docs/cli/hooks.md (modified, +1/-0)

Code Example

"context7": {
  "command": "npx",
  "args": ["-y", "@upstash/context7-mcp", "--api-key", "..."] 
}

---

"context7": {
  "command": "context7-mcp",
  "args": ["--api-key", "..."] 
}
RAW_BUFFERClick to expand / collapse

Summary

MCP stdio servers using npx are spawned per-session but never cleaned up when sessions end. Over time, orphaned processes accumulate and consume significant RAM.

Observed Behavior

On a 30GB RAM server, 41 orphaned context7-mcp processes were found consuming ~2.4GB of RAM total (~60-100MB each). Each subagent/session spawn creates a new npm exec @upstash/context7-mcp process chain that persists after the parent session ends.

Timeline of accumulation:

  • 19:30 → 6 processes
  • 19:39 → +3 (9 total)
  • 20:35 → +3 (18 total)
  • 23:32 → +9 (33 total, burst from parallel subagent spawns)
  • 23:49 → +3 (42 total)

Root Cause

  1. MCP stdio protocol requires each client to spawn its own server process
  2. OpenClaw gateway spawns a new MCP server per session/subagent invocation
  3. When the session/subagent ends, the MCP server process is not terminated (no SIGTERM/SIGKILL sent)
  4. npx exacerbates this by spawning a parent npm process + child node process (double the overhead)

Workaround

Installing the MCP server globally (npm install -g @upstash/context7-mcp) and changing the config from:

"context7": {
  "command": "npx",
  "args": ["-y", "@upstash/context7-mcp", "--api-key", "..."] 
}

to:

"context7": {
  "command": "context7-mcp",
  "args": ["--api-key", "..."] 
}

This reduces per-process overhead (~40MB vs ~100MB) but does not fix the orphaning issue. Processes still accumulate; they just use less RAM each.

Expected Behavior

The gateway should track child MCP server PIDs and send SIGTERM when the parent session/subagent exits, regardless of exit reason (completion, error, timeout, cancellation).

Environment

  • OpenClaw version: 2026.4.14
  • Host OS: Linux 6.8.0-110-generic (x64)
  • Host: Hetzner VPS, 32GB RAM
  • Session type: Telegram direct chat + subagent spawns

Related Issues

  • #60656 (same root cause, earlier report)
  • #69145 (cron session leak variant)
  • #65694 (MCP resource leak)

extent analysis

TL;DR

The most likely fix involves modifying the OpenClaw gateway to track and terminate orphaned MCP server processes when their parent sessions end.

Guidance

  • Investigate the OpenClaw gateway's process management to determine why it doesn't send a SIGTERM signal to MCP server processes when their parent sessions exit.
  • Consider implementing a mechanism to track child process PIDs and send SIGTERM signals when necessary, as described in the Expected Behavior section.
  • Evaluate the effectiveness of the proposed workaround, which reduces per-process overhead but doesn't address the underlying orphaning issue.
  • Review related issues (#60656, #69145, #65694) to identify potential patterns or solutions that could be applied to this problem.

Example

No code snippet is provided, as the issue doesn't contain sufficient information to create a concrete example.

Notes

The provided workaround reduces memory consumption but doesn't fix the root cause of the issue. A more comprehensive solution is needed to prevent orphaned processes from accumulating.

Recommendation

Apply the workaround to reduce memory consumption while investigating a more comprehensive solution to address the root cause of the issue. This will help mitigate the problem's impact on system resources.

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 Bug: MCP stdio server processes orphaned on session end — 2.4GB RAM leak from context7-mcp [1 pull requests]