use std::path::PathBuf;
use crate::agents::planning as agent_planning;
use crate::error::AgentConfigError;
use crate::integration::{InstallReport, McpSurface, UninstallReport};
use crate::paths;
use crate::plan::{InstallPlan, UninstallPlan};
use crate::scope::{Scope, ScopeKind};
use crate::spec::{HookSpec, McpSpec};
use crate::status::StatusReport;
use crate::util::{mcp_json_object, ownership};
use super::ClineAgent;
impl ClineAgent {
pub(super) fn mcp_path(scope: &Scope) -> Result<PathBuf, AgentConfigError> {
match scope {
Scope::Global => paths::cline_mcp_global_file(),
Scope::Local(_) => Err(AgentConfigError::UnsupportedScope {
id: "cline",
scope: ScopeKind::Local,
}),
}
}
}
impl McpSurface for ClineAgent {
fn id(&self) -> &'static str {
"cline"
}
fn supported_mcp_scopes(&self) -> &'static [ScopeKind] {
&[ScopeKind::Global]
}
fn mcp_status(
&self,
scope: &Scope,
name: &str,
expected_owner: &str,
) -> Result<StatusReport, AgentConfigError> {
McpSpec::validate_name(name)?;
let cfg = Self::mcp_path(scope)?;
let ledger = ownership::mcp_ledger_for(&cfg);
let presence = mcp_json_object::config_presence(&cfg, name)?;
let recorded = ownership::owner_of(&ledger, name)?;
Ok(StatusReport::for_mcp(
name,
cfg,
ledger,
presence,
expected_owner,
recorded,
))
}
fn plan_install_mcp(
&self,
scope: &Scope,
spec: &McpSpec,
) -> Result<InstallPlan, AgentConfigError> {
agent_planning::mcp_json_object_install(
McpSurface::id(self),
scope,
spec,
Self::mcp_path(scope),
)
}
fn plan_uninstall_mcp(
&self,
scope: &Scope,
name: &str,
owner_tag: &str,
) -> Result<UninstallPlan, AgentConfigError> {
agent_planning::mcp_json_object_uninstall(
McpSurface::id(self),
scope,
name,
owner_tag,
Self::mcp_path(scope),
)
}
fn install_mcp(
&self,
scope: &Scope,
spec: &McpSpec,
) -> Result<InstallReport, AgentConfigError> {
spec.validate()?;
let cfg = Self::mcp_path(scope)?;
spec.validate_local_secret_policy(scope)?;
scope.ensure_contained(&cfg)?;
let ledger = ownership::mcp_ledger_for(&cfg);
mcp_json_object::install(&cfg, &ledger, spec)
}
fn uninstall_mcp(
&self,
scope: &Scope,
name: &str,
owner_tag: &str,
) -> Result<UninstallReport, AgentConfigError> {
McpSpec::validate_name(name)?;
HookSpec::validate_tag(owner_tag)?;
let cfg = Self::mcp_path(scope)?;
scope.ensure_contained(&cfg)?;
let ledger = ownership::mcp_ledger_for(&cfg);
mcp_json_object::uninstall(&cfg, &ledger, name, owner_tag, "mcp server")
}
}