agent_config/agents/cline/
mcp.rs1use std::path::PathBuf;
6
7use crate::agents::planning as agent_planning;
8use crate::error::AgentConfigError;
9use crate::integration::{InstallReport, McpSurface, UninstallReport};
10use crate::paths;
11use crate::plan::{InstallPlan, UninstallPlan};
12use crate::scope::{Scope, ScopeKind};
13use crate::spec::{HookSpec, McpSpec};
14use crate::status::StatusReport;
15use crate::util::{mcp_json_object, ownership};
16
17use super::ClineAgent;
18
19impl ClineAgent {
20 pub(super) fn mcp_path(scope: &Scope) -> Result<PathBuf, AgentConfigError> {
21 match scope {
22 Scope::Global => paths::cline_mcp_global_file(),
23 Scope::Local(_) => Err(AgentConfigError::UnsupportedScope {
24 id: "cline",
25 scope: ScopeKind::Local,
26 }),
27 }
28 }
29}
30
31impl McpSurface for ClineAgent {
32 fn id(&self) -> &'static str {
33 "cline"
34 }
35
36 fn supported_mcp_scopes(&self) -> &'static [ScopeKind] {
37 &[ScopeKind::Global]
38 }
39
40 fn mcp_status(
41 &self,
42 scope: &Scope,
43 name: &str,
44 expected_owner: &str,
45 ) -> Result<StatusReport, AgentConfigError> {
46 McpSpec::validate_name(name)?;
47 let cfg = Self::mcp_path(scope)?;
48 let ledger = ownership::mcp_ledger_for(&cfg);
49 let presence = mcp_json_object::config_presence(&cfg, name)?;
50 let recorded = ownership::owner_of(&ledger, name)?;
51 Ok(StatusReport::for_mcp(
52 name,
53 cfg,
54 ledger,
55 presence,
56 expected_owner,
57 recorded,
58 ))
59 }
60
61 fn plan_install_mcp(
62 &self,
63 scope: &Scope,
64 spec: &McpSpec,
65 ) -> Result<InstallPlan, AgentConfigError> {
66 agent_planning::mcp_json_object_install(
67 McpSurface::id(self),
68 scope,
69 spec,
70 Self::mcp_path(scope),
71 )
72 }
73
74 fn plan_uninstall_mcp(
75 &self,
76 scope: &Scope,
77 name: &str,
78 owner_tag: &str,
79 ) -> Result<UninstallPlan, AgentConfigError> {
80 agent_planning::mcp_json_object_uninstall(
81 McpSurface::id(self),
82 scope,
83 name,
84 owner_tag,
85 Self::mcp_path(scope),
86 )
87 }
88
89 fn install_mcp(
90 &self,
91 scope: &Scope,
92 spec: &McpSpec,
93 ) -> Result<InstallReport, AgentConfigError> {
94 spec.validate()?;
95 let cfg = Self::mcp_path(scope)?;
96 spec.validate_local_secret_policy(scope)?;
97 scope.ensure_contained(&cfg)?;
98 let ledger = ownership::mcp_ledger_for(&cfg);
99 mcp_json_object::install(&cfg, &ledger, spec)
100 }
101
102 fn uninstall_mcp(
103 &self,
104 scope: &Scope,
105 name: &str,
106 owner_tag: &str,
107 ) -> Result<UninstallReport, AgentConfigError> {
108 McpSpec::validate_name(name)?;
109 HookSpec::validate_tag(owner_tag)?;
110 let cfg = Self::mcp_path(scope)?;
111 scope.ensure_contained(&cfg)?;
112 let ledger = ownership::mcp_ledger_for(&cfg);
113 mcp_json_object::uninstall(&cfg, &ledger, name, owner_tag, "mcp server")
114 }
115}