Skip to main content
Glama

Kleap — website infrastructure for AI agents

CI CLI MCP 33 tools license

Your agent builds. Kleap ships it live. Let any AI agent — Claude, ChatGPT, Cursor, or a bash-tool agent like Claude Code — build, edit and publish real, live websites for you. Hosting, database, auth and domains included.

An alternative to Lovable / v0 / Bolt — except it's driven by your agent, and every publish comes with the verified-live guarantee: a site is only ever reported online once it is provably serving — never a hallucinated dead link.

This package is both a CLI (kleap create "…", kleap publish 42, …) and an MCP server (kleap mcp / no args) — same account, same ~/.kleap/config.json auth, same underlying /api/v1 REST API. Pick whichever fits your agent: a shell/bash-tool agent (Claude Code, a cron script, CI) wants the CLI — one compact line per call, no JSON-RPC framing. An MCP-native client (Claude Desktop, Cursor, ChatGPT connectors) wants the MCP server, which this package also is, unchanged.

A real, unedited run: an agent writes a page with write_files, publishes, and it is live and serving in seconds.

Above: a real run — your agent writes the code with write_files, publish_app builds & deploys it, and the page is live in seconds. Or just ask Kleap's AI in plain English.

No secrets live in this package — it reads your own KLEAP_API_KEY (or the token saved by kleap auth login) and talks only to kleap.co.


CLI (for agent shells — Claude Code, Codex, scripts)

If your agent drives a bash tool rather than MCP, use the CLI directly. Output is 1-3 lines by default (token-efficient — built for an agent reading its own tool output, not a human terminal), clean exit codes (0 ok / 1 failed / 2 still running), and a --json flag whenever you want the full structured response.

npx -y kleap-cli auth login              # opens your browser once, no key to paste
# — or, for CI / non-interactive: npx -y kleap-cli auth key kleap_live_sk_...

npx -y kleap-cli create "a one-page site for my bakery, warm palette"
# ✓ created app 4821 — https://warm-bakery-fold.kleap.io

npx -y kleap-cli edit 4821 "change the headline to 'Roasted slow'"
# ✓ edited app 4821 — https://warm-bakery-fold.kleap.io

npx -y kleap-cli publish 4821
# ✓ published https://warm-bakery-fold.kleap.io

npx -y kleap-cli status warm-bakery-fold.kleap.io   # by id, slug, kleap.io URL, or connected custom domain
# ✓ Bakery (4821) — live: https://warm-bakery-fold.kleap.io

Commands

Command

What it does

kleap auth login

Sign in via browser (OAuth, PKCE loopback) — no key to copy

kleap auth key <KEY>

Store a kleap_live_sk_... key instead (CI / non-interactive)

kleap auth logout / kleap auth status

Clear / show current auth

kleap create "<prompt>" [--visibility public|personal] [--webhook <url>] [--no-wait] [--json]

Create a site, wait for the build (~5-15 min), print the live URL

kleap edit <app> "<prompt>" [--webhook <url>] [--no-wait] [--json]

Ask Kleap's AI to change a site, wait for it to redeploy

kleap publish <app> [--no-wait] [--json]

Publish/redeploy with the verified-live guarantee

kleap status <app> [--json]

One-line status: name, id, live URL or "not published"

kleap list [--limit N] [--q text] [--json]

Your apps, one tab-separated row each: id name url

kleap domains search <query> [--tlds .com,.io] [--json]

Available domains, one per line

kleap domains connect <domain> <app> [--json]

Connect a domain you own; prints the A record to set

kleap screenshot <app>

Capture a preview screenshot, print its URL

kleap task <task_id> [--wait] / kleap task retry <task_id> [--wait]

A create/edit task's status (long-poll with --wait) / resume a failed one

kleap rename <app> <name> · kleap wake <app> · kleap messages <app> · kleap credits

Rename (URL unchanged) · wake a preview sandbox · chat history · credit balance + plan

kleap files ls <app> · files cat <app> <path...>

List source paths · print file contents

kleap files write <app> <path> --file <local> | --stdin | --content "<text>"

Write a file (binary extensions go base64 automatically, 512 KB max) → then publish

kleap files edit <app> <path> --find "<old>" --replace "<new>" [--all]

Replace text inside a file

kleap files rm <app> <path...>

Delete pages/assets (live until the next publish)

kleap image <app> <public/name.webp> "<prompt>" [--hd]

Generate an image into the site → then publish

kleap forms <app> [--since ISO] [--limit N]

Form submissions (leads), newest first; --json is flattened

kleap analytics <app> [--period 7d|30d|90d]

Visitors, pageviews, top pages

kleap search-console <app> · search-console connect <app>

Google Search numbers · the consent link the user opens

kleap db schema <app>

Tables, row counts, columns of the app's Postgres

