-
Notifications
You must be signed in to change notification settings - Fork 4.9k
fix: force kill MCP server processes on dispose to prevent orphan processes #7424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
|
The following comment was made by an LLM, it may be inaccurate: No duplicate PRs found |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request introduces force-kill process cleanup for MCP (Model Context Protocol) server processes to prevent orphan processes from accumulating when graceful shutdown fails. The change tracks local MCP server transports and forcefully terminates their processes after attempting graceful closure, addressing a memory leak issue where ~300MB+ processes could persist after OpenCode exits.
Key changes:
- Added
forceKillProcess()helper with platform-specific process termination (taskkill on Windows, SIGKILL on Unix) - Introduced
LocalTransportInfotype to track StdioClientTransport instances alongside MCP clients - Modified dispose and disconnect logic to force-kill processes after 2-second graceful close timeout
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| packages/opencode/src/mcp/index.ts | Core implementation: adds LocalTransportInfo tracking, forceKillProcess helper, and force-kill logic in dispose/disconnect flows |
| packages/opencode/test/mcp/process-cleanup.test.ts | Unit tests verifying PID tracking for local transports and client.close() invocation during disconnect |
Comments suppressed due to low confidence (1)
packages/opencode/src/mcp/index.ts:529
- When listTools fails during client creation, the code closes the MCP client but doesn't force kill the local process. If the graceful close fails (as described in the PR description), this could leave orphan processes. Consider adding force kill logic here as well, similar to the disconnect function, by checking if localTransport is defined and calling forceKillProcess after the failed close attempt.
if (!result) {
await mcpClient.close().catch((error) => {
log.error("Failed to close MCP client", {
error,
})
})
status = {
status: "failed",
error: "Failed to get tools",
}
return {
mcpClient: undefined,
localTransport: undefined,
status: {
status: "failed" as const,
error: "Failed to get tools",
},
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
1be530c to
a43aead
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
a43aead to
275599f
Compare
…cesses Track StdioClientTransport instances for local MCP servers to enable forceful process termination on dispose. The MCP SDK's client.close() relies on AbortController signals which don't work for all processes (e.g., docker containers without --init, hung processes). Changes: - Track LocalTransportInfo (transport + name) alongside MCP clients - Add forceKillProcess() helper for cross-platform process termination - Use taskkill on Windows, SIGKILL on Unix for forceful termination - Add timeout to client.close() calls to prevent hanging on dispose - Update connect() and disconnect() to track/cleanup local transports - Add tests for transport tracking and client lifecycle This prevents orphan MCP server processes from accumulating across sessions, which was causing significant memory usage (~300MB+ per orphan process). Related: anomalyco#7261
077dfab to
43e5068
Compare
Relates to #3013, #7261
Summary
forceKillProcess()helper for cross-platform process terminationProblem
The MCP SDK's
client.close()usesAbortController.abort()which may not work reliably for:--initflagSolution
Defensive fallback that only triggers if graceful close doesn't work:
client.close()with 2 second timeoutTesting
Added tests in
test/mcp/process-cleanup.test.ts.