Download the PHP package shaxzodbek-uzb/laravel-model-mcp without Composer
On this page you can find all versions of the php package shaxzodbek-uzb/laravel-model-mcp. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download shaxzodbek-uzb/laravel-model-mcp
More information about shaxzodbek-uzb/laravel-model-mcp
Files in shaxzodbek-uzb/laravel-model-mcp
Package laravel-model-mcp
Short Description Auto-expose Eloquent models as policy-enforced MCP tools. Safe-by-default CRUD over the Model Context Protocol, gated by your Laravel Policies, scoped to your tenant, and audited.
License MIT
Homepage https://github.com/shaxzodbek-uzb/laravel-model-mcp
Informations about the package laravel-model-mcp
Laravel Model MCP
Expose your Eloquent models to AI agents as MCP tools — without handing them the keys to your database.
laravel-model-mcp turns any Eloquent model into a full set of Model Context
Protocol tools (list, view, create,
update, delete, search) on top of the official
laravel/mcp package — and every single call
is checked against your Laravel Policies, scoped to the current tenant,
and audited. Safe by default, no boilerplate.
The problem
The official laravel/mcp package is excellent, but it makes you hand-write one
tool class per operation, and authorization is a manual if inside each handler:
Multiply that by 6 operations × every model you want to expose. Forget the
can() check on one of them, and an agent can now edit anything.
The solution
List the models. Register one server. Done — policy-enforced CRUD for all of them:
That's it. You now have list_posts, get_post, create_post, update_post,
delete_post, search_posts, describe_post (and the same for comment) — each one running
PostPolicy@viewAny, @view, @create, @update, @delete for the
authenticated user before it touches a row.
Why this package
laravel/mcp alone |
laravel-model-mcp |
|
|---|---|---|
| Eloquent → MCP CRUD tools | hand-written | auto-generated |
| Laravel Policy enforced per call | manual can() in each handler |
built in, fail-closed |
| Multi-tenant row scoping | DIY | built in |
| Audit log of every tool call | DIY | built in |
| Token-safe pagination & field limits | DIY | built in |
| JSON Schema from casts/columns | hand-written | generated |
This package builds on laravel/mcp — it does not replace it. Transport,
OAuth, and the protocol stay with the official package; this layer adds the
opinionated, safe-by-default model exposure on top.
Installation
Requires PHP 8.2+ and Laravel 12.41+ / 13.x (it relies on laravel/mcp's
JSON Schema builder). If you haven't set up laravel/mcp yet:
Optionally publish the config:
Quickstart
1. Add a policy for the model you want to expose (standard Laravel — nothing special):
2. Expose the model:
3. Register the server in routes/ai.php behind your auth middleware:
4. See exactly what you exposed:
Point any MCP client (Claude, your agent, php artisan mcp:inspector) at the
server and the tools are live — each one acting as the authenticated user.
The security model
This is the whole point, so it's worth being explicit. By default:
- Nothing is exposed implicitly. Only models in
model-mcp.models(or tagged with#[McpModel]) become tools. -
Every operation enforces the matching policy ability for the authenticated MCP user, before any read or write:
Operation Policy ability list,searchviewAnyviewviewcreatecreateupdateupdatedeletedelete - Fail-closed. No policy for the model → every operation is denied. No authenticated user → denied. (Both configurable, both default to safe.)
- Tenant scope is applied to the query before the policy runs, so even a missing or over-permissive policy can't leak another tenant's rows. If tenancy is enabled and no tenant resolves, the request fails closed.
- Writes are limited to
$fillable; reads honor$hidden; andfields.always_hiddenis a hard block on top (e.g.password).
Denials and errors come back as MCP isError results with safe messages — the
agent can recover, and your internals never leak. Every call (allowed, denied,
errored) is recorded by the audit log.
See SECURITY.md for the full model and how to report issues.
Configuration
The published config/model-mcp.php is fully documented. The essentials:
Read-only or partial exposure
Expose only the operations you want, per model:
Or flip a single global kill-switch so no model can ever be mutated — only
list / view / search tools are generated, regardless of per-model settings:
describe — so the agent stops guessing
Without it, the only way for an agent to learn a model's shape is to call list
and read whatever comes back. That needs a row to exist, needs the caller to be
allowed to see it, and still says nothing about which fields are writable,
which are required, or what a date column expects. Each unknown becomes a failed
create and a retry.
It is metadata only: it reads the model's schema and this package's config, never a row. So it needs no tenant scope and cannot leak data.
It is still gated on viewAny, and it hides exactly what every other response
hides ($hidden, fields.always_hidden). Which models exist and what columns
they have is itself information — describe must not become the way to discover
a column the model deliberately hides. Switch it off per model like any other
operation.
Multi-tenancy
If your app already scopes models with global scopes (a BelongsToTenant
trait, #[ScopedBy], stancl/tenancy, spatie/laravel-multitenancy), you need
to do nothing — every query runs through Model::query(), so your scopes
apply transparently and are never stripped.
Turn on the package's own explicit scoping only when a global scope alone won't
filter (e.g. you want a hard where(tenant_column, id) regardless):
The default AuthUserTenantResolver reads the column off the authenticated user
($user->tenant_id). Provide your own by binding
Blaze\ModelMcp\Contracts\TenantResolver.
Audit log
Every tool call is recorded with the acting user, the model, the operation, and
the outcome (allowed / denied / error). The default LogAuditor writes to
your log channel; swap in your own to persist to a table:
Attribute discovery (optional)
Prefer to opt in from the model itself? Enable discovery and tag your models — it's off by default so nothing is ever exposed by accident:
Extending
- Custom tools alongside generated ones — subclass
ModelMcpServerand add your hand-written tools to the$toolsarray; the generated ones are merged in. - Custom policies — point a model's
policyoption at any class, or rely on Laravel's normal policy resolution. - Custom auditor / tenant resolver — implement the contract and bind it.
Requirements
- PHP 8.2+
- Laravel 12.41+ or 13.x
laravel/mcp^0.8
Testing
Credits
Built by Blaze. Stands on the shoulders of the
laravel/mcp team.
License
The MIT License (MIT). See LICENSE.
All versions of laravel-model-mcp with dependencies
laravel/mcp Version ^0.8 || ^0.9.3
illuminate/auth Version ^12.41 || ^13.0
illuminate/console Version ^12.41 || ^13.0
illuminate/contracts Version ^12.41 || ^13.0
illuminate/database Version ^12.41 || ^13.0
illuminate/support Version ^12.41 || ^13.0
illuminate/validation Version ^12.41 || ^13.0
spatie/laravel-package-tools Version ^1.16
symfony/finder Version ^7.0 || ^8.0