[BUG] Plugin update fails silently when MCP server holds open file handles; stale binary continues serving requests

Open 💬 0 comments Opened Jul 8, 2026 by jnbarlow

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When a plugin is updated while its MCP server process is running, the new files are not copied to ~/.claude/plugins/data/<plugin>/. The metadata (installed_plugins.json) shows the correct version, but the actual binary on disk remains stale. Every tool call returns errors from old code until manually fixed by killing and restarting the MCP process + copying files yourself.

What Should Happen?

Expected: New version is copied from cache → data dir and MCP server restarts with new code. Tool calls work correctly.

Error Messages/Logs

**Actual:** File copy fails silently because Node.js holds open file descriptors to the running binary. Old process continues serving requests with stale code. Every tool call returns errors even though metadata says latest version is installed.

Steps to Reproduce

Reproduction Steps

  1. Install any plugin with an MCP server (stdio-based) at version X.Y.Z
  2. Start Claude Code session → MCP server spawns, holds open file handles to dist/index.js and other files under ~/.claude/plugins/data/<plugin>/mcp-server/
  3. Publish new version (X+1).Y.Z with changed code in the same paths
  4. Run claude plugin update <name> or wait for auto-update during session reload
  5. Observe: metadata updated to X.Y.Z, but files under data dir still contain old code

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.202

Platform

Other

Operating System

Windows

Terminal/Shell

WSL (Windows Subsystem for Linux)

Additional Information

Root Cause

The plugin updater copies files from ~/.claude/plugins/cache/<author>/<name>/vX.Y.Z/ to ~/.claude/plugins/data/<plugin-id>/. On Linux, when a Node.js process has open file handles (which the MCP server does for its own binary), in-place overwrites fail silently. The copy tool skips locked files without logging an error or updating status.json.

Additionally, there is no mechanism to kill and restart MCP servers after plugin updates — even if you bounce Claude Code entirely, stale files remain on disk so the new process loads old code again.

Impact

  • Silent failure: User sees correct version in claude plugin list but gets errors from tools. No indication that update failed mid-copy.
  • No workaround without manual intervention: Killing Claude Code does NOT fix it (stale files persist). Must manually kill MCP process, copy new files to data dir, then restart session.
  • Affects ALL plugins with persistent MCP servers, not just one plugin — any stdio-based MCP server that holds open file handles will exhibit this behavior.

Suggested Fixes

  1. Kill and restart affected MCP servers during update: Before copying new files, terminate processes for the updated plugin. Copy files to a temp directory first, then rename atomically (rename is atomic on same filesystem; avoids partial-copy race conditions). Restart MCP server with new code after copy completes successfully.
  2. Add claude mcp restart <name> command: Allow hot-reloading individual MCP servers without bouncing the entire session for debugging plugin updates and verifying changes in development workflows.
  3. Log errors when file copy fails during update instead of silently skipping locked files — user should know their update partially failed so they can take action.

View original on GitHub ↗