First Deployment
There are two ways to deploy: an AI agent via the MCP server, or the HTTP API directly. Both end up creating a VibedApp and returning a URL.
Connect Claude Desktop (MCP)
vibeD speaks HTTP streamable MCP at /mcp. Bridge Claude Desktop to it with mcp-remote. Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"vibed": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:8080/mcp"]
}
}
}
Port 8080 is the host port kind's extraPortMappings bridges to vibeD's /mcp endpoint, so no kubectl port-forward is needed (see local dev for the full bridge table). Fully quit and reopen Claude Desktop. With auth disabled (dev default) no token is needed.
Using a different agent? The How-Tos cover Claude Code and pi, plus the authenticated / production variants for Claude Desktop.
Then ask Claude to deploy something:
"Deploy a simple portfolio website with my name to vibeD."
Claude calls deploy_artifact; vibeD classifies the source, claims a warm sandbox, injects the source, and returns a URL once the app is Ready. See the MCP tools overview.
Connect Goose (MCP)
Goose speaks MCP natively, so it connects to vibeD's /mcp endpoint directly as a Streamable HTTP extension, with no mcp-remote bridge needed.
Interactively:
goose configure
# → Add Extension → Remote Extension (Streamable HTTP)
# Name: vibed
# URL: http://localhost:8080/mcp
Or add it to ~/.config/goose/config.yaml directly:
extensions:
vibed:
enabled: true
type: streamable_http
name: vibed
uri: http://localhost:8080/mcp
timeout: 300
If you've enabled auth on the vibeD API, pass the token as a header (dev installs need none):
headers:
Authorization: "Bearer <your-token>"
Then start a session and ask Goose to deploy; it calls the same deploy_artifact tool:
goose session
"Deploy a static site that says hello to vibeD."
Deploy via the HTTP API
POST /v1/deploy takes a multipart upload: a gzipped source tarball plus a JSON metadata blob.
# build a tiny static site
mkdir site && printf '<!doctype html><h1>Hello vibeD</h1>' > site/index.html
( cd site && COPYFILE_DISABLE=1 tar -czf ../site.tgz . )
curl -X POST http://localhost:8080/v1/deploy \
-F 'source=@site.tgz;type=application/gzip' \
-F 'metadata={"name":"hello"};type=application/json'
# → {"app_id":"hello","url":"http://6fcr8uffk2pd.localhost"}
The classifier picks static-nginx automatically. To force a lane/template, add it to metadata:
{"name":"hello","runtime":{"template":"static-nginx"}}
A 200 means the app reached Ready within the latency budget and the url is live. A 202 with a status_url means it took a slow path; poll GET /v1/apps/{app_id} until phase: Ready.
The dev install runs the static-nginx, node-24 and python-313 warm pools, so static, JS and Python sources deploy with no extra step. The heavier go-123 and base-al2023 slots stay opt-in: deploying one of those first returns Phase=Failed, Reason=TemplateMissing, and the app's message field says which slot is missing. That message is the only diagnosis available, because an app that never gets a pod has no logs. Enable the slot with make enable-go-pool / make enable-base-pool; see Local development → warm pools.
See it
# Open the returned URL in a browser, or:
curl http://6fcr8uffk2pd.localhost/
# Or list apps
curl http://localhost:8080/v1/apps
*.localhost resolves to 127.0.0.1 in Chrome/Firefox. In Safari add an /etc/hosts entry for the specific label, or use Chrome. Deployed apps also appear in the dashboard at http://localhost:8080/.