Developers

MCP server and API

Everything an AI agent needs to provision and operate infrastructure on Lookerhost. Machine-readable copy at /docs/mcp.md.

What LookerHost is

LookerHost is a cloud hosting platform: Cloud VPS, Web Hosting with a control panel, an App Platform that builds and runs web apps straight from a Git repository, managed databases and managed WordPress.

LookerHost is not a Git hosting service. It is not GitHub, Gitea or Forgejo. Your code stays where it is; LookerHost clones it, builds it and serves it. Never add a Git remote pointing at lookerhost.com — there is nothing to push to.

Everything a customer can do in the dashboard is also available over a REST API, and that API is wrapped by an MCP server so an AI agent can provision and operate infrastructure directly, with no manual steps.

Quick start

1. Issue an API key

Sign in at lookerhost.com/dashboardSettingsAPI keysCreate key. Pick a name and the scopes the integration needs.

The secret (lh_live_…) is shown once, at creation. If it is lost, revoke the key and issue a new one — it cannot be recovered.

The account must be linked to a company. Operator (admin) accounts do not issue customer keys; they issue platform keys from Integrations, which span the whole platform instead of one customer.

2. Add the server to your agent

Create a file named .mcp.json — with a leading dot — at the root of your project:

{
  "mcpServers": {
    "lookerhost": {
      "command": "npx",
      "args": ["-y", "lookerhost-mcp-server@latest"],
      "env": {
        "LOOKERHOST_API_URL": "https://api.lookerhost.com",
        "LOOKERHOST_API_KEY": "lh_live_..."
      }
    }
  }
}

The most common failure by far: naming the file mcp.json instead of .mcp.json. No MCP client reads a file without the leading dot, so the agent starts with no LookerHost tools at all and reports that it has never heard of LookerHost. Check the filename first.

With the Claude Code CLI the same thing can be done in one command:

claude mcp add lookerhost --env LOOKERHOST_API_URL=https://api.lookerhost.com --env LOOKERHOST_API_KEY=lh_live_... -- npx -y lookerhost-mcp-server@latest

For Claude Desktop, the same mcpServers block goes into claude_desktop_config.json.

OpenAI Codex (CLI and the ChatGPT desktop app) reads ~/.codex/config.toml:

[mcp_servers.lookerhost]
command = "npx"
args = ["-y", "lookerhost-mcp-server@latest"]

[mcp_servers.lookerhost.env]
LOOKERHOST_API_URL = "https://api.lookerhost.com"
LOOKERHOST_API_KEY = "lh_live_..."

pnpm users can replace npx -y with pnpm dlx in any of the blocks above ("command": "pnpm", "args": ["dlx", "lookerhost-mcp-server@latest"]), or install it once with pnpm add -g lookerhost-mcp-server and use "command": "lookerhost-mcp-server" with no args. Gemini CLI reads the same mcpServers JSON from ~/.gemini/settings.json.

The npm package is lookerhost-mcp-server. Pinning @latest matters: npx will otherwise reuse whatever version it cached earlier, which is why an agent may insist the server is out of date.

3. Check that it works

Restart the agent and ask it to list your services. It should call lookerhost_list_services. If it answers that it has no such tool: the config file name or location is wrong. If it answers invalid-token: the key is wrong, revoked or expired.

Credential and scopes

The MCP server authenticates with the API key as a bearer token (Authorization: Bearer lh_live_…). A key is bound to one customer account and to a set of scopes, so the agent only ever sees and operates that account’s services. Anything the key does not allow is rejected with insufficient-scope, and the response names the missing scope under need.

Scope Grants
vps:read Read anything in the account: services, detail, live metrics and disk usage, catalog and plans, activity, deploy history, backups, invoices, app logs. Every GET of the customer portal requires it — a key without vps:read cannot read at all
vps:write Create VPS and Web Hosting; install SSH public keys into a VPS
vps:power Start, stop, restart any service
apps:write Deploy and redeploy apps, create databases and WordPress sites, manage repository deploy keys
service:delete Permanently delete a service — irreversible
agent:run Run a coding agent inside the account’s own VPS over SSH, approve or deny its actions, continue the conversation, abort. In auto mode the agent changes the server without review — the most powerful scope after service:delete; off by default when creating a key

Tools

