Skip to content

Commit a5c57bc

Browse files
authored
Feat/agent mode and mcp (#14)
* feat(cli): add --agent mode and MCP server for AI agent integration Add two features for AI agent integration with Verda CLI: **--agent mode:** - Global `--agent` flag (and `VERDA_AGENT=1` env var) that forces JSON output, disables interactive prompts, and returns structured errors - AgentError type with JSON serialization and semantic exit codes - Agent prompter that returns structured errors instead of blocking - vm create: returns MISSING_REQUIRED_FLAGS error instead of wizard - vm action: adds --action and --yes flags for non-interactive use **MCP server (`verda mcp serve`):** - Model Context Protocol server over stdio for Claude Code, Cursor, etc. - 15 tools: discovery (locations, instance types, images, availability), cost (balance, estimate, running), VM lifecycle (create, list, describe, action), SSH (keys, ssh command), volumes (list, create, trash) - Uses Verda Go SDK directly, reuses CLI credential resolution - Configured via standard MCP client settings * feat(cli): standardize agent error classification with design doc Add ClassifyError() that maps all errors to structured AgentError types in --agent mode. Errors are classified by priority: 1. Already an AgentError (from explicit command checks) 2. SDK APIError → mapped by HTTP status (401→AUTH, 404→NOT_FOUND, 402→INSUFFICIENT_BALANCE) 3. SDK ValidationError → VALIDATION_ERROR with field/reason 4. Auth-related message heuristic → AUTH_ERROR 5. Fallback → generic ERROR This ensures agents always receive JSON errors on stderr, never plain text. Also adds docs/agent-errors.md with the complete error format specification for developers and AI agents. * fix(mcp): skip credential resolution at startup for instant handshake PersistentPreRunE runs opts.Complete() for every command, which resolves credentials from ~/.verda/credentials and can be slow (network calls for token exchange). This caused MCP clients like Cursor to time out during the handshake. Now mcp serve skips opts.Complete() at startup and defers credential resolution to the lazy client func called on first tool invocation. The handshake completes in ~0.3s instead of 14+s.
1 parent cfee0cb commit a5c57bc

36 files changed

Lines changed: 3804 additions & 289 deletions

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ bin/
33
_output/
44
verda
55

6+
# Git worktrees
7+
.worktrees/
8+
9+
610
# Local smoke-test output (see test/run.sh)
711
tmp/
812

@@ -240,6 +244,8 @@ cscope.po.out
240244

241245
# Other names that would make sense
242246
*tests
247+
!tests/
248+
!tests/**
243249
*testsdir
244250
*testsfile
245251
*testsfiles

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
OUTPUT_DIR ?= bin
22

3-
.PHONY: all build clean lint lint.fix test fmt changelog hooks.install pre-commit help
3+
.PHONY: all build clean lint lint.fix test test.integration fmt changelog hooks.install pre-commit help
44

55
## Build -------------------------------------------------------------------
66

@@ -25,6 +25,10 @@ lint.fix: ## Run golangci-lint with auto-fix
2525
test: ## Run all tests
2626
@go test -count=1 ./...
2727

28+
test.integration: build ## Run integration tests (requires staging credentials in [test] profile)
29+
@cp $(OUTPUT_DIR)/verda /usr/local/bin/verda-test
30+
@VERDA_BIN=$(CURDIR)/$(OUTPUT_DIR)/verda go test -tags=integration -v -count=1 -timeout=5m ./tests/integration/
31+
2832
fmt: ## Format code with gofmt and goimports
2933
@gofmt -w .
3034
@goimports -w -local github/verda-cloud/verda-cli .

README.md

Lines changed: 63 additions & 212 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
Command-line interface for [Verda Cloud](https://verda.com) — manage VMs, volumes, SSH keys, startup scripts, and more from your terminal.
44

5+
![verda vm create](docs/images/vm-create-demo.gif)
6+
7+
Both interactive and non-interactive modes — use the wizard for quick tasks, flags for scripts and automation.
8+
59
## Install
610

711
### Quick install (macOS / Linux)
@@ -16,56 +20,36 @@ Install to a custom directory:
1620
VERDA_INSTALL_DIR=~/.local/bin curl -sSL https://raw.githubusercontent.com/verda-cloud/verda-cli/main/scripts/install.sh | sh
1721
```
1822

19-
Install a specific version:
20-
21-
```bash
22-
VERDA_VERSION=v1.0.0 curl -sSL https://raw.githubusercontent.com/verda-cloud/verda-cli/main/scripts/install.sh | sh
23-
```
24-
2523
### Manual download
2624

2725
Download the binary for your platform from [GitHub Releases](https://github.com/verda-cloud/verda-cli/releases):
2826

29-
30-
| Platform | File |
31-
| --------------------- | ----------------------------------- |
27+
| Platform | File |
28+
|----------|------|
3229
| macOS (Apple Silicon) | `verda_VERSION_darwin_arm64.tar.gz` |
33-
| macOS (Intel) | `verda_VERSION_darwin_amd64.tar.gz` |
34-
| Linux (x86_64) | `verda_VERSION_linux_amd64.tar.gz` |
35-
| Linux (ARM64) | `verda_VERSION_linux_arm64.tar.gz` |
36-
| Windows (x86_64) | `verda_VERSION_windows_amd64.zip` |
37-
| Windows (ARM64) | `verda_VERSION_windows_arm64.zip` |
38-
39-
40-
Extract and move to your PATH:
30+
| macOS (Intel) | `verda_VERSION_darwin_amd64.tar.gz` |
31+
| Linux (x86_64) | `verda_VERSION_linux_amd64.tar.gz` |
32+
| Linux (ARM64) | `verda_VERSION_linux_arm64.tar.gz` |
33+
| Windows (x86_64) | `verda_VERSION_windows_amd64.zip` |
34+
| Windows (ARM64) | `verda_VERSION_windows_arm64.zip` |
4135

4236
```bash
4337
tar xzf verda_*.tar.gz
4438
sudo mv verda /usr/local/bin/
4539
```
4640

47-
### Go install (for Go developers)
41+
### Go install
4842

4943
```bash
5044
go install github.com/verda-cloud/verda-cli/cmd/verda@latest
5145
```
5246

53-
### Verify installation
54-
55-
```bash
56-
verda version
57-
```
58-
59-
### Update to latest version
60-
61-
```bash
62-
verda update
63-
```
64-
65-
Or install a specific version:
47+
### Verify & update
6648

6749
```bash
68-
verda update --version v1.0.0
50+
verda version # verify installation
51+
verda update # update to latest
52+
verda update --version v1.0.0 # specific version
6953
```
7054

7155
## Getting Started
@@ -76,17 +60,15 @@ verda update --version v1.0.0
7660
verda auth login
7761
```
7862

79-
This starts an interactive wizard to save your API credentials to `~/.verda/credentials`.
80-
81-
### 2. List your VMs
63+
### 2. Explore available resources
8264

8365
```bash
84-
verda vm list
66+
verda locations # datacenter locations
67+
verda instance-types --gpu # GPU instance types with pricing
68+
verda availability --location FIN-01 # what's in stock
8569
```
8670

87-
### 3. Create a VM
88-
89-
![verda vm create](docs/images/vm-create-demo.gif)
71+
### 3. Deploy a VM
9072

9173
```bash
9274
# Interactive wizard
@@ -102,202 +84,66 @@ verda vm create \
10284
--hostname gpu-runner
10385
```
10486

105-
## Commands
106-
107-
```
108-
Auth Commands:
109-
auth Manage shared credentials and profiles
110-
111-
VM Commands:
112-
vm Manage VM instances
113-
ssh SSH into a running VM instance
114-
115-
Resource Commands:
116-
availability Check instance type availability
117-
images List available OS images
118-
instance-types List instance types with specs and pricing
119-
locations List datacenter locations
120-
ssh-key Manage SSH keys
121-
startup-script Manage startup scripts
122-
volume Manage volumes
123-
124-
Info Commands:
125-
cost Cost estimation, pricing, and billing
126-
127-
Other Commands:
128-
completion Generate shell completion scripts
129-
settings Manage CLI settings
130-
update Update Verda CLI to latest or specific version
131-
version Print version information
132-
```
133-
134-
### VM
135-
136-
137-
| Command | Description |
138-
| -------------------- | ------------------------------------------ |
139-
| `verda vm create` | Create a VM (interactive wizard or flags) |
140-
| `verda vm list` | List and inspect VM instances |
141-
| `verda vm describe` | Show detailed info about a single VM |
142-
| `verda vm action` | Start, shutdown, hibernate, or delete a VM |
143-
144-
145-
### SSH
87+
### 4. Connect
14688

14789
```bash
148-
# Connect by hostname
14990
verda ssh gpu-runner
150-
151-
# Connect with options
152-
verda ssh gpu-runner --user ubuntu --key ~/.ssh/id_ed25519
153-
154-
# Port forwarding and other ssh args
155-
verda ssh gpu-runner -- -L 8080:localhost:8080
156-
```
157-
158-
### Volume
159-
160-
161-
| Command | Description |
162-
| ----------------------- | -------------------------------------------- |
163-
| `verda volume create` | Create a block storage volume |
164-
| `verda volume list` | List volumes |
165-
| `verda volume describe` | Show detailed info about a single volume |
166-
| `verda volume action` | Detach, rename, resize, clone, or delete |
167-
| `verda volume trash` | List deleted volumes (restorable within 96h) |
168-
169-
170-
### Instance Types, Images, Locations & Availability
171-
172-
```bash
173-
# Browse instance types with specs and pricing
174-
verda instance-types
175-
verda instance-types --gpu # GPU only
176-
verda instance-types --cpu # CPU only
177-
verda instance-types --spot # spot pricing
178-
179-
# List all OS images
180-
verda images
181-
verda images --type 1V100.6V # compatible with instance type
182-
verda images --category ubuntu # filter by category
183-
184-
# List datacenter locations
185-
verda locations
186-
187-
# Check capacity
188-
verda availability # full matrix
189-
verda availability --location FIN-01 # specific location
190-
verda availability --type 1V100.6V # specific type
191-
verda availability --spot # spot only
19291
```
19392

194-
### Cost & Billing
93+
## AI Agent Integration (MCP) — Beta
19594

196-
```bash
197-
# Estimate costs before creating
198-
verda cost estimate --type 1V100.6V --os-volume 100 --storage 500
199-
verda cost estimate --type 1V100.6V --spot
95+
The Verda CLI includes a built-in [MCP](https://modelcontextprotocol.io/) server that lets AI agents (Claude Code, Cursor, etc.) manage your infrastructure through natural language. This feature is in **beta** — feedback welcome.
20096

201-
# See what your running instances are costing you
202-
verda cost running
97+
### Setup
20398

204-
# Account balance
205-
verda cost balance
99+
```json
100+
{
101+
"mcpServers": {
102+
"verda": {
103+
"command": "verda",
104+
"args": ["mcp", "serve"]
105+
}
106+
}
107+
}
206108
```
207109

208-
### SSH Keys & Startup Scripts
209-
210-
211-
| Command | Description |
212-
| ------------------------------------------ | ---------------------- |
213-
| `verda ssh-key list / add / delete` | Manage SSH keys |
214-
| `verda startup-script list / add / delete` | Manage startup scripts |
215-
216-
217-
### Settings
218-
219-
220-
| Command | Description |
221-
| ------------------------------- | ------------------------------ |
222-
| `verda settings theme` | View or change the color theme |
223-
| `verda settings theme --select` | Interactive theme picker |
224-
225-
226-
Available themes: `default`, `dracula`, `catppuccin`, `catppuccin-latte`, `nord`, `tokyonight`, `github-light`, `solarized-light`
227-
228-
### Update
229-
230-
231-
| Command | Description |
232-
| ------------------------------- | ------------------------------------------------- |
233-
| `verda update` | Update to the latest version |
234-
| `verda update --version v1.0.0` | Install a specific version (upgrade or downgrade) |
235-
| `verda update --list` | List available versions |
110+
Add this to your agent's MCP config:
236111

112+
| Agent | Config file |
113+
|-------|------------|
114+
| Claude Code | `.mcp.json` in project root |
115+
| Cursor | `~/.cursor/mcp.json` |
237116

238-
### Auth
117+
### Usage
239118

119+
Once configured, just talk to your agent:
240120

241-
| Command | Description |
242-
| ------------------------ | ----------------------------------------- |
243-
| `verda auth login` | Save API credentials (interactive wizard) |
244-
| `verda auth show` | Show active profile and credentials path |
245-
| `verda auth use PROFILE` | Switch active auth profile |
246-
247-
248-
### Shell Completion
249-
250-
```bash
251-
# Bash
252-
source <(verda completion bash)
253-
254-
# Zsh (add to ~/.zshrc or run once)
255-
verda completion zsh > "${fpath[1]}/_verda"
256-
257-
# Fish
258-
verda completion fish | source
259121
```
260-
261-
## Global Flags
262-
263-
264-
| Flag | Description |
265-
| ----------------- | ----------------------------------------------------- |
266-
| `--output, -o` | Output format: `table`, `json`, `yaml` (default: table) |
267-
| `--debug` | Enable debug output (API request/response details) |
268-
| `--timeout` | HTTP request timeout (default: 30s) |
269-
| `--base-url` | Override API base URL |
270-
| `--config` | Path to config file (default: `~/.verda/config.yaml`) |
271-
272-
### Structured Output
273-
274-
All list and describe commands support `--output json` and `--output yaml` for scripting:
275-
276-
```bash
277-
# Pipe to jq
278-
verda vm list -o json | jq '.[].hostname'
279-
280-
# YAML output
281-
verda volume describe vol-123 -o yaml
282-
283-
# Use in CI/CD scripts
284-
INSTANCE_ID=$(verda vm list -o json | jq -r '.[0].id')
122+
"What GPU types are available right now?"
123+
"How much does an 8x H100 cost per hour?"
124+
"I need a cheap GPU for testing — what's the best option?"
125+
"Deploy a V100 GPU VM with 100GB OS volume"
126+
"Show my running VMs and what they're costing me"
127+
"Shut down my training VM"
285128
```
286129

287-
### Wait for Operations
130+
Credentials are shared with the CLI — run `verda auth login` first.
288131

289-
Async commands support `--wait` to poll until completion:
132+
### Agent Mode
133+
134+
For scripts and agents that use the CLI directly (without MCP):
290135

291136
```bash
292-
verda vm create --hostname gpu-runner --wait --wait-timeout 10m
293-
verda vm action --id abc-123 --wait
294-
verda volume create --name data --size 500 --wait
137+
verda --agent vm list # JSON output, no prompts
138+
verda --agent vm create ... # structured errors for missing flags
139+
verda --agent vm action --id X --action shutdown --yes
295140
```
296141

142+
See [Agent Error Format](docs/agent-errors.md) for the structured error specification.
297143

298144
## Configuration
299145

300-
Credentials are stored in `~/.verda/credentials` (AWS-style INI format):
146+
Credentials are stored in `~/.verda/credentials` (INI format):
301147

302148
```ini
303149
[default]
@@ -306,9 +152,14 @@ verda_client_id = your-client-id
306152
verda_client_secret = your-client-secret
307153
```
308154

309-
Settings (theme, etc.) are stored in `~/.verda/config.yaml`.
155+
Multiple profiles are supported — switch with `verda auth use PROFILE`.
156+
157+
## Documentation
310158

311-
Override the config directory with `VERDA_HOME` environment variable.
159+
| Doc | Description |
160+
|-----|-------------|
161+
| [Command Reference](docs/commands.md) | Full list of commands, flags, and examples |
162+
| [Agent Error Format](docs/agent-errors.md) | Structured error specification for `--agent` mode |
312163

313164
## Contributing
314165

0 commit comments

Comments
 (0)