Putting an MCP Server Inside a Laravel App
AI agents need more than just a scraped UI. They need a way to call specific tools with proper permissions. This is what the Model Context Protocol (MCP) does.
I recently integrated an MCP server directly into a Laravel application. I want to share the architectural decisions for building this securely.
The Receptionist Metaphor Think of your app as an office building.
- The web UI is the lobby for humans.
- The REST API is the staff entrance for systems.
- The MCP server is a reception desk for AI agents.
The agent shows an ID and asks for a specific task. The receptionist does not give them the keys to the building. They check permissions, perform one task, and return a structured answer.
Key Design Decisions
Use a single endpoint Do not create many routes for different tools. Use one /mcp endpoint. The protocol handles tool discovery automatically. A single surface is easier to secure and document.
Support dual authentication Different callers need different security methods:
- First-party callers (like CLI tools) use Sanctum personal access tokens.
- Third-party agents (acting for users) use OAuth 2.1.
Use a driver-style resolver to handle both. The tool code should only care about the authenticated user, not how they logged in.
Enforce existing RBAC Authentication only proves who the caller is. You must still check what they can do. Every tool should map to an existing ability. If a user cannot view participants in the web UI, they should not be able to do it via MCP.
Limit data output Never return a full database model. Treat MCP output like a public API. Return only the specific fields the agent needs. This prevents accidental data leaks.
Testing for Security Your tests must prove that the system fails correctly. Test that:
- An unauthorized user receives a 403 Forbidden error.
- An authorized user receives only the allowed fields.
A good test suite is your best defense against data leaks when using autonomous agents.
Summary To build a responsible MCP server, follow these three rules:
- Authenticate every caller using the right scheme.
- Authorize every tool using your existing permission model.
- Treat every tool output as a limited public resource.