kleap db rows <app> <table> [--where json] [--limit] [--offset] [--order-by col --order asc|desc]

Read rows (one JSON object per line)

kleap db insert <app> <table> '<json>'|--file rows.json

Insert one object or an array (chunked at 500)

kleap db update <app> <table> --where json --set json · db delete <app> <table> --where json

--where is mandatory and non-empty

kleap db sql <app> "<sql>" [--params json]

One SQL statement with $1..$n params (owner-level: needs database:write even for SELECT; 500 rows / 5 MB cap)

kleap domains buy <domain> [--years N] [--app <app>]

Creates a Stripe checkout link the user pays — never bought until they do

kleap domains check <domain>

DNS / connection status (also: did the paid domain get registered?)

kleap mcp

Run the MCP stdio server explicitly (same as no args)

<app> accepts a numeric app id, a slug.kleap.io URL, a bare slug, or a connected custom domain — resolved server-side in one call (GET /apps/resolve), same as the MCP find_app tool.

Example: a Claude Code / bash-tool agent

# One-shot: build it, publish it, hand back a URL a human can click.
url=$(npx -y kleap-cli create "a landing page for my podcast" --json | node -e \
  'let d="";process.stdin.on("data",c=>d+=c).on("end",()=>console.log(JSON.parse(d).url))')
echo "Live: $url"

# Non-blocking flow (agent does other work while it builds):
npx -y kleap-cli create "a landing page for my podcast" --no-wait --json   # → { task_id, app_id, ... }
# ... later ...
npx -y kleap-cli status 4821

Exit codes are always clean: 0 on success, 1 on any failure, 2 when a build is still running after the wait cap (9 min, KLEAP_WAIT_MINUTES to change it) — not a failure: the line gives the kleap task <id> --wait to keep waiting. Failures print a single ✗ <reason> line on stderr (or {"error":{"message":...}} with --json) — safe to check with $? / try/except subprocess.run(..., check=True) without scraping prose.

Install once (optional — npx -y above needs no install)

npm i -g kleap-cli
kleap auth login
kleap create "a one-page site for my bakery"

Related MCP server: shiply — Static Site Hosting & Deployment

MCP server (for MCP-native clients — Claude Desktop, Cursor, ChatGPT)

Same package, same account, same ~/.kleap/config.json auth — just a different transport for clients that speak MCP instead of a bash tool.

Easiest — connect with OAuth, no key

Add the hosted connector and sign in. Nothing to generate, nothing to paste — you authorize Kleap in your browser like any other app. Works in Claude Desktop, ChatGPT and Cursor.

https://kleap.co/api/mcp
  • Claude Desktop — Settings → Connectors → Add custom connector → paste the URL → Connect → sign in to Kleap.

  • ChatGPT — Settings → Connectors → add the URL → authorize with OAuth.

  • Cursor — Settings → MCP → Add server → paste the URL → authorize.

That's it — all 34 hosted tools (the 33 listed below plus upgrade_plan) are available after OAuth sign-in. Skip straight to step 3.


Or — local CLI, sign in with your browser (no key)

Prefer a local stdio process? Sign in once — no key to generate or paste:

npx kleap-cli auth login

This opens your browser, you authorize Kleap, and the token is saved to ~/.kleap/config.json. After that, npx -y kleap-cli just works. (kleap auth logout / kleap auth status are there too.) Then add a keyless stdio entry to your client, e.g. Claude Desktop claude_desktop_config.json:

{ "mcpServers": { "kleap": { "command": "npx", "args": ["-y", "kleap"] } } }

Or — local CLI with an API key

Prefer a key (e.g. for CI or scripting the REST API directly)?

1. Get an API key — open kleap.co/settings/api-key and click Create my API key (kleap_live_sk_...).

2. Add Kleap to your AI client:

{
  "mcpServers": {
    "kleap": {
      "command": "npx",
      "args": ["-y", "kleap"],
      "env": { "KLEAP_API_KEY": "kleap_live_sk_..." }
    }
  }
}
{
  "mcpServers": {
    "kleap": {
      "command": "npx",
      "args": ["-y", "kleap"],
      "env": { "KLEAP_API_KEY": "kleap_live_sk_..." }
    }
  }
}
claude mcp add kleap -e KLEAP_API_KEY=kleap_live_sk_... -- npx -y kleap-cli
{
  "mcpServers": {
    "kleap": {
      "command": "npx",
      "args": ["-y", "kleap"],
      "env": { "KLEAP_API_KEY": "kleap_live_sk_..." }
    }
  }
}
{
  "mcpServers": {
    "kleap": {
      "command": "npx",
      "args": ["-y", "kleap"],
      "env": { "KLEAP_API_KEY": "kleap_live_sk_..." }
    }
  }
}

