Deploying a Laravel MCP App to Production with Laravel Cloud
Laravel AI #Laravel #MCP #Deployment #Laravel Cloud #AI

Deploying a Laravel MCP App to Production with Laravel Cloud

8 min read Mohamed Said Mohamed Said

In a previous post, we explored creating an MCP server to expose Laravel applications to AI clients like Claude and ChatGPT. While local development is straightforward, deploying a connected MCP app introduces additional complexities. This article focuses on taking a SaaS support workflow from local development to a production-ready Laravel MCP application hosted on Laravel Cloud.

We will build three tools to provide Claude with live access to subscription data, then test and deploy the entire MCP app to production with a single Git push. For detailed installation and protocol background, refer to the Laravel MCP documentation.

The Scenario: Building an MCP App for a Support Workflow

Consider a support team using Claude daily. A common scenario involves a customer whose trial expired prematurely. The support representative needs to quickly access the customer's plan, subscription status, invoice history, and confirm the safety of extending the trial. Without structured tools, this involves multiple manual steps, increasing the risk of errors.

With a deployed Laravel MCP server, Claude can handle lookups, invoice checks, and trial extensions within a single conversation. The tools incorporate types, annotations, and role-based access controls to ensure appropriate actions are taken by authorized personnel. The goal is to build with deployment in mind from the outset.

The MCP Tools

IdentifyCustomerTool

This tool identifies a customer by email, returning their plan name, subscription status, and trial end date in a typed response format readable by Claude.

Retrieving Invoice History

GetInvoiceHistoryTool retrieves the last 12 months of invoice line items for a specified user. It is a read-only tool, allowing Claude to identify anomalies without manual intervention. The months parameter uses an enum constraint to prevent unbounded history requests, and the output schema ensures reliable summaries from Claude.

IssueTrialExtensionTool

This tool extends a customer's trial end date. It is marked with #[IsDestructive], prompting an explicit confirmation step from Claude before execution. For tools modifying billing data, it's crucial to add an audit entry within the handle() method to record who extended the trial, by how many days, and when. This creates a complete audit trail for all actions taken through the MCP server.

All three tools are registered on the server and exposed via routes/ai.php.

Securing the MCP Endpoint

Authenticating the MCP Client

The MCP client requires a Sanctum API token, scoped to the necessary actions. This token is generated once per client, stored securely, and rotated periodically. Refer to the Laravel MCP auth and security best practices guide for more details.

Creating a Scoped Token

$token = $user->createToken('mcp-client', ['mcp:read', 'mcp:write'])->plainTextToken;

Checking Abilities in Tools

Token abilities enable different permission levels for a single MCP endpoint. For instance, a read-only integration might receive a token with only mcp:read. Destructive tools should verify these abilities before proceeding:

if (! $request->user()->tokenCan('mcp:write')) {
    throw new UnauthorizedException('You do not have permission to perform this action.');
}

Token Rotation

Tokens should have an expiration date. Automate rotation by scheduling a job to generate new tokens and revoke old ones. A 90-day lifetime is a reasonable starting point.

Rate Limiting the MCP Endpoint

Every MCP tool call interacts with your database. Implement rate limiting to prevent abuse from misconfigured clients or prompt injection loops. Laravel's built-in rate limiter can be applied to the MCP route:

Route::middleware(['throttle:30,1'])->group(function () {
    // MCP routes
});

For destructive tools, consider stricter per-tool limits within the handle() method to prevent rapid, repeated actions.

Handling Errors Gracefully

In production, errors are inevitable. Unhandled exceptions return raw errors, which are unhelpful to AI assistants. Implement structured error responses by wrapping handle() methods in try/catch blocks. This allows for clear, human-readable messages for validation errors, missing models, and generic messages for unexpected errors, preventing internal details from leaking.

Gating Tools by Role with shouldRegister

The shouldRegister method allows tools to inspect the current request and determine if they should be registered. This ensures that destructive tools, like IssueTrialExtensionTool, are only available to authorized users (e.g., billing administrators). If shouldRegister returns false, the tool is invisible to the MCP client, providing a robust security guard.

public function shouldRegister(Request $request): bool
{
    return $request->user()->hasRole('billing-admin');
}

This pattern also works for subscription-based access.

Testing Your MCP App

Laravel MCP includes testing helpers for direct tool invocation and assertion on responses. This allows you to simulate Claude's interaction with your server.

Testing Read-Only Tools

Use SupportServer::tool() to call tools with arguments and assert the exact JSON shape of the response using assertStructuredContent. assertHasErrors verifies structured error responses for validation failures.

Testing Destructive Tools

