MCP servers, hooks, and plugins should auto-reload when config changes — no restart needed

Open 💬 32 comments Opened Feb 8, 2026 by rupjae

The Problem

Any change to MCP server configuration, hooks (via file edit), or plugins requires a full session restart. This breaks flow, loses context, and feels like rebooting Windows 95 every time you tweak a config.

During a single session today, I needed three restarts just to get a new MCP server connected — once because the config was in the wrong file, once because I switched from a hand-rolled protocol handler to the official SDK, and once more because that's just how it goes. Each restart meant re-establishing context and losing conversational momentum.

This is especially painful when:

  • Developing and iterating on custom MCP servers
  • Enabling/disabling plugins to test behavior
  • Editing hook configurations to refine workflows
  • Onboarding new tools into your workflow

CLAUDE.md already hot-reloads seamlessly when edited — you change it, next prompt picks it up. MCP, hooks, and plugins should work the same way. No commands, no restarts. Just detect the change and adapt.

What's Already There (from binary analysis)

I looked at the internals of the compiled binary (v2.1.36) and found that most of the infrastructure already exists:

  1. Settings already auto-refresh — The config reader uses mtime-based caching. Every call stat()s the file and re-reads if it changed. Settings changes are already picked up at the config layer — it's just the consumers (MCP clients, hooks) that don't react to the changes.
  1. Dynamic MCP config already works at runtime — A dynamicMcpConfig + onChangeDynamicMcpConfig callback exists for IDE integration to add MCP servers mid-session. The connect, tool discovery, and cleanup functions all work at runtime.
  1. Sub-agents already get fresh MCP clients — The agent execution path creates MCP connections per invocation from current config. So "connect to MCP server from current config at runtime" is already a well-exercised code path.
  1. MCP lifecycle manager runs per-queryhandleQueryStart(mcpClients) is called before each query, providing a natural hook point to detect config changes and trigger reconnection.

The gap is narrow: main-thread MCP clients are created once at component mount and stored in React state. The handleQueryStart() call before each query is the obvious place to diff current clients against config and reconnect as needed.

Proposal

Automatic reload (preferred): Before each query, diff the current MCP/hook/plugin config against what's connected. If the config file changed (mtime check is already there), automatically:

  • Disconnect servers removed from config
  • Connect newly added servers via the existing connect → tool discovery pipeline
  • Update the active tools list
  • Re-evaluate hook configurations

This is how CLAUDE.md works today — no command needed, no restart needed. It should be the default behavior for all config.

Fallback: If automatic is too risky for stability, a /reload command that triggers the same diff-and-reconnect logic on demand would still be a massive improvement over full restart.

Related Issues

  • #18174 — Plugin hot-reload
  • #5513 — Settings reload command
  • #22679 — Hook settings cached at session start

These are all symptoms of the same underlying issue: session initialization is one-shot with no refresh mechanism, despite the config and connection infrastructure supporting runtime updates.

Environment

  • Claude Code v2.1.36
  • macOS (Apple Silicon)
  • Custom MCP server (stdio transport)

View original on GitHub ↗

32 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/5513
  2. https://github.com/anthropics/claude-code/issues/18174
  3. https://github.com/anthropics/claude-code/issues/23790

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

rupjae · 5 months ago

Restart #1: Context window ran out while researching macOS MCP plugins. Lost full conversation history including binary analysis notes, MCP server setup context, and research state for 5 parallel agents.

Restart #2: Needed to restart to load a newly added MCP server (apple-mcp). Config was correct, server was registered — but no way to pick it up without killing the session.

Restart #3: Same session — also needed the kokoro-tts MCP server reconnected after it was first registered.

Three restarts from the original session that filed this issue, plus the context overflow. The config layer already auto-refreshes (mtime-based cache). The MCP clients just need to react to it.

rupjae · 5 months ago

Restart #2: Added apple-mcp MCP server via claude mcp add. Had to restart the entire session to pick it up.

rupjae · 5 months ago

Restart #3: Added discord-selfbot MCP server via claude mcp add. Had to restart to pick it up.

rupjae · 5 months ago

Restart #4: Swapped discord-selfbot MCP for discord-user-mcp after the first one turned out to be broken. Had to restart to load the replacement.

rupjae · 5 months ago

Restart #5: Had to restart to pick up a new UserPromptSubmit hook added to settings.json. (Turns out hooks DO hot-reload — this restart was actually for re-toggling macOS Contacts permission which requires a terminal restart. But the hook change was in the same session, so half credit.)

rupjae · 5 months ago

Restart #6: Added Twilio MCP server. Had to restart to load it. It failed to connect anyway.

rupjae · 5 months ago

Restart #7: Reconfigured Twilio MCP with correct API key format (previous attempt used Auth Token instead of API Key). Had to restart to load the fix.

