visualbuilder/eloquent-schema
Adds MCP tools for Laravel Boost to introspect Eloquent models. Automatically discovers app and vendor models, extracts columns, relationships, and accessors, and serves complete model schemas with caching—helping AI assistants and dev tools generate accurate queries and code faster.
Installation:
composer require visualbuilder/eloquent-schema
php artisan vendor:publish --tag=eloquent-schema-config
Configure config/eloquent-schema.php with your model paths and cache settings.
First Use Case: Warm the cache to discover models and preload schemas:
php artisan eloquent-schema:cache
Test the MCP tools directly:
php artisan eloquent-schema:mcp list-models
php artisan eloquent-schema:mcp model-schema --model='App\Models\User'
Quick Integration:
For Laravel Boost users, add the tools to config/boost.php under mcp.tools.include:
\Visualbuilder\EloquentSchema\Mcp\Tools\ListModels::class,
\Visualbuilder\EloquentSchema\Mcp\Tools\ModelSchema::class,
\Visualbuilder\EloquentSchema\Mcp\Tools\ModelFields::class,
Workflow:
config/boost.php or your custom MCP server.model-schema to fetch full model details (columns, relationships, accessors) for AI-generated queries.Order records with status = 'shipped' and their related User data:
// MCP Request
{
"tool": "ModelSchema",
"args": {"model": "App\\Models\\Order", "max_depth": 2}
}
// AI-generated Eloquent code (based on schema)
Order::with(['user', 'lineItems'])
->where('status', 'shipped')
->get();
Tip: Cache schemas with max_depth=1 for lightweight queries, then fetch deeper relationships on demand.
Pattern: Use the programmatic API to build dynamic CLI commands.
// In a custom Artisan command
public function handle()
{
$schema = app(ModelSchemaService::class);
$fields = $schema->getFlatFieldList(Order::class);
$this->info("Available fields for Order: " . implode(', ', $fields['columns']));
$this->info("Relationships: " . implode(', ', $fields['relationships']));
}
Use Case: Auto-generate --filter options for CLI tools based on model schemas.
Workflow:
php artisan eloquent-schema:discover
spatie/laravel-permission) and update config/eloquent-schema.php.$schema = app(ModelSchemaService::class);
$roleSchema = $schema->getSchema(\Spatie\Permission\Models\Role::class);
Tip: Use include_vendor: true in list-models to filter vendor models in AI tools.
Pattern: Fetch model-fields to populate UI components.
// Frontend (via MCP)
const response = await mcp.call('ModelFields', {
model: 'App\\Models\\Product'
});
// Render checkboxes for each column/relationship
Laravel Example:
// In a controller
$fields = app(ModelSchemaService::class)->getFlatFieldList(Product::class);
return view('admin.products.create', compact('fields'));
Pattern: Compare schemas before/after migrations.
// Pre-migration
$oldSchema = app(ModelSchemaService::class)->getSchema(Order::class);
// Post-migration
$newSchema = app(ModelSchemaService::class)->getSchema(Order::class);
// Log differences
$diff = array_diff($oldSchema['columns'], $newSchema['columns']);
Caching Quirks:
php artisan eloquent-schema:clear --schema or disable caching (cache_ttl: 0) in development.php artisan eloquent-schema:cache --max-depth=1 for lightweight caching during active development.Vendor Model Deduplication:
User model extends Spatie\Permission\Models\User, but both appear in list-models.php artisan eloquent-schema:mcp list-models --vendor
Relationship Depth Limits:
max_depth: 2 returns incomplete schemas for deeply nested relationships.max_depth: 3 (max allowed) but cache separately to avoid memory spikes:
php artisan eloquent-schema:cache --max-depth=3 --cache-key=deep_schemas
Enum/Accessors Serialization:
// app/Providers/EloquentSchemaServiceProvider.php
use Visualbuilder\EloquentSchema\Services\ModelSchemaService;
public function boot()
{
$schemaService = app(ModelSchemaService::class);
$schemaService->extendSchema(function ($schema, $model) {
$schema['custom_accessors'] = $model->getCustomAccessors();
});
}
Inspect Raw Schema Data:
$schema = app(ModelSchemaService::class)->getSchema(Order::class);
dd($schema); // Debug the full structure
Check Discovery Logs:
php artisan eloquent-schema:cache --verbose
Validate MCP Tools:
php artisan mcp:tools --describe ModelSchema
Custom Schema Fields: Add metadata to schemas via service providers:
$schemaService->extendSchema(function ($schema, $model) {
$schema['api_resource'] = $model->getApiResource();
});
Dynamic Model Filtering: Override the discovery service to exclude models:
app()->bind(ModelDiscoveryService::class, function ($app) {
$service = new \Visualbuilder\EloquentSchema\Services\ModelDiscoveryService();
$service->excludeModels([
\App\Models\ExcludedModel::class,
]);
return $service;
});
Cache Tags: Use cache tags for model-specific invalidation:
Cache::tags(['eloquent-schema', 'App\Models\User'])->put(...);
Cache Granularity:
model-fields separately from model-schema if you frequently need lightweight data:
Cache::remember("fields_{$model}", now()->addHours(1), fn() => $schema->getFlatFieldList($model));
Lazy-Load Relationships: For large apps, fetch relationships on-demand:
$schema = $schemaService->getSchema(Order::class, max_depth: 0);
$schema['relationships'] = $schemaService->getRelationships(Order::class, max_depth: 1);
Vendor Package Optimization: Disable vendor model discovery if unused:
'included_packages' => [], // Empty array
How can I help you explore Laravel packages today?