Add the hosted connector at https://kleap.co/api/mcp and authorize with OAuth (or paste your kleap_live_sk_ key). Same tools, no install.

Every stdio config is identical — npx -y kleap-cli + a KLEAP_API_KEY env var — so any MCP client works.

Least-privilege keys: when you generate a key, pick a scope — Read-only (inspect sites, no changes), Build, or Full. Buying domains is never included by default. Give a read-only agent a read-only key.

3. Restart the client and just ask:

"Build me a one-page site for my bakery, publish it, and give me the live URL." "Add a contact form to my site and redeploy." "Change the headline to 'Roasted slow' and publish."

Works with any MCP-compatible agent: Claude · ChatGPT · Cursor · Claude Code · Codex.


Tools

Find & build — find_app · create_app · modify_app · check_task · retry_task · rename_app · get_screenshot · wake_app Files — list_app_files · read_files · write_files · edit_files · delete_files · generate_image Publish & domains — publish_app · get_publish_status · search_domains · buy_domain · check_domain · connect_domain Leads, traffic, SEO — get_form_submissions · get_analytics · get_search_console · connect_search_console Database — get_database_schema · query_database_rows · insert_database_rows · update_database_rows · delete_database_rows · run_database_sql Account — list_apps · get_app · get_credits

Tool

What it does

find_app

Resolve a domain / URL / slug → app_id in one call

create_app / modify_app

Build a site from a prompt / ask its AI for a change → returns a task (auto-deploys live)

check_task / retry_task

Long-poll a task (wait up to 50s) / resume a failed one (new task_id)

read_files → edit_files / write_files / delete_files

Read current contents, then change exactly what must change (base64 for binaries) → publish_app

generate_image

Generate a real image into public/ without sending bytes

publish_app / get_publish_status

Publish with verified-live; confirm it + read the post-deploy report

search_domains / buy_domain

Find domains / create a checkout link the user pays (nothing is bought by the agent)

connect_domain / check_domain

Connect a domain the user owns / its DNS status

get_form_submissions

The site's leads, newest first (since for only new ones)

get_analytics / get_search_console / connect_search_console

Traffic / Google Search numbers / consent link for Search Console

get_database_schema … run_database_sql

The app's Postgres: schema, row CRUD (where required for update/delete), SQL

rename_app / get_screenshot / wake_app

Rename (URL unchanged) / screenshot URL / wake a preview sandbox

list_apps / get_app / get_credits

Your apps, one app's details, credit balance + plan

Database and checkout tools need the database:* / domains:checkout scopes: a key created before they existed gets 403 INSUFFICIENT_SCOPE — create a new key with the Full preset.

App arguments are snake_case: app_id, task_id, prompt, message, visibility.

Recipes

