Cipi Agent
Installation
cipi-agent is a lightweight Laravel package that connects your application to Cipi.
It provides a webhook endpoint for automatic deploys on git push, a health check
endpoint, an MCP server for AI assistants, a database anonymizer for GDPR-safe data exports,
and a set of useful Artisan commands.
$ composer require cipi/agent
The service provider auto-discovers — no configuration or config/app.php change is
needed. Cipi already injected the required .env variables during
cipi app create, so the package works out of the box.
Artisan commands
| Command | Description |
|---|---|
| php artisan cipi:status | Show Cipi config values and connectivity status |
| php artisan cipi:deploy-key | Print the SSH deploy key for this app |
| php artisan cipi:mcp | Show the MCP endpoint URL and setup snippets for Cursor, VS Code, and Claude Desktop |
| php artisan cipi:generate-token {type} | Generate a secure token. Type can be mcp, health, or
anonymize
|
| php artisan cipi:service {type} --enable|--disable | Toggle a service on or off. Updates .env in place. Type can be
mcp or anonymize
|
| php artisan cipi:init-anonymize | Scaffold the anonymization config at
/home/{app_user}/.db/anonymization.json
|
Webhook — Automatic Deploys
The agent exposes a POST endpoint at /cipi/webhook. When your Git provider sends a push
event, the agent verifies the signature and writes a .deploy-trigger flag file. A cron
job running every minute as the app user detects this file, removes it, and runs Deployer in the
background.
This design means the webhook response is instant (no HTTP timeout waiting for deployment to
complete) and Deployer runs with the correct user permissions — no sudo required.
Configure your Git provider
| Provider | Webhook URL | Secret field |
|---|---|---|
| GitHub | https://yourdomain.com/cipi/webhook | Secret |
| GitLab | https://yourdomain.com/cipi/webhook | Secret token |
The token to use is stored in .env as CIPI_WEBHOOK_TOKEN. You can also
retrieve it any time with:
$ cipi deploy myapp --webhook
Branch filtering
By default every push triggers a deploy. To restrict deploys to a specific branch, add this to your
.env:
CIPI_DEPLOY_BRANCH=main
Pushes to any other branch will receive a skipped response and no deploy will be
triggered.
Health Check
The agent also exposes a GET endpoint at /cipi/health that returns a JSON payload with
the status of the app, database, cache, queue, and the currently deployed Git commit hash. Useful
for external monitoring services such as UptimeRobot. Protected by the
CIPI_HEALTH_TOKEN Bearer token — generate one with
php artisan cipi:generate-token health.
$ curl -H "Authorization: Bearer YOUR_CIPI_HEALTH_TOKEN" \
https://yourdomain.com/cipi/health
{
"status": "healthy",
"app_user": "myapp",
"php": "8.5",
"laravel": "12.0.0",
"commit": "a1b2c3d",
"checks": {
"database": { "ok": true },
"cache": { "ok": true },
"queue": { "ok": true, "pending_jobs": 0 }
}
}
The commit field shows the short Git hash of the currently deployed release, useful
for verifying which version is running in production.
MCP Server
cipi-agent includes a built-in MCP server (Model Context Protocol)
that exposes your application to AI assistants such as Cursor,
VS Code (with GitHub Copilot), and Claude Desktop. The endpoint
implements MCP 2024-11-05 over HTTP using JSON-RPC 2.0
and is protected by the CIPI_MCP_TOKEN Bearer token.
The MCP endpoint is available at POST /cipi/mcp and is disabled by default. To enable
it:
$ php artisan cipi:service mcp --enable $ php artisan cipi:generate-token mcp
Available tools
The MCP server exposes six tools that an AI assistant can invoke by name:
| Tool | Description |
|---|---|
| health | App, database, cache, and queue status — same data as the
/cipi/health endpoint
|
| app_info | Full application configuration: app user, PHP version, Laravel version, environment, queue/cache/session drivers, deploy branch, and all Cipi URLs |
| deploy | Trigger a new zero-downtime deployment — writes the
.deploy-trigger file; Deployer picks it up within 1 minute
|
| logs | Read the last N lines (default 50, max 500) from application logs. Supports
type (laravel, nginx, php,
worker, deploy), level for Laravel severity
filtering (e.g. error), and search for keyword filtering.
Laravel daily rotation (laravel-YYYY-MM-DD.log) is auto-detected.
|
| db_query | Execute SQL queries against the application database — equivalent to
cipi app tinker. Supports SELECT, SHOW, DESCRIBE, EXPLAIN (read) and
INSERT, UPDATE, DELETE (write). Results formatted as ASCII table, capped at 100 rows.
Destructive DDL (DROP TABLE/DATABASE, TRUNCATE, GRANT/REVOKE, file I/O) is blocked.
|
| artisan | Run any Artisan command (e.g. migrate:status,
queue:size, cache:clear). Long-running and interactive
commands like serve, queue:work, and
tinker are blocked
|
Setup instructions
Run the cipi:mcp Artisan command to get the endpoint URL and ready-to-paste
configuration snippets for your AI client:
$ php artisan cipi:mcp
The command prints the available tools and the JSON configuration for Cursor, VS Code, and Claude Desktop.
Cursor
Add the following to ~/.cursor/mcp.json (or go to Cursor → Settings → MCP):
{
"mcpServers": {
"cipi-myapp": {
"type": "http",
"url": "https://yourdomain.com/cipi/mcp",
"headers": {
"Authorization": "Bearer YOUR_CIPI_MCP_TOKEN"
}
}
}
}
Replace cipi-myapp with your app user name, yourdomain.com with your
actual domain, and YOUR_CIPI_MCP_TOKEN with the token from your
.env. Cursor connects natively over HTTP — no bridge needed.
VS Code
VS Code (with GitHub Copilot) supports MCP natively since version 1.102. Add the following to
.vscode/mcp.json in your project (or run MCP: Open User Configuration
for a global setup):
{
"servers": {
"cipi-myapp": {
"type": "http",
"url": "https://yourdomain.com/cipi/mcp",
"headers": {
"Authorization": "Bearer YOUR_CIPI_MCP_TOKEN"
}
}
}
}
Replace cipi-myapp, yourdomain.com, and
YOUR_CIPI_MCP_TOKEN
as above. Use MCP: Add Server from the Command Palette for a guided setup. VS Code
connects over HTTP — no bridge needed.
Claude Desktop
Claude Desktop requires the mcp-remote bridge to convert stdio to HTTP. Add the
following to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"cipi-myapp": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://yourdomain.com/cipi/mcp",
"--header",
"Authorization: Bearer YOUR_CIPI_MCP_TOKEN"
]
}
}
}
Install mcp-remote globally once with:
$ npm install -g mcp-remote
What you can do with it
Once connected, your AI assistant can interact with the Cipi-managed application in natural language. For example:
User: Is the app healthy? Any pending jobs in the queue? Claude: Calling health tool... Status: healthy — database, cache, and queue all OK. Queue: 0 pending jobs. User: Show me the last errors from the log. Claude: Calling logs tool (lines: 100)... Found 2 errors in the last 100 lines: [2026-03-04 14:22:01] production.ERROR: Connection refused [...] [2026-03-04 14:23:15] production.ERROR: Redis timeout [...] User: Clear the cache and deploy the latest version. Claude: Calling artisan tool (cache:clear)... Cache cleared successfully. Calling deploy tool... Deploy queued — Deployer will run within 1 minute. User: What's the current migration status? Claude: Calling artisan tool (migrate:status)... All 47 migrations have been run. User: How many users signed up in the last 7 days? Claude: Calling db_query tool (SELECT COUNT(*) FROM users WHERE created_at >= ...)... | count | |-------| | 23 |
CIPI_MCP_TOKEN secret. Anyone with the token can trigger deploys,
read logs, run database queries, and run Artisan commands through the MCP endpoint. If you
suspect a leak, regenerate
the token with php artisan cipi:generate-token mcp and restart the application.
Database Anonymizer
cipi-agent includes a built-in database anonymizer that creates sanitized copies of your production database — ideal for sharing with developers, QA teams, or staging environments without exposing real user data. It supports both MySQL and PostgreSQL and uses Faker-based transformations configured via a JSON file.
How it works
- A
POST /cipi/dbrequest queues anAnonymizeDatabaseJobin the background - The job runs
php artisan cipi:anonymize, which dumps the database, applies Faker-based transformations according toanonymization.json, and produces a sanitized SQL file - When complete, an email notification is sent with a signed download URL
GET /cipi/db/{token}serves the anonymized dump via a signed URL that expires after 15 minutes
A utility endpoint POST /cipi/db/user is also available for user ID lookup, useful
when building anonymization rules.
Setup
Scaffold the anonymization configuration file:
$ php artisan cipi:init-anonymize
This creates /home/{app_user}/.db/anonymization.json with a starter template. The
file is stored outside the project repository for security — it never gets committed.
Configuration
Edit /home/{app_user}/.db/anonymization.json to define which tables and columns to
anonymize:
{
"tables": {
"users": {
"name": "name",
"email": "safeEmail",
"phone": "phoneNumber",
"address": "address"
},
"orders": {
"shipping_address": "address",
"notes": "sentence"
}
}
}
Each key under tables is a database table name. Each nested key is a column name,
and the value is a Faker
formatter (e.g. name, safeEmail,
phoneNumber, address, sentence).
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /cipi/db | Queue an anonymization job. Returns immediately; sends email when done. |
| POST | /cipi/db/user | User ID lookup utility |
| GET | /cipi/db/{token} | Download the anonymized dump (signed URL, expires in 15 minutes) |
All endpoints are protected by the CIPI_ANONYMIZER_TOKEN Bearer token.
Enable the anonymizer
The anonymizer is disabled by default. Enable it and generate a token:
$ php artisan cipi:service anonymize --enable $ php artisan cipi:generate-token anonymize
/home/{app_user}/.db/ is already excluded).
Never commit it to version control.ENV Variables
These variables are automatically injected by Cipi into the app's .env during
cipi app create. You normally do not need to set them manually.
| Variable | Description | Default |
|---|---|---|
| CIPI_WEBHOOK_TOKEN | HMAC secret / token for webhook validation | auto-generated |
| CIPI_DEPLOY_BRANCH | Branch that triggers a deploy (empty = all branches) | empty |
| CIPI_APP_USER | Linux user owning this app | auto-set |
| CIPI_MCP | Enable or disable the MCP server endpoint at /cipi/mcp |
false |
| CIPI_MCP_TOKEN | Bearer token for MCP endpoint authentication | none |
| CIPI_HEALTH_TOKEN | Bearer token for the /cipi/health endpoint |
none |
| CIPI_ANONYMIZER | Enable or disable the database anonymizer endpoints at /cipi/db |
false |
| CIPI_ANONYMIZER_TOKEN | Bearer token for the anonymizer endpoints | none |
php artisan cipi:generate-token {type} to generate tokens for
mcp, health, or anonymize. Use
php artisan cipi:service {type} --enable|--disable to toggle services — the
command updates your .env in place.