library: Pi's mcp.json is backed up to ~/.config/magpie/backups before magpie moves it whole to mcp-adapter.json, as it already was before a merge (#1097, heliar-k)
piMove renamed mcp.json to mcp-adapter.json when the adapter's file wasn't
there yet, with no copy kept. The user's file is now copied aside first;
one that can't be copied isn't moved.
Verified: TestPiMCPWholeMoveKeepsABackup (the reporter's layout: adapter
only in npm/node_modules, packages: [], a user-owned mcp.json) fails
without the change ("backups of mcp.json: []") and passes with it.
go test -race ./internal/library green under a temp HOME.
This commit is contained in:
1 parent
c83c0d5fef
commit
d40fee800d
2 files changed
+37
-3
No files matched your search
@@ -267,8 +267,8 @@ var piKey = regexp.MustCompile(`^[A-Za-z0-9_-]+$`)
|
||||
|
||||
// piMove moves what pi-mcp-adapter read from mcp.json into
|
||||
// mcp-adapter.json: the whole file when there is none yet, as the adapter's
|
||||
// own warning says; into one there, each server and setting it hasn't got
|
||||
// (the file backed up first). A server or setting the two have
|
||||
// own warning says; into one there, each server and setting it hasn't got.
|
||||
// Either way the files are backed up first. A server or setting the two have
|
||||
// differently stays in mcp.json for the user to merge, as does anything
|
||||
// the adapter never read; mcp.json goes once nothing is left in it.
|
||||
//
|
||||
@@ -285,7 +285,11 @@ func piMove(from, to string, serversOnly bool) {
|
||||
return
|
||||
}
|
||||
if !serversOnly && !exists(to) {
|
||||
os.Rename(from, to)
|
||||
// the user's mcp.json is copied aside before it is moved, as it is
|
||||
// before a merge (#1097); one that can't be kept stays where it is
|
||||
if newBackups().keep("pi", from) == nil {
|
||||
os.Rename(from, to)
|
||||
}
|
||||
return
|
||||
}
|
||||
var have map[string]json.RawMessage
|
||||
|
||||
@@ -313,3 +313,33 @@ func TestPiNativeVersions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// heliar-k on #1097: the adapter found, mcp.json was moved whole to
|
||||
// mcp-adapter.json with no backup, the servers the user added with
|
||||
// `pi mcp add` leaving the file Pi reads. Whatever moves it, the user's
|
||||
// mcp.json is copied aside first, byte for byte, and its servers survive.
|
||||
func TestPiMCPWholeMoveKeepsABackup(t *testing.T) {
|
||||
h := sandbox(t)
|
||||
d := filepath.Join(h, ".pi/agent")
|
||||
write(t, filepath.Join(d, "settings.json"), `{ "quietStartup": false, "packages": [] }`)
|
||||
write(t, filepath.Join(d, "npm/node_modules/pi-mcp-adapter/package.json"), `{"name": "pi-mcp-adapter", "version": "4.0.0"}`)
|
||||
old, adapter := filepath.Join(d, "mcp.json"), filepath.Join(d, "mcp-adapter.json")
|
||||
mine := `{ "mcpServers": { "demo": { "url": "https://mcp.exa.ai/mcp" } } }
|
||||
`
|
||||
write(t, old, mine)
|
||||
targetByID("pi")
|
||||
bs, _ := filepath.Glob(filepath.Join(BackupDir(), "*", "pi", "mcp.json"))
|
||||
if len(bs) != 1 {
|
||||
t.Fatalf("backups of mcp.json: %v", bs)
|
||||
}
|
||||
if got := read(t, bs[0]); got != mine {
|
||||
t.Errorf("backup: %q, want the user's %q", got, mine)
|
||||
}
|
||||
if exists(old) {
|
||||
if piServers(t, old)["demo"] == nil {
|
||||
t.Errorf("mcp.json lost demo: %s", read(t, old))
|
||||
}
|
||||
} else if piServers(t, adapter)["demo"] == nil {
|
||||
t.Errorf("demo neither in mcp.json nor in mcp-adapter.json: %s", read(t, adapter))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user