feat: support mcp.json in the root of bundle repos as well as in the legacy functions directory

This commit is contained in:
2026-08-26 15:48:16 -06:00
parent 3762bbe09f
commit df62c32822
+32 -2
View File
@@ -32,7 +32,7 @@ pub fn install_remote(git_url: &str, filter: Option<InstallFilter>, force: bool)
if layout.is_empty() { if layout.is_empty() {
println!( println!(
"No recognized assets found in {git_url}. Expected one or more of: \ "No recognized assets found in {git_url}. Expected one or more of: \
agents/, roles/, skills/, macros/, functions/tools/, functions/mcp.json" agents/, roles/, skills/, macros/, functions/tools/, mcp.json"
); );
return Ok(()); return Ok(());
} }
@@ -1263,6 +1263,11 @@ fn scan_remote_layout(root: &Path) -> Result<RemoteLayout> {
layout.macros = Some(macros); layout.macros = Some(macros);
} }
let root_mcp = root.join("mcp.json");
if root_mcp.is_file() {
layout.mcp_json = Some(root_mcp);
}
let functions = root.join("functions"); let functions = root.join("functions");
if functions.is_dir() { if functions.is_dir() {
let tools = functions.join("tools"); let tools = functions.join("tools");
@@ -1270,8 +1275,9 @@ fn scan_remote_layout(root: &Path) -> Result<RemoteLayout> {
layout.functions_tools = Some(tools); layout.functions_tools = Some(tools);
} }
// Legacy bundle layout; a root-level mcp.json wins when both exist.
let mcp = functions.join("mcp.json"); let mcp = functions.join("mcp.json");
if mcp.is_file() { if layout.mcp_json.is_none() && mcp.is_file() {
layout.mcp_json = Some(mcp); layout.mcp_json = Some(mcp);
} }
} }
@@ -2642,6 +2648,30 @@ mod tests {
let _ = fs::remove_dir_all(&root); let _ = fs::remove_dir_all(&root);
} }
#[test]
fn scan_remote_layout_finds_root_mcp_json() {
let root = fresh_temp_dir("scan-root-mcp-test-");
touch(&root.join("mcp.json"));
let layout = scan_remote_layout(&root).unwrap();
assert_eq!(layout.mcp_json, Some(root.join("mcp.json")));
let _ = fs::remove_dir_all(&root);
}
#[test]
fn scan_remote_layout_prefers_root_mcp_json_over_functions() {
let root = fresh_temp_dir("scan-mcp-precedence-test-");
touch(&root.join("mcp.json"));
fs::create_dir_all(root.join("functions")).unwrap();
touch(&root.join("functions/mcp.json"));
let layout = scan_remote_layout(&root).unwrap();
assert_eq!(layout.mcp_json, Some(root.join("mcp.json")));
let _ = fs::remove_dir_all(&root);
}
#[test] #[test]
fn scan_remote_layout_finds_skills_only() { fn scan_remote_layout_finds_skills_only() {
let root = fresh_temp_dir("scan-skills-only-"); let root = fresh_temp_dir("scan-skills-only-");