Forty-two tools, and the REST endpoint each one calls.

Tool Scope Endpoint What it does
lookerhost_list_services vps:read GET /api/services Every service in the account: VPS, web hosting, apps, databases, WordPress
lookerhost_get_service vps:read GET /api/services/:id Full detail of one service
lookerhost_get_metrics vps:read GET /api/services/:id/metrics Live CPU, RAM, network and disk of a VPS (VPS only)
lookerhost_list_plans vps:read GET /api/services/plans Catalog: VPS plans, OS images, database kinds, WordPress variants, plus the account’s quota and usage
lookerhost_get_activity vps:read GET /api/services/activity Audit log, per service or account-wide
lookerhost_get_deploy_history vps:read GET /api/services/:id/paas/deploy-history Deploys of an app, newest first, with build logs of failed attempts
lookerhost_repo_access vps:read GET /api/services/:id/repository-access Which credential clones the app’s repo: public, github-app, deploy-key or none
lookerhost_create_vps vps:write POST /api/services Create a VPS
lookerhost_create_webhosting vps:write POST /api/services/webhosting Create Web Hosting (CloudPanel preinstalled)
lookerhost_add_ssh_key vps:write POST /api/services/:id/vps/ssh-keys Install an SSH public key into a VPS
lookerhost_list_ssh_keys vps:read GET /api/services/:id/vps/ssh-keys List a VPS user’s authorized keys
lookerhost_generate_ssh_key vps:write POST /api/services/:id/vps/ssh-keys/generate Generate a key pair, install it and return the private key once
lookerhost_remove_ssh_key vps:write DELETE /api/services/:id/vps/ssh-keys Remove a key (confirm: true)
lookerhost_set_vps_password vps:write POST /api/services/:id/vps/password Set a user password, optionally allow SSH passwords (confirm: true)
lookerhost_list_port_forwards vps:read GET /api/services/:id/portforwards List the public ports mapped to a VPS
lookerhost_open_port vps:write POST /api/services/:id/portforwards Open a public port to a VPS port (confirm: true; pending approval unless trusted)
lookerhost_close_port vps:write DELETE /api/services/:id/portforwards/:pfId Release a port-forward (confirm: true)
lookerhost_deploy_app apps:write POST /api/services/apps Create and deploy an app from a Git repository
lookerhost_redeploy_app apps:write POST /api/services/:id/paas/deploy Redeploy an existing app (or restart a catalog AI app). Returns deployId to poll
lookerhost_get_deploy vps:read GET /api/services/:id/paas/deploys/:deployId How one deployment ended (latest accepted). On failure it carries errorCode, a one-line reason and the fix
lookerhost_rollback_app apps:write POST /api/services/:id/paas/rollback Return to a previous version. Edge apps only (static sites and workers), restoring the stored artifact; container apps answer rollback-not-supported
lookerhost_repo_deploy_key apps:write POST /api/services/:id/repository-access/deploy-key Generate a read-only deploy key for a private repo
lookerhost_create_database apps:write POST /api/services/databases Managed PostgreSQL, MySQL, MongoDB or Redis
lookerhost_create_redis apps:write POST /api/services/redis Dedicated Redis instance in Docker: own endpoint, ACL username/password and IP allow-list. Born CLOSED: no allowed IPs, no public endpoint
lookerhost_get_redis vps:read GET /api/services/:id/redis Configuration, endpoint, allow-list and live container state. Never returns the password
lookerhost_redis_connection apps:write GET /api/services/:id/redis/connection Username, password and full redis:// URI. Only way to recover the password after creation; every call is audited
lookerhost_redis_allowed_ips apps:write PUT /api/services/:id/redis/allowed-ips Replace the list of IPs/CIDRs allowed to connect. Widening needs confirm: true; an empty list closes the endpoint
lookerhost_update_redis apps:write PATCH /api/services/:id/redis Version, ACL username, memory cap, eviction policy or persistence. Recreates the container; data survives
lookerhost_redis_password apps:write POST /api/services/:id/redis/password Rotate the ACL user’s password (confirm: true): cuts every connection using the old one
lookerhost_create_wordpress apps:write POST /api/services/wordpress Managed WordPress site, database included
lookerhost_create_aiapp apps:write POST /api/services/aiapps One-click AI app: n8n, Hermes Agent, OpenClaw or Steel Browser
lookerhost_app_volumes apps:write (list: vps:read) GET/POST/DELETE /api/services/:id/paas/volumes List, add or remove a PaaS app’s persistent volumes — without one, every redeploy loses anything written to disk. Removing needs confirm: true
lookerhost_agent_chat apps:write POST /api/services/:id/aiapp/api Chat with the account’s Hermes Agent through its OpenAI-compatible API, reached over LookerHost’s internal network (the agent’s API is never exposed to the internet directly). api_key is the app’s own API_SERVER_KEY
lookerhost_aiapp_api apps:write (GET: vps:read) POST /api/services/:id/aiapp/api Allow-listed call to an AI app’s API — Hermes runs/jobs, Steel Browser sessions and scraping
lookerhost_browser_session apps:write POST /api/services/:id/aiapp/api Create, list, get or release a session on the account’s Steel Browser app — returns a CDP endpoint for Playwright/Puppeteer
lookerhost_browser_scrape apps:write POST /api/services/:id/aiapp/api Render and extract a web page (markdown, HTML or readability) with the account’s own Steel Browser, no session bookkeeping needed
lookerhost_power_service vps:power POST /api/services/:id/power Start, stop or restart any service
lookerhost_delete_service service:delete DELETE /api/services/:id Delete a service permanently — also requires confirm: true
lookerhost_run_agent agent:run POST /api/agent/jobs Start an autonomous coding/ops agent inside one VPS from a natural-language task (like Claude Code logged into the server). approval_mode: write-approval (default), auto (needs confirm: true), manual
lookerhost_agent_job agent:run GET /api/agent/jobs/:id Status, transcript tail, pending approvals and final result of a job
lookerhost_list_agent_jobs agent:run GET /api/agent/jobs Jobs of the account, optionally per VPS
lookerhost_agent_approve agent:run POST /api/agent/jobs/:id/approval Allow (confirm: true) or deny one command or file write the agent asked for
lookerhost_agent_message agent:run POST /api/agent/jobs/:id/message Follow-up instruction or files for a finished job; the agent resumes with full context
lookerhost_agent_abort agent:run POST /api/agent/jobs/:id/abort Stop a running job (confirm: true)

