Skip to content

fix(mcp): auto-fall-back to user-installed providers.json; backfill UNIFIED_PROVIDERS_CONFIG#162

Merged
jobordu merged 2 commits into
mainfrom
fix/unified-mcp-fallback-config
May 12, 2026
Merged

fix(mcp): auto-fall-back to user-installed providers.json; backfill UNIFIED_PROVIDERS_CONFIG#162
jobordu merged 2 commits into
mainfrom
fix/unified-mcp-fallback-config

Conversation

@jobordu
Copy link
Copy Markdown

@jobordu jobordu commented May 12, 2026

Summary

Closes the real root cause of the persistent unhealthy@1ms / error state in /nf:mcp-status that PRs #158 / #159 / #161 didn't fully address. Even on a fresh Claude Code session with all prior fixes pulled into main, every vanilla MCP slot still exits with Unknown PROVIDER_SLOT and never registers its tools.

Root cause

The mcpServers entries that /nf:mcp-setup historically created have only env: { PROVIDER_SLOT: <name> } — no UNIFIED_PROVIDERS_CONFIG. The MCP server defaults to __dirname/providers.json, which ships intentionally empty (populated at install time into ~/.claude/nf/bin/providers.json). So the spawned server sees zero providers, can't find its PROVIDER_SLOT, and exits before any tools register.

Fix

Two complementary changes:

1. bin/unified-mcp-server.mjs — when neither UNIFIED_PROVIDERS_CONFIG nor a populated repo-source providers.json is available, fall back to ~/.claude/nf/bin/providers.json. This self-heals existing user installs with zero install re-run required — the next session start picks up the right config.

Precedence: explicit env → populated repo source → user-installed copy.

2. bin/install.js — when creating mcpServers entries OR re-processing existing ones, set UNIFIED_PROVIDERS_CONFIG explicitly. Old entries get backfilled on next install so the env is self-documenting going forward.

Verified live

$ PROVIDER_SLOT=codex-1 node bin/unified-mcp-server.mjs
[mcp] Resolved codex: codex -> /Users/jonathanborduas/.nvm/.../bin/codex
[mcp] Resolved gemini: gemini -> /Users/jonathanborduas/.nvm/.../bin/gemini
[mcp] Resolved opencode: opencode -> /opt/homebrew/bin/opencode
[mcp] Resolved copilot: copilot -> /opt/homebrew/bin/copilot
[mcp] Resolved claude:  claude -> /Users/jonathanborduas/.local/bin/claude
[unified-mcp-server] started [slot: codex-1]
→ health_check returns: {"healthy":true,"latencyMs":38}

Previously: exited with Unknown PROVIDER_SLOT: codex-1 at session start.

Test plan

  • npm run test:ci — 1550 pass, 0 fail
  • npm run lint:isolation — clean
  • npm run check:assets — clean
  • Live: spawn server with only PROVIDER_SLOT env, no UNIFIED_PROVIDERS_CONFIG → starts cleanly, health_check returns healthy:true
  • After merge + restart Claude Code: /nf:mcp-status shows all 7 slots available

🤖 Generated with Claude Code

jobordu and others added 2 commits May 12, 2026 20:51
Even on a fresh Claude Code session with all merged fixes pulled, every
vanilla MCP slot (codex-1, gemini-1, opencode-1, copilot-1, claude-1)
exits with "Unknown PROVIDER_SLOT" on launch and never registers its
tools. Root cause:

The mcpServers entries in ~/.claude.json that /nf:mcp-setup created
historically have only `env: { PROVIDER_SLOT: <name> }` — no pointer to
where the per-slot config lives. unified-mcp-server defaults to
`__dirname/providers.json`, which ships intentionally empty (populated
at install time into ~/.claude/nf/bin/providers.json). So the spawned
server sees zero providers, can't find PROVIDER_SLOT, and exits.

Two complementary fixes:

1. bin/unified-mcp-server.mjs: when neither UNIFIED_PROVIDERS_CONFIG nor
   a populated repo-source providers.json is available, fall back to
   ~/.claude/nf/bin/providers.json. This self-heals existing user installs
   with no install re-run required.

2. bin/install.js: when creating new mcpServers entries OR re-processing
   existing ones, set UNIFIED_PROVIDERS_CONFIG explicitly to the
   user-installed path. Old entries get backfilled on next install so
   the env is self-documenting going forward.

Verified live: spawning the server with only `PROVIDER_SLOT=codex-1` (no
explicit config env) now resolves all 5 CLI binaries and health_check
returns healthy:true at 38ms — previously exited with "Unknown
PROVIDER_SLOT" at session start.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adding the loadProvidersConfig() helper shifted two pre-existing baselined
hashes by 28 lines (490→518, 920→948). Hashes unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 12, 2026 19:52
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

Warning

Rate limit exceeded

@jobordu has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 49 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1dd26e81-c735-4291-8bef-20b17eeb6b35

📥 Commits

Reviewing files that changed from the base of the PR and between 600908a and e1e00fa.

📒 Files selected for processing (3)
  • .secrets.baseline
  • bin/install.js
  • bin/unified-mcp-server.mjs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/unified-mcp-fallback-config

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@jobordu jobordu merged commit 49ca516 into main May 12, 2026
25 checks passed
Copy link
Copy Markdown

Copilot AI left a 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 PR fixes MCP slot startup failures by ensuring unified-mcp-server can always find a populated providers.json, even for older MCP entries that only set PROVIDER_SLOT. It introduces a runtime fallback to the user-installed providers config and updates the installer to explicitly set/backfill UNIFIED_PROVIDERS_CONFIG in ~/.claude.json.

Changes:

  • Add providers config resolution precedence in unified-mcp-server.mjs (env override → repo source if populated → user-installed copy).
  • Backfill UNIFIED_PROVIDERS_CONFIG into existing ~/.claude.json mcpServers entries during install, and set it for newly-created entries.
  • Refresh .secrets.baseline line references due to code movement.

Reviewed changes

Copilot reviewed 1 out of 3 changed files in this pull request and generated no comments.

File Description
bin/unified-mcp-server.mjs Adds config loading logic to fall back to the user-installed providers.json when the repo copy is empty/unset.
bin/install.js Ensures MCP server entries always include UNIFIED_PROVIDERS_CONFIG, including backfilling older entries.
.secrets.baseline Updates stored line numbers / generated timestamp after code shifts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

jobordu added a commit that referenced this pull request May 12, 2026
…mpty (#163)

PR #162 added a backfill loop that sets UNIFIED_PROVIDERS_CONFIG on
existing mcpServers entries — but it lives in the non-empty branch of
ensureMcpSlotsFromProviders, which never runs when bin/providers.json
(repo source) is empty. The empty case is the typical install state
(providers.json is populated at install time into ~/.claude/nf/bin/),
so the backfill never actually executed for any normal user.

Fix: add the same backfill inline in the empty-source branch, right
after the reconstructed providers.json is written. Iterates the same
mcpSlots list used to build the reconstructed file. Self-heals 5
vanilla entries (codex-1, gemini-1, opencode-1, copilot-1, claude-1)
on first install after this lands.

Verified live: stripped UNIFIED_PROVIDERS_CONFIG from 5 entries, ran
install, all 5 were backfilled cleanly.

Co-authored-by: jobordu <jonathan@jonathanborduas.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants