claude_code/commands/
mcp.rs1use crate::commands::command::ClaudeCommandRequest;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum McpScope {
5 Local,
6 User,
7 Project,
8}
9
10impl McpScope {
11 fn as_arg_value(self) -> &'static str {
12 match self {
13 McpScope::Local => "local",
14 McpScope::User => "user",
15 McpScope::Project => "project",
16 }
17 }
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum McpTransport {
22 Stdio,
23 Sse,
24 Http,
25}
26
27impl McpTransport {
28 fn as_arg_value(self) -> &'static str {
29 match self {
30 McpTransport::Stdio => "stdio",
31 McpTransport::Sse => "sse",
32 McpTransport::Http => "http",
33 }
34 }
35}
36
37#[derive(Debug, Clone)]
38pub struct McpAddRequest {
39 pub name: String,
40 pub command_or_url: String,
41 pub args: Vec<String>,
42 pub scope: Option<McpScope>,
43 pub transport: Option<McpTransport>,
44 pub env: Vec<String>,
45 pub headers: Vec<String>,
46}
47
48impl McpAddRequest {
49 pub fn new(name: impl Into<String>, command_or_url: impl Into<String>) -> Self {
50 Self {
51 name: name.into(),
52 command_or_url: command_or_url.into(),
53 args: Vec::new(),
54 scope: None,
55 transport: None,
56 env: Vec::new(),
57 headers: Vec::new(),
58 }
59 }
60
61 pub fn args(mut self, args: impl IntoIterator<Item = impl Into<String>>) -> Self {
62 self.args = args.into_iter().map(Into::into).collect();
63 self
64 }
65
66 pub fn scope(mut self, scope: McpScope) -> Self {
67 self.scope = Some(scope);
68 self
69 }
70
71 pub fn transport(mut self, transport: McpTransport) -> Self {
72 self.transport = Some(transport);
73 self
74 }
75
76 pub fn env(mut self, env: impl IntoIterator<Item = impl Into<String>>) -> Self {
77 self.env = env.into_iter().map(Into::into).collect();
78 self
79 }
80
81 pub fn headers(mut self, headers: impl IntoIterator<Item = impl Into<String>>) -> Self {
82 self.headers = headers.into_iter().map(Into::into).collect();
83 self
84 }
85
86 pub fn into_command(self) -> ClaudeCommandRequest {
87 let mut req = ClaudeCommandRequest::new(["mcp", "add"]);
88 if let Some(scope) = self.scope {
89 req = req.args(["--scope", scope.as_arg_value()]);
90 }
91 if let Some(transport) = self.transport {
92 req = req.args(["--transport", transport.as_arg_value()]);
93 }
94 for e in self.env {
95 req = req.args(["--env".to_string(), e]);
96 }
97 for h in self.headers {
98 req = req.args(["--header".to_string(), h]);
99 }
100 req.args([self.name, self.command_or_url]).args(self.args)
101 }
102}
103
104#[derive(Debug, Clone)]
105pub struct McpRemoveRequest {
106 pub name: String,
107 pub scope: Option<McpScope>,
108}
109
110impl McpRemoveRequest {
111 pub fn new(name: impl Into<String>) -> Self {
112 Self {
113 name: name.into(),
114 scope: None,
115 }
116 }
117
118 pub fn scope(mut self, scope: McpScope) -> Self {
119 self.scope = Some(scope);
120 self
121 }
122
123 pub fn into_command(self) -> ClaudeCommandRequest {
124 let mut req = ClaudeCommandRequest::new(["mcp", "remove"]);
125 if let Some(scope) = self.scope {
126 req = req.args(["--scope", scope.as_arg_value()]);
127 }
128 req.arg(self.name)
129 }
130}
131
132#[derive(Debug, Clone)]
133pub struct McpGetRequest {
134 pub name: String,
135}
136
137impl McpGetRequest {
138 pub fn new(name: impl Into<String>) -> Self {
139 Self { name: name.into() }
140 }
141
142 pub fn into_command(self) -> ClaudeCommandRequest {
143 ClaudeCommandRequest::new(["mcp", "get"]).arg(self.name)
144 }
145}
146
147#[derive(Debug, Clone)]
148pub struct McpAddJsonRequest {
149 pub name: String,
150 pub json: String,
151 pub scope: Option<McpScope>,
152}
153
154impl McpAddJsonRequest {
155 pub fn new(name: impl Into<String>, json: impl Into<String>) -> Self {
156 Self {
157 name: name.into(),
158 json: json.into(),
159 scope: None,
160 }
161 }
162
163 pub fn scope(mut self, scope: McpScope) -> Self {
164 self.scope = Some(scope);
165 self
166 }
167
168 pub fn into_command(self) -> ClaudeCommandRequest {
169 let mut req = ClaudeCommandRequest::new(["mcp", "add-json"]);
170 if let Some(scope) = self.scope {
171 req = req.args(["--scope", scope.as_arg_value()]);
172 }
173 req.args([self.name, self.json])
174 }
175}
176
177#[derive(Debug, Clone)]
178pub struct McpServeRequest {
179 pub args: Vec<String>,
180}
181
182impl McpServeRequest {
183 pub fn new() -> Self {
184 Self { args: Vec::new() }
185 }
186
187 pub fn args(mut self, args: impl IntoIterator<Item = impl Into<String>>) -> Self {
188 self.args = args.into_iter().map(Into::into).collect();
189 self
190 }
191
192 pub fn into_command(self) -> ClaudeCommandRequest {
193 ClaudeCommandRequest::new(["mcp", "serve"]).args(self.args)
194 }
195}
196
197impl Default for McpServeRequest {
198 fn default() -> Self {
199 Self::new()
200 }
201}
202
203#[derive(Debug, Clone)]
204pub struct McpAddFromClaudeDesktopRequest {
205 pub scope: Option<McpScope>,
206}
207
208impl McpAddFromClaudeDesktopRequest {
209 pub fn new() -> Self {
210 Self { scope: None }
211 }
212
213 pub fn scope(mut self, scope: McpScope) -> Self {
214 self.scope = Some(scope);
215 self
216 }
217
218 pub fn into_command(self) -> ClaudeCommandRequest {
219 let mut req = ClaudeCommandRequest::new(["mcp", "add-from-claude-desktop"]);
220 if let Some(scope) = self.scope {
221 req = req.args(["--scope", scope.as_arg_value()]);
222 }
223 req
224 }
225}
226
227impl Default for McpAddFromClaudeDesktopRequest {
228 fn default() -> Self {
229 Self::new()
230 }
231}