Laravel’s AI SDK Just Made MCP Mandatory. Here’s What That Actually Breaks

Why v0.11.2 requires laravel/mcp for agent tools now, what changes in your existing agent code, and whether 7.4M installs means you can trust it in production.


composer require laravel/ai alone, on v0.11.2, does not install laravel/mcp. That’s worth stating precisely before anything else, because “mandatory” is the right word for a specific, common situation and the wrong word if read as “every laravel/ai install now pulls in MCP.” Checking the actual composer.json on Packagist: laravel/mcp sits in require-dev (^0.8) and again in suggests, with the suggestion’s description spelling out exactly when it’s actually needed — “Required to use MCP client tools or MCP server tools with Laravel AI agents.” Not required to install the package. Required the moment an agent’s tools() array includes an MCP-backed tool. That distinction is the entire subject of this post, because it’s exactly narrow enough to be easy to miss and exactly consequential enough to break a production deploy when it is.


What Actually Shipped, and Where It Actually Lives

Laravel’s AI SDK — laravel/ai, the official package, maintained by the same team behind the framework — added MCP support a few months back, and the mechanism is worth understanding before the dependency question makes sense. An agent in the SDK exposes a tools() method returning an array of callable tools the model can invoke. MCP tools go directly into that same array, sitting next to hand-written PHP tool classes, with no separate registration path and no different mental model for the developer wiring the agent together.

class SupportAgent extends Agent
{
    public function tools(): array
    {
        return [
            new SendSlackMessage(),           // a normal, hand-written tool
            ...$this->mcpServer('nightwatch')->tools(), // MCP tools, same array
        ];
    }
}

Under the hood, the SDK detects which array entries are MCP-backed, translates the MCP tool’s input schema into Laravel’s own JSON schema representation, and normalizes whatever comes back — structured payloads, plain text, streamed updates, errors — into the same result shape a hand-written tool would return. The model never knows the difference between a tool you wrote and a tool that arrived over MCP from a remote server (GitHub, Notion, an internal server, Nightwatch’s own tools for pulling a stack trace or browsing an issue) — which is genuinely well-designed: it means adopting MCP tools doesn’t require learning a second way of thinking about agent tooling, just a different source for the same array entry.

That translation and wrapping logic is exactly what laravel/mcp provides, and it’s why the dependency exists at all rather than being folded directly into laravel/ai‘s own codebase — MCP client/server behavior is a large enough surface (transports, schema translation, connection handling) that the SDK team kept it a separate, independently versioned package, pulled in only when a project actually uses it.


Why require-dev Is the Detail That Actually Matters Here

This is the part the title’s “mandatory” is really pointing at, and it’s more interesting than “a new dependency got added.” laravel/mcp sitting in require-dev means Composer treats it as something needed to develop and test laravel/ai itself — which makes sense from the SDK maintainers’ side, since their own test suite covers MCP tool wrapping and needs the package present to do that. It does not mean laravel/mcp ships to a consuming application’s production environment by default.

# A standard production deploy step, run in a huge number of CI pipelines
composer install --no-dev

Here’s the actual gap: --no-dev is completely standard, sensible practice for a production deploy — dev dependencies (test frameworks, static analysis tools, code style fixers) have no business shipping to production. But laravel/mcp isn’t purely a dev-only tool the way Pest or PHPStan are — for an application whose production agent code actually calls out to a remote MCP server (Nightwatch, GitHub, an internal server providing live tool access), that’s a runtime dependency, not a development one, sitting in a require-dev slot that a standard --no-dev production install strips out entirely.

// This line works fine in local dev, where laravel/mcp is present
// because require-dev packages ARE installed locally by default
$tools = $this->mcpServer('nightwatch')->tools();

// The same line, in a production environment built with --no-dev,
// where laravel/mcp was never installed: a class-not-found error,
// discovered at runtime, the first time this specific code path
// actually executes against a real request

This is the concrete thing that breaks, and it’s exactly the kind of gap that passes every local test and every staging smoke test that doesn’t specifically exercise a --no-dev-built environment, and then fails the first time a real production deploy — built the standard, correct way — actually tries to run the MCP-dependent code path for the first time in front of a user.

The fix is explicit, and it’s a one-line change worth making deliberately rather than discovering the hard way: any application using MCP tools in production needs laravel/mcp moved to its own top-level require, not left to inherit from laravel/ai‘s require-dev/suggests entries, which were never a promise that the package would be present outside a dev environment.

# The fix — explicit, in the consuming app's own composer.json,
# not inherited from laravel/ai's dev/suggest entries
composer require laravel/mcp

What Changes in Existing Agent Code

For most existing agents — the ones that don’t use MCP tools at all — nothing changes. tools() returning only hand-written tool classes never touches laravel/mcp regardless of whether it’s installed, and v0.11.2 is not a breaking change for that entire category of usage. The actual audit worth running, for any team that’s already shipping agents built on this SDK, is narrow and mechanical:

# Find every place an agent's tools() array touches an MCP server —
# these are the specific spots a --no-dev production build needs
# laravel/mcp actually present for
grep -r "mcpServer(" app/

For every result that turns up: confirm laravel/mcp is in the application’s own composer.json under require, not assumed present because laravel/ai happens to list it somewhere. This is a five-minute audit for most codebases and a genuinely easy one to skip, precisely because the code in question has probably been working correctly in every environment the team actually tests in — local dev, most CI pipelines that don’t specifically mirror a production --no-dev build — right up until it hits a production environment built the standard, recommended way.


Whether 7.5 Million Installs Means You Can Trust It in Production

Packagist’s own numbers on laravel/ai, checked directly rather than assumed: roughly 7.5 million installs, 221 dependents (other packages built on top of it), 1,149 GitHub stars, and zero published security advisories as of this writing. That’s a real, substantial adoption number for a package still in a 0.x version line — worth taking seriously as a signal, and worth being precise about what kind of signal it actually is.

What a large install count genuinely tells you: the core API surface — text generation, structured output, the agent/tool pattern itself — has been exercised by a large number of real applications, which is meaningfully more validation than a brand-new package with a clever design and no adoption yet. Zero security advisories on a package this widely used, this actively developed (the changelog shows frequent point releases addressing specific provider quirks — a Gemini token-count fix, an OpenAI streaming edge case, an Anthropic citation handling fix), and this exposed to scrutiny is a genuinely reassuring signal, not a guarantee.

What it doesn’t tell you: a 0.x version number is Semantic Versioning’s own explicit signal that breaking changes are still expected between minor versions — this is the framework maintainers’ own stated contract, not a technicality to route around. The MCP dependency situation in this post is a live example of exactly that kind of change: not a bug, not a regression, a genuine behavioral shift in a require-dev/suggests relationship that a 0.11.1-to-0.11.2 bump was free to make under semver’s own rules for a pre-1.0 package. Large install numbers describe how much the existing API surface has been battle-tested. They say nothing about whether the next point release keeps that surface stable — which, for a 0.x package, it’s explicitly not obligated to.

The honest verdict: 7.5 million installs is a real reason to trust the quality of what’s shipped — the core functionality is genuinely production-tested at scale. It’s not a reason to skip pinning a specific version, reading the changelog before every update, and treating every point release the way you’d treat any pre-1.0 dependency: something to update deliberately, with the changelog actually read, not auto-merged by a dependency bot that trusts the install count more than the version number is telling you to.


The One Rule

The real story here isn’t “Laravel added a scary new mandatory dependency” — it’s a normal, well-reasoned package boundary (MCP support as a separate, optionally-installed package) intersecting with a normal, well-reasoned deployment practice (--no-dev in production) in a way that quietly assumes the other side made the opposite assumption. laravel/mcp isn’t mandatory for laravel/ai. It’s mandatory the moment your agent’s tools() array touches an MCP server, and mandatory in your application’s own require, not borrowed from a dependency’s require-dev list that was never a promise about your production environment in the first place. The five-minute audit — grep for mcpServer(, confirm the dependency is explicit — is cheap. Finding out the hard way, in production, the first time that code path actually runs against a --no-dev build, is not.

Leave a Reply

Your email address will not be published. Required fields are marked *