For four months this series has carried the same two watch items from issue to issue: laravel/mcp's road to 1.0 and the AI SDK's longer, stranger one. September closed both in nine days. MCP 1.0 landed on September 14, and the AI SDK followed on September 23, four months and eleven 0.x releases after we first wrote "inching toward 1.0" in the May edition.
Here's the part nobody puts in an announcement post, and the reason we think September mattered more than the version numbers suggest. Within a week of each release, each package had a published security advisory and a same-week patch: an SSRF hole in the AI SDK's brand-new chat adapters, an OAuth redirect weakness in MCP. If you want to know whether software has really crossed into production, don't look at the changelog. Look at whether security researchers have started treating it as a target worth filing against. By that measure, Laravel's AI stack grew up in September.
We felt the other September story in our own work before we could name it. An agent we were building for an e-learning platform crossed twenty tools this quarter, and we watched its accuracy quietly degrade as the list grew: every request carried every schema, and the model had more chances to pick the wrong one. September's MCP release ships the fix for exactly that disease, with measured numbers attached, and the engineering story behind it is the best thing Laravel published all month.
In This Article
The short version, if you only read one section:
- Both 1.0s shipped. laravel/mcp v1.0.0 on September 14 (conformance suite, OAuth challenges, test assertions, legacy-client compatibility) and laravel/ai v1.0.0 on September 23 (classification, step middleware, finalized approvals, rebuilt conversation storage).
- Update both packages now. Each got a security advisory within a week: SSRF in the AI SDK's Vercel and AG-UI adapters (fixed in 1.0.1) and an insecure OAuth redirect in MCP (fixed in 1.0.1, and 0.9.6 for the 0.x line). Neither has a CVE ID, so CVE-driven scanners will not flag them.
- Searchable tool catalogs are the sleeper feature of the year. Wrap rarely used MCP tools in a catalog and the tools/list payload stays 1,431 bytes whether you have 10 tools or 100.
- The framework shipped a Mercure broadcast driver, contributed by Kévin Dunglas himself: real-time events over server-sent events with no websocket server to operate, including presence channels and end-to-end encrypted channels.
- The one thing worth doing this week: run composer update laravel/ai laravel/mcp, and if you deployed the AI SDK's chat endpoints, do it today. The SSRF advisory applies to anyone whose Vercel or AG-UI adapter is reachable by untrusted clients.
The Nine Days That Ended Two Watches
August's issue predicted the milestone order: MCP would beat the AI SDK to 1.0. It did, by nine days.
laravel/mcp v1.0.0 (September 14) is the quieter release of the two, and that's to its credit, because the breaking modernization already happened in the August beta. What 1.0 added is the stuff you ship when you expect to be depended on: a local MCP conformance suite you can run against your own server, OAuth challenges exposed on authenticated MCP routes, client logo and URI support in the OAuth flow, and a set of test assertions (assertNotRegistered plus registered-tool, prompt, and resource assertions on TestResponse) that make an MCP server as testable as a controller. It also quietly serves legacy initialize-handshake clients alongside the modern protocol, so the hard line the beta drew got a pragmatic softening for the agents that haven't caught up. Nested request input now supports Laravel-style dot notation, which sounds small until you write your first tool that accepts a structured filter.
laravel/ai v1.0.0 (September 23) is the bigger surface, and it gets its own section below. The headline worth stating up front: after four months of watching, the 1.0 means what you hope it means. The conversations schema, the approval flow, the middleware contract, and the usage shape are now commitments, and the upgrade guide walks each breaking change with before-and-after code.
One more thing happened between the two releases that most changelogs will miss. On September 11, three days before MCP 1.0, Laravel published an engineering post explaining the release's defining feature, and it reads like nothing else they've put out this year.
MCP 1.0 and the Catalog That Doesn't Grow
Here's the problem, with Anthropic's own numbers. Before an agent reads a single word of your question, the name, description, and full JSON schema of every tool on the server is already sitting in its context window. A setup with 50-plus tools costs roughly 72,000 tokens up front, about a thousand per tool, on every single turn. Worse than the token bill is the accuracy cost: on Anthropic's MCP evaluations with large tool libraries, deferring tool definitions moved Opus 4 from 49 percent to 74 percent. Forty tool descriptions are forty chances to pick the wrong one. That's the degradation we watched happen on our own twenty-tool agent.
Laravel MCP 1.0 ships the fix as searchable tool catalogs. You keep your always-used tools advertised normally and move the long tail behind a catalog, declared with ToolSearch::class as a key in your server's tools array:
1use Laravel\Mcp\Server;
2use Laravel\Mcp\Server\Tools\ToolSearch;
3
4class StoreServer extends Server
5{
6 protected array $tools = [
7 OrderLookupTool::class,
8 CustomerLookupTool::class,
9 ToolSearch::class => [
10 RefundTool::class,
11 InventoryTool::class,
12 ShippingEstimateTool::class,
13 // ...the other fifteen
14 ],
15 ];
16}The server now advertises the two frequently used tools plus two meta-tools: search_tools, which searches the catalog, and execute_tools, which runs a batch of calls from it. Laravel measured the tools/list payload with identically shaped tools: 10 tools advertised directly cost 5,843 bytes against 1,431 through a catalog, and at 100 tools it's 58,585 against the same 1,431. The catalog column never moves. Everything you add behind it is free at rest.
| Tools | Advertised directly | Through a catalog | Reduction |
|---|---|---|---|
| 10 | 5,843 bytes | 1,431 bytes | 75.5% |
| 20 | 11,703 bytes | 1,431 bytes | 87.8% |
| 40 | 23,423 bytes | 1,431 bytes | 93.9% |
| 100 | 58,585 bytes | 1,431 bytes | 97.6% |
The engineering post behind this feature is worth your time for the honesty alone. The author shipped four versions and threw away three: a Code Mode port that generated PHP functions and ran agent-written code through eval() (killed after sitting with what an unsandboxed language model can reach), a survey of sandboxes that all meant shipping new infrastructure inside a Composer package, and a restricted PHP dialect enforced with PHP-Parser that failed precisely because the model's fluency in real PHP made it constantly write constructs the allowlist rejected. The lesson he lands on deserves to be a design principle: a partial language is worse than no language. What shipped instead is a JSON batch format the model has no wrong priors about, plus deterministic lexical search. No embeddings, no new dependencies, nothing to operate.
Two details show the framework advantage. Search scores parameter names as documentation, so a query for "rainfall" finds a tool whose only mention of rain is a parameter called rainfall_mm. And every call in an executed batch becomes a real JsonRpcRequest that runs through ToolInvoker, the exact class a normal tools/call uses, with conditional registration re-checked at execution time. A search result is never a capability grant. Limits are config, not ceremony: mcp.tool_search.max_tool_calls defaults to 25 calls per batch and max_output_bytes to 65,536.
In practice: the crossover comes earlier than you'd guess. Laravel's own rule of thumb after measuring: past 10 or 15 tools, advertising everything is a cost you have to justify, not a default. For the agent work we do, the pattern is to leave the two or three tools a session always touches advertised and catalog the rest; for an e-learning assistant that means enrollment lookup and course search stay resident while grade exports, SCORM package queries, and reporting tools become discoverable. If you've read our post on building multi-agent systems in Laravel, this composes directly: sub-agents keep their own small tool sets, and the orchestrator's surface stays flat. The pattern has a name in the wider industry (progressive tool discovery), Cloudflare's Code Mode MCP server arrived at the same two-tool shape, and there's an open MCP specification proposal to standardize it, so this is Laravel landing early on a converging standard rather than inventing a dialect.
AI SDK 1.0: Classification, Step Middleware, and a Fixed Memory
The AI SDK's 1.0 is really four releases wearing one tag: a new capability, a new control surface, a finalized safety contract, and a storage rebuild.
Classification is the new capability, and it's a different kind of model, not a cheaper prompt. Routing a ticket, flagging a comment, picking a branch in a workflow: these are decisions, not writing. TypeSafe (the creators of the Jev models) calls them System One models, and they answer in milliseconds at a fraction of the cost of a full LLM call. The SDK now treats classification as a capability of its own alongside text, images, audio, and embeddings, running on TypeSafe and OpenRouter today, with the same API ready for other providers. The simplest door into it is the new decide macro:
1use Illuminate\Support\Str;
2
3if (Str::decide($comment->body, 'Is this comment spam or promotional?', threshold: 0.8)) {
4 $comment->flagForReview();
5}One question, one boolean, with a threshold argument that sets how certain the model must be. Under the hood it builds a Classification::of() request with a Boolean question, and the full API handles multi-question classification over strings or structured state. True to the house style, it's testable from day one: Classification::fake() plus assertClassified() and assertNothingClassified() work exactly the way Mail and Queue fakes do. In practice: every contact form, comment stream, and support inbox has a "should a human look at this first" decision in it somewhere, and most of us have been paying full LLM latency and price for what is really a System One judgment. We're moving the lead-qualification check in one client pipeline to a decide call first, and keeping the expensive model for drafting the reply.
Step middleware is the new control surface. Agent middleware used to run once per prompt. It now wraps every generation step, so an agent that calls three tools before answering runs your middleware three times, and each step arrives as a PendingStep you can inspect and copy with changes:
1use Closure;
2use Laravel\Ai\PendingStep;
3
4class TrimExpensiveTools
5{
6 public function handle(PendingStep $step, Closure $next)
7 {
8 if (! $step->isFirstStep()) {
9 $step = $step->withoutTools('deep_research');
10 }
11
12 return $next($step);
13 }
14}The PendingStep API covers withModel, withInstructions, withMessages, withTools, onlyTools, withoutTools, withToolChoice, withMaxTokens, and withProviderOptions, which means mid-run you can swap to a cheaper model once the hard reasoning is done, summarize a long history before it snowballs, or return a cached answer without calling the provider at all. Notice the theme shared with MCP's catalogs: September's entire AI story is about not paying for capability you aren't using on this step.
Approvals are now a contract. July introduced human-in-the-loop tool approval; 1.0 finalizes it. A tool implements Approvable (with the InteractsWithApprovals trait), the agent pauses instead of invoking it, and you resume with a decision per pending call: approve it, reject it with a reason the model gets to read, or edit the arguments before the tool runs. It works across prompt, stream, queue, and the broadcast methods. If you've been following this series' agents-in-production thread, this is the stop button we called the real production feature back in July, now stable enough to build a compliance story on.
And the storage rebuild is the honest one. The team knew the conversations table would be the hardest thing to change after 1.0, so they changed it first. Messages now carry a steps JSON column with one entry per model round-trip, each tool result stored beside the call that produced it. The old flat lists couldn't tell a tool call that never ran from one waiting on approval, and rebuilding provider history meant guessing. Conversations stay one row per turn and the toolCalls and toolResults accessors keep working, but raw SQL against the old columns must migrate, and there's a required backfill migration to run before you deploy 1.0. Alongside: a hosted CodeExecution provider tool runs agent code in the provider's own sandbox (Anthropic, OpenAI, Azure, Gemini, and xAI), the SDK's own ToolSearch wrapper defers rarely used tool definitions on OpenAI and Anthropic, sub-agent activity now streams by default, usage reporting is unified as inputTokens and outputTokens with cached and reasoning tokens as subsets of those totals, and the default models moved up a generation (Anthropic's "smartest" alias now resolves to Claude Opus 5.5).
The upgrade path is its own small cultural milestone: Laravel's official recommendation is to let an AI assistant do the upgrade, via Laravel Boost's guided /upgrade-ai-sdk-v1 prompt in Claude Code, Cursor, or your editor of choice, which walks the assistant through the upgrade guide one breaking change at a time. The framework that spent 2026 shipping agent tooling now assumes you'll point an agent at your own codebase.
Week One: Both 1.0s Got Security Advisories
We said the advisories are the real production signal, so here they are, specifically, because both demand action.
Laravel AI SDK: SSRF via client-supplied file URLs (GHSA-6qhr-3g93-pxhw, moderate, CVSS 5.3). The Vercel adapter and the AG-UI adapter, both new in 1.0, accept file parts with a URL from the client and fetched that URL from your server without validating it. Anyone who could reach a chat endpoint built on either adapter could make your server issue GET requests to internal addresses: cloud metadata services, localhost, private networks. Version 1.0.1 (September 29) fixes it. If you cannot upgrade immediately, reject URL-based file parts in incoming chat requests.
Laravel MCP: insecure OAuth redirect (GHSA-mx2h-h55v-pm44, low, published September 24). A weakness in OAuth redirect URL validation could send an authenticated user to an unintended destination during the flow, and under certain configurations a crafted link could leak authorization codes or tokens. It requires user interaction and a social-engineering step, hence the low severity. Fixed in v1.0.1, and backported as v0.9.6 for servers still on the 0.x line.
The action line is one command: composer update laravel/ai laravel/mcp. One operational wrinkle worth knowing: neither advisory has a CVE ID assigned, so a scanner that only watches CVE feeds will not flag either package. GitHub's advisory database and composer audit are the feeds that catch these.
In practice: the SSRF one is the sharp edge, because the vulnerable adapters are the exact feature that makes 1.0 attractive for chat UIs, and a chat endpoint is by definition reachable by untrusted clients. If you wired up Vercel::chat or the AG-UI protocol in the three weeks they existed, this is a same-day update, and it's worth adding an egress rule that your app servers cannot reach the cloud metadata IP range anyway. That control has now paid for itself twice in our client work this year.
The Framework Kept Moving: v13.30 to v13.34
Five Tuesday releases (September 1 through 29), and the headline comes from outside the Laravel team entirely.
Laravel got a Mercure broadcast driver, contributed by Kévin Dunglas (v13.32, September 15). If the name is familiar, it's because he created Mercure, FrankenPHP, and API Platform in the Symfony world. Mercure runs real-time events over server-sent events, so there is no websocket server to operate: with FrankenPHP the built-in hub works with zero extra infrastructure and publishes in-process, and any external Mercure hub works too. This is not a toy driver. It covers public, private, and presence channels, whispers that go straight from client to hub without a Laravel round-trip, a batch auth endpoint that mints one httpOnly cookie covering every joined channel, and end-to-end encrypted channels with per-channel AES-256-GCM keys that the hub itself never sees. Laravel Echo gained a matching Mercure connector that rides the browser's native EventSource API with no extra client library, and install:broadcasting now offers Mercure as an option. Under the hood it delegates to the battle-tested Symfony Mercure component.
The signal here is bigger than the feature. Laravel already has Reverb, its own first-party websocket server, and it still merged a first-party alternative built on a competing protocol, authored by one of Symfony's most prolific maintainers. In practice: for the dashboards and notification feeds that make up most real-time work (the e-learning platforms we build on Laravel and Moodle LMS rarely need bidirectional sockets, they need "the gradebook updated"), SSE through Mercure means one less long-running process to babysit, and it fits hosting environments where a websocket server was never going to be approved.
Scout learned semantic search. The Typesense engine now supports semantic() and hybrid() searches, generating vectors with Laravel AI, using Typesense's auto-embedding, or accepting yours; the Meilisearch engine can now use Meilisearch's native embedders. Combined with August's MariaDB vector support, "add semantic search" has stopped implying "add Postgres and pgvector" for a lot of stacks. In practice: course-catalog and knowledge-base search is where hybrid wins fastest, because learners search "how do I reset a student password" with none of the words your article title uses.
Per-tenant AI credentials became a one-liner. Ai::build() constructs a provider from a runtime config array without touching your configured providers, with on-demand names guarded against collisions, and built providers work in failover lists. Every multi-tenant SaaS that lets customers bring their own API key has hand-rolled this manager; now the SDK owns it.
The queue layer continued August's observability arc, from the worker's point of view. Jobs can now be notified before a timeout occurs so they can checkpoint instead of dying mid-write, workers can opt out of being killed on job timeout, a JobInterrupted event fires when a worker is stopped mid-job, JobProcessed now carries the job's duration, worker crashes can count toward a job's maxExceptions so a segfaulting payload stops retrying forever, and queue:flush accepts a --queue option. Redis queues got genuinely hardened: the driver is now cluster-safe, phpredis commands retry when a connection reset surfaces as a warning, pipelines rebuild their client on lost connections, and the valkey:// and valkeys:// protocol schemes are recognized. In practice: the timeout pre-notification is the one to adopt first. Any job that writes in batches (imports, exports, media processing) can now flush its progress when warned instead of leaving a half-written mess for the retry to trip over.
And the steady accumulation. Collections gained chunkBy, which splits a collection every time the given key or callback's value changes between adjacent items:
1$entries->chunkBy(fn ($entry) => $entry->created_at->format('Y-m'));Storage gained copyToDisk() and moveToDisk(), which stream a file between disks and, for moves, delete the source only after the copy succeeds (the perfect companion to August's read-through migration driver). The memoized cache now supports tags, schema builders gained an inplace() DDL modifier so index and foreign-key operations on MySQL use the online algorithm, Postgres connections accept server options, SQLite schema dumps stopped including shadow tables, and the session layer got a deliberate security adjustment to when password hashes are stored, alongside PHP 9.0 forward-compatibility work. Scattered through the same changelogs: Cloud read replicas, opt-in native Postgres pooling, IAM-authenticated S3 disks, and smarter Cloud job retries, all landing in the open-source framework. Which brings us to the platform those PRs serve.
Laravel Cloud: Every Pull Request Gets Its Own Stack
September's Cloud release is the one that changes a team habit: isolated preview environments. Every open pull request can now get its own environment with fresh resources, never pointing at production data. Each preview carries its own password protection, environment variables, and automatic-deletion settings; the Deployments page shows a row per open pull request with its branch, latest commit, and a link. The companion piece is that previews sleep between review sessions on Flex compute sizes and are deleted when the pull request merges or closes. June's scale-to-zero arc was the enabler: an environment that costs nothing while idle is an environment you can afford to create for every branch. The "better together" framing in Laravel's September 28 post is accurate for once.
The rest of the month rounds out the operations story. A new Requests tab under Monitoring shows request counts, response codes, and timings by page with no package to install. Managed database users let you create scoped read-only or read-write credentials per database instead of sharing the default ones (Laravel MySQL, RDS MySQL, and RDS Postgres). Laravel MySQL databases now grow their own storage: at 90 percent full, Cloud adds 50 percent more while the database stays online, with a configurable cap. Enterprise plans can stream application logs to their own S3 bucket in real time. And in a nice piece of ecosystem courtesy, Cloud now detects Statamic at deploy time and configures NGINX to serve its full-measure static cache directly from public/static, so cached pages never wake PHP at all.
In practice: preview environments kill the shared-staging bottleneck, where two features queue for one environment and QA tests a merge of both. With managed database users, the preview can run against a scoped, disposable user from day one. The pattern to steal even if you're not on Cloud: Laravel also published a detailed engineering playbook on September 30 about migrating Pinkary from Forge to Cloud, and its sections on SQLite-to-MySQL behavior differences and local-storage coupling are a free checklist for any hosting migration, including the Forge-to-anywhere kind.
What This Means for Teams Shipping Laravel
First, the August scorecard, settled honestly:
| August's tease | What September delivered |
|---|---|
| MCP 1.0 final watch | Shipped September 14, patched September 24. The conformance suite and searchable tool catalogs came with it |
| AI SDK 1.0, month four of the vigil | Shipped September 23, patched September 29. The vigil is over |
| State of Laravel survey results | Still unpublished as we write. The watch continues into its third month |
| Vite+ rollout through the starter kits | Resolved before September even started: every official starter kit switched to Vite+ on August 28, two days before our August issue went out. Lint and format now collapse into a single vp check |
| Laravel 14 signals | First hard facts, September 21 via Laravel News: Q1 2027 expected, PHP 8.4 minimum, standard support cycle. The waiting features are contract changes that cannot ship in a 13.x minor |
Three threads worth carrying into your planning:
A 1.0 is a risk-model document, not a feature peak. Both packages kept moving immediately (the AI SDK's 1.1 already shipped in early October with Agent Skills support), and both needed a patch within a week. What changed is what you can now rely on: the conversations schema, the approval contract, the MCP protocol surface. If you held off building on laravel/ai because 0.x churn burned you in the spring (it burned us in the 0.9 gateway rearchitecture), the reason to wait is gone, but pin at least 1.0.1 and subscribe to composer audit, because the CVE feeds will not cover you here.
Context economics is now a framework concern. Searchable tool catalogs, the SDK's deferred tool loading, and step middleware that trims tools mid-run are all the same idea wearing three APIs: stop paying tokens for capability this request is not using. The measured numbers (97.6 percent payload reduction at 100 tools, 25-point accuracy swings on large tool libraries) say this is where agent performance actually lives, well before you reach for a bigger model. Audit your agents' tool lists the way you audit queries.
The boundaries are getting porous in both directions. Symfony's Kévin Dunglas shipping Laravel's Mercure driver is the healthiest kind of cross-pollination the PHP ecosystem has seen in years, and Cloud's preview environments are built directly on framework-level scale-to-zero primitives that also landed as ordinary open-source PRs. The lesson from three straight months of this: before you build operational scaffolding, check whether the framework just absorbed it. The streak is now images (July), storage migration (August), and tool-surface management (September).
October's watchlist: Laravel 14 season starts in earnest (Route::query() and Eloquent model defaults() already landed in v13.35 on October 7, as we publish), the AI SDK 1.1 line with Agent Skills, the State of Laravel results (third time on this list, and we're starting to wonder), and whether MCP's progressive-disclosure proposal gets standardized upstream now that Laravel, Cloudflare, and Anthropic have all converged on the same shape. We'll cover all of it in the October roundup.
Related reading
- What's New in Laravel: August 2026 (Read-Through Filesystems & Agent Observability)
- Building Multi-Agent Systems in Laravel: Sub-Agents, Orchestrators & AgentTool Internals
- AI Agents in Production: Architecture, Tools & Lessons Learned
- Laravel API Development Best Practices for 2026
Frequently Asked Questions
What is new in Laravel AI SDK 1.0?
What are searchable tool catalogs in Laravel MCP 1.0?
When will Laravel 14 be released?
What are Laravel Cloud preview environments?
Ready to start your project?
Tell us about your requirements and we'll get back with a clear plan within 24 hours. No sales pitch, just an honest conversation.

Co-founded Treesha Infotech and leads all technology decisions across the company. Full-stack architect with deep expertise in Laravel, Next.js, AI integrations, cloud infrastructure, and SaaS platform development. Ritesh drives engineering standards, code quality, and product innovation across every project the team delivers.