Skip to main content
Glama
README.md
# vlp-mcp-agent

MCP server for VLP lab VM automation. Runs on the manager VM of an EPC HOL SKU vPOD alongside the existing `vlp-tools-agent`. Exposes VM capabilities as first-class MCP tools so Cursor, Claude Code, and other AI agents can automate lab tasks without manual SSH sessions.

## What it does

Wraps the co-located [`vlp-tools-agent`](https://github.com/ATE-Labs/vlp-tools-agent) REST API at `localhost:8787` and adds general VM tooling on top. The existing agent's WebSocket connection to the VLP Hub is untouched.

```
Developer Machine
  └── SSH tunnel :8789  →  Manager VM :5480
                               ├── vlp-mcp-agent (this project)  :8789
                               │     └── calls localhost:8787
                               └── vlp-tools-agent (Spring Boot)  :8787
                                     └── outbound WSS → VLP Hub
```

## Tools available to the AI agent

### VLP-specific

| Tool | What it does |
|---|---|
| `trigger_vlp_operation` | Trigger a VLP platform operation (e.g. `killApp`) via the vlp-tools-agent |
| `execute_script` | Execute a sh/PowerShell/Python script — via agent API or direct subprocess fallback |
| `get_vm_info` | Return VM identity and network info (requestId, tenant, vmName, etc.) |

### General VM tools

| Tool | What it does |
|---|---|
| `run_command` | Run a shell command on this VM |
| `read_file` | Read a text file from this VM |
| `write_file` | Write a text file to this VM |
| `list_directory` | List a directory on this VM |
| `upload_file` | Push a binary file to this VM (base64) |
| `download_file` | Pull a binary file from this VM (base64) |
| `http_request` | Make an HTTP request from this VM's network perspective |

---

## Remote side — install once (manager VM)

```bash
git clone git@benhtodd-bc:ATE-Labs/vlp-mcp-agent.git
cd vlp-mcp-agent
./install.sh
```

Installs to `/opt/vlp-mcp-agent/`. Service is installed but **not started**.

---

## Local side — connect when needed

### Start / stop

```bash
# Connect (starts service on manager VM + opens SSH tunnel)
./connect-manager.sh holuser@<manager-ip>

# Disconnect (closes tunnel + stops service)
# Press Ctrl-C in the connect-manager.sh terminal — it handles cleanup automatically.
# Or manually:
./disconnect-manager.sh holuser@<manager-ip>
```

Environment variable overrides:
```bash
VLP_SSH_PORT=5480   # SSH port for the manager VM (default: 5480)
VLP_MCP_PORT=8789   # MCP port to tunnel (default: 8789)
```

### On-demand via SSH (no tunnel, no persistent service)

For one-off use, Cursor can launch the server as a subprocess over SSH — no tunnel needed:

```json
{
  "mcpServers": {
    "vlp-manager": {
      "command": "ssh",
      "args": ["-p", "5480", "holuser@<manager-ip>",
               "/opt/vlp-mcp-agent/venv/bin/python",
               "/opt/vlp-mcp-agent/vlp_mcp_agent/server.py",
               "--stdio"]
    }
  }
}
```

---

## Agent config — connect via SSH tunnel

After `connect-manager.sh` is running:

### Cursor

Edit `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project):

```json
{
  "mcpServers": {
    "vlp-manager": {
      "url": "http://localhost:8789/sse"
    }
  }
}
```

### Claude Code

Edit `~/.claude/settings.json`:

```json
{
  "mcpServers": {
    "vlp-manager": {
      "url": "http://localhost:8789/sse"
    }
  }
}
```

---

## Development / local testing

```bash
# Install deps
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"   # or: pip install -r requirements.txt

# Run locally (no vlp-tools-agent required — tools that need it will report gracefully)
python vlp_mcp_agent/server.py --port 8789

# Run tests
pytest
```

---

## Relationship to vlp-tools-agent

This project is a **companion**, not a replacement. The `vlp-tools-agent` continues to:
- Maintain the WebSocket connection to the VLP Hub
- Handle `executeVmScript` messages from VLP
- Manage reconnection, heartbeats, and pending message queues

This agent adds the MCP interface layer on top, enabling AI-driven automation. When the vlp-tools-agent owners add a `POST /api/script/execute` endpoint, `execute_script` will automatically use it; until then it falls back to direct subprocess execution.

---

## Security

- Binds to `127.0.0.1` only — not reachable without SSH access to the manager VM
- SSH (port 5480) is the authentication layer — no separate token needed
- Configurable command timeouts and blocked path prefixes in `config.yaml`
- `Restart=no` in systemd unit — never auto-starts, must be started manually