Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src-tauri/src/acp/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22379,4 +22379,51 @@ mod tests {
strip_unknown_config_options(&mut untyped, "session/new");
assert_eq!(untyped["configOptions"].as_array().unwrap().len(), 1);
}

#[test]
fn mcp_over_acp_store_is_forwarded_to_custom_agents_over_the_wire() {
// Custom agents have no native MCP config file: the MCP-over-ACP
// store is their ONLY source, delivered as `session/new`'s
// `mcpServers`. pi-acp drops that field on the floor, so its sessions
// must stay empty no matter what the store holds.
let dir = tempfile::tempdir().expect("tempdir");
temp_env::with_var("CODEG_HOME", Some(dir.path()), || {
let path = crate::paths::codeg_mcp_over_acp_store_path();
std::fs::create_dir_all(path.parent().expect("parent")).expect("mkdir");
std::fs::write(
&path,
serde_json::to_vec_pretty(&serde_json::json!({
"mcpServers": {
"ctx7": {
"type": "stdio",
"command": "/usr/local/bin/npx",
"args": ["-y", "ctx7-mcp"],
}
}
}))
.expect("serialize store"),
)
.expect("write store");

let agent_type = AgentType::custom("my-agent").expect("custom agent type");
let servers = load_mcp_servers_for_agent(agent_type);
assert_eq!(
servers.len(),
1,
"custom agents receive exactly the store's servers"
);
match &servers[0] {
McpServer::Stdio(s) => {
assert_eq!(s.name, "ctx7");
assert_eq!(s.command, std::path::PathBuf::from("/usr/local/bin/npx"));
}
other => panic!("expected Stdio variant, got {other:?}"),
}

assert!(
load_mcp_servers_for_agent(AgentType::Pi).is_empty(),
"pi drops wire MCP regardless of store contents"
);
});
}
}
10 changes: 10 additions & 0 deletions src-tauri/src/commands/backup/sections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ pub const MANAGED_SECTIONS: &[ManagedSection] = &[
policy: SectionPolicy::ReplaceIfPresent,
live_path: |_| crate::paths::codeg_home_dir().join("preferences.json"),
},
ManagedSection {
// MCP-over-ACP assignments: codeg's own record of which servers a
// custom ACP agent receives as `session/new`'s `mcpServers`. Nothing
// else holds a copy, and losing it silently detaches every user
// server from those agents.
id: "mcp-over-acp.json",
kind: SectionKind::File,
policy: SectionPolicy::ReplaceIfPresent,
live_path: |_| crate::paths::codeg_mcp_over_acp_store_path(),
},
];

/// `db/codeg.db` is deliberately NOT a managed section: its live filename
Expand Down
Loading
Loading