Two ways to put code on a site — pick per task:

  • write_files (deterministic): your model writes the exact file contents; you push them and Kleap builds + deploys as-is. No Kleap-AI step → no Kleap credits, never stalls. Then publish_app. Unlike Lovable/v0/Bolt, your agent can write the code itself.

  • modify_app (Kleap's AI): describe the outcome in plain English and Kleap's AI writes it. Like Lovable's message-passing — kept for when you'd rather it figure out the change.

Either way Kleap hosts it (build, deploy, SSL, DB, auth, domains, verified-live).

  • Edit existing files SAFELY (don't rewrite blind) — list_app_files(app_id) → read_files(app_id, ["src/components/Header.astro"]) → edit only what must change with your own model → write_files(app_id, [{ path, content }]) → publish_app(app_id). This read→edit→write loop is the reliable way to fix headers/footers, wrong phone numbers, broken links or dead forms without breaking the rest of the site.

  • Edit a site named by its address — find_app("mysite.ch") → read_files(...) → write_files(...) → publish_app(...), or modify_app(app_id, "…") → check_task(task_id, wait=45).

  • Many pages (programmatic SEO) — BEST: generate a dynamic route + a data file with your own model and push them in one write_files, then publish_app:

    write_files(app_id, [{ path: "src/pages/[service]/[city].astro", content: … }, { path: "src/data/locations.json", content: … }]) → publish_app(app_id) Deterministic, scales to thousands, no stall, no credits. (Or ask Kleap's AI to do the same in one modify_app — never loop one call per page.)

  • Don't babysit a 5-15 min build — check_task long-polls (default wait=45), or pass a webhook_url to create_app / modify_app for a fully hands-off flow.

  • A build failed — TASK_TIMEOUT/STALE_TASK = transient, call retry_task; it returns a new task_id — poll that one. TASK_FAILED = read the message, retry once.

The verified-live guarantee

Most tools tell the agent "it's online" the moment a deploy is requested. Kleap reports a site as published only once the new version is provably serving at its live URL — otherwise it rolls back and reports "not confirmed live." Your agent can never hand a user a dead link.

If check_task reports failed (a transient generation stall), call retry_task with that task_id to resume from where it stopped — it returns a new task_id to poll, and partial work is kept. Or skip the AI entirely and write_files the exact code yourself, then publish_app.

FAQ

Do I need an API key? No. The easiest path is the OAuth connector (https://kleap.co/api/mcp) — you sign in with your browser and never copy a key. An API key is only needed for the local CLI / direct REST use.

Is it safe? Yes. Whether you connect with OAuth or an API key, an agent can only ever touch your own Kleap apps. OAuth tokens and kleap_live_sk_ keys are scoped, sent only over HTTPS, and revocable anytime in https://kleap.co/settings/api-key. Credentials from kleap auth login / kleap auth key are stored in ~/.kleap/config.json (permissions 0600); kleap auth logout deletes that file. A stored OAuth login is bound to the origin that issued it — if KLEAP_API_URL points anywhere else, the CLI refuses to send the token (CREDENTIAL_ORIGIN_MISMATCH) so a malicious/typo'd endpoint can't capture it. For custom endpoints (e.g. staging), use KLEAP_API_KEY or kleap auth key — an explicit secret you provide is sent where you point it. Details in SECURITY.md.

How much does it cost? Connecting is free. Builds and edits use Kleap credits (get_credits reports your balance) — see pricing.

Which agents work? Any MCP client: Claude Desktop, Claude Code, Cursor, ChatGPT (hosted connector), and others.

Requirements & run

Node ≥ 18. Run it directly:

KLEAP_API_KEY=kleap_live_sk_... npx -y kleap-cli
# → [kleap-mcp] ready (stdio) → https://kleap.co. Tools: list_apps, ...

Override the API base with KLEAP_API_URL (default https://kleap.co). Missing key → the server exits with a clear message. Note: a stored OAuth login only works against the origin it was issued by — with a custom KLEAP_API_URL, authenticate via KLEAP_API_KEY or kleap auth key instead (see SECURITY.md).

Maintained by the Kleap team. MIT © Kleap.

Available Tools

13 tools
check_domainAInspect

Check a domain's connection / DNS status for a Kleap app.

Inputs: domain (required).

check_taskAInspect

Poll an async task (app creation or edit). Returns status + result when done. If status is 'failed' (e.g. a transient generation stall), call retry_task with the same task_id to resume — don't start over.

Inputs: task_id (required).

connect_domainAInspect

Connect a domain the user ALREADY OWNS to a published Kleap app (sets up routing + automatic TLS). The app must be published first; the user points the domain's A record to Kleap. Does not buy anything.

Inputs: app_id (required), domain (required).

create_appAInspect

Create a new Kleap website from a natural-language prompt. Returns a task — poll check_task until it completes.

Inputs: prompt (required), visibility.

get_appAInspect

Get one Kleap app's metadata: status, slug, production_url, published state.

Inputs: app_id (required).

get_creditsAInspect

Check the authenticated account's remaining credit balance and plan.

Inputs: no named parameters.

get_publish_statusBInspect

Check whether an app is actually published and live (production_url + published state).

Inputs: app_id (required).

list_app_filesBInspect

List the source files of a Kleap app.

Inputs: app_id (required).

list_appsAInspect

List the Kleap apps (websites) owned by the authenticated account.

Inputs: limit, offset.

modify_appCInspect

Ask a Kleap app's AI to change it (edit copy, add a section, fix a bug). Returns a task — poll check_task.

Inputs: app_id (required), message (required).

publish_appAInspect

Publish a Kleap app to its live URL with the VERIFIED-LIVE guarantee: it is only reported live once the new version is provably serving (otherwise it reports 'not confirmed live' — never a false positive). Returns a deploy handle — poll get_publish_status.

Inputs: app_id (required).

retry_taskAInspect

Resume a failed or stalled create/modify task from where it stopped (partial files are preserved). Use this when check_task reports 'failed' before starting a brand-new create_app. Returns a fresh task — poll check_task on the new task_id.

Inputs: task_id (required).

search_domainsAInspect

Search for available domains for a site (e.g. 'mybakery'). Returns available names across TLDs. NOTE: agents cannot buy a domain — purchase is confirmed by the user in Kleap. Use connect_domain for a domain the user already owns.

Inputs: query (required), tlds.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 13 tools

    Disambiguation5/5

    Each tool targets a distinct action (check, connect, create, modify, publish, list, etc.) with clear boundaries. No two tools have overlapping purposes.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern in snake_case, making the set predictable and easy to navigate.

    Tool Count5/5

    13 tools cover the core workflows of app creation, modification, publishing, domain management, and task handling without excess or deficiency.

    Completeness4/5

    The tool surface covers creation, modification, publishing, and domain management, but lacks a delete operation for apps or domains, which is a minor gap.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers