-
Notifications
You must be signed in to change notification settings - Fork 60
Expand file tree
/
Copy pathcommands.rs
More file actions
459 lines (422 loc) · 14.7 KB
/
commands.rs
File metadata and controls
459 lines (422 loc) · 14.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//! CLI command definitions for wassette
use std::path::PathBuf;
use clap::{Args, Parser, Subcommand, ValueEnum};
use serde::{Deserialize, Serialize};
use crate::format::OutputFormat;
/// Supported shell types for completion generation
#[derive(ValueEnum, Clone, Debug)]
#[allow(clippy::enum_variant_names)]
pub enum Shell {
/// Bash shell
Bash,
/// Zsh shell
Zsh,
/// Fish shell
Fish,
/// PowerShell
PowerShell,
/// Elvish shell
Elvish,
}
#[derive(Parser, Debug)]
#[command(
name = "wassette-mcp-server",
about = "A security-oriented runtime that runs WebAssembly Components via MCP",
long_about = None
)]
pub struct Cli {
/// Print version information
#[arg(long, short = 'V')]
pub version: bool,
/// Directory where components are stored (ignored when using --version)
#[arg(long)]
pub component_dir: Option<std::path::PathBuf>,
#[command(subcommand)]
pub command: Option<Commands>,
}
#[derive(Subcommand, Debug)]
pub enum Commands {
/// Start a MCP Server
Serve(Serve),
/// Manage WebAssembly components.
Component {
#[command(subcommand)]
command: ComponentCommands,
},
/// Manage component policies.
Policy {
#[command(subcommand)]
command: PolicyCommands,
},
/// Manage component permissions.
Permission {
#[command(subcommand)]
command: PermissionCommands,
},
/// Manage component secrets.
Secret {
#[command(subcommand)]
command: SecretCommands,
},
/// Inspect a WebAssembly component and display its JSON schema (for debugging).
Inspect {
/// Component ID to inspect
component_id: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
/// Manage tools (list, read, invoke).
Tool {
#[command(subcommand)]
command: ToolCommands,
},
/// Search and fetch components from the registry.
Registry {
#[command(subcommand)]
command: RegistryCommands,
},
/// Generate shell completion scripts.
Autocomplete {
/// Shell type to generate completions for
#[arg(value_enum)]
shell: Shell,
},
}
#[derive(Parser, Debug, Clone, Serialize, Deserialize)]
pub struct Serve {
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
#[serde(skip_serializing_if = "Option::is_none")]
pub component_dir: Option<PathBuf>,
#[command(flatten)]
pub transport: TransportFlags,
/// Set environment variables (KEY=VALUE format). Can be specified multiple times.
#[arg(long = "env", value_parser = crate::parse_env_var)]
#[serde(skip)]
pub env_vars: Vec<(String, String)>,
/// Load environment variables from a file (supports .env format)
#[arg(long = "env-file")]
#[serde(skip)]
pub env_file: Option<PathBuf>,
/// Disable built-in tools (load-component, unload-component, list-components, etc.)
#[arg(long)]
#[serde(default)]
pub disable_builtin_tools: bool,
/// Bind address for HTTP-based transports (SSE and StreamableHttp). Defaults to 127.0.0.1:9001
#[arg(long)]
#[serde(skip_serializing_if = "Option::is_none")]
pub bind_address: Option<String>,
/// Path to provisioning manifest for headless deployment mode
#[arg(long)]
#[serde(skip_serializing_if = "Option::is_none")]
pub manifest: Option<PathBuf>,
}
#[derive(Args, Debug, Clone, Serialize, Deserialize, Default)]
#[group(required = false, multiple = false)]
pub struct TransportFlags {
/// Serving with SSE transport
#[arg(long)]
#[serde(skip)]
pub sse: bool,
/// Serving with stdio transport
#[arg(long)]
#[serde(skip)]
pub stdio: bool,
/// Serving with streamable HTTP transport
#[arg(long)]
#[serde(skip)]
pub streamable_http: bool,
}
#[derive(Debug)]
pub enum Transport {
Sse,
Stdio,
StreamableHttp,
}
impl From<&TransportFlags> for Transport {
fn from(f: &TransportFlags) -> Self {
match (f.sse, f.stdio, f.streamable_http) {
(true, false, false) => Transport::Sse,
(false, true, false) => Transport::Stdio,
(false, false, true) => Transport::StreamableHttp,
_ => Transport::Stdio, // Default case: use stdio transport
}
}
}
#[derive(Subcommand, Debug)]
pub enum ComponentCommands {
/// Load a WebAssembly component from a file path or OCI registry.
Load {
/// Path to the component (file:// or oci://)
path: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
/// Optional comma-separated list of tool names to load from the component. If not specified, all tools will be loaded.
#[arg(long, value_delimiter = ',')]
tools: Option<Vec<String>>,
},
/// Unload a WebAssembly component.
Unload {
/// Component ID to unload
id: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
/// List all loaded components.
List {
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
/// Output format
#[arg(short = 'o', long = "output-format", default_value = "json")]
output_format: OutputFormat,
},
}
#[derive(Subcommand, Debug)]
pub enum PolicyCommands {
/// Get policy information for a component.
Get {
/// Component ID to get policy for
component_id: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
/// Output format
#[arg(short = 'o', long = "output-format", default_value = "json")]
output_format: OutputFormat,
},
}
#[derive(Subcommand, Debug)]
pub enum PermissionCommands {
/// Grant permissions to a component.
Grant {
#[command(subcommand)]
permission: GrantPermissionCommands,
},
/// Revoke permissions from a component.
Revoke {
#[command(subcommand)]
permission: RevokePermissionCommands,
},
/// Reset all permissions for a component.
Reset {
/// Component ID to reset permissions for
component_id: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
}
#[derive(Subcommand, Debug)]
pub enum GrantPermissionCommands {
/// Grant storage permission to a component.
#[command(after_help = "EXAMPLES:
# Grant read-only access to a directory
wassette permission grant storage my-component fs:///tmp/cache --access read
# Grant read and write access to a directory
wassette permission grant storage my-component fs:///tmp/output --access read,write
# Grant write-only access to a workspace
wassette permission grant storage my-component fs:///home/user/workspace --access write")]
Storage {
/// Component ID to grant permission to
component_id: String,
/// URI of the storage resource (e.g., fs:///path/to/directory)
uri: String,
/// Access level (read, write, or read,write)
#[arg(long, value_delimiter = ',')]
access: Vec<String>,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
/// Grant network permission to a component.
#[command(after_help = "EXAMPLES:
# Grant access to a specific API endpoint
wassette permission grant network my-component api.example.com
# Grant access to a backup server
wassette permission grant network my-component backup.example.com
# Grant access to a CDN
wassette permission grant network my-component cdn.example.com")]
Network {
/// Component ID to grant permission to
component_id: String,
/// Host to grant access to
host: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
/// Grant environment variable permission to a component.
#[command(
name = "environment-variable",
after_help = "EXAMPLES:
# Grant access to an API key environment variable
wassette permission grant environment-variable my-component API_KEY
# Grant access to a configuration URL
wassette permission grant environment-variable my-component CONFIG_URL
# Grant access to a database connection string
wassette permission grant environment-variable my-component DATABASE_URL"
)]
EnvironmentVariable {
/// Component ID to grant permission to
component_id: String,
/// Environment variable key
key: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
/// Grant memory permission to a component.
#[command(after_help = "EXAMPLES:
# Grant 512 MiB memory limit
wassette permission grant memory my-component 512Mi
# Grant 1 GiB memory limit
wassette permission grant memory my-component 1Gi
# Grant 2048 KiB memory limit
wassette permission grant memory my-component 2048Ki")]
Memory {
/// Component ID to grant permission to
component_id: String,
/// Memory limit (e.g., 512Mi, 1Gi, 2048Ki)
limit: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
}
#[derive(Subcommand, Debug)]
pub enum RevokePermissionCommands {
/// Revoke storage permission from a component.
Storage {
/// Component ID to revoke permission from
component_id: String,
/// URI of the storage resource (e.g., fs:///path/to/directory)
uri: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
/// Revoke network permission from a component.
Network {
/// Component ID to revoke permission from
component_id: String,
/// Host to revoke access from
host: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
/// Revoke environment variable permission from a component.
#[command(name = "environment-variable")]
EnvironmentVariable {
/// Component ID to revoke permission from
component_id: String,
/// Environment variable key
key: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
}
#[derive(Subcommand, Debug)]
pub enum SecretCommands {
/// List secrets for a component.
List {
/// Component ID to list secrets for
component_id: String,
/// Show secret values (prompts for confirmation)
#[arg(long)]
show_values: bool,
/// Skip confirmation prompt when showing values
#[arg(long)]
yes: bool,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
/// Output format
#[arg(short = 'o', long = "output-format", default_value = "json")]
output_format: OutputFormat,
},
/// Set secrets for a component.
Set {
/// Component ID to set secrets for
component_id: String,
/// Secrets in KEY=VALUE format. Can be specified multiple times.
#[arg(value_parser = crate::parse_env_var)]
secrets: Vec<(String, String)>,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
/// Delete secrets for a component.
Delete {
/// Component ID to delete secrets from
component_id: String,
/// Secret keys to delete
keys: Vec<String>,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
},
}
#[derive(Subcommand, Debug)]
pub enum ToolCommands {
/// List all available tools.
List {
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
/// Output format
#[arg(short = 'o', long = "output-format", default_value = "json")]
output_format: OutputFormat,
},
/// Read details of a specific tool.
Read {
/// Name of the tool to read
name: String,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
/// Output format
#[arg(short = 'o', long = "output-format", default_value = "json")]
output_format: OutputFormat,
},
/// Invoke a tool with parameters.
Invoke {
/// Name of the tool to invoke
name: String,
/// Arguments in JSON format (e.g., '{"key": "value"}')
#[arg(long)]
args: Option<String>,
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
component_dir: Option<PathBuf>,
/// Output format
#[arg(short = 'o', long = "output-format", default_value = "json")]
output_format: OutputFormat,
},
}
#[derive(Subcommand, Debug)]
pub enum RegistryCommands {
/// Search for components in the registry.
Search {
/// Search query (matches against component name and description)
query: Option<String>,
/// Output format
#[arg(short = 'o', long = "output-format", default_value = "json")]
output_format: OutputFormat,
},
/// Fetch and load a component from the registry.
Get {
/// Component name or URI from the registry
component: String,
/// Directory where plugins are stored. Defaults to $XDG_DATA_HOME/wassette/components
#[arg(long)]
plugin_dir: Option<PathBuf>,
},
}