Laravel package that exposes a REST API, an MCP server, and Swagger documentation for the Cipi server control panel.
- PHP 8.2+
- Laravel 12+
composer require cipi/apiPublish the configuration and assets:
php artisan vendor:publish --tag=cipi-config
php artisan vendor:publish --tag=cipi-assets
php artisan migrateSeed the API user and create a token:
php artisan cipi:seed-api-user
php artisan cipi:token-create- REST API — CRUD for apps, aliases, www redirects, app/path redirects, prefix proxies, Node apps, databases, SSL, and async jobs (
/api/*), secured with Laravel Sanctum and token abilities. App create supports optional Git for custom apps (SFTP-only), matching Cipi 4.4.4+. Apps can also be taken offline and restored with suspend / unsuspend (HTTP 503 maintenance page), matching Cipi 4.5.8+. HTTP Basic Auth can be enabled, disabled, and inspected per app via/api/apps/{name}/basicauth/*(synchronous, wrapscipi basicauth). App.env(GET|PUT /api/apps/{name}/env, abilityapps-env) merges key/value pairs without replacing the whole file. Sharedauth.json(/api/apps/{name}/auth, abilityapps-auth) is Composer/structured JSON — not HTTP Basic Auth. Artisan (POST /api/apps/{name}/artisan, abilityapps-artisan) runs as an async job; pollGET /api/jobs/{id}for output. Whitelisted app run (POST /api/apps/{name}/run,GET /api/run-commands, abilityapps-run) executes non-interactive binaries as the app user (composer, npm, ls, rm, git, … — no nano/vim/less/bash/tinker). Deploy config (GET|PUT /api/apps/{name}/deploy-config, abilityapps-deploy-config) edits structured Deployer options (keep_releases, hooks, node_build, extra_artisan) and regeneratesdeploy.php— not a raw PHP upload. Env/auth/artisan/run/deploy-config need Cipi ≥ 5.0.3. WWW / apex redirects (/api/apps/{name}/www/*, abilitywww-manage) andPOST …/ssl/forcematch Cipi 4.8+. Multi-engine databases (MariaDB + optional PostgreSQL) viaengineon/api/dbs*andGET /api/dbs/engines. App logs (GET /api/apps/{name}/logs) return paginated nginx, PHP-FPM, and Laravel snapshots (requiresapps-view). Server status (GET /api/status) returns the same data ascipi statusas structured JSON (requiresstatus-view). App/path redirects (/api/apps/{name}/redirect*, abilitiesredirects-view/redirects-manage) and prefix proxies (/api/apps/{name}/proxies, abilitiesproxies-view/proxies-manage) wrapcipi redirect/cipi proxysynchronously (nginx test + revert) — Cipi ≥ 5.3.1 with API sudoers ≥ 5.4.1. Node apps (Cipi 5.4.0+): app create/edit acceptnode(spa|static|ssr),framework,node_version,build,start,output,health_path;GET /api/nodelists runtimes,GET /api/apps/{name}/nodeshows app Node status, andPOST /api/apps/{name}/node/restartdoes a blue/green restart (abilitiesnode-view/node-manage). Deploy audit (GET /api/apps/{name}/deploy/audit, abilitydeploy-manage, Cipi 5.4.0+) returns the hash-chained ledger records. Meilisearch (GET /api/search,POST /api/apps/{name}/search/enable|disable, abilitiessearch-view/search-manage, Cipi 5.2.2+). Read-only host insights:GET /api/packages(packages-view),GET /api/monitor(monitor-view),GET /api/zt(zt-view).POST /api/apps/{name}/fix-permissions(abilityapps-edit, Cipi 5.2.1+) restores the app home permission model. Wildcard primary domains (*.example.com) are accepted since Cipi 5.1.1. - IP whitelist — optional client IP allowlist for
/api/*and/mcp(/etc/cipi/api-ip-whitelist, default*= allow all). Manage withcipi api ip-whitelistorGET|PUT|POST|DELETE /api/ip-whitelist(abilitiesip-whitelist-view/ip-whitelist-manage). Requires Cipi ≥ 5.0.8. - MCP Server — Model Context Protocol endpoint at
/mcpfor AI-powered integrations. - Swagger Docs — Interactive API reference at
/docs, generated frompublic/api-docs/openapi.json. The spec covers apps (including env, auth.json, artisan), aliases, www, deploy, SSL, databases (GET /api/dbs//dbs/enginesvia CLI; other/api/dbs/*actions use jobs), and job polling (including structuredresulttypes per job). - Artisan Commands —
cipi:token-create,cipi:token-list,cipi:token-revoke.
The MCP server is exposed at /mcp using Streamable HTTP transport and is secured with the same Sanctum token used by the REST API. A token with the mcp-access ability is sufficient for all MCP tools — per-endpoint REST abilities (apps-view, deploy-manage, etc.) are not required on /mcp.
Generate a token if you haven't already:
php artisan cipi:token-createReplace https://your-server.com and YOUR_TOKEN in the examples below with your actual Cipi host and token.
Create (or edit) .vscode/mcp.json in your workspace:
{
"inputs": [
{
"type": "promptString",
"id": "cipi-token",
"description": "Cipi API Token",
"password": true
}
],
"servers": {
"cipi-api": {
"type": "http",
"url": "https://your-server.com/mcp",
"headers": {
"Authorization": "Bearer ${input:cipi-token}"
}
}
}
}Restart VS Code after adding the configuration. The token will be requested on first connection and securely stored.
Create (or edit) .cursor/mcp.json in your project root:
{
"mcpServers": {
"cipi-api": {
"url": "https://your-server.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}Restart Cursor after adding the configuration (Cursor v0.40+).
Run the following command from your terminal:
claude mcp add --transport http cipi-api https://your-server.com/mcp \
--header "Authorization: Bearer YOUR_TOKEN"Verify the server is connected:
claude mcp listOnce connected, the following tools are available to the AI agent:
| Tool | Description |
|---|---|
AppList |
List all apps with domains, PHP versions, and aliases |
AppShow |
Show details of a specific app |
AppArtisan |
Run Artisan on a Laravel app (sync; REST uses async jobs) |
AppRun |
Whitelisted non-interactive cmd as app user (async job; Cipi ≥ 5.0.3) |
AppRunCommands |
List allowed AppRun binaries |
AppDeployConfigShow |
Show structured deploy.php options |
AppDeployConfigUpdate |
Update deploy options (regenerates template) |
AppEnvShow |
List Laravel app .env keys (Cipi ≥ 5.0.3; secrets redacted) |
AppEnvUpdate |
Merge/unset .env keys |
AppAuthJsonShow |
Show shared auth.json (not HTTP Basic Auth) |
AppAuthJsonCreate |
Create shared auth.json |
AppAuthJsonUpdate |
Replace shared auth.json |
AppAuthJsonDelete |
Delete shared auth.json |
AppCreate |
Create a new app (custom for non-Laravel apps; optional Git for custom SFTP-only sites, Cipi 4.4.4+) |
AppEdit |
Edit an existing app |
AppDelete |
Delete an app |
AppDeploy |
Deploy an app |
AppDeployRollback |
Rollback the last deploy |
AppDeployUnlock |
Unlock a stuck deploy |
AppSuspend |
Take an app offline (HTTP 503) without deleting it |
AppUnsuspend |
Bring a suspended app back online |
AppFixPermissions |
Restore the app home permission model (async job; Cipi ≥ 5.2.1) |
AppBasicAuthStatus |
Show HTTP Basic Auth status (enabled + usernames) |
AppBasicAuthEnable |
Enable Nginx HTTP Basic Auth on an app |
AppBasicAuthDisable |
Disable HTTP Basic Auth on an app |
AliasList |
List aliases for an app |
AliasAdd |
Add an alias to an app |
AliasRemove |
Remove an alias from an app |
WwwStatus |
Show www/apex redirect status (Cipi 4.8+) |
WwwAdd |
Add www/apex counterpart alias |
WwwForceToRoot |
301 redirect www → apex |
WwwForceFromRoot |
301 redirect apex → www |
WwwClear |
Clear www canonical redirect |
RedirectList |
List whole-app + path redirects (Cipi ≥ 5.4.1) |
RedirectSet |
Redirect every hostname of an app to a URL |
RedirectToggle |
Enable/disable the saved whole-app redirect |
RedirectUnset |
Remove the whole-app redirect (forget target) |
RedirectAdd |
Add/update a path redirect (prefix or exact) |
RedirectRemove |
Remove a path redirect |
ProxyList |
List prefix reverse proxies |
ProxyAdd |
Add/update a prefix proxy (loopback guard enforced) |
ProxyRemove |
Remove a prefix proxy |
NodeRuntimes |
List installed Node runtimes + server default (Cipi 5.4.0+) |
NodeStatus |
Node status of an app (mode, framework, build/start) |
NodeRestart |
Blue/green restart of an SSR Node app (async job) |
DeployAudit |
Deploy audit ledger records for an app (Cipi 5.4.0+) |
SearchStatus |
Meilisearch status + search-enabled apps (Cipi 5.2.2+) |
SearchEnable |
Enable Meilisearch/Scout for a Laravel app |
SearchDisable |
Disable search (restores previous SCOUT_DRIVER) |
PackageList |
Optional host packages catalog (read-only) |
MonitorList |
System monitor checks + state (read-only, Cipi 5.3.0+) |
ZtStatus |
Cloudflare Zero Trust status (read-only, Cipi 5.3.0+) |
DbEngines |
List installed DB engines and default (Cipi 4.8+) |
DbList |
List databases (optional engine filter) |
DbCreate |
Create a database (engine = mariadb|pgsql) |
DbBackup |
Create a compressed backup of a database |
DbRestore |
Restore a database from a backup file |
DbPassword |
Regenerate database password |
SslInstall |
Install an SSL certificate for an app |
SslForce |
Re-apply HTTP → HTTPS redirect (no new issuance) |
JobShow |
Poll async job status, result, and CLI output |
AppLogs |
Read recent app logs (cipi app logs types) |
ApiLogShow |
Read Cipi API host Laravel logs |
ServerStatus |
Server snapshot (same JSON as GET /api/status) |
ServiceList |
System service status (cipi service list) |
This package is automatically installed and configured by cipi api. No manual setup is needed.
The CIPI_APPS_JSON env variable defaults to /etc/cipi/apps.json.
Token abilities for cipi api token create are defined in config/cipi.php (token_abilities) and exposed via php artisan cipi:token-abilities. The Cipi CLI checklist calls that command when the API package is installed.
GET /api/dbs runs sudo cipi db list on the host (synchronously), like the Cipi server CLI: vault and MariaDB access stay inside Cipi, not duplicated in PHP.
Why other API actions worked but db failed: Cipi configures /etc/sudoers.d/cipi-api so www-data may run NOPASSWD only for an explicit list of cipi subcommands (app, deploy, alias, ssl, …). Database commands were missing from that whitelist until Cipi 4.4.17, so sudo tried to ask for a password and failed without a TTY (sudo: a terminal is required). Update the server with cipi self-update (applies migration 4.4.17) or add the cipi db … lines to cipi-api sudoers manually (see Cipi setup.sh).
AppArtisan / env / auth.json: require Cipi CLI ≥ 5.0.3 (cipi self-update) so /etc/sudoers.d/cipi-api allows app artisan, app env, and auth create|edit|show|delete, and so non-interactive env/auth flags exist. REST Artisan is async (POST /api/apps/{name}/artisan → poll job); MCP AppArtisan stays synchronous.
AppRun / AppDeployConfig*: require Cipi CLI ≥ 5.0.3. App run is non-interactive only. Deploy config is structured knobs (never raw deploy.php upload).
ServerStatus / ServiceList: ServerStatus returns structured JSON (same as GET /api/status), preferring sudo cipi status with a host-read fallback. ServiceList runs sudo cipi service list on the host. Both require mcp-access only on /mcp. Ensure cipi-api sudoers allows status and service list (see Cipi setup.sh).
Redirects / Proxies / Node: require Cipi CLI ≥ 5.4.1 (cipi self-update, migration 5.4.1) so /etc/sudoers.d/cipi-api allows redirect *, proxy *, and node list|status|restart. The commands themselves exist since Cipi 5.3.1 (redirect/proxy) and 5.4.0 (node). All redirect/proxy writes are synchronous: the CLI validates the rule (loops, collisions, reserved paths, charset), regenerates the vhost, runs nginx -t, and reverts on failure. The proxy loopback guard is never bypassed from the API (no --force).
Search / Packages / Monitor / Zero Trust: the API exposes only what the panel sudoers allow — search status|list|enable|disable, package list, monitor list, zt status. Installing or upgrading Meilisearch, installing packages, changing monitor thresholds, and every zt mutation stay with the operator on the host CLI, by design.
Deploy audit: GET /api/apps/{name}/deploy/audit and the DeployAudit MCP tool read the root-only hash-chained ledger via sudo cipi deploy <app> --audit --json (Cipi 5.4.0+). An empty list means the ledger has not been written yet (first deploy after cipi self-update).
MIT