For tools that modify data, tests should verify both the response and the database state, including audit trails. actingAs($admin) authenticates the request, ensuring audit logs record the correct actor.

Testing shouldRegister Gating

Verify that non-administrators cannot access destructive tools. When shouldRegister returns false, the server responds as if the tool does not exist, confirmed by assertHasErrors.

Deploying to Laravel Cloud in Minutes

Laravel Cloud is designed for Laravel applications, handling provisioning, scaling, zero-downtime deployments, and SSL automatically. It simplifies the deployment process significantly.

  1. Connect your repository: Sign in to Laravel Cloud, create a project, and link your GitHub or GitLab repository. Cloud builds a Docker image optimized for Laravel on each push.
  2. Set environment variables: Configure APP_KEY, database credentials, and any Laravel Sanctum settings in the Cloud dashboard.
  3. Add a deploy command: In deployment settings, configure your deploy commands.
  4. Push to ship: A git push to your production branch triggers an automatic deployment. Laravel Cloud builds the Docker image, runs deploy commands, and brings the new container online with zero downtime.

This streamlined deployment process is crucial for iterative MCP tool development, allowing rapid testing and deployment of changes.

Watching Your App in Production

Since an AI model autonomously calls a deployed MCP server, robust logging and monitoring are essential.

Logging Tool Invocations

Implement a middleware or listener to log every tool call, including parameters, authenticated user, and response time. Log to a dedicated mcp channel to keep tool invocations separate from general application logs.

What to Monitor

Track the following metrics from your MCP logs:

  • Invocation count per tool: Detects spikes that might indicate prompt injection or misconfiguration.
  • Error rate per tool: Identifies data sync issues or other problems.
  • p95 latency per tool: Ensures tools respond quickly to maintain a fluid conversation with Claude.
  • Unique users per hour: Helps in right-sizing rate limits.

Your MCP App, Live in a Single Git Push

Bridging the gap between local development and production deployment for an MCP app is now significantly faster with laravel/mcp and Laravel Cloud. You can develop tools using familiar Eloquent patterns, define schemas for Claude, gate access with shouldRegister, and deploy to a managed Cloud environment with a single git push.

The IdentifyCustomerTool, GetInvoiceHistoryTool, and IssueTrialExtensionTool provide a core support workflow. #[IsReadOnly] and #[IsDestructive] annotations inform Claude, while shouldRegister ensures data security.

For further exploration, consult the Laravel MCP documentation for resources on prompts, OAuth 2.1, and more. Then, try Laravel Cloud (with $5 in usage credit) to experience the efficiency of the full development and deployment cycle.

Key Takeaways:

  • Structured Tooling: Build specific MCP tools (e.g., IdentifyCustomerTool, GetInvoiceHistoryTool, IssueTrialExtensionTool) to enable AI clients like Claude to interact with your Laravel application's data and functionality.
  • Robust Security: Implement auth:sanctum middleware, scoped API tokens, ability checks within tools, token rotation, and rate limiting to secure your MCP endpoint.
  • Graceful Error Handling: Wrap handle() methods in try/catch blocks to provide structured, human-readable error messages to AI clients, preventing internal details from leaking.
  • Role-Based Access Control: Utilize the shouldRegister method to gate tool availability based on user roles or subscription status, ensuring only authorized users can access specific functionalities.
  • Streamlined Deployment: Leverage Laravel Cloud for zero-downtime deployments, automatic provisioning, scaling, and SSL, enabling a "single Git push" deployment workflow for your MCP app.
  • Comprehensive Testing: Use Laravel MCP's testing helpers to simulate AI client interactions, verify tool responses, database changes, and shouldRegister gating.
  • Production Monitoring: Implement logging for tool invocations and monitor key metrics like invocation count, error rates, and latency to ensure the health and security of your deployed MCP app.

Source: Deploy a Laravel MCP App to Production with Laravel Cloud

Found this useful?

Frequently Asked Questions

3 questions
Q01 What is a Laravel MCP app?
A Laravel MCP (Machine-to-Cloud Protocol) app exposes your Laravel application's functionalities and data to AI clients like Claude and ChatGPT through structured tools, enabling AI to interact with your system programmatically.
Q02 How does Laravel Cloud simplify MCP app deployment?
Laravel Cloud automates provisioning, scaling, zero-downtime deployments, and SSL for Laravel applications. It integrates with Git, allowing a single `git push` to trigger an automatic deployment of your MCP app to production.
Q03 What security measures are crucial for a Laravel MCP endpoint?
Key security measures include authenticating MCP clients with scoped Sanctum API tokens, checking token abilities within tools, implementing token rotation, rate limiting the endpoint, and handling errors gracefully with structured responses to prevent data leakage.

Continue reading

More Articles

View all