From a316b7e09d8d2bd2277127a918ae4e903c1ceec0 Mon Sep 17 00:00:00 2001 From: Young Joon Lee Date: Sun, 18 Oct 2026 16:28:49 +0900 Subject: [PATCH] fix(ai): accept agy's empty mcp_config.json in dot ai memory install Closes #286 Claude-Session: https://claude.ai/code/session_01XvHSJEw2XHhXhfrF74SoRA --- internal/aisettings/claudemem.go | 9 ++++++--- internal/aisettings/claudemem_selection_test.go | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/internal/aisettings/claudemem.go b/internal/aisettings/claudemem.go index 5817eb3..39f1ef8 100644 --- a/internal/aisettings/claudemem.go +++ b/internal/aisettings/claudemem.go @@ -944,12 +944,15 @@ func ensureMCPEntry(path, dotPath string, variant mcpEntryVariant) (bool, error) func ensureScopedMCPEntry(path, dotPath string, variant mcpEntryVariant, home, pluginRoot string) (bool, error) { doc := map[string]json.RawMessage{} - if raw, err := os.ReadFile(path); err == nil { + raw, err := os.ReadFile(path) + if err != nil && !os.IsNotExist(err) { + return false, err + } + // agy ships its MCP config as an empty file; treat that as no servers. + if len(bytes.TrimSpace(raw)) > 0 { if err := json.Unmarshal(raw, &doc); err != nil { return false, fmt.Errorf("parse MCP config %s: %w", path, err) } - } else if !os.IsNotExist(err) { - return false, err } servers := map[string]json.RawMessage{} if raw := doc["mcpServers"]; len(raw) > 0 { diff --git a/internal/aisettings/claudemem_selection_test.go b/internal/aisettings/claudemem_selection_test.go index 46bcd50..3e3a736 100644 --- a/internal/aisettings/claudemem_selection_test.go +++ b/internal/aisettings/claudemem_selection_test.go @@ -204,3 +204,20 @@ func TestSelectedAntigravityGetsMCPRecall(t *testing.T) { t.Fatal("unselected qwen was wired") } } + +// agy creates mcp_config.json as an empty file; the entry still lands, while +// a non-empty broken file is still rejected. +func TestMCPEntryAcceptsEmptyConfigFile(t *testing.T) { + path := filepath.Join(t.TempDir(), "mcp_config.json") + mustWriteFile(t, path, "") + if _, err := ensureMCPEntry(path, "/opt/bin/dot", mcpVariantStandard); err != nil { + t.Fatal(err) + } + if !hasManagedMCPEntry(path, "/opt/bin/dot") { + t.Fatal("entry missing after empty config") + } + mustWriteFile(t, path, "{broken") + if _, err := ensureMCPEntry(path, "/opt/bin/dot", mcpVariantStandard); err == nil { + t.Fatal("broken config accepted") + } +}