Laravel · MCP · debug · seeders

How to use cipi/agent in Laravel — project MCP for debug and seeders

By · Last updated: · free to read, no paywall

SSHing into production for a migrate:status, a failed-job peek or a staging seeder is slow, unshareable and useless to an AI assistant. The official Laravel package cipi/agent puts webhooks, health checks and — most useful — a project MCP inside the app, so Cursor can read logs, run Artisan and query the database over HTTPS.

In this guide
  1. Why an agent inside the app
  2. Install cipi/agent
  3. What the package actually does
  4. Turn on the project MCP
  5. Connect Cursor, VS Code or Claude
  6. Debug without SSH
  7. Seeders, migrate and cache via artisan
  8. A daily loop you can copy
  9. Project MCP vs panel API MCP
  10. Tokens, blocks and least privilege
  11. FAQ

Why an agent inside the app

Cipi already owns the server: Nginx, PHP, databases, SSL, zero-downtime deploys. That is infrastructure. A Laravel app still has its own world — Eloquent models, seeders, Horizon queues, daily log rotation, the current migration set. An AI that only sees the repo guesses. An AI that can call tools on the running app stops guessing.

That is what the project MCP is for. It lives at POST /cipi/mcp on the app domain, talks MCP 2024-11-05 over HTTPS, and exposes six tools scoped to that application. No root SSH. No shared deploy key in the IDE. The assistant asks for health, tails laravel.log, runs db:seed --class=RoleSeeder on staging, and checks the row count with db_query.

Health check and MCP work on any Laravel 12+ host. Webhook deploys and the full log set (nginx, php, worker, deploy) expect a Cipi-managed environment. The reference lives in the Cipi Agent docs.

Install cipi/agent

Requirements: PHP 8.3+ and Laravel 12 or 13. The service provider auto-discovers — leave config/app.php alone.

$ composer require cipi/agent $ php artisan cipi:status # config + live DB connectivity

On a Cipi VPS, cipi app create already injects CIPI_APP_USER, CIPI_WEBHOOK_TOKEN and the deploy paths. You only enable the optional services you want. Off Cipi, publish the config if you need different defaults:

$ php artisan vendor:publish --tag=cipi-config

Commit and push. The next deploy picks the package up. Nothing else to wire on the panel side.

What the package actually does

FeatureEndpointWhen you use it
Webhook deployPOST /cipi/webhookGitHub / GitLab push writes .deploy-trigger; Deployer runs as the app user within a minute
Health checkGET /cipi/healthUptimeRobot / Grafana: app, database, cache, queue backlog, last commit
Project MCPPOST /cipi/mcpCursor / VS Code / Claude: health, logs, SQL, Artisan, deploy — this guide
DB anonymizerPOST /cipi/dbGDPR-safe dumps for local/QA, Faker transforms, signed 15-minute download

Each feature has its own Bearer token and can be switched off independently. A disabled endpoint returns 404 — it does not exist, as far as a scanner is concerned.

Turn on the project MCP

The MCP server is off by default. Enable it, mint a dedicated token, then print the client snippets:

$ php artisan cipi:service mcp --enable $ php artisan cipi:generate-token mcp $ php artisan cipi:mcp

cipi:mcp prints the six tools and ready-to-paste JSON for Cursor (native HTTP), VS Code / Copilot, and Claude Desktop (via mcp-remote). The token lands in .env as CIPI_MCP_TOKEN. Do not reuse the webhook secret.

Connect Cursor, VS Code or Claude

For Cursor, put this in ~/.cursor/mcp.json (or Settings → MCP). Replace the domain and the token from your .env:

{ "mcpServers": { "cipi-myapp": { "type": "http", "url": "https://yourdomain.com/cipi/mcp", "headers": { "Authorization": "Bearer YOUR_CIPI_MCP_TOKEN" } } } }

VS Code 1.102+ uses the same HTTP transport in .vscode/mcp.json under a servers key. Claude Desktop needs the mcp-remote stdio bridge — php artisan cipi:mcp prints that block too.

Name the server after the app user (cipi-myapp, cipi-staging). One Laravel app, one MCP. If you run staging and production, register two servers and say which one you mean.

Debug without SSH

This is the part that changes the daily rhythm. You stay in the IDE. The assistant talks to the live app.

health — is it even up?

Same payload as GET /cipi/health: Laravel version, APP_DEBUG, database name, cache, queue driver, pending jobs, last deploy commit. Ask: “Is production healthy? Any queue backlog?” If checks.app.debug is true on a public host, you just found a problem without opening .env.

logs — last errors, not the whole file

The logs tool reads the last N lines (default 50, max 500) and keeps stack traces intact. Filters:

Daily rotation (laravel-YYYY-MM-DD.log) is detected automatically. A useful first prompt after a 500: “Show the last 100 Laravel errors, then the matching nginx lines.”

db_query — look, don’t wreck

Read: SELECT, SHOW, DESCRIBE, EXPLAIN. Write: INSERT, UPDATE, DELETE. Blocked: DROP, TRUNCATE, GRANT, REVOKE, file I/O. Results come back as an ASCII table, capped at 100 rows — enough to confirm a seeder, not enough to dump the users table.

# after a RoleSeeder on staging SELECT id, name, created_at FROM roles ORDER BY id; # did today’s signups land? SELECT COUNT(*) FROM users WHERE created_at >= CURRENT_DATE;

Seeders, migrate and cache via artisan

The artisan tool is the reason this package earns a slot in a Laravel repo. It runs any Artisan command except the long-running / interactive ones (serve, tinker, queue:work, queue:listen, schedule:work, horizon, octane:start, reverb:start). Everything else — including seeders — is fair game.

Prompts that actually save a hop to SSH:

Do not point this at production and say “run the DatabaseSeeder”. migrate:fresh --seed is not in the blocked list — the package will execute it. Use named seeders, on staging, and confirm with db_query. Production data is not a playground just because the transport is MCP instead of SSH.

A safe staging pattern: one seeder class per fixture, idempotent where you can, called by name. The assistant runs the class, reads the table, and only then do you promote the same seeder through CI. That is the opposite of “dump production and pray”.

Pair it with the anonymizer when local needs volume without PII: anonymize a production-shaped dump, load it locally, keep MCP seeders for the small reference tables (roles, plans, feature flags) that change every sprint.

A daily loop you can copy

You: Staging healthy? Any pending jobs? Agent: health → healthy, queue 0, debug false, commit a1b2c3d You: Last Laravel errors, search "InvoiceJob" Agent: logs type=laravel level=error search=InvoiceJob → 1 error, missing column invoices.paid_at You: migrate:status. Is 2026_08_22_add_paid_at pending? Agent: artisan migrate:status → yes, pending You: After I deploy, seed InvoiceStatusSeeder only. Agent: deploy → queued artisan db:seed --class=InvoiceStatusSeeder db_query SELECT id, name FROM invoice_statuses → 4 rows

No SSH session. No copy-paste from storage/logs. The same conversation works for a teammate who has the MCP token and should never have root on the box — which is most of the team.

Project MCP vs panel API MCP

Cipi ships two MCP servers. Mixing them up is the usual first mistake.

Project MCP (cipi/agent)Panel API MCP (cipi/api)
WherePOST /cipi/mcp on the app domainPOST /mcp on the API vhost
ScopeOne Laravel app: its DB, logs, Artisan, deploy flagThe whole server: apps, SSL, databases, PHP, workers
Tools6 — health, app_info, deploy, logs, db_query, artisan50+ — create apps, issue certs, edit .env, run as app user
Use it forDebug, seeders, migrate:status, queue peekProvision, SSL, list every database, server cockpit

Keep both in Cursor if you like. Ask the project MCP about this app; ask the panel API MCP to create the next staging clone. The spec-driven AI guide covers the wider loop — this page is the in-app half.

Tokens, blocks and least privilege

Install the package, then the server

cipi/agent is the Laravel companion. Cipi is the free, open-source deploy CLI that injects the env and runs Deployer when the webhook or the MCP deploy tool fires.

composer require cipi/agent

Frequently asked questions

Do I need SSH to use the project MCP?

No. Once the package is deployed and CIPI_MCP is on, the IDE talks to https://yourdomain.com/cipi/mcp with the Bearer token. That is the point for teammates who should never log in as root.

What is the difference between the agent MCP and the Cipi API MCP?

The agent MCP is inside one Laravel app (six tools: health, logs, SQL, Artisan, deploy). The panel API MCP manages the whole VPS — create apps, SSL, databases, PHP. Use the agent for debug and seeders; use the API to provision.

Can I run db:seed on production through MCP?

Technically yes — db:seed is not blocked. Practically, only run a named, reviewed seeder, and never migrate:fresh --seed on live data. Prefer staging, then confirm with db_query.

Which Artisan commands are blocked?

serve, tinker, queue:work, queue:listen, schedule:work, horizon, octane:start, reverb:start. Long-running and interactive processes do not belong on an HTTP tool call.

Does cipi/agent work without a Cipi server?

Health check and MCP yes, on any Laravel 12+ host. Webhook-triggered Deployer deploys and the extra log types expect the Cipi layout under /home/<app>/.

How do I rotate a leaked MCP token?

php artisan cipi:generate-token mcp, restart the app (or reload PHP-FPM / Octane), update ~/.cursor/mcp.json. The old token dies with the .env rewrite.

Keep reading