| name | forge-mcp |
| description | MCP server for Laravel Forge — manage servers, sites, deployments, SSL, databases, and more via AI agents |
| keywords | ["forge","laravel","servers","deployment","devops","mcp"] |
Laravel Forge MCP Server
MCP (Model Context Protocol) server for Laravel Forge. Provides two tools: forge for read operations and forge_write for write operations.
Quick Start
Before your first interaction with any resource, call action="help" with that resource to discover required fields and examples.
Tools
forge — Read Operations
Safe, read-only queries. Use for listing, getting details, resolving names, fetching context snapshots, help, and schema.
Actions: list, get, resolve, context, help, schema
forge(resource, action, [parameters...])
forge_write — Write Operations
Mutating operations that modify server state. Always requires confirmation.
Actions: create, update, delete, deploy, reboot, restart, activate, run
forge_write(resource, action, [parameters...])
Resources & Actions
| Resource | Read Actions (forge) | Write Actions (forge_write) | Scope |
|---|
servers | list, get, resolve, context | create, delete, reboot | global |
sites | list, get, resolve, context | create, delete | server |
deployments | list | deploy, update | site |
env | get | update | site |
nginx | get | update | site |
certificates | get | create, delete, activate | domain |
databases | list, get | create, delete | server |
database-users | list, get | create, delete | server |
daemons | list, get | create, delete, restart | server |
firewall-rules | list, get | create, delete | server |
ssh-keys | list, get | create, delete | server |
security-rules | list, get | create, delete | site |
redirect-rules | list, get | create, delete | site |
monitors | list, get | create, delete | server |
nginx-templates | list, get | create, update, delete | server |
recipes | list, get | create, delete, run | global |
scheduled-jobs | list, get | create, delete | server |
backups | list, get | create, delete | server |
commands | list, get | create | site |
user | get | — | global |
batch | run | — | global |
Scope Guide
- global: No parent ID needed (e.g.
servers, recipes)
- server: Requires
server_id (e.g. sites, databases, daemons)
- site: Requires
server_id + site_id (e.g. deployments, env)
- domain: Requires
server_id + site_id + domain_id (e.g. certificates)
Auto-Resolve: Names Instead of IDs
server_id and site_id accept name strings in addition to numeric IDs. When a non-numeric value is provided, the server automatically performs a case-insensitive partial match against known resources:
server_id: Matched against server names (e.g. "prod" resolves "production-web-01")
site_id: Matched against site domains (e.g. "myapp" resolves "myapp.example.com")
Resolution rules:
- Exact single match → resolved silently, the call proceeds normally
- Ambiguous (multiple matches) → error listing all candidates; use a more specific name or numeric ID
- No match → error with a hint to use
action: "resolve" to search
This applies to every resource and action automatically — no special syntax needed.
Use action: "resolve" explicitly when you need to search or preview matches before acting:
{ "resource": "servers", "action": "resolve", "query": "prod" }
{ "resource": "sites", "action": "resolve", "server_id": "123", "query": "myapp" }
Getting Help
Use action: "help" to get detailed documentation for any resource:
{ "resource": "servers", "action": "help" }
{ "resource": "deployments", "action": "help" }
Use action: "schema" for a compact machine-readable spec:
{ "resource": "sites", "action": "schema" }
Common Parameters
| Parameter | Type | Description |
|---|
resource | string | Required. Resource type (see table above) |
action | string | Required. Action to perform |
organizationSlug | string | Organization slug — pass per-call to override configured value (auth/env/config) |
id | string | Resource ID (for get, delete, activate, restart) |
server_id | string | Server ID or name — numeric IDs are used as-is; names are auto-resolved via partial match |
site_id | string | Site ID or domain name — auto-resolved via partial match; requires server_id |
domain_id | string | Domain record ID (for certificate operations) |
query | string | Search query for resolve action (partial, case-insensitive match against resource names/domains) |
compact | boolean | Compact output (default: true) |
content | string | Content for env/nginx update and deployment script update |
operations | array | Array of operations for batch run (max 10). Each item needs resource, action, and extra params. |
Common Workflows
Deploy a Site
{ "resource": "servers", "action": "list" }
{ "resource": "sites", "action": "list", "server_id": "123" }
{ "resource": "deployments", "action": "deploy", "server_id": "123", "site_id": "456" }
Check Server Status
{ "resource": "servers", "action": "get", "id": "123" }
{ "resource": "sites", "action": "list", "server_id": "123" }
{ "resource": "databases", "action": "list", "server_id": "123" }
{ "resource": "daemons", "action": "list", "server_id": "123" }
Manage SSL Certificates (per-domain)
{ "resource": "certificates", "action": "get", "server_id": "123", "site_id": "456", "domain_id": "789" }
{ "resource": "certificates", "action": "create", "server_id": "123", "site_id": "456", "domain_id": "789", "type": "letsencrypt" }
{ "resource": "certificates", "action": "activate", "server_id": "123", "site_id": "456", "domain_id": "789" }
Update Environment Variables
{ "resource": "env", "action": "get", "server_id": "123", "site_id": "456" }
{ "resource": "env", "action": "update", "server_id": "123", "site_id": "456", "content": "APP_ENV=production\nAPP_DEBUG=false" }
Create a Queue Worker
{
"resource": "daemons",
"action": "create",
"server_id": "123",
"command": "php artisan queue:work --tries=3",
"user": "forge"
}
Run a Recipe on Multiple Servers
{ "resource": "recipes", "action": "create", "name": "Clear caches", "script": "php artisan cache:clear" }
{ "resource": "recipes", "action": "run", "id": "456", "servers": [1, 2, 3] }
Auto-Resolve: Deploy Using Names Instead of IDs
No need to look up numeric IDs first — just pass names directly:
{ "resource": "deployments", "action": "deploy", "server_id": "prod", "site_id": "myapp.example.com" }
{ "resource": "env", "action": "get", "server_id": "production", "site_id": "myapp" }
Resolve: Find Resources by Name
Use action: "resolve" to search resources by name before acting:
{ "resource": "servers", "action": "resolve", "query": "prod" }
{ "resource": "sites", "action": "resolve", "server_id": "123", "query": "myapp" }
Context: Get a Full Snapshot in One Call
action: "context" fetches a resource plus all its sub-resources in a single parallel call — ideal for orientation at the start of a session:
{ "resource": "servers", "action": "context", "id": "123" }
{ "resource": "sites", "action": "context", "server_id": "123", "id": "456" }
{ "resource": "servers", "action": "context", "id": "prod" }
Batch: Multiple Reads in a Single Call
resource: "batch" with action: "run" executes up to 10 read operations in parallel, reducing round-trips:
{
"resource": "batch",
"action": "run",
"operations": [
{ "resource": "servers", "action": "list" },
{ "resource": "user", "action": "get" }
]
}
{
"resource": "batch",
"action": "run",
"operations": [
{ "resource": "env", "action": "get", "server_id": "123", "site_id": "456" },
{ "resource": "commands", "action": "list", "server_id": "123", "site_id": "456" },
{ "resource": "deployments", "action": "list", "server_id": "123", "site_id": "456" }
]
}
Result shape:
{
"_batch": { "total": 2, "succeeded": 2, "failed": 0 },
"results": [
{ "index": 0, "resource": "servers", "action": "list", "data": [...] },
{ "index": 1, "resource": "user", "action": "get", "data": {...} }
]
}
Per-operation failures are isolated — a single error doesn't abort the rest.
Note: Batch only supports read actions (list, get, resolve, context, help, schema). Write operations must use forge_write individually.
Authentication
Organization Slug
All API calls require an organization slug. You can provide it in three ways (in priority order):
- Per-request: Pass
organizationSlug in each tool call (highest priority, allows switching orgs)
- Environment variable: Set
FORGE_ORG env var
- Configuration: Use
forge_configure tool (stdio) or enter during OAuth login (HTTP)
Stdio Mode (Claude Desktop)
Set environment variables FORGE_API_TOKEN and FORGE_ORG, or use the forge_configure tool:
{ tool: "forge_configure", arguments: { apiToken: "your-token", organizationSlug: "your-org" } }
{ tool: "forge_get_config", arguments: {} }
HTTP Mode (OAuth)
During OAuth authentication, you can optionally enter your organization slug in the login form. This value is stored in your access token and used for all subsequent requests unless overridden per-call.
Getting Your API Token
- Log into Laravel Forge
- Go to Account → API Tokens
- Create a new token
- Copy the token (shown only once)
Read-Only Mode
The server can run in read-only mode where the forge_write tool is not available at all:
forge-mcp --read-only
FORGE_READ_ONLY=true forge-mcp
When enabled, only forge (read operations), forge_configure, and forge_get_config are registered.
Audit Logging
All forge_write operations are automatically logged to ~/.config/forge-tools/audit.log (configurable via FORGE_AUDIT_LOG env var). Sensitive fields (tokens, passwords) are redacted. Logging never interrupts operations.
Tips for Efficient Usage
- Use help first: Call
action="help" for any resource before using it
- Use schema for specs: Call
action="schema" for compact field metadata
- Start with list: Use
action="list" to discover existing resources
- Chain operations: List servers → list sites → deploy (follow the hierarchy)
- Scope matters: Server-scoped resources need
server_id, site-scoped need both server_id and site_id
- Read vs Write: Use
forge for queries, forge_write for mutations — MCP clients enforce this split
- Use names, not IDs: Pass server names and site domains directly — they are auto-resolved to numeric IDs
- Use
context for orientation: One call fetches a server or site plus all its sub-resources in parallel
- Use
batch to cut round-trips: Bundle up to 10 read operations into a single forge call
- Use
resolve to preview: Search for resources by name before committing to an action