use std::path::Path;
use anyhow::Result;
use super::{Area, Report};
use crate::home::Home;
use crate::integrity::Lock;
use crate::mcp::{self, pins::Kind, tools};
pub(super) fn lines(report: &mut Report, home: &Home, lock: &Lock, binary: &Path) {
let cwd = std::env::current_dir().ok();
let found = match mcp::review(home, lock, &mcp::set_up_hosts(home, binary), cwd.as_deref()) {
Ok(found) => found,
Err(e) => {
report.line(Area::Mcp, false, format!("mcp servers {e:#}"));
return;
}
};
if !found.pinned {
report.warn(
"mcp servers not pinned yet: `openmoat mcp accept` shows them and pins them, so a \
changed definition is held back",
);
} else if found.changes.is_empty() && found.unreadable.is_empty() {
report.line(
Area::Mcp,
true,
format!(
"mcp servers {} definitions pinned, unchanged",
found.pin_count
),
);
}
if found.pinned {
for change in &found.changes {
let accept = format!("`openmoat mcp accept {}` shows it and asks", change.name);
let what = match &change.kind {
Kind::Added => "is new",
Kind::Changed(_) => "changed; its tool calls are refused",
Kind::Removed => "was removed",
};
report.line(
Area::Mcp,
false,
format!(
"mcp servers `{}` in {} {what}: {accept}",
change.name,
change.file.display()
),
);
}
}
for (path, why) in &found.unreadable {
report.line(
Area::Mcp,
false,
format!(
"mcp servers {} cannot be read ({why}); every MCP call of its agent is refused",
path.display()
),
);
}
match mcp::outside::report(home, binary, cwd.as_deref()) {
Ok(found) => {
for outside in &found {
report.warn(&format!("mcp servers {}", outside.describe()));
}
}
Err(e) => report.warn(&format!(
"mcp servers cannot list the servers that start outside OpenMoat: {e:#}"
)),
}
match tools::all(home) {
Ok(all) => {
for (_, pins) in all.iter().filter(|(_, p)| !p.held.is_empty()) {
report.line(
Area::Mcp,
false,
format!(
"mcp tools `{}` lists {}, hidden until `openmoat mcp accept {}`",
pins.server,
pins.held_summary(),
pins.server
),
);
}
}
Err(e) => report.line(Area::Mcp, false, format!("mcp tools {e:#}")),
}
}
pub(super) fn accept(report: &mut Report, home: &Home, binary: &Path) -> Result<()> {
if !super::super::mcp::review_and_accept(home, binary, None, &mut report.out)? {
return Ok(());
}
let lock = Lock::load(&home.lock_path())?;
let cwd = std::env::current_dir().ok();
let found = mcp::review(
home,
&lock,
&mcp::set_up_hosts(home, binary),
cwd.as_deref(),
)?;
let held = tools::all(home)?.iter().any(|(_, p)| !p.held.is_empty());
if found.changes.is_empty() && found.unreadable.is_empty() && !held {
report.problems.retain(|(area, _)| *area != Area::Mcp);
}
Ok(())
}