laravel-mcp-guard maintained by stvnrlnd
Laravel MCP Guard
A governance layer for Laravel MCP servers.
Laravel MCP lets you expose application capabilities to AI agents as tools. What it
does not give you is a way to say which agent may call which tool, how often, or
what happened afterwards. Its authorization story is HTTP middleware on the server
route — all-or-nothing for the whole server — plus whatever Gate checks you
remember to write inside each tool.
MCP Guard adds the missing layer:
- Scoped permissions — per-agent tool allowlists, wildcards, and deny lists.
- Rate limiting — per caller, per tool, on Laravel's own rate limiter.
- Audit logging — every call, allowed or denied, with arguments and timing.
- Approval workflow — hold mutating tool calls until a human approves them.
It integrates by substituting Laravel MCP's tools/call handler in the container.
Your servers, tools, and routes stay exactly as they are.
Status: Phase 1 (scaffold). The interception point is built and tested; the policy layers land in subsequent phases.
Requirements
- PHP 8.2+
- Laravel 12 or 13
laravel/mcp^0.9.1
Installation
composer require stvnrlnd/laravel-mcp-guard
The service provider is auto-discovered. Publish the config if you want to edit it:
php artisan vendor:publish --tag=mcp-guard-config
How interception works
Laravel\Mcp\Server resolves its JSON-RPC method handlers out of the container by
class name. MCP Guard binds Laravel\Mcp\Server\Methods\CallTool to its own
subclass, so every tools/call request passes through the guard before the tool's
handle() method is reached — with no changes to user code.
Denials are returned as MCP tool errors (a successful JSON-RPC result carrying
isError: true), not as transport-level errors, so the calling agent actually
receives and can reason about the reason it was blocked.
use McpGuard\Decision;
use McpGuard\Facades\McpGuard;
McpGuard::before(fn ($call, $tool) => $call->tool === 'delete_customer'
? Decision::deny('This agent may not delete customers.')
: null);
Set MCP_GUARD_ENABLED=false to take the guard out of the path entirely.
Testing
composer test
License
MIT. See LICENSE.