use agent_config::{mcp_by_id, AgentConfigError, McpSpec, Result, Scope};
fn main() -> Result<()> {
let project = tempfile::tempdir().expect("create tempdir");
let scope = Scope::Local(project.path().to_path_buf());
let claude = mcp_by_id("claude").expect("claude supports MCP");
let server_a = McpSpec::builder("github")
.owner("app-a")
.stdio("npx", ["-y", "@modelcontextprotocol/server-github"])
.env_from_host("GITHUB_TOKEN")
.try_build()?;
let server_b = McpSpec::builder("filesystem")
.owner("app-b")
.stdio(
"npx",
["-y", "@modelcontextprotocol/server-filesystem", "."],
)
.try_build()?;
let _ = claude.install_mcp(&scope, &server_a)?;
let _ = claude.install_mcp(&scope, &server_b)?;
println!("both servers installed in {:?}", project.path());
let ledger = project.path().join(".agent-config-mcp.json");
println!(
"ledger ({}):\n{}",
ledger.display(),
std::fs::read_to_string(&ledger).expect("ledger exists")
);
let err = claude
.uninstall_mcp(&scope, "filesystem", "app-a")
.unwrap_err();
match err {
AgentConfigError::NotOwnedByCaller {
kind,
name,
expected,
actual,
} => {
println!(
"\nrefused cross-owner uninstall: kind={kind} name={name} expected={expected} actual={actual:?}"
);
assert_eq!(actual.as_deref(), Some("app-b"));
}
other => return Err(other),
}
let _ = claude.uninstall_mcp(&scope, "github", "app-a")?;
let _ = claude.uninstall_mcp(&scope, "filesystem", "app-b")?;
let recovery_spec = McpSpec::builder("manual")
.owner("app-a")
.stdio("manual-cmd", [] as [&str; 0])
.adopt_unowned(true)
.try_build()?;
println!(
"\nrecovery spec ready (adopt_unowned={})",
recovery_spec.adopt_unowned
);
Ok(())
}