fix(doctor): detect MCP server in project-level settings (#1104)
Apply same fix as #1091 to isMCPServerInstalled(): check all three settings locations (user-level, project-level, and project-local). - Extract checkMCPInSettings() helper function - Check ~/.claude/settings.json, .claude/settings.json, and .claude/settings.local.json - Add TestIsMCPServerInstalledProjectLevel with positive and negative cases Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -142,15 +142,39 @@ func checkPluginInSettings(settingsPath string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// isMCPServerInstalled checks if MCP server is configured
|
||||
// isMCPServerInstalled checks if MCP server is configured.
|
||||
// It checks user-level (~/.claude/settings.json) and project-level settings
|
||||
// (.claude/settings.json and .claude/settings.local.json).
|
||||
func isMCPServerInstalled() bool {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
settingsPath := filepath.Join(home, ".claude/settings.json")
|
||||
data, err := os.ReadFile(settingsPath) // #nosec G304 -- settingsPath is constructed from user home dir, not user input
|
||||
// Check user-level settings
|
||||
userSettings := filepath.Join(home, ".claude", "settings.json")
|
||||
if checkMCPInSettings(userSettings) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check project-level settings
|
||||
projectSettings := filepath.Join(".claude", "settings.json")
|
||||
if checkMCPInSettings(projectSettings) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check project-level local settings (gitignored)
|
||||
projectLocalSettings := filepath.Join(".claude", "settings.local.json")
|
||||
if checkMCPInSettings(projectLocalSettings) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// checkMCPInSettings checks if beads MCP server is configured in a settings file
|
||||
func checkMCPInSettings(settingsPath string) bool {
|
||||
data, err := os.ReadFile(settingsPath) // #nosec G304 -- settingsPath is constructed from known safe locations, not user input
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -169,6 +169,64 @@ func TestIsMCPServerInstalled(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsMCPServerInstalledProjectLevel(t *testing.T) {
|
||||
mcpContent := `{"mcpServers":{"beads":{"command":"beads-mcp"}}}`
|
||||
|
||||
// Test that MCP server is detected in each project-level settings file
|
||||
for _, filename := range []string{"settings.json", "settings.local.json"} {
|
||||
t.Run(filename, func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
t.Chdir(tmpDir)
|
||||
|
||||
if err := os.MkdirAll(".claude", 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(".claude", filename), []byte(mcpContent), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !isMCPServerInstalled() {
|
||||
t.Errorf("expected to detect MCP server in .claude/%s", filename)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Test negative cases
|
||||
t.Run("no mcpServers section", func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
t.Chdir(tmpDir)
|
||||
|
||||
if err := os.MkdirAll(".claude", 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
content := `{"hooks":{}}`
|
||||
if err := os.WriteFile(filepath.Join(".claude", "settings.json"), []byte(content), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if isMCPServerInstalled() {
|
||||
t.Error("expected NOT to detect MCP server when mcpServers section missing")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("mcpServers but not beads", func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
t.Chdir(tmpDir)
|
||||
|
||||
if err := os.MkdirAll(".claude", 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
content := `{"mcpServers":{"other-server":{"command":"other"}}}`
|
||||
if err := os.WriteFile(filepath.Join(".claude", "settings.json"), []byte(content), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if isMCPServerInstalled() {
|
||||
t.Error("expected NOT to detect MCP server when beads not present")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsBeadsPluginInstalled(t *testing.T) {
|
||||
// Similar sanity check for plugin detection
|
||||
result := isBeadsPluginInstalled()
|
||||
|
||||
Reference in New Issue
Block a user