Provisioning is asynchronous. Creating a VPS returns it with status provisioning; poll lookerhost_get_service until it reads running, typically one to three minutes. The first app of an account also provisions its Docker host, so that first deploy is noticeably slower.

Build packs

lookerhost_deploy_app takes a build pack:

Nothing LookerHost-specific has to be committed to the repository.

Public repositories need only their URL. For a private repository, call lookerhost_repo_deploy_key to get a read-only public key and add it on GitHub under Settings → Deploy keys, leaving Allow write access unchecked. The private half stays encrypted on the platform and is never shown. lookerhost_repo_access reports which credential is in play — a build that fails with repository-credential-missing means the repository is private and no credential covers it.

Using the REST API without the MCP server

The MCP server is a convenience wrapper; the same key works directly.

curl -s https://api.lookerhost.com/api/services \
  -H "Authorization: Bearer lh_live_..."
curl -s https://api.lookerhost.com/api/services/apps \
  -H "Authorization: Bearer lh_live_..." \
  -H "Content-Type: application/json" \
  -d '{"label":"my-site","repoUrl":"https://github.com/acme/my-site","branch":"main","buildPack":"static","static":true}'

Errors

Every failure returns JSON with an error code. The ones worth handling:

Code Meaning
no-token No key was sent — check LOOKERHOST_API_KEY
invalid-token Key is invalid, revoked or expired
insufficient-scope The key lacks a scope; need names it. Re-issue with that scope
no-customer The key’s user is not linked to a company
account-not-active Account pending or suspended: read-only until staff activates it
quota-exceeded Account hit its service quota
no-docker-host No PaaS Docker host yet; deploying an app provisions one
protected Adopted VM, protected from self-service deletion
rate-limited Too many requests; wait a few minutes
timeout The call timed out but the operation may still be running — check with lookerhost_get_service before retrying

Machine-readable endpoints

For agents that need to discover all of this on their own:

The manifest at /.well-known/mcp.json is the source of truth for the tool list.

Support

Email support@lookerhost.com, or open an issue at github.com/Cloudcity-Colombia/lookerhost.