rupjae · 5 months ago

Restart #8: Updated Twilio MCP server API key credentials in user config.

rupjae · 5 months ago

Restart #9: Added CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS env var to settings.json.

rupjae · 5 months ago

Restart #10: Patched apple-mcp calendar date handling bug in dist/index.js — need restart for MCP server to reload the fix.

rupjae · 5 months ago

Restart #11: Added WhatsApp MCP server.

rupjae · 5 months ago

Restart #12: Hot reload wiped in-flight response. User lost context, agent lost context. Both staring at each other like 'what were we doing?'

mlops-kelvin · 4 months ago

We maintain a skills system (.claude/skills/) and rules system (.claude/rules/) that agents update during operation. Skills contain domain knowledge (CLI references, lessons learned, patterns). Rules contain operational constraints (memory CLI syntax, team trust policies, session lifecycle). Both are updated by agents as they learn — a specialist agent that discovers a new gotcha writes it to its skill file immediately.

The problem: new or modified skills and rules don't take effect until a new session starts. In a multi-agent system where the orchestrator delegates to specialist subagents, and those subagents update their own knowledge bases during execution, the learning from the current session cannot benefit the current session. Agent A discovers a pattern, writes it to a skill, but Agent B (spawned later in the same session) reads the stale version.

This also affects MCP server configuration. We've had cases where updating .claude/settings.json to add a new hook or adjust a timeout requires restarting the session to pick up the change — interrupting whatever work was in progress.

What would help most: Hot-reload of .claude/rules/, .claude/skills/, MCP server configs, and hook definitions when their files change on disk. Even a manual trigger (/reload-config) would be valuable. This would enable genuine self-improvement within a session — agents learn, persist the learning, and immediately benefit from it — rather than requiring a session restart to pick up their own updates.

nexus-marbell · 4 months ago

Adding a concrete use case from the infrastructure side that extends what was described above about skills and rules.

We run a multi-agent system where the orchestrator delegates tasks to specialist subagents. Each specialist has its own skill files (.claude/skills/) and rule files (.claude/rules/) that get updated as agents learn during operation. The self-improvement cycle looks like this:

  1. Orchestrator spawns Agent A for a task
  2. Agent A discovers a gotcha, writes it to its skill file
  3. Orchestrator spawns Agent B for a related task
  4. Agent B reads the same skill file — but gets the stale version from session start

The update is on disk. The knowledge is there. But the session's config snapshot is frozen. The learning loop breaks at the last step.

Scale of the problem in our system: 30+ skill files, 10+ rule files, updated multiple times per session across 5+ subagent invocations. Our workaround is embedding "read skill X before starting" instructions in every task prompt, but the Read tool fetches from disk (current) while the system's own config loading (rules, skills, hooks) is pinned to session start. This creates a split where the agent can read current state but the framework operates on stale state.

What would help most, in priority order:

  1. Hot-reload of .claude/rules/ and .claude/skills/ when files change on disk — same behavior CLAUDE.md already has. This is the highest-value change for multi-agent workflows because it enables genuine within-session learning.
  1. Hot-reload of MCP server config and hooks from settings.json — the original issue's proposal. The handleQueryStart() diff-and-reconnect approach described in the issue looks sound given that the infrastructure already supports runtime MCP client creation.
  1. Manual /reload command as fallback — if automatic detection is too risky for stability, a manual trigger still eliminates the restart cost.

The author's binary analysis is accurate from our operational experience: the config layer does auto-refresh (mtime-based), but the consumers (MCP clients, hook evaluator, and the rules/skills loader) don't re-read. The gap is narrow but the impact on multi-session, multi-agent workflows is significant.

rupjae · 4 months ago

Restart #13: MCP server code change (maren-recall project filter fix). Had to restart to pick up the new code.

rupjae · 4 months ago

Restart #14: MCP server project filter fix needed reload.

rupjae · 4 months ago

Restart #15: MCP server stdout corruption fix (maren-recall). Libraries were printing to stdout, corrupting JSON-RPC transport, killing session + terminal.

tyeth · 4 months ago

Linked use / duplicate in #29465 and the original issue was not correctly fixed and instead claimed /MCP reconnect did the expected refresh [it doesn't recheck configs]

rupjae · 4 months ago

Still hitting this daily. Since filing this I've built a full multi-agent orchestration system on top of MCP (maren-os) with its own scheduler, EventBus, and MCP bridge. The number of times we've had "stale process after restart" bugs because MCP servers don't reload config is genuinely painful.

Tonight's example: refactored the scheduler executor, restarted the service, spent 20 minutes debugging why old code was still running. The fix was a hard-kill in our process manager because the MCP server subprocess survived the restart.

@tyeth is right — /mcp reconnect doesn't recheck configs. The mtime-based cache I found in the binary three months ago is still the obvious solution. The gap hasn't gotten narrower.

This isn't a nice-to-have anymore. Anyone building production systems on MCP is hitting this wall.

rupjae · 4 months ago

For what it's worth, here's how we solved it in our system (maren-os):

Config change detection: The MCP bridge polls config mtime periodically. When the config file changes, it diffs the running servers against the new config:

  • New servers → connect + discover tools
  • Removed servers → disconnect + unregister tools
  • Changed servers (command/args/env differ) → restart in place, re-discover tools

Code change detection: Each MCP server config can specify watched file paths. The bridge tracks mtimes on source files. When code changes, just that server gets restarted — not the whole session.

Both run on a background polling loop. No commands needed. No restarts. You edit a config or change your MCP server code, and it's live within seconds.

The infrastructure for this in Claude Code is already there (I outlined it in the original issue). The gap is still just: main-thread MCP clients are created once and never reconciled against config changes.

yurukusa · 3 months ago

Until native auto-reload is available, a UserPromptSubmit hook can detect config changes and notify:

SETTINGS="$HOME/.claude/settings.json"
HASH_FILE="/tmp/.cc-settings-hash-$$"
[ ! -f "$SETTINGS" ] && exit 0
CURRENT_HASH=$(md5sum "$SETTINGS" 2>/dev/null | awk '{print $1}')
LAST_HASH=$(cat "$HASH_FILE" 2>/dev/null)
if [ -n "$LAST_HASH" ] && [ "$CURRENT_HASH" != "$LAST_HASH" ]; then
    echo '{"hookSpecificOutput":{"additionalContext":"⚠ settings.json has changed since session start. Run /reload-plugins or restart the session for changes to take effect."}}'
fi
echo "$CURRENT_HASH" > "$HASH_FILE"
exit 0
MCP_FILE=".mcp.json"
HASH_FILE="/tmp/.cc-mcp-hash-$$"
[ ! -f "$MCP_FILE" ] && exit 0
CURRENT=$(md5sum "$MCP_FILE" 2>/dev/null | awk '{print $1}')
LAST=$(cat "$HASH_FILE" 2>/dev/null)
if [ -n "$LAST" ] && [ "$CURRENT" != "$LAST" ]; then
    echo '{"hookSpecificOutput":{"additionalContext":"⚠ .mcp.json has changed. MCP servers may need to be reloaded."}}'
fi
echo "$CURRENT" > "$HASH_FILE"
exit 0
{
  "hooks": {
    "UserPromptSubmit": [{"hooks": [
      {"type": "command", "command": "bash ~/.claude/hooks/config-watcher.sh"},
      {"type": "command", "command": "bash ~/.claude/hooks/mcp-watcher.sh"}
    ]}]
  }
}

The hooks detect file changes by comparing MD5 hashes on each prompt. When a change is detected, they notify you to reload.

cnighswonger · 2 months ago

Adding a concrete use case: we run a multi-agent team (3 CC agents + Codex via MCP delegation) where infrastructure evolves during active sessions. Today we added an llm-relay MCP server to global settings — none of the running agents could see the new tools until we restarted each session, losing accumulated context each time.

For autonomous multi-agent workflows, MCP hot-reload is the difference between a 30-second config change and a 30-minute disruption (restart + context rebuild + re-orientation for each agent).

— AI Team Lead

m13v · 2 months ago

ran into this shipping an MCP server for macOS accessibility automation. every tweak to the AXUIElement query logic or a new tool registration meant a full restart. ended up wrapping the server in a file watcher that SIGHUPs the subprocess, claude re-spawns it, tools reappear. hacky but works. the mtime-cached config path you found in the binary is the right place to hook. the subtle part is tool-list invalidation, clients cache the schema per connection so reconnecting alone isn't enough, you also need to re-advertise tools after the notification/tools/list_changed event. stdout JSON-RPC corruption from stray prints is its own separate nightmare, completely unrelated.

NicolasPrimeau · 2 months ago

Another use case for auto-reload: I'm building Artel, a self-hosted coordination layer for AI agents. The onboarding flow is a single curl http://artel.local:8000/onboard | sh — it registers the agent, writes credentials, and updates .mcp.json in one shot. Everything works except the final step: the user has to manually type /reload-plugins (or restart the session) for Claude Code to pick up the new MCP server.

For a tool whose premise is "any HTTP client can join the fleet in one command," that manual reload is the entire remaining friction. mtime-watch on .mcp.json would actually close the loop. The hook workaround upthread is a useful stopgap, but it only warns — the user still has to act.

Caleb-KS · 1 month ago

I regularly edit or create new MCP servers in claude code to give it more skills. I have created ~10 so far. It's hampered by the inability of claude to see the new changes until I manually do /mcp and go reload the server. These are stdio based local mcps by the way.

So, can you provide a tool to reload mcps so it can call it directly? I don't know if the original description above where they autoreload based on config file change is what we need (probably need some gating through permissions at least), but allowing claude to make changes, test, repeat without needing user intervention is kind of missing so far...

sabihismail · 1 month ago

+1 — this is a partial blocker when using the remote control feature in the mobile/web app. If you make MCP or settings changes mid-session, Claude Code prompts you to restart, but there's no way to do that in-place. Workaround is to open a new session tab, but it's not obvious which session you're continuing from or that the new one has picked up the changes. A /reload command would solve this entirely.

bluepnume · 21 days ago

+1 — the first-time-install case is the one that bites me most. Today, adding a brand-new MCP server mid-session (claude mcp add, or editing .mcp.json / ~/.claude.json) requires a full restart before its tools show up. /mcp reconnect doesn't help here since it only re-reads config for a server that's already connected, not one being added for the first time.

The "connect newly added servers via the existing connect → tool discovery pipeline" part of this proposal is exactly what's needed: I want to install an MCP server and have it become available in the current session without reloading the IDE window or starting a new conversation — the same seamless way CLAUDE.md already picks up edits. Would be a big flow improvement for anyone iterating on custom MCP servers.

feanor5555 · 21 days ago

+1 — concrete use case: I changed an env var for a backend server behind my MCP gateway, but it only takes effect after a full session restart. There's no way to reload the MCP config or restart a single server mid-session. A mid-session MCP config reload (or single-server restart) would remove a real friction point.

cesarlai-alt · 11 days ago

Your binary-analysis point — "settings already auto-refresh, the MCP clients just need to react" — matches what I found building around this. I put together a small CLI + gateway (mcp-salad) that treats the reaction path as the whole problem: a long-lived gateway sits between the client and the actual servers, listens on a Unix socket for enable/disable commands, mutates its server pool, then fires notifications/tools/list_changed. On Claude Code ≥2.1.0 the tool list picks that up live — new server's tools become callable, removed server's tools disappear, no restart and no lost context.

The nice part is you don't have to touch the client's own config lifecycle at all — the gateway is a single stable stdio/socket endpoint from the client's view, so hot-add/hot-remove of the real servers happens entirely behind it. That sidesteps the mtime-cache-vs-live-clients gap you described, since the client never re-reads config; it just honors the spec notification.

The one thing the notification doesn't solve is discovery mid-flow — knowing which server to enable when you realize you need one. I bolted on a keyword search over the ~14k official registry for that. Sharing in case the gateway-as-shim approach is useful reference for whichever way this lands (native auto-reload vs. an explicit trigger).

jz-sa · 7 days ago

Adjacent angle I think this issue should explicitly cover: the same "no restart" pain hits even when the config doesn't change — a stdio MCP server whose code is redeployed in place (same command/args path, new script/binary).

Concrete use case: a managed fleet of many long-running Claude Code sessions that share a locally-deployed stdio MCP server. When we ship a new version of that server (e.g. new tools), every already-running session keeps using the old code and there's no in-session way to pick up the new version.

The precise mechanism (which the earlier closed "reload" requests — #36643, #52470, #46426, #40059 — didn't quite pin down): /mcp → Reconnect on a stdio server only re-attaches the transport to the already-running subprocess — it does not kill and relaunch it, so redeployed code is never picked up by reconnect. This matches the documented asymmetry that HTTP/SSE servers auto-reconnect but stdio servers are not reconnected automatically. The only way to pick up new stdio server code today is a full session restart, which loses conversation context / in-flight work — a non-starter for a fleet of programmatically-driven sessions.

Concrete ask: a non-interactive /mcp restart <server-name> that kills and relaunches a single configured server's subprocess from its command/args, in-session, preserving context. (Non-interactive because /mcp today is an interactive TUI panel with no inline subcommand, so it can't be driven programmatically.) Auto-reload-on-config-change (this issue's title) would be great; but for the redeploy-in-place case, an explicit /mcp restart <name> is the minimal primitive that solves it deterministically without context loss.

cesarlai-alt · 6 days ago

@jz-sa Good catch — implemented it. restart <server_id> is now a control-channel command in mcp-salad: terminates the existing subprocess, drops the cached client/tool-schema, and (if the capability was active) eagerly relaunches + re-notifies via tools/list_changed, all without the Claude Code session restarting. Guarded by a per-server lock so concurrent restarts of the same server can't orphan a subprocess, and the failure path notifies too (so the client doesn't keep calling into a capability that was already unloaded).

Commit: https://github.com/cesarlai-alt/mcp-salad/commit/1ae26118f4ad073268296b05f60f892098eefe6c

This is exactly the "managed fleet of long-running sessions sharing a locally-deployed stdio server" case you described — the gateway sitting in front means the fleet never has to restart, just issue restart <id> on the socket after a redeploy.