Skip to content

Commit 12ca7ac

Browse files
comchangsclaude
andcommitted
feat: update AI integrations for v0.2.0
MCP Server: add tow_ssh and tow_doctor tools (total 9 tools) Claude Skill: complete rewrite with all v0.2.0 commands - deployment, monitoring, diagnostics, config management, maintenance - safe production deploy workflow - multi-server monitoring workflow Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3bf798e commit 12ca7ac

2 files changed

Lines changed: 163 additions & 54 deletions

File tree

Lines changed: 62 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,94 @@
1-
# Tow Deploy — Claude Code Agent Skill
2-
# by neurosam.AI — https://neurosam.ai
3-
#
4-
# Place this file in your project's .claude/skills/ directory
5-
# or reference it in CLAUDE.md to enable deployment via Claude Code.
6-
71
You have access to the `tow` CLI for deploying applications to remote servers.
82

93
## Available Commands
104

11-
### Check Status
5+
### Deployment
126
```bash
13-
tow status -e <environment> -m <module>
14-
tow status -e prod -m api-server -o json # machine-readable
7+
tow status -e <env> -m <module> # Check status
8+
tow status -e <env> # All modules status
9+
tow auto -e <env> -m <module> -y # Full deploy pipeline
10+
tow auto -e <env> -m <module> --rolling -y # Rolling deploy
11+
tow auto -e <env> -m <module> --auto-rollback -y # Deploy with auto-rollback
12+
tow deploy -e <env> -m <module> -y # Package + deploy only
13+
tow build -e <env> -m <module> # Build only
14+
tow package -e <env> -m <module> # Package only
15+
tow rollback -e <env> -m <module> -y # Rollback
16+
tow start -e <env> -m <module> # Start
17+
tow stop -e <env> -m <module> # Stop
18+
tow restart -e <env> -m <module> # Restart
1519
```
1620

17-
### Deploy
21+
### Monitoring & Diagnostics
1822
```bash
19-
# Full pipeline: build → package → upload → install → restart
20-
tow auto -e <environment> -m <module> -y
21-
22-
# With rolling deployment (one server at a time)
23-
tow auto -e <environment> -m <module> --rolling -y
24-
25-
# With auto-rollback on failure
26-
tow auto -e <environment> -m <module> --auto-rollback -y
23+
tow logs -e <env> -m <module> -n 50 # Last 50 lines
24+
tow logs -e <env> -m <module> -f "ERROR" # Filter errors
25+
tow logs -e <env> -m <module> --all -F # Stream all servers
26+
tow logs -e <env> -m <module> -s srv-1,srv-2 # Multiple servers
27+
tow ssh -e <env> -m <module> --all -- "free -h" # Run command on servers
28+
tow ssh -e <env> -m <module> -- "df -h" # Disk space
29+
tow doctor -e <env> -m <module> # Pre-flight diagnostics
30+
tow diff -e <env> -m <module> # What will be deployed
2731
```
2832

29-
### Rollback
33+
### History & Information
3034
```bash
31-
tow rollback -e <environment> -m <module> -y
32-
tow rollback -e <environment> -m <module> -t <timestamp> -y # specific version
35+
tow list deployments -e <env> -m <module> # Deployment history
36+
tow list deployments -e <env> -m <module> -o json # JSON format
37+
tow status -e <env> -m <module> -o json # Status as JSON
38+
tow list modules # All modules
39+
tow list envs # All environments
3340
```
3441

35-
### Monitor
42+
### Configuration Management
3643
```bash
37-
tow logs -e <environment> -m <module> -n 50 # last 50 lines
38-
tow logs -e <environment> -m <module> -f "ERROR" -n 100 # filter errors
39-
tow list deployments -e <environment> -m <module> -o json
44+
tow config server list -e <env> # List servers
45+
tow config server add -e <env> --name srv --host IP --modules mod1,mod2
46+
tow config server remove -e <env> --name srv
47+
tow config module add my-api --type springboot --port 8080
48+
tow config module remove my-api
49+
tow config assign -e <env> --server srv --modules mod1,mod2
50+
tow config unassign -e <env> --server srv --modules mod1
4051
```
4152

42-
### Manage
53+
### Maintenance
4354
```bash
44-
tow start -e <environment> -m <module>
45-
tow stop -e <environment> -m <module>
46-
tow restart -e <environment> -m <module>
47-
tow cleanup -e <environment> -m <module> --keep 3
55+
tow cleanup -e <env> -m <module> --keep 3 # Clean old deploys
56+
tow threaddump -e <env> -m <module> # Java thread dump
57+
tow provision -e <env> -m <module> --jre --tools # Server setup
58+
tow plugin list # Available plugins
4859
```
4960

5061
## Safety Rules
5162

52-
1. **ALWAYS check status before deploying**: `tow status -e <env> -m <module>`
53-
2. **ALWAYS use `-y` flag** when running non-interactively
54-
3. **For production**: Confirm with the user before running any deploy/rollback
55-
4. **After deploy**: Verify with `tow status` and check logs for errors
56-
5. **If deploy fails**: Check logs first, then consider `tow rollback`
63+
1. ALWAYS check status before deploying: `tow status -e <env> -m <module>`
64+
2. ALWAYS use `-y` flag when running non-interactively
65+
3. For production: confirm with the user before running any deploy/rollback
66+
4. After deploy: verify with `tow status` and check logs for errors
67+
5. If deploy fails: check logs first, then consider `tow rollback`
5768

5869
## Common Workflows
5970

6071
### Safe Production Deploy
6172
```bash
62-
# 1. Check current status
63-
tow status -e prod -m api-server
64-
65-
# 2. Deploy with auto-rollback safety net
66-
tow auto -e prod -m api-server --auto-rollback -y
67-
68-
# 3. Verify
69-
tow status -e prod -m api-server
70-
tow logs -e prod -m api-server -f "ERROR" -n 20
73+
tow doctor -e prod -m api-server # Pre-flight check
74+
tow diff -e prod -m api-server # Review changes
75+
tow auto -e prod -m api-server --auto-rollback -y # Deploy with safety net
76+
tow status -e prod -m api-server # Verify
77+
tow logs -e prod -m api-server -f "ERROR" -n 20 # Check for errors
7178
```
7279

7380
### Investigate Production Issue
7481
```bash
75-
# 1. Check status
76-
tow status -e prod -m api-server -o json
77-
78-
# 2. Check recent logs
79-
tow logs -e prod -m api-server -f "ERROR" -n 100
80-
81-
# 3. If needed, rollback
82-
tow rollback -e prod -m api-server -y
82+
tow status -e prod -m api-server -o json # Quick status
83+
tow logs -e prod -m api-server -f "ERROR" -n 100 # Recent errors
84+
tow ssh -e prod -m api-server -- "free -h" # Memory check
85+
tow ssh -e prod -m api-server -- "df -h" # Disk check
86+
tow rollback -e prod -m api-server -y # Rollback if needed
87+
```
8388

84-
# 4. Verify recovery
85-
tow status -e prod -m api-server
89+
### Multi-Server Monitoring
90+
```bash
91+
tow logs -e prod -m kafka --all -n 10 # All Kafka servers
92+
tow ssh -e prod -m kafka --all -- "df -h" # Disk on all nodes
93+
tow status -e prod # All modules overview
8694
```

integrations/mcp-server/server.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,32 @@ func (s *Server) Tools() []Tool {
171171
"properties": {}
172172
}`),
173173
},
174+
{
175+
Name: "tow_ssh",
176+
Description: "Execute an ad-hoc command on remote servers and return the output",
177+
InputSchema: json.RawMessage(`{
178+
"type": "object",
179+
"properties": {
180+
"environment": {"type": "string", "description": "Target environment"},
181+
"module": {"type": "string", "description": "Module name"},
182+
"command": {"type": "string", "description": "Shell command to execute on the server"},
183+
"server": {"type": "string", "description": "Server name (empty = first server)"}
184+
},
185+
"required": ["environment", "module", "command"]
186+
}`),
187+
},
188+
{
189+
Name: "tow_doctor",
190+
Description: "Run pre-flight diagnostics on a module — checks config, SSH, disk space, and deploy locks",
191+
InputSchema: json.RawMessage(`{
192+
"type": "object",
193+
"properties": {
194+
"environment": {"type": "string", "description": "Target environment"},
195+
"module": {"type": "string", "description": "Module name (optional)"}
196+
},
197+
"required": ["environment"]
198+
}`),
199+
},
174200
}
175201
}
176202

@@ -275,11 +301,86 @@ func (s *Server) HandleToolCall(name string, args map[string]interface{}) (strin
275301
return s.handleListModules()
276302
case "tow_list_environments":
277303
return s.handleListEnvironments()
304+
case "tow_ssh":
305+
return s.handleSSH(args)
306+
case "tow_doctor":
307+
return s.handleDoctor(args)
278308
default:
279309
return "", fmt.Errorf("unknown tool: %s", name)
280310
}
281311
}
282312

313+
func (s *Server) handleSSH(args map[string]interface{}) (string, error) {
314+
env := argString(args, "environment")
315+
mod := argString(args, "module")
316+
command := argString(args, "command")
317+
serverName := argString(args, "server")
318+
319+
servers, envCfg, err := s.cfg.GetServersForModule(env, mod, 0)
320+
if err != nil {
321+
return "", err
322+
}
323+
324+
// Filter by server name if specified
325+
if serverName != "" {
326+
var filtered []config.Server
327+
for _, srv := range servers {
328+
if srv.ID() == serverName {
329+
filtered = append(filtered, srv)
330+
}
331+
}
332+
if len(filtered) > 0 {
333+
servers = filtered
334+
}
335+
} else {
336+
servers = servers[:1] // default: first server
337+
}
338+
339+
var results []string
340+
for _, srv := range servers {
341+
result, err := s.ssh.Exec(envCfg, srv.Host, command)
342+
if err != nil {
343+
results = append(results, fmt.Sprintf("[%s] ERROR: %v", srv.ID(), err))
344+
} else {
345+
results = append(results, fmt.Sprintf("[%s]\n%s", srv.ID(), result.Stdout))
346+
}
347+
}
348+
349+
return strings.Join(results, "\n"), nil
350+
}
351+
352+
func (s *Server) handleDoctor(args map[string]interface{}) (string, error) {
353+
env := argString(args, "environment")
354+
355+
envCfg, ok := s.cfg.Environments[env]
356+
if !ok {
357+
return "", fmt.Errorf("environment %q not found", env)
358+
}
359+
360+
var checks []string
361+
362+
// Check SSH connectivity to first server
363+
if len(envCfg.Servers) > 0 {
364+
srv := envCfg.Servers[0]
365+
result, err := s.ssh.Exec(envCfg, srv.Host, "echo OK && df -h / | tail -1 | awk '{print $4}'")
366+
if err != nil {
367+
checks = append(checks, fmt.Sprintf("✗ SSH to %s: %v", srv.Host, err))
368+
} else {
369+
lines := strings.Split(strings.TrimSpace(result.Stdout), "\n")
370+
if len(lines) >= 2 {
371+
checks = append(checks, fmt.Sprintf("✓ SSH to %s: connected, disk available: %s", srv.Host, lines[1]))
372+
} else {
373+
checks = append(checks, fmt.Sprintf("✓ SSH to %s: connected", srv.Host))
374+
}
375+
}
376+
}
377+
378+
checks = append(checks, fmt.Sprintf("✓ Servers: %d configured", len(envCfg.Servers)))
379+
checks = append(checks, fmt.Sprintf("✓ Modules: %d configured", len(s.cfg.Modules)))
380+
381+
return strings.Join(checks, "\n"), nil
382+
}
383+
283384
func (s *Server) handleStatus(args map[string]interface{}) (string, error) {
284385
env := argString(args, "environment")
285386
mod := argString(args, "module")

0 commit comments

Comments
 (0)