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.

bash
$ 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.

After installing the package, commit and push. Cipi will pick it up on the next deploy automatically.

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:

bash
$ 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:

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.

bash
$ curl -H "Authorization: Bearer YOUR_CIPI_HEALTH_TOKEN" \
    https://yourdomain.com/cipi/health
json
{
  "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:

bash
$ 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:

bash
$ 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):

json
{
  "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):

json
{
  "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:

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:

bash
$ 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:

conversation
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    |
The MCP server does not require SSH access to the VPS. It works entirely over HTTPS using the same Bearer token used by the webhook and health check endpoints. This makes it ideal for teams where developers should be able to monitor and deploy without root access.
Keep your 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

  1. A POST /cipi/db request queues an AnonymizeDatabaseJob in the background
  2. The job runs php artisan cipi:anonymize, which dumps the database, applies Faker-based transformations according to anonymization.json, and produces a sanitized SQL file
  3. When complete, an email notification is sent with a signed download URL
  4. 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:

bash
$ 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:

json
{
  "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:

bash
$ php artisan cipi:service anonymize --enable
$ php artisan cipi:generate-token anonymize
The anonymization config file contains the mapping of your database schema. Keep it outside your repository (the default path /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
Use 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.