claude-code - ✅(Solved) Fix [FEATURE] Pre-MCP-init hook so plugins can prepare shared infrastructure before .mcp.json is read [1 pull requests]

Official PRs (…)
ON THIS PAGE

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…

Fix Action

Fix / Workaround

  1. #24057 (MCP / hooks / plugins hot-reload on config change). If .mcp.json changes were picked up mid-session, the SessionStart hook could swap the config and the same session would pick it up. This solves the use case reactively rather than preventatively and would also be great to have.
  2. Pre-warm infrastructure at plugin install. Post-install script runs docker compose up -d. Invasive (runs outside Claude's context), doesn't help if Docker isn't running when Claude eventually opens, still needs a fallback.
  3. Current workaround — two-launch UX. Ship stdio as the default; swap to streamable-http on disk via SessionStart for the next session. Works, but every install and update costs one throwaway session.

PR fix notes

PR #7: fix: create graphify graph.json placeholder during rig init

Description (problem / solution / changelog)

Summary

  • Creates graphify-out/graph.json with {"nodes": [], "links": []} during rig init so the graphify MCP server doesn't crash at startup when no graph exists
  • Adds graphify-out/ to rig-managed .gitignore entries
  • Fixes gitignore migration to append missing entries to existing rig-managed sections (previously skipped if markers existed)

Root cause

Graphify's MCP server calls _load_graph() at startup and sys.exit(1) if the file is missing (serve.py:159 → :26). MCP servers initialize before SessionStart hooks run (confirmed via anthropics/claude-code#51148), so the hook can't create the file in time. rig init runs before any session, making it the correct insertion point.

Test plan

  • npx vitest run tests/cli/init.test.ts — 43/43 pass
  • Rebuilt and reinstalled in claude-rig, ai-news, my-claw
  • Verified placeholder created in all three projects
  • Verified gitignore migration works on existing installs (ai-news, my-claw)

🤖 Generated with Claude Code

Changed files

  • .claude/settings.json (modified, +3/-3)
  • src/cli/init.ts (modified, +25/-0)
  • tests/cli/init.test.ts (modified, +40/-0)

Code Example

{
  "hooks": {
    "PreMcpInit": [
      {
        "hooks": [
          { "type": "command", "command": "bash start-mcp-stack.sh", "timeout": 30 }
        ]
      }
    ]
  }
}
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing requests — closest is #24057 (MCP config hot-reload); this is a different, complementary ask
  • This is a single feature request

Problem Statement

.mcp.json is read once at session startup, before any plugin hook (including SessionStart) fires. This ordering makes it impossible for a plugin to prepare shared MCP infrastructure in time for the first session after install or update.

Concrete case: a plugin wants to run an MCP server as a shared, long-lived Docker container that all Claude Code windows connect to (via streamable-http on a fixed port), instead of each window spawning its own docker run --rm stdio container. Shared stack = lower RAM, faster startup, one place to debug.

The only way to ship this today is a two-file shuffle:

  1. Ship .mcp.json as stdio (safe default — docker run --rm is self-contained).
  2. SessionStart hook runs docker compose up -d in the background.
  3. Once the stack is healthy, the hook overwrites .mcp.json with a streamable-http config.
  4. The current session still uses the stdio containers it already spawned; the next session picks up streamable-http.

Net effect: every fresh install and every plugin update costs one "bad" session with random-name containers before the shared stack takes over. The ordering — not the plugin design — is what forces this.

Proposed Solution

Add a new hook event that fires before .mcp.json is read:

{
  "hooks": {
    "PreMcpInit": [
      {
        "hooks": [
          { "type": "command", "command": "bash start-mcp-stack.sh", "timeout": 30 }
        ]
      }
    ]
  }
}

Behavior:

  • Claude blocks on the hook up to a bounded timeout (configurable, default ~10s).
  • If the hook exits 0 within the timeout, Claude proceeds to read .mcp.json normally. The hook has had the chance to bring up whatever infrastructure the config points to.
  • If the hook times out or fails, Claude falls through to .mcp.json as today — no hang, graceful degrade.
  • Optionally: allow the hook to emit a replacement config path on stdout (e.g., MCP_CONFIG=/path/to/streamable-http.json) so plugins can pick the right config without mutating .mcp.json on disk.

Alternative Solutions

  1. #24057 (MCP / hooks / plugins hot-reload on config change). If .mcp.json changes were picked up mid-session, the SessionStart hook could swap the config and the same session would pick it up. This solves the use case reactively rather than preventatively and would also be great to have.
  2. Pre-warm infrastructure at plugin install. Post-install script runs docker compose up -d. Invasive (runs outside Claude's context), doesn't help if Docker isn't running when Claude eventually opens, still needs a fallback.
  3. Current workaround — two-launch UX. Ship stdio as the default; swap to streamable-http on disk via SessionStart for the next session. Works, but every install and update costs one throwaway session.

Priority

Medium — Would be very helpful

Feature Category

MCP server integration

Use Case Example

  1. Team ships an internal plugin bundling ~12 MCP servers (Jira, Oracle, Datadog, etc.) via a Docker compose stack.
  2. User runs /update-ai-tools. Plugin reinstalls, .mcp.json returns to the stdio default.
  3. User opens Claude Code. Claude reads stdio .mcp.json → each of the 12 MCP servers spawns its own docker run --rm container. SessionStart hook runs docker compose up -d in the background.
  4. User closes, reopens Claude. Now .mcp.json has been swapped to streamable-http by the hook. Claude connects to the shared mcp-* stack. From here, every window shares one stack.

With PreMcpInit, steps 3 and 4 collapse: the hook brings up the shared stack before Claude reads .mcp.json, so the first session already uses streamable-http and no per-session containers are ever spawned.

Additional Context

Claude Code version: 2.1.x (all recent) Platform: cross-platform (Windows/macOS/Linux) — the ordering constraint is platform-independent Related: #24057

extent analysis

TL;DR

Implement a PreMcpInit hook to run before .mcp.json is read, allowing plugins to prepare shared MCP infrastructure.

Guidance

  • Introduce a new hook event PreMcpInit that fires before .mcp.json is read, enabling plugins to set up necessary infrastructure.
  • Configure the PreMcpInit hook to run a command (e.g., bash start-mcp-stack.sh) with a bounded timeout (e.g., 10s) to bring up the shared stack.
  • If the hook succeeds, Claude proceeds to read .mcp.json normally; otherwise, it falls back to the current behavior.
  • Consider allowing the hook to emit a replacement config path on stdout to pick the right config without mutating .mcp.json on disk.

Example

{
  "hooks": {
    "PreMcpInit": [
      {
        "hooks": [
          { "type": "command", "command": "bash start-mcp-stack.sh", "timeout": 30 }
        ]
      }
    ]
  }
}

Notes

The proposed solution assumes that the PreMcpInit hook can be implemented without significant changes to the existing architecture. Alternative solutions, such as hot-reloading .mcp.json changes or pre-warming infrastructure at plugin install, may also be viable but have their own trade-offs.

Recommendation

Apply the proposed PreMcpInit hook workaround to enable plugins to prepare shared MCP infrastructure before .mcp.json is read, improving the user experience and reducing the need for throwaway 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

claude-code - ✅(Solved) Fix [FEATURE] Pre-MCP-init hook so plugins can prepare shared infrastructure before .mcp.json is read [1 pull requests]