id: task-299 title: 'Fix MCP initialization for multiple AI coding agents (Codex, Gemini, Claude)' status: Done assignee:
- '@codex' created_date: '2025-10-16 20:07' updated_date: '2025-10-17 19:22' labels:
- mcp
- init
- multi-agent-support dependencies: [] priority: high
Description
Why
When users initialize Backlog MCP on multiple projects, Codex CLI shows "1 success + N failures" because it uses global-only configuration and tries to start ALL registered MCP servers in EVERY project. Claude Code doesn't have this issue because it supports project-scoped configuration.
The root cause: Codex has no project-scope support, so when you register backlog-project1 and backlog-project2 globally, both try to start everywhere but only one finds the correct backlog/ folder.
Solution
Register ONE global backlog server that auto-detects its context:
- If
backlog/folder exists → start normally with full tools - If not → start successfully but only provide
backlog://init-requiredresource that instructs the agent to tell the user to runbacklog init
This works universally across Claude, Codex, and Gemini.
Acceptance Criteria
-
[x] #1 When user opens Codex in a project with multiple backlog projects configured, all MCP servers start successfully (0 failures, N successes)
-
[x] #2 MCP server starts successfully in non-backlog directories and provides backlog://init-required resource
-
[x] #3 backlog://init-required resource contains instructions for agent to tell user to run backlog init
-
[x] #4 All agents register single global 'backlog' server name (not per-project names)
-
[x] #5 Init command updated to register global scope for all agents
-
[x] #6 Manual testing confirms: 3 projects (2 with backlog), 1 global server registration, all agents show 1 success + 0 failures
-
[x] #7 Migration guide added for users with existing backlog-project* registrations
Implementation Plan
Implementation Approach
1. MCP Server Auto-Detection
When backlog mcp start runs:
- Check if
backlog/config.ymlexists in CWD - If YES → start normally, serve full tools and resources
- If NO → start successfully but only provide
backlog://init-requiredresource
2. Fallback Resource
Provide this resource when backlog is not initialized:
{
"uri": "backlog://init-required",
"name": "Backlog.md Not Initialized",
"description": "Instructions for initializing Backlog.md in this project",
"mimeType": "text/markdown"
}
Content instructs the agent: "Tell the user to run backlog init to set up task management for this project."
3. Universal Agent Configuration
All agents register identically:
# Claude Code
claude mcp add backlog --command backlog --args "mcp,start" --scope user
# Codex
codex mcp add backlog --command backlog --args "mcp,start"
# Gemini
gemini mcp add backlog -s user --command backlog --args "mcp,start"
4. Implementation Files
src/mcp/server.ts- Add startup detection logicsrc/commands/init.ts- Change to globalbacklogserver registrationsrc/mcp/resources/- Addinit-requiredresource
5. Testing Strategy
Manual verification in multi-project setup:
- 3 projects, backlog initialized in 2
- Register global server, test each agent
- Verify: 1 success per agent, 0 failures
- Verify fallback resource appears in non-backlog projects
Implementation Notes
Research Findings (2025-10-16)
1. Claude Code - Multi-Scope System (Most Flexible)
Configuration Scopes:
- Local Scope (default): Project-specific user settings, private to individual developers
- Project Scope:
.mcp.jsonat project root, version-controlled, team-shared - User Scope: Global across all projects, private to user account
Configuration Files:
- Project:
.mcp.json(at project root) - User:
~/.claude.jsonor~/.claude/settings.local.json
Scope Precedence: Local → Project → User
Key Features:
- Environment variable expansion:
${VAR}and${VAR:-default} - Security approval prompts for project-scoped servers
- Version control friendly with
.mcp.json
Why it works for Backlog: When running claude mcp add backlog-{project-name}, Claude Code likely respects the current working directory and adds the server with project scope, preventing cross-project interference.
2. OpenAI Codex CLI - Global Only (Problematic)
Configuration Approach:
- Fully global - NO project-specific configuration support
- Single config file:
~/.codex/config.toml - Shared between CLI and VSCode extension
Multi-Project Handling:
- All MCP servers are available to ALL projects simultaneously
- No built-in mechanism for project-specific servers
- When you add multiple
backlog-{project-name}servers, ALL attempt to start in EVERY project
Why it causes failures:
- Codex tries to initialize ALL registered MCP servers regardless of current directory
- Each
backlog mcp startcommand tries to run in context of current project - Only the one matching the current project succeeds; others fail (wrong CWD)
Configuration Format (TOML):
[mcp_servers.backlog-project1]
command = "backlog"
args = ["mcp", "start"]
[mcp_servers.backlog-project2]
command = "backlog"
args = ["mcp", "start"]
3. Gemini CLI - Dual Scope (Flexible)
Configuration Scopes:
- User-level (global):
~/.gemini/settings.json - Project-level:
.gemini/settings.json(in project directory)
Configuration Method:
gemini mcp add <server> -s user(global)gemini mcp add <server> -s project(project-specific)
Multi-Project Handling:
- Supports both global and project-specific servers
- Scope-based configuration similar to Claude Code
- Can maintain shared configs globally + project-specific overrides
Key Features:
- FastMCP integration:
fastmcp install gemini-cli - OAuth 2.0 for remote servers
- Docker MCP Toolkit support
The Root Cause
The problem occurs specifically with Codex because:
- Codex uses global-only configuration - all MCP servers are registered globally
- When you run
backlog initon Project A, it addsbacklog-projectAto~/.codex/config.toml - When you run
backlog initon Project B, it addsbacklog-projectBto~/.codex/config.toml - Now Codex tries to start BOTH servers in EVERY project, but:
backlog mcp startreads from the current directory'sbacklog/folder- Only ONE project has the right backlog structure
- Result: 1 success + N failures
Claude Code and Gemini CLI don't have this issue because they support project-scoped configuration, so each project only initializes its own MCP server.
Problem Scenarios
Scenario 1: User has 3 projects with Backlog + Codex
~/.codex/config.toml contains:
[mcp_servers.backlog-project1]
[mcp_servers.backlog-project2]
[mcp_servers.backlog-project3]
When Codex starts in project1:
- Tries to init backlog-project1 ✅ SUCCESS (finds backlog/ folder)
- Tries to init backlog-project2 ❌ FAIL (wrong directory)
- Tries to init backlog-project3 ❌ FAIL (wrong directory)
Scenario 2: Same setup with Claude Code
Each project has its own .mcp.json:
project1/.mcp.json → backlog-project1
project2/.mcp.json → backlog-project2
project3/.mcp.json → backlog-project3
When Claude starts in project1:
- Only reads project1/.mcp.json
- Only tries to init backlog-project1 ✅ SUCCESS
Official Documentation Sources
- Claude Code MCP: https://docs.claude.com/en/docs/claude-code/mcp
- Codex MCP: https://developers.openai.com/codex/mcp/
- Gemini CLI MCP: https://google-gemini.github.io/gemini-cli/docs/tools/mcp-server.html
Implementation Summary (2025-10-17)
- Added fallback detection in
src/mcp/server.tsso the server exposes onlybacklog://init-requiredwhen invoked outside an initialized project and boots normally otherwise. - Introduced
src/mcp/resources/init-requiredplussrc/guidelines/mcp/init-required.mdand wired the guide throughMCP_INIT_REQUIRED_GUIDEfor MCP resources and tests. - Simplified CLI registration by replacing the per-project server name helper with a shared
MCP_SERVER_NAME = "backlog", ensuring all agents register the same global MCP target duringbacklog init. - Expanded automated coverage with the new
src/test/mcp-fallback.test.tssuite and refreshed existing MCP server and task integration tests to exercise the fallback path. - Manually validated fallback mode and global registration idempotency: started the server from an uninitialized temp directory via Inspector stdio, and reran
claude/codex/gemini mcp add backlog -- backlog mcp start+ respective list commands to confirm duplicate adds report "already configured" without extra entries. - Ran the full regression pack with
bun testto ensure the broader CLI surface still passes.