Skip to content

Commit 22c6442

Browse files
author
User
committed
feat: just dashboard, standardized README badges, GitHub metadata
1 parent 7a3e64c commit 22c6442

6 files changed

Lines changed: 164 additions & 7 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,5 @@ target/
134134
# Backup / temp files
135135
*.bak
136136
pytest_full_output.txt
137+
138+
_dashboard/

README.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# virtualization-mcp
22

3+
<p align="center">
4+
<a href="https://github.com/casey/just"><img src="https://img.shields.io/badge/just-ready_to_go-7c5cfc?style=flat-square&logo=just&logoColor=white" alt="Just"></a>
5+
<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"></a>
6+
<a href="https://python.org"><img src="https://img.shields.io/badge/Python-3.13+-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python"></a>
7+
<a href="https://biomejs.dev"><img src="https://img.shields.io/badge/Linted_with-Biome-60a5fa?style=flat-square&logo=biome&logoColor=white" alt="Biome"></a>
8+
<a href="https://github.com/PrefectHQ/fastmcp"><img src="https://img.shields.io/badge/FastMCP-3.2-7c5cfc?style=flat-square" alt="FastMCP"></a>
9+
</p>
10+
311
**Spin up VMs, sandboxes, and dev environments — from your AI assistant.**
412

513
A Model Context Protocol server that gives your AI (Claude Desktop, Cursor, etc.) direct control over VirtualBox, Hyper-V, and Windows Sandbox. Talk to your VMs, don't click through menus.
@@ -9,16 +17,19 @@ A Model Context Protocol server that gives your AI (Claude Desktop, Cursor, etc.
917
→ 30 seconds, all through chat
1018
```
1119

12-
## Quick start
20+
## Quick Start
1321

1422
```powershell
1523
git clone https://github.com/sandraschi/virtualization-mcp
1624
cd virtualization-mcp
17-
just install
18-
webapp\start.ps1
25+
just
1926
```
2027

21-
Open `http://localhost:10700` — you'll see your VMs, sandbox launcher, app fleet, and console.
28+
This opens an interactive dashboard showing all available commands. Run `just bootstrap` to install dependencies, then `just serve` or `just dev` to start.
29+
30+
### Manual Setup
31+
32+
If you don't have `just` installed:
2233

2334
## What you get
2435

justfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ set windows-shell := ["pwsh.exe", "-NoLogo", "-Command"]
22

33
# ── Default ──────────────────────────────────────────────────────────────────
44

5-
# Show available recipes
5+
# Open the interactive recipe dashboard in the browser
66
default:
7-
@just --list
7+
@pwsh.exe -NoProfile -ExecutionPolicy Bypass -File ../mcp-central-docs/scripts/just-dashboard.ps1 -Path .
88

99
# ── Setup ────────────────────────────────────────────────────────────────────
1010

webapp/start.ps1

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
Param([switch]$Headless)
1+
Param([switch]$Headless)
2+
$SkipFrontend = $Headless
23

34
# --- SOTA Headless Standard ---
45
if ($Headless -and ($Host.UI.RawUI.WindowTitle -notmatch 'Hidden')) {
@@ -64,6 +65,7 @@ $pollAndOpen = "for (`$i = 0; `$i -lt 60; `$i++) { try { `$null = Invoke-WebRequ
6465
Start-Process powershell -ArgumentList "-NoProfile", "-WindowStyle", "Hidden", "-Command", $pollAndOpen
6566

6667
Write-Host "Browser will open automatically when Vite is ready." -ForegroundColor Gray
68+
if ($SkipFrontend) { return }
6769
npm run dev -- --port $WebPort --host
6870

6971

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
Param([switch]$Headless)
2+
3+
# --- SOTA Headless Standard ---
4+
if ($Headless -and ($Host.UI.RawUI.WindowTitle -notmatch 'Hidden')) {
5+
Start-Process pwsh -ArgumentList '-NoProfile', '-File', $PSCommandPath, '-Headless' -WindowStyle Hidden
6+
exit
7+
}
8+
$WindowStyle = if ($Headless) { 'Hidden' } else { 'Normal' }
9+
# ------------------------------
10+
11+
# Webapp Start - Standardized SOTA (Auto-Repaired V2.5)
12+
$WebPort = 10700
13+
$BackendPort = 10701
14+
$ProjectRoot = Split-Path -Parent $PSScriptRoot
15+
16+
# 1. Kill any process squatting on the ports
17+
Write-Host "Checking for port squatters on $WebPort and $BackendPort..." -ForegroundColor Yellow
18+
$pids = Get-NetTCPConnection -LocalPort $WebPort, $BackendPort -ErrorAction SilentlyContinue | Where-Object { $_.OwningProcess -gt 4 } | Select-Object -ExpandProperty OwningProcess -Unique
19+
foreach ($p in $pids) {
20+
Write-Host "Found squatter (PID: $p). Terminating..." -ForegroundColor Red
21+
try { Stop-Process -Id $p -Force -ErrorAction Stop } catch { Write-Host "Warning: Could not terminate PID $p." -ForegroundColor Gray }
22+
}
23+
24+
# 2. Setup
25+
Set-Location $PSScriptRoot
26+
if (Test-Path "frontend") { Set-Location "frontend" }
27+
if (-not (Test-Path "node_modules")) { npm install }
28+
29+
# 3. Start the Python backend (Background)
30+
Write-Host "Starting Python backend on port $BackendPort ..." -ForegroundColor Cyan
31+
32+
# uv --project finds package; CWD stays webapp (no repo-root run).
33+
$backendCmd = "Set-Location '$PSScriptRoot'; uv run --project '$ProjectRoot' uvicorn virtualization_mcp.web.app:app --host 127.0.0.1 --port $BackendPort --log-level info"
34+
35+
Start-Process powershell -ArgumentList "-NoExit", "-Command", $backendCmd -WindowStyle Normal
36+
37+
# 4. Wait for backend to be listening (avoid ECONNREFUSED when frontend loads)
38+
$healthUrl = "http://127.0.0.1:$BackendPort/api/v1/health"
39+
$maxAttempts = 15
40+
$attempt = 0
41+
Write-Host "Waiting for backend at $healthUrl ..." -ForegroundColor Cyan
42+
while ($attempt -lt $maxAttempts) {
43+
try {
44+
$null = Invoke-WebRequest -Uri $healthUrl -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
45+
Write-Host "Backend is up." -ForegroundColor Green
46+
break
47+
} catch {
48+
$attempt++
49+
if ($attempt -ge $maxAttempts) {
50+
Write-Host "Backend did not respond after ${maxAttempts} attempts. Starting frontend anyway." -ForegroundColor Yellow
51+
break
52+
}
53+
Start-Sleep -Seconds 2
54+
}
55+
}
56+
57+
# 5. Run server (Vite dev)
58+
Write-Host "Starting Vite frontend on port $WebPort ..." -ForegroundColor Green
59+
if (Test-Path "frontend") { Set-Location "frontend" }
60+
61+
# 4b. Launch background task to open browser once frontend is ready (Auto-opened by Antigravity)
62+
$frontendUrl = "http://127.0.0.1:$WebPort/"
63+
$pollAndOpen = "for (`$i = 0; `$i -lt 60; `$i++) { try { `$null = Invoke-WebRequest -Uri '$frontendUrl' -TimeoutSec 2 -UseBasicParsing -ErrorAction Stop; Start-Process '$frontendUrl'; exit } catch { Start-Sleep -Seconds 1 } }"
64+
Start-Process powershell -ArgumentList "-NoProfile", "-WindowStyle", "Hidden", "-Command", $pollAndOpen
65+
66+
Write-Host "Browser will open automatically when Vite is ready." -ForegroundColor Gray
67+
npm run dev -- --port $WebPort --host
68+
69+
70+
71+
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
Param([switch]$Headless)
2+
3+
# --- SOTA Headless Standard ---
4+
if ($Headless -and ($Host.UI.RawUI.WindowTitle -notmatch 'Hidden')) {
5+
Start-Process pwsh -ArgumentList '-NoProfile', '-File', $PSCommandPath, '-Headless' -WindowStyle Hidden
6+
exit
7+
}
8+
$WindowStyle = if ($Headless) { 'Hidden' } else { 'Normal' }
9+
# ------------------------------
10+
11+
# Webapp Start - Standardized SOTA (Auto-Repaired V2.5)
12+
$WebPort = 10700
13+
$BackendPort = 10701
14+
$ProjectRoot = Split-Path -Parent $PSScriptRoot
15+
16+
# 1. Kill any process squatting on the ports
17+
Write-Host "Checking for port squatters on $WebPort and $BackendPort..." -ForegroundColor Yellow
18+
$pids = Get-NetTCPConnection -LocalPort $WebPort, $BackendPort -ErrorAction SilentlyContinue | Where-Object { $_.OwningProcess -gt 4 } | Select-Object -ExpandProperty OwningProcess -Unique
19+
foreach ($p in $pids) {
20+
Write-Host "Found squatter (PID: $p). Terminating..." -ForegroundColor Red
21+
try { Stop-Process -Id $p -Force -ErrorAction Stop } catch { Write-Host "Warning: Could not terminate PID $p." -ForegroundColor Gray }
22+
}
23+
24+
# 2. Setup
25+
Set-Location $PSScriptRoot
26+
if (Test-Path "frontend") { Set-Location "frontend" }
27+
if (-not (Test-Path "node_modules")) { npm install }
28+
29+
# 3. Start the Python backend (Background)
30+
Write-Host "Starting Python backend on port $BackendPort ..." -ForegroundColor Cyan
31+
32+
# uv --project finds package; CWD stays webapp (no repo-root run).
33+
$backendCmd = "Set-Location '$PSScriptRoot'; uv run --project '$ProjectRoot' uvicorn virtualization_mcp.web.app:app --host 127.0.0.1 --port $BackendPort --log-level info"
34+
35+
Start-Process powershell -ArgumentList "-NoExit", "-Command", $backendCmd -WindowStyle Normal
36+
37+
# 4. Wait for backend to be listening (avoid ECONNREFUSED when frontend loads)
38+
$healthUrl = "http://127.0.0.1:$BackendPort/api/v1/health"
39+
$maxAttempts = 15
40+
$attempt = 0
41+
Write-Host "Waiting for backend at $healthUrl ..." -ForegroundColor Cyan
42+
while ($attempt -lt $maxAttempts) {
43+
try {
44+
$null = Invoke-WebRequest -Uri $healthUrl -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
45+
Write-Host "Backend is up." -ForegroundColor Green
46+
break
47+
} catch {
48+
$attempt++
49+
if ($attempt -ge $maxAttempts) {
50+
Write-Host "Backend did not respond after ${maxAttempts} attempts. Starting frontend anyway." -ForegroundColor Yellow
51+
break
52+
}
53+
Start-Sleep -Seconds 2
54+
}
55+
}
56+
57+
# 5. Run server (Vite dev)
58+
Write-Host "Starting Vite frontend on port $WebPort ..." -ForegroundColor Green
59+
if (Test-Path "frontend") { Set-Location "frontend" }
60+
61+
# 4b. Launch background task to open browser once frontend is ready (Auto-opened by Antigravity)
62+
$frontendUrl = "http://127.0.0.1:$WebPort/"
63+
$pollAndOpen = "for (`$i = 0; `$i -lt 60; `$i++) { try { `$null = Invoke-WebRequest -Uri '$frontendUrl' -TimeoutSec 2 -UseBasicParsing -ErrorAction Stop; Start-Process '$frontendUrl'; exit } catch { Start-Sleep -Seconds 1 } }"
64+
Start-Process powershell -ArgumentList "-NoProfile", "-WindowStyle", "Hidden", "-Command", $pollAndOpen
65+
66+
Write-Host "Browser will open automatically when Vite is ready." -ForegroundColor Gray
67+
npm run dev -- --port $WebPort --host
68+
69+
70+
71+

0 commit comments

Comments
 (0)