Boosting Laravel Boost

August 23, 2025

Hello 👋

cover

It's been a while since I wrote an article. I mean, why would I? You prompt AI about a subject, and it spits out everything you need. That kinda killed the joy for me, I ended up drafting like 10 articles but never publishing any of them. Still, part of me believes people enjoy reading something human-made. Like, an AI wouldn't make you sit through this boring intro, but hey, it's human, crappy, but human. Thanks by the way.

Anyway, I'm writing about AI today (the irony ha). Laravel just dropped a new package, Laravel Boost, which basically makes AI suck less. It makes it more deterministic by giving it rules and extra context to follow. Because yeah, the main bottlenecks of LLMs (at least from my day-to-day usage) are the prompt and the context.

WTF are MCPs

I'm not going to lecture you about prompt engineering, there are tons of resources out there already. Instead, let's talk about the second bottleneck: context.

LLMs are trained on massive datasets, and those datasets are their reference point. For example, if the training data only goes up to 2023 and you ask about today's weather, it won't have a clue. So what do we do?

We empower LLMs, give them up-to-date context, through tools. You have probably used this without even realizing it. Ask an LLM about the latest news and you will see "searching web". That's a tool in action, feeding the AI fresh data so it can answer you. Neat.

But "searching web" is just a built-in tool. If you asked it about your latest Jira ticket, it wouldn't know. And think about it, providers like OpenAI or Anthropic can't build tools for every possible need. For instance, you might want your LLM to query internal company data. That's where the idea of bringing your own tool comes in. The LLM can call your tool, fetch the data it needs, and then respond. Again, pretty neat.

So neat that Anthropic introduced the Model Context Protocol (MCP) to document this. It standardizes how LLMs call tools, how you plug tools into them, and how they fetch more context. So, if you have never heard of MCPs, well, we just covered them. At the core, they are just a thin layer that lets LLMs use tools (like the "searching web" tool) to grab more context.

MCPs do a bit more too.

And these tools can be anything, API calls, system calls, method calls, whatever. As long as they can provide an answer back to the LLM, the model can use it to finish the task.

Cool. Now you know about MCPs. You can read more about them here.

Hmm, Laravel Boost?

So Laravel Boost is basically an MCP server that exposes a set of tools. These tools revolve around the Laravel ecosystem, things like reading routes, checking logs, or searching the Laravel docs.

So when you prompt an LLM to fix your vibe coded SaaS, it can decide which tool to use. Though, nothing's guaranteed, an LLM can be a bitch and just ignore the tools, making up a method that never existed 🤷🏽.

And then you undo the change, get pissed, prompt again, and deal with a "sorry, you are absolutely right"...

I'm not going to cover how to install it, there's already an official YouTube video, a Laracasts episode, and a bunch of community guides. Besides, I'm a bit late to the party.

Though, I do want to show you how to boost Laravel boost.

What's My Purpose?

Boost lets you give your application a "purpose", basically a description of your product so the AI knows the context. Say you are building a SaaS, you could write something like:

This application is a SaaS that provides X services, etc.

You know your product best buddy.

First, make sure you have published the Boost config:

php artisan vendor:publish --tag=boost-config

At the time of writing, the config file looks like this:

<?php

declare(strict_types=1);

return [
    /*
    |--------------------------------------------------------------------------
    | Boost Master Switch
    |--------------------------------------------------------------------------
    |
    | This option may be used to disable all Boost functionality, which
    | simply provides a single and convenient way to enable or disable
    | Boost's AI development tools.
    |
    */

    'enabled' => env('BOOST_ENABLED', true),

    /*
    |--------------------------------------------------------------------------
    | Boost Browser Logs Watcher
    |--------------------------------------------------------------------------
    |
    | The following option may be used to enable or disable the browser logs
    | watcher feature within Laravel Boost. The log watcher will read any
    | errors within the browser's console to give Boost better context.
    */

    'browser_logs_watcher' => env('BOOST_BROWSER_LOGS_WATCHER', true),

];

To add the application purpose we just talked about, drop a new entry in the config:

// omitted for breivety
'purpose' => 'Describe your application purpose'

For this to take effect, you will need to re-generate the guidelines:

php artisan boost:install

In the published guidelines, for example, if you are using Cursor, you will find your purpose (I hope we all do lol) in .cursor/rules/laravel-boost.mdc, in the "Foundational Context" section.

Less is More

Boost ships with 15+ tools, but depending on your app you might not need them all. If you are building a pure API, you don't need a BrowserLogs tool, you are spared from frontend hell. Personally, I also found GetConfig and ListAvailableConfigKeys kinda useless, the LLM can just read configs directly without jumping through those hoops. So let's exclude them.

Tweak the boost.php config:

<?php

use Laravel\Boost\Mcp\Tools\GetConfig;
use Laravel\Boost\Mcp\Tools\BrowserLogs;
use Laravel\Boost\Mcp\Tools\ListAvailableConfigKeys;

// omitted for breivety
'mcp' => [
    'tools' => [
        'exclude' => [BrowserLogs::class, GetConfig::class, ListAvailableConfigKeys::class],
    ],
],

Boom, 3 tools gone.

And just like excluding tools, you can add your own. For example, I like having a tool that lists all registered events in the app. If you are pulling in third-party packages, this makes it easier for the LLM to spot events it can hook into instead of building extra logic or extending classes.

Under the hood, Boost uses a new first-party package, laravel/mcp, which handles tool creation and all the fun stuff. You can create a new tool with:

php artisan make:mcp-tool ListEvents

The tool code for listing event is something like:

<?php

namespace App\Mcp\Tools;

use Illuminate\Support\Facades\Artisan;
use Laravel\Mcp\Server\Tool;
use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly;
use Laravel\Mcp\Server\Tools\ToolInputSchema;
use Laravel\Mcp\Server\Tools\ToolResult;
use Symfony\Component\Console\Command\Command as CommandAlias;
use Symfony\Component\Console\Output\BufferedOutput;

#[IsReadOnly]
class ListEvents extends Tool
{
    public function description(): string
    {
        return 'List all available events defined in the application';
    }

    public function schema(ToolInputSchema $schema): ToolInputSchema
    {
        return $schema;
    }

    /**
     * @param array<string> $arguments
     */
    public function handle(array $arguments): ToolResult
    {
        $eventsOutput = $this->artisan('event:list');

        return ToolResult::text($eventsOutput);
    }

    /**
     * @param array<string|bool> $options
     */
    private function artisan(string $command, array $options = []): string
    {
        $output = new BufferedOutput;
        $result = Artisan::call($command, $options, $output);

        if ($result !== CommandAlias::SUCCESS) {
            return 'Failed to list routes: '.$output->fetch();
        }

        return trim($output->fetch());
    }
}

Then register it in, you guessed it, the config file:

<?php

use App\Mcp\Tools\ListEvents;
use Laravel\Boost\Mcp\Tools\GetConfig;
use Laravel\Boost\Mcp\Tools\BrowserLogs;
use Laravel\Boost\Mcp\Tools\ListAvailableConfigKeys;

// omitted for breivty
'mcp' => [
    'tools' => [
        'exclude' => [BrowserLogs::class, GetConfig::class, ListAvailableConfigKeys::class],
        'include' => [ListEvents::class], // include the tool
    ],
],

And just like that, you add added a custom tool.

Bonus tip: The MCP server Boost uses comes with an inspector, so you can test new tools right away. Just run:

php artisan mcp:inspector laravel-boost

You will see all available tools, test them, etc.

Don't call me, Don't come by my house

If you are using a modular monolith architecture with a modules/ directory... bad news: Boost only checks enums, models, and controllers inside app/.

Would be nice if there was a native way to customize this, but until then, we do it ourselves.

All you need to do is rebind Laravel\Boost\Install\GuidelineAssist to your own custom GuidelineAssist, which scans modules/ (or wherever).

Your custom guideline might look like:

<?php

declare(strict_types=1);

namespace App\Support;

use Illuminate\Database\Eloquent\Model;
use Laravel\Boost\Install\GuidelineAssist;
use ReflectionClass;
use Symfony\Component\Finder\Finder;

class CustomGuidelineAssist extends GuidelineAssist
{
    public function __construct()
    {
        $this->modelPaths = $this->discover(fn ($reflection) => ($reflection->isSubclassOf(Model::class) && ! $reflection->isAbstract()));
        $this->controllerPaths = $this->discover(fn (ReflectionClass $reflection) => (stripos($reflection->getName(), 'controller') !== false || stripos($reflection->getNamespaceName(), 'controller') !== false));
        $this->enumPaths = $this->discover(fn ($reflection) => $reflection->isEnum());
    }

    private function discover(callable $cb): array
    {
        $classes = [];

        if (empty(self::$classes)) {
            $finder = Finder::create()
                ->in([app_path(), base_path('modules')])
                ->files()
                ->name('/[A-Z].*\.php$/');

            foreach ($finder as $file) {
                $relativePath = $file->getRelativePathname();
                $isModule = str_starts_with($file->getRealPath(), base_path('modules'));

                $className = $isModule
                    ? 'Modules\\'.str_replace(['/', '.php'], ['\\', ''], $relativePath)
                    : app()->getNamespace().str_replace(['/', '.php'], ['\\', ''], $relativePath);

                try {
                    if ($this->fileHasClassLike($file->getRealPath()) && class_exists($className)) {
                        self::$classes[$className] = $file->getRealPath();
                    }
                } catch (\Throwable) {
                    // Ignore exceptions from class loading
                }
            }
        }

        foreach (self::$classes as $className => $path) {
            if ($cb(new ReflectionClass($className))) {
                $classes[$className] = $path;
            }
        }

        return $classes;
    }
}

It's mostly the parent discover() with minor tweaks.

Don't forget to rebind it in a service provider. Once you do, testing the "application-info" tool from the inspector should show all your models listed correctly.

That's it

AI sucks? Maybe. But it sucks a lot less with the right tool, something like Boost.

But don't stop there. There are MCPs for everything, Github, Sentry, Linear. They add tons of value. You can even build your own MCP for fun, I had one that turned on my air fryer (yes, it cooked fries), and another that played a Spotify playlist based on how shitty the code was.

Fun fact: even though I'm shitting on AI a bit here, I used AI to correct my poor grammar. Fixing grammar while getting insulted, cool lol. Sorry AI, you do push me over the line sometimes.


Profile picture

Written by Oussama Mater Software Engineer, and CTF Player.
Find me on X, Linkedin, Github, and Laracasts.