> ## Documentation Index
> Fetch the complete documentation index at: https://docs.laravelify.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP: deploy with an AI assistant

> Connect Claude Code, Claude Desktop, or Cursor to your panel and let it deploy and manage your websites.

Laravelify has a built-in [MCP](https://modelcontextprotocol.io) server. Connect an AI assistant to it and ask in plain words: *"Deploy acme/shop on shop.example.com with a MySQL database."* It picks the right site type, creates the website, deploys it, follows the log, and fixes what fails.

## 1. Create a token

In the panel open **Settings → MCP**, give the token a name (one per computer or app), and press **Create token**. It asks for your authenticator code, then shows the token **once**. Copy it.

Anyone with the token can manage this panel's websites, so keep it like a password. **Revoke** a token there at any time; the list shows when and from where each one was last used.

## 2. Connect your AI app

The server address is `https://your-panel-domain/mcp`. The **Settings → MCP** page shows these commands with your address and token filled in.

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={null}
    claude mcp add --transport http laravelify https://panel.example.com/mcp --header "Authorization: Bearer YOUR_TOKEN"
    ```
  </Tab>

  <Tab title="Claude Desktop">
    **Settings → Developer → Edit config**, add this to `claude_desktop_config.json`, and restart Claude Desktop (needs Node.js):

    ```json theme={null}
    {
      "mcpServers": {
        "laravelify": {
          "command": "npx",
          "args": ["-y", "mcp-remote", "https://panel.example.com/mcp", "--header", "Authorization:${AUTH}"],
          "env": { "AUTH": "Bearer YOUR_TOKEN" }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Cursor and others">
    `.cursor/mcp.json` (other apps that take a remote server with headers use the same shape):

    ```json theme={null}
    {
      "mcpServers": {
        "laravelify": {
          "url": "https://panel.example.com/mcp",
          "headers": { "Authorization": "Bearer YOUR_TOKEN" }
        }
      }
    }
    ```
  </Tab>
</Tabs>

## 3. Ask it

* "Deploy **acme/shop** on **shop.example.com** with a MySQL database."
* "Deploy this project folder to my Laravelify server on **app.example.com**."
* "Why did the last deploy of **shop** fail? Fix it and deploy again."
* "Set **MAIL\_HOST** and **MAIL\_PORT** on **shop**."
* "Which of my websites are turned off?"
* "Upload the Firebase key from my backup's private.tgz into storage/app/private of the API site."

Claude also offers a ready-made **deploy-project** prompt: give it a repository or a folder and a domain.

## What it can do

| Tool | What it does |
| - | - |
| `list-groups`, `create-group` | See and make groups |
| `list-site-types` | The kinds of app it can deploy, and the PHP and Node versions |
| `list-sources` | The connected GitHub Apps (and their repositories) and Cloudflare tunnels |
| `list-websites`, `get-website` | What runs on the server, with the last deployment. Environment variable names only, never values |
| `create-website` | Create a site from a repository (or an example project) on a domain or HTTP port, with env variables and a MySQL database, and deploy it |
| `deploy-website`, `get-deployment` | Deploy again and follow the status and the end of the log |
| `update-environment` | Set or remove `.env` variables |
| `upload-file` | Put a file the repository does not carry into the site (like a Firebase key in `storage/app/private`), or unpack a `.zip`, `.tar.gz`, or `.tgz` into a folder. Up to 20 MB |
| `get-nginx`, `update-nginx` | Read and change a site's nginx block, for example to send OAuth or payment callback paths to a Laravel API. nginx checks it first; a rejected file is put back |
| `list-ports` | Which port is used by what, including apps still running from an old server |
| `set-website-enabled` | Turn a site off or on |

Deleting websites and changing server settings are not available through MCP; do those in the panel.

## Deploying a folder from your computer

The server cannot read files on your computer, so the assistant pushes the folder to a new private GitHub repository first (`gh repo create --private --source . --push`), then deploys that repository. Make sure your Laravelify GitHub App can read it (GitHub → **Settings → Applications** → the App → **Repository access**). After that, every push deploys by itself.

## Private files and ports

* **Private files.** Keys and certificates are not in Git. After a site's first deploy, the assistant uploads them with `upload-file` (a single file or an archive it unpacks). Deploys keep them: a deploy only resets files that Git tracks. Paths must stay inside the site folder, and links inside archives are skipped.
* **Ports are picked for you.** Every new site gets a port that nothing uses: not another website, not a Laravelify service, and not anything listening on the server right now (for example an app still running from an old server). Ports from an old server's nginx files do not matter, only the domains do. A port you choose yourself is refused if something holds it, with the name of what holds it.

## Moving from an old server

* **Databases.** With `create_database`, the site uses the MySQL database and login the panel makes. `DB_*` values from an old `.env` are left out, so the old server's login cannot lock the site out. Import your data into the new database (phpMyAdmin, or `mysql` on the server); MCP does not import dumps.
* **APP\_KEY.** Keep the old server's `APP_KEY` in the env so data it encrypted still opens. A deploy only creates a key when there is none.
* **Special nginx rules.** Paths the old nginx sent elsewhere (callbacks, webhooks) can be added with `update-nginx`.
* **Allow the tools in Claude Code.** In auto mode Claude Code may ask before each Laravelify call or before reading backup files. Allow them once: run `/permissions` in Claude Code and add `mcp__laravelify`.

## Good to know

* Deploys started by the assistant show **Mcp** as their trigger, in the panel and in Telegram.
* `/mcp` signs in with the token only, so the [access prompt](/security/authentication#access-prompt-for-the-panel-and-phpmyadmin) does not get in the way. Ten wrong tokens in a minute block that IP for a minute.
* Behind the Cloudflare tunnel the address is your panel's normal HTTPS domain; nothing else needs opening.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.