Skip to content

Commit 40f2b3c

Browse files
authored
Split local and remote commands in the binary (#534)
1 parent 65dd374 commit 40f2b3c

File tree

12 files changed

+232
-86
lines changed

12 files changed

+232
-86
lines changed

docker-compose.example.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ services:
4444
# Uses the default CMD from Dockerfile - no need to specify
4545

4646
# Option 1: Override with stdio transport
47-
# command: ["wassette", "serve", "--stdio"]
47+
# command: ["wassette", "run"]
4848

4949
# Option 2: Override with SSE transport
5050
# command: ["wassette", "serve", "--sse"]

docs/deployment/docker.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Then connect to `http://localhost:9001` from your MCP client.
4646
For use with MCP clients that expect stdio, override the default command:
4747

4848
```bash
49-
docker run -i --rm wassette:latest wassette serve --stdio
49+
docker run -i --rm wassette:latest wassette run
5050
```
5151

5252
### Run with SSE Transport
@@ -89,7 +89,7 @@ docker run --rm -p 9001:9001 \
8989
# For stdio transport, override the default:
9090
# docker run -i --rm \
9191
# -v $(pwd)/examples/filesystem-rs/target/wasm32-wasip2/release:/home/wassette/.local/share/wassette/components:ro \
92-
# wassette:latest wassette serve --stdio
92+
# wassette:latest wassette run
9393
```
9494

9595
### Example: Running with Multiple Component Directories

docs/mcp-clients.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,20 @@ If you haven't installed Wassette yet, follow the [installation instructions](ht
66

77
Add the Wassette MCP Server to GitHub Copilot in Visual Studio Code by clicking the **Install in VS Code** or **Install in VS Code Insiders** badge below:
88

9-
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22wassette%22%2C%22gallery%22%3Afalse%2C%22command%22%3A%22wassette%22%2C%22args%22%3A%5B%22serve%22%2C%22--stdio%22%5D%7D) [![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode-insiders:mcp/install?%7B%22name%22%3A%22wassette%22%2C%22gallery%22%3Afalse%2C%22command%22%3A%22wassette%22%2C%22args%22%3A%5B%22serve%22%2C%22--stdio%22%5D%7D)
9+
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22wassette%22%2C%22gallery%22%3Afalse%2C%22command%22%3A%22wassette%22%2C%22args%22%3A%5B%22run%22%5D%7D) [![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode-insiders:mcp/install?%7B%22name%22%3A%22wassette%22%2C%22gallery%22%3Afalse%2C%22command%22%3A%22wassette%22%2C%22args%22%3A%5B%22run%22%5D%7D)
1010

1111
Alternatively, you can add the Wassete MCP server to VS Code from the command line using the `code` command in a bash/zsh or PowerShell terminal:
1212

1313
### bash/zsh
1414

1515
```bash
16-
code --add-mcp '{"name":"Wassette","command":"wassette","args":["serve","--stdio"]}'
16+
code --add-mcp '{"name":"Wassette","command":"wassette","args":["run"]}'
1717
```
1818

1919
### PowerShell
2020

2121
```powershell
22-
code --% --add-mcp "{\"name\":\"wassette\",\"command\":\"wassette\",\"args\":[\"serve\",\"--stdio\"]}"
22+
code --% --add-mcp "{\"name\":\"wassette\",\"command\":\"wassette\",\"args\":[\"run\"]}"
2323
```
2424

2525
You can list and configure MCP servers in VS Code by running the command `MCP: List Servers` in the command palette (Ctrl+Shift+P or Cmd+Shift+P).
@@ -33,7 +33,7 @@ To add Wassette to Cursor, you'll need to manually configure it in your MCP sett
3333
"mcpServers": {
3434
"wassette": {
3535
"command": "wassette",
36-
"args": ["serve", "--stdio"]
36+
"args": ["run"]
3737
}
3838
}
3939
}
@@ -50,7 +50,7 @@ npm install -g @anthropic-ai/claude-code
5050
Add the Wassette MCP server to Claude Code using the following command:
5151

5252
```bash
53-
claude mcp add -- wassette wassette serve --stdio
53+
claude mcp add -- wassette wassette run
5454
```
5555

5656
This will configure the Wassette MCP server as a local stdio server that Claude Code can use to execute Wassette commands and interact with your data infrastructure.
@@ -80,7 +80,7 @@ To add the Wassette MCP server to Gemini CLI, you need to configure it in your s
8080
"mcpServers": {
8181
"wassette": {
8282
"command": "wassette",
83-
"args": ["serve", "--stdio"]
83+
"args": ["run"]
8484
}
8585
}
8686
}
@@ -107,7 +107,7 @@ brew install codex
107107
Add the Wassette MCP server to Codex CLI using the following command:
108108

109109
```bash
110-
codex mcp add wassette wassette serve --stdio
110+
codex mcp add wassette wassette run
111111
```
112112

113113
Run `codex` to start the CLI.

docs/quick-start.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ After installing Wassette, get started in 3 simple steps:
66

77
For VS Code with GitHub Copilot, click to install:
88

9-
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22wassette%22%2C%22gallery%22%3Afalse%2C%22command%22%3A%22wassette%22%2C%22args%22%3A%5B%22serve%22%2C%22--stdio%22%5D%7D)
9+
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22wassette%22%2C%22gallery%22%3Afalse%2C%22command%22%3A%22wassette%22%2C%22args%22%3A%5B%22run%22%5D%7D)
1010

1111
Or use the command line:
1212
```bash
13-
code --add-mcp '{"name":"Wassette","command":"wassette","args":["serve","--stdio"]}'
13+
code --add-mcp '{"name":"Wassette","command":"wassette","args":["run"]}'
1414
```
1515

1616
**2. Load a component**

docs/reference/cli.md

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ wassette component load oci://ghcr.io/microsoft/time-server-js:latest
3030
# Load a component from a local file
3131
wassette component load file:///path/to/component.wasm
3232

33-
# Start the MCP server (traditional mode)
34-
wassette serve --stdio
33+
# Start the MCP server for local development (stdio transport)
34+
wassette run
3535
```
3636

3737
## Command Structure
@@ -40,7 +40,8 @@ Wassette uses a hierarchical command structure organized around functional areas
4040

4141
```
4242
wassette
43-
├── serve # Start MCP server
43+
├── run # Start MCP server with stdio transport (local development)
44+
├── serve # Start MCP server with HTTP transports (remote access)
4445
├── component # Component lifecycle management
4546
│ ├── load # Load components
4647
│ ├── unload # Remove components
@@ -63,28 +64,35 @@ wassette
6364

6465
## Server Commands
6566

66-
### `wassette serve`
67+
### `wassette run`
6768

68-
Start the Wassette MCP server to handle client requests.
69+
Start the Wassette MCP server with stdio transport for local development and testing. This is the recommended mode for MCP clients.
6970

70-
**Stdio Transport (recommended for MCP clients):**
71+
**Basic usage:**
7172
```bash
7273
# Start server with stdio transport
73-
wassette serve --stdio
74+
wassette run
7475

7576
# Use with specific configuration directory
76-
wassette serve --stdio --component-dir /custom/components
77+
wassette run --component-dir /custom/components
7778
```
7879

79-
**HTTP Transport (for development and debugging):**
80-
```bash
81-
# Start server with HTTP transport
82-
wassette serve --http
80+
**Options:**
81+
- `--component-dir <PATH>`: Set component storage directory (default: `$XDG_DATA_HOME/wassette/components`)
82+
- `--env <KEY=VALUE>`: Set environment variables (can be specified multiple times)
83+
- `--env-file <PATH>`: Load environment variables from a file
84+
- `--disable-builtin-tools`: Disable built-in tools (load-component, unload-component, etc.)
8385

84-
# Use Server-Sent Events (SSE) transport
85-
wassette serve --sse
86+
### `wassette serve`
87+
88+
Start the Wassette MCP server with HTTP transports for remote access. This is intended for remote deployment scenarios.
89+
90+
**Server-Sent Events (SSE) transport:**
91+
```bash
92+
# Start server with SSE transport (default)
93+
wassette serve
8694

87-
# Use custom bind address
95+
# Use SSE with custom bind address
8896
wassette serve --sse --bind-address 0.0.0.0:8080
8997

9098
# Use environment variables for bind address
@@ -93,12 +101,20 @@ export BIND_HOST=0.0.0.0
93101
wassette serve --sse
94102
```
95103

104+
**Streamable HTTP transport:**
105+
```bash
106+
# Start server with streamable HTTP transport
107+
wassette serve --streamable-http
108+
```
109+
96110
**Options:**
97-
- `--stdio`: Use stdio transport (recommended for MCP clients)
98-
- `--http`: Use HTTP transport on 127.0.0.1:9001
99-
- `--sse`: Use Server-Sent Events transport
100-
- `--bind-address <ADDRESS>`: Set bind address for HTTP-based transports (default: `127.0.0.1:9001`)
111+
- `--sse`: Use Server-Sent Events transport (default)
112+
- `--streamable-http`: Use streamable HTTP transport
113+
- `--bind-address <ADDRESS>`: Set bind address for HTTP transports (default: `127.0.0.1:9001`)
101114
- `--component-dir <PATH>`: Set component storage directory (default: `$XDG_DATA_HOME/wassette/components`)
115+
- `--env <KEY=VALUE>`: Set environment variables (can be specified multiple times)
116+
- `--env-file <PATH>`: Load environment variables from a file
117+
- `--disable-builtin-tools`: Disable built-in tools (load-component, unload-component, etc.)
102118

103119
## Component Management
104120

docs/reference/environment-variables.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Default: `$XDG_CONFIG_HOME/wassette/config.toml`
4545

4646
```bash
4747
export OPENWEATHER_API_KEY="your_key"
48-
wassette serve --stdio
48+
wassette run
4949
wassette permission grant environment-variable weather-tool OPENWEATHER_API_KEY
5050
```
5151

src/commands.rs

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ pub struct Cli {
4747

4848
#[derive(Subcommand, Debug)]
4949
pub enum Commands {
50-
/// Start a MCP Server
50+
/// Run locally with stdio transport (for local development and testing).
51+
Run(Run),
52+
/// Serve remotely over HTTP transports (SSE or StreamableHttp).
5153
Serve(Serve),
5254
/// Manage WebAssembly components.
5355
Component {
@@ -95,6 +97,31 @@ pub enum Commands {
9597
},
9698
}
9799

100+
/// Configuration for running locally with stdio transport
101+
#[derive(Parser, Debug, Clone, Serialize, Deserialize)]
102+
pub struct Run {
103+
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
104+
#[arg(long)]
105+
#[serde(skip_serializing_if = "Option::is_none")]
106+
pub component_dir: Option<PathBuf>,
107+
108+
/// Set environment variables (KEY=VALUE format). Can be specified multiple times.
109+
#[arg(long = "env", value_parser = crate::parse_env_var)]
110+
#[serde(skip)]
111+
pub env_vars: Vec<(String, String)>,
112+
113+
/// Load environment variables from a file (supports .env format)
114+
#[arg(long = "env-file")]
115+
#[serde(skip)]
116+
pub env_file: Option<PathBuf>,
117+
118+
/// Disable built-in tools (load-component, unload-component, list-components, etc.)
119+
#[arg(long)]
120+
#[serde(default)]
121+
pub disable_builtin_tools: bool,
122+
}
123+
124+
/// Configuration for serving remotely over HTTP transports
98125
#[derive(Parser, Debug, Clone, Serialize, Deserialize)]
99126
pub struct Serve {
100127
/// Directory where components are stored. Defaults to $XDG_DATA_HOME/wassette/components
@@ -103,7 +130,7 @@ pub struct Serve {
103130
pub component_dir: Option<PathBuf>,
104131

105132
#[command(flatten)]
106-
pub transport: TransportFlags,
133+
pub transport: HttpTransportFlags,
107134

108135
/// Set environment variables (KEY=VALUE format). Can be specified multiple times.
109136
#[arg(long = "env", value_parser = crate::parse_env_var)]
@@ -131,19 +158,15 @@ pub struct Serve {
131158
pub manifest: Option<PathBuf>,
132159
}
133160

161+
/// HTTP transport options for the Serve command
134162
#[derive(Args, Debug, Clone, Serialize, Deserialize, Default)]
135163
#[group(required = false, multiple = false)]
136-
pub struct TransportFlags {
164+
pub struct HttpTransportFlags {
137165
/// Serving with SSE transport
138166
#[arg(long)]
139167
#[serde(skip)]
140168
pub sse: bool,
141169

142-
/// Serving with stdio transport
143-
#[arg(long)]
144-
#[serde(skip)]
145-
pub stdio: bool,
146-
147170
/// Serving with streamable HTTP transport
148171
#[arg(long)]
149172
#[serde(skip)]
@@ -153,17 +176,15 @@ pub struct TransportFlags {
153176
#[derive(Debug)]
154177
pub enum Transport {
155178
Sse,
156-
Stdio,
157179
StreamableHttp,
158180
}
159181

160-
impl From<&TransportFlags> for Transport {
161-
fn from(f: &TransportFlags) -> Self {
162-
match (f.sse, f.stdio, f.streamable_http) {
163-
(true, false, false) => Transport::Sse,
164-
(false, true, false) => Transport::Stdio,
165-
(false, false, true) => Transport::StreamableHttp,
166-
_ => Transport::Stdio, // Default case: use stdio transport
182+
impl From<&HttpTransportFlags> for Transport {
183+
fn from(f: &HttpTransportFlags) -> Self {
184+
match (f.sse, f.streamable_http) {
185+
(true, false) => Transport::Sse,
186+
(false, true) => Transport::StreamableHttp,
187+
_ => Transport::Sse, // Default case: use SSE transport for serve
167188
}
168189
}
169190
}

src/config.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use etcetera::BaseStrategy;
99
use figment::providers::{Env, Format, Serialized, Toml};
1010
use serde::{Deserialize, Serialize};
1111

12-
use crate::commands::Serve;
12+
use crate::commands::{Run, Serve};
1313

1414
/// Get the default component directory path based on the OS
1515
pub fn get_component_dir() -> Result<PathBuf, anyhow::Error> {
@@ -107,6 +107,37 @@ impl Config {
107107
.context("Unable to merge configs")
108108
}
109109

110+
/// Creates a new config from a Run struct for local stdio transport
111+
pub fn from_run(run_config: &Run) -> Result<Self, anyhow::Error> {
112+
// Start with the base config using existing logic
113+
let mut config = Self::new(run_config)?;
114+
115+
// Load environment variables from file if specified
116+
if let Some(env_file) = &run_config.env_file {
117+
let file_env_vars = crate::utils::load_env_file(env_file).with_context(|| {
118+
format!("Failed to load environment file: {}", env_file.display())
119+
})?;
120+
121+
// Merge file environment variables (they have lower precedence than CLI args)
122+
for (key, value) in file_env_vars {
123+
config.environment_vars.insert(key, value);
124+
}
125+
}
126+
127+
// Apply CLI environment variables (highest precedence)
128+
for (key, value) in &run_config.env_vars {
129+
config.environment_vars.insert(key.clone(), value.clone());
130+
}
131+
132+
// Also include system environment variables that aren't overridden
133+
// This maintains backward compatibility
134+
for (key, value) in std::env::vars() {
135+
config.environment_vars.entry(key).or_insert(value);
136+
}
137+
138+
Ok(config)
139+
}
140+
110141
/// Creates a new config from a Serve struct that includes environment variable handling
111142
pub fn from_serve(serve_config: &Serve) -> Result<Self, anyhow::Error> {
112143
// Start with the base config using existing logic
@@ -148,6 +179,26 @@ mod tests {
148179

149180
use super::*;
150181

182+
#[allow(dead_code)]
183+
fn create_test_run_config() -> Run {
184+
Run {
185+
component_dir: Some(PathBuf::from("/test/component/dir")),
186+
env_vars: vec![],
187+
env_file: None,
188+
disable_builtin_tools: false,
189+
}
190+
}
191+
192+
#[allow(dead_code)]
193+
fn empty_test_run_config() -> Run {
194+
Run {
195+
component_dir: None,
196+
env_vars: vec![],
197+
env_file: None,
198+
disable_builtin_tools: false,
199+
}
200+
}
201+
151202
fn create_test_cli_config() -> Serve {
152203
Serve {
153204
component_dir: Some(PathBuf::from("/test/component/dir")),

0 commit comments

Comments
 (0)