<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:media="http://search.yahoo.com/mrss/" >

<channel>
	<title>Laraval Development &#8211; Macronimous Blog</title>
	<atom:link href="https://www.macronimous.com/blog/category/php-development/laraval-development/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.macronimous.com/blog</link>
	<description>Web design, web programming, Mobile apps, Opensource , SEO etc</description>
	<lastBuildDate>Fri, 09 Oct 2026 15:18:29 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>
	<item>
		<title>PHP MCP Server: A PHP Developer&#8217;s Guide to the Model Context Protocol</title>
		<link>https://www.macronimous.com/blog/mcp-for-php-development/</link>
					<comments>https://www.macronimous.com/blog/mcp-for-php-development/#respond</comments>
		
		<dc:creator><![CDATA[Benny]]></dc:creator>
		<pubDate>Thu, 14 Aug 2025 07:37:46 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[AI Programming]]></category>
		<category><![CDATA[Laraval Development]]></category>
		<category><![CDATA[PHP Development]]></category>
		<category><![CDATA[AI in web development]]></category>
		<category><![CDATA[AI web development]]></category>
		<category><![CDATA[MCP]]></category>
		<category><![CDATA[MCP for PHP development]]></category>
		<guid isPermaLink="false">https://www.macronimous.com/blog/?p=4813</guid>

					<description><![CDATA[<p>A PHP MCP server is a PHP application that exposes tools, resources, and prompts to AI clients through the Model Context Protocol (MCP). In 2026 you build one with the official mcp/sdk package or, in a Laravel app, with laravel/mcp. Since the 2026-07-28 revision made MCP stateless, every call is an ordinary HTTP request, which [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.macronimous.com/blog/mcp-for-php-development/">PHP MCP Server: A PHP Developer&#8217;s Guide to the Model Context Protocol</a> first appeared on <a rel="nofollow" href="https://www.macronimous.com/blog">Macronimous Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<a href="https://www.macronimous.com/blog/wp-content/uploads/2025/08/MCP-for-PHP-development.png"><img fetchpriority="high" decoding="async" width="2240" height="1260" src="https://www.macronimous.com/blog/wp-content/uploads/2025/08/MCP-for-PHP-development.png" alt="MCP for PHP development" class="aligncenter size-full wp-image-4876" /></a>
<div class="mac-direct-answer">
<p><strong>A PHP <a href="https://www.macronimous.com/blog/building-a-wordpress-mcp-server-when-the-spec-changed/">MCP</a> server</strong> is a PHP application that exposes tools, resources, and prompts to <a href="https://www.macronimous.com/blog/the-code-your-ai-wants-to-delete-is-load-bearing/">AI</a> clients through the Model Context Protocol (MCP). In 2026 you build one with the official <code>mcp/sdk</code> package or, in a Laravel app, with <code>laravel/mcp</code>. Since the 2026-07-28 revision made MCP stateless, every call is an ordinary HTTP request, which is how PHP has always worked.</p>
</div>
<div class="mac-toc">
<p class="mac-toc-title">In this post</p>
<ul>
<li><a href="#what-changed">What changed since the first version</a></li>
<li><a href="#what-it-exposes">What a PHP MCP server exposes</a></li>
<li><a href="#stateless-php">Why the stateless spec suits PHP</a></li>
<li><a href="#wire-format">What a tool call looks like on the wire</a></li>
<li><a href="#official-sdk">Build one in plain PHP with the official SDK</a></li>
<li><a href="#laravel-mcp">Build one in Laravel with laravel/mcp</a></li>
<li><a href="#mcp-vs-rest">MCP vs REST vs GraphQL</a></li>
<li><a href="#security">Security: what I&#8217;d lock down first</a></li>
<li><a href="#where-id-wait">Where I&#8217;d wait</a></li>
<li><a href="#faq">FAQ</a></li>
</ul>
</div>
<p><em>Update, October 2026:</em> I first published this post in August 2025. It aged badly, and fast. About three weeks after it went up, the PHP Foundation, Symfony, and Anthropic&#8217;s MCP team <a href="https://thephp.foundation/blog/2025/09/05/php-mcp-sdk/" target="_blank" rel="noopener">announced an official PHP SDK</a>, which made both packages I&#8217;d recommended the wrong place to start. Then in July 2026 the protocol itself changed shape. So I&#8217;ve thrown out the old version and written this one from scratch. (The URL is the same. Almost nothing else is.)</p>
<p>If you write PHP for a living and somebody has asked you to &#8220;make the app work with AI agents,&#8221; this is what I&#8217;d tell you over coffee.</p>
<h2 id="what-changed">What changed since the first version</h2>
<p>Four things, and I&#8217;ll go through them in the order they hurt.</p>
<ul>
<li><strong>There&#8217;s an official SDK now.</strong> It&#8217;s <a href="https://github.com/modelcontextprotocol/php-sdk" target="_blank" rel="noopener"><code>mcp/sdk</code></a>, it grew out of Kyrian Obikwelu&#8217;s PHP-MCP project and the Symfony AI work, and the Symfony team leads maintenance. It covers servers <em>and</em> clients. It&#8217;s also still pre-1.0, and the README says &#8220;experimental&#8221; in plain words, so pin your version.</li>
<li><strong>Laravel ships its own package.</strong> <a href="https://laravel.com/docs/mcp" target="_blank" rel="noopener"><code>laravel/mcp</code></a> is first-party, documented alongside the framework, and comes with Artisan generators, a test API, and an MCP client.</li>
<li><strong>The protocol went stateless.</strong> The <a href="https://modelcontextprotocol.io/specification/2026-07-28" target="_blank" rel="noopener">2026-07-28 revision</a> removed the opening handshake and the protocol-level session. More on this below, because for PHP it&#8217;s the big one.</li>
<li><strong>Authorization grew up.</strong> OAuth 2.1 is the mechanism the spec documents. A bearer token still works with plenty of clients, but &#8220;use an API token&#8221; (which is all I said last time) isn&#8217;t the whole answer anymore.</li>
</ul>
<p>And one correction I owe you. The JSON example in the old post called a method named <code>tool</code>. There&#8217;s no such method. It&#8217;s <code>tools/call</code>, and it was <code>tools/call</code> back then too. Sorry about that.</p>
<h2 id="what-it-exposes">What a PHP MCP server exposes</h2>
<p>This part hasn&#8217;t changed, so I&#8217;ll keep it short. A server offers three kinds of things to an AI client.</p>
<p><strong>Tools</strong> are functions the model can call: create a project, send an invoice, look up an order. <strong>Resources</strong> are read-only data the client can pull in as context, addressed by a URI. <strong>Prompts</strong> are reusable templates the server hands to the client.</p>
<p>Start with tools. In the servers we&#8217;ve built, tools did nearly all the useful work, and resources came a distant second. I&#8217;d leave prompts until a real user asks for one.</p>
<h2 id="stateless-php">Why the stateless spec suits PHP</h2>
<p>Until this summer, MCP over HTTP was a conversation. The client opened with an <code>initialize</code> handshake, the server handed back a session ID, and every later request had to carry that ID so the server could remember who it was talking to.</p>
<p>That&#8217;s fine in Node or Python, where one long-lived process sits in memory holding the session. It&#8217;s a nuisance in PHP, because PHP-FPM on an ordinary host gives you a fresh process for each request that remembers nothing, which meant you needed a session store (files on one server, Redis on several), and then you needed the load balancer to cooperate, and then somebody&#8217;s shared hosting plan killed the long-running stream the server wanted to keep open, and at that point a perfectly sane developer would ask why a remote procedure call needed all this furniture.</p>
<p>The 2026-07-28 revision removes the furniture. There&#8217;s no handshake and no protocol session. Each request carries its own protocol version and client details, any worker on any machine can answer it, and list results come with cache hints. Cloudflare, AWS, and the MCP maintainers all describe it the same way: MCP now scales like any other HTTP API.</p>
<div class="mac-key-point">
<p>PHP got teased for twenty years for forgetting everything between requests. The protocol has now adopted that as its design.</p>
</div>
<p>What if your server really does need to remember something, like a cart or a half-finished import? The spec&#8217;s guidance is to return a handle from one tool and accept it as an argument on the next. In other words, a primary key. We&#8217;ve been doing that since PHP 3.</p>
<p>There&#8217;s a cost, and you should hear it from me before you hear it from a client. The new revision isn&#8217;t backward compatible. A server that only speaks 2026-07-28 may not work with an older client, and the reverse. So for a while you&#8217;ll be supporting both eras, and that&#8217;s a good reason to use an SDK instead of hand-rolling the JSON. (We hand-rolled once. I wrote up what happened in <a href="https://www.macronimous.com/blog/building-a-wordpress-mcp-server-when-the-spec-changed/">building a WordPress MCP server while the spec changed</a>.)</p>
<h2 id="wire-format">What a tool call looks like on the wire</h2>
<p>MCP messages are JSON-RPC 2.0, a small remote procedure call format where every message names a method and carries an ID. Here&#8217;s a client asking a server to run a tool.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "create_project",
    "arguments": {
      "project_name": "New Website Launch",
      "due_date": "2026-12-31"
    },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28"
    }
  }
}</pre><p>&nbsp;</p>
<p>I&#8217;ve trimmed the <code>_meta</code> block. The spec requires client info and client capabilities in there too, and your SDK fills them in. On HTTP, the client also sends <code>MCP-Protocol-Version</code>, <code>Mcp-Method</code>, and <code>Mcp-Name</code> headers, so a load balancer or firewall can route the call without opening the body. If you&#8217;ve ever fought a web application firewall over a JSON payload (I have, on our own host), you&#8217;ll like that.</p>
<p>The server answers like this.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "resultType": "complete",
    "content": [
      { "type": "text", "text": "Created project 42: New Website Launch" }
    ],
    "structuredContent": { "project_id": 42, "name": "New Website Launch" },
    "isError": false
  }
}</pre><p>&nbsp;</p>
<p>Two details matter. <code>structuredContent</code> is the machine-readable result, and the text block is the fallback for clients that only read text. And when your business logic fails, say the due date is in the past, you return a normal result with <code>isError</code> set to <code>true</code> and a message the model can act on. Save real JSON-RPC errors for broken requests and unknown tools.</p>
<h2 id="official-sdk">Build one in plain PHP with the official SDK</h2>
<p>This works in any PHP project: plain PHP, CodeIgniter, Slim, a legacy app with no framework at all. The steps below build a local server that talks over STDIO (standard input and output, the way a desktop AI client starts a server as a child process).</p>
<p><strong>Goal.</strong> A PHP file exposes one tool named <code>create_project</code>, and MCP Inspector can call it.</p>
<p><strong>Before you start.</strong> You need Composer and Node.js installed. Check the PHP version the SDK requires on its Packagist page before you install.</p>
<p><strong>Step 1: Install the SDK.</strong> Run this command in an empty project folder. Composer prints the installed version when it finishes.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">composer require mcp/sdk</pre><p>&nbsp;</p>
<p><strong>Step 2: Create the server file.</strong> Save this code as <code>server.php</code> in the same folder. The tool body is a stub, so replace it with a call to your own service class later.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">&lt;?php

require __DIR__ . '/vendor/autoload.php';

use Mcp\Server;
use Mcp\Server\Transport\StdioTransport;

class ProjectTools
{
    /**
     * Create a project and return its ID.
     */
    public function createProject(string $projectName, string $dueDate): array
    {
        // Call your existing service class here.
        return ['project_id' =&gt; 42, 'name' =&gt; $projectName, 'due_date' =&gt; $dueDate];
    }
}

$server = Server::builder()
    -&gt;setServerInfo('Project Server', '1.0.0')
    -&gt;addTool([ProjectTools::class, 'createProject'], 'create_project')
    -&gt;build();

$server-&gt;run(new StdioTransport());</pre><p>&nbsp;</p>
<p><strong>Step 3: Open the server in MCP Inspector.</strong> MCP Inspector is the official browser tool for testing a server by hand. Replace the path with the full path to your <code>server.php</code>.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">npx @modelcontextprotocol/inspector php /Users/YOU/project-server/server.php</pre><p>&nbsp;</p>
<p><strong>Check.</strong> The Inspector&#8217;s Tools tab lists <code>create_project</code> with two string inputs. You run it, and the result shows <code>project_id</code> 42.</p>
<p><strong>If it fails.</strong> The usual cause is stray output. On STDIO, anything your script prints (a warning, a debug <code>echo</code>, a byte order mark) lands in the protocol stream and breaks it. Send logs to a file or to standard error.</p>
<p><strong>Undo.</strong> Delete the project folder. Nothing else on your machine changed.</p>
<p>For a remote server you swap the transport for the SDK&#8217;s <code>StreamableHttpTransport</code>, which takes a PSR-7 request (the standard PHP interface for an HTTP message) and returns a response. The <a href="https://github.com/modelcontextprotocol/php-sdk/blob/main/docs/transports.md" target="_blank" rel="noopener">transports guide</a> has the wiring. Read the protocol versions page while you&#8217;re there. As far as I can tell from the repository, support for the stateless revision has been landing release by release, so check what your installed version speaks before you promise a client anything.</p>
<h2 id="laravel-mcp">Build one in Laravel with laravel/mcp</h2>
<p>If the app is Laravel, don&#8217;t use the plain SDK. Use the first-party package. You get the container, validation, policies, and middleware you already know, and the tool class ends up looking like a small controller.</p>
<p><strong>Goal.</strong> Your Laravel app serves an authenticated MCP endpoint at <code>/mcp/projects</code> with one tool that creates a project.</p>
<p><strong>Before you start.</strong> The package needs PHP 8.2 or newer and Laravel 11, 12, or 13. The steps assume Sanctum (Laravel&#8217;s token authentication package) is already installed, and that you have a <code>ProjectService</code> class and a <code>Project</code> policy. Swap in your own names.</p>
<p><strong>Step 1: Install the package.</strong></p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">composer require laravel/mcp</pre><p>&nbsp;</p>
<p><strong>Step 2: Publish the routes file.</strong> This command creates <code>routes/ai.php</code>, where MCP servers are registered.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">php artisan vendor:publish --tag=ai-routes</pre><p>&nbsp;</p>
<p><strong>Step 3: Generate the server class.</strong> The file appears in <code>app/Mcp/Servers</code>.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">php artisan make:mcp-server ProjectServer</pre><p>&nbsp;</p>
<p><strong>Step 4: Generate the tool class.</strong> The file appears in <code>app/Mcp/Tools</code>.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">php artisan make:mcp-tool CreateProjectTool</pre><p>&nbsp;</p>
<p><strong>Step 5: Write the tool.</strong> Replace the generated tool with this code. Notice the order: authorize, validate, then call the service.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">&lt;?php

namespace App\Mcp\Tools;

use App\Models\Project;
use App\Services\ProjectService;
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Attributes\Description;
use Laravel\Mcp\Server\Tool;

#[Description('Creates a project for the signed-in user. Needs a name and a due date.')]
class CreateProjectTool extends Tool
{
    public function handle(Request $request, ProjectService $projects): Response
    {
        if (! $request-&gt;user()-&gt;can('create', Project::class)) {
            return Response::error('Permission denied.');
        }

        $validated = $request-&gt;validate([
            'project_name' =&gt; 'required|string|max:120',
            'due_date' =&gt; 'required|date|after:today',
        ]);

        $project = $projects-&gt;create($request-&gt;user(), $validated);

        return Response::structured([
            'project_id' =&gt; $project-&gt;id,
            'name' =&gt; $project-&gt;name,
        ]);
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'project_name' =&gt; $schema-&gt;string()
                -&gt;description('The project name.')
                -&gt;required(),
            'due_date' =&gt; $schema-&gt;string()
                -&gt;description('The due date as YYYY-MM-DD.')
                -&gt;required(),
        ];
    }
}</pre><p>&nbsp;</p>
<p><strong>Step 6: Register the tool on the server.</strong> Open <code>app/Mcp/Servers/ProjectServer.php</code> and set the <code>$tools</code> property.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">protected array $tools = [
    \App\Mcp\Tools\CreateProjectTool::class,
];</pre><p>&nbsp;</p>
<p><strong>Step 7: Register the route.</strong> Put this code in <code>routes/ai.php</code>. The <code>throttle:mcp</code> middleware expects a rate limiter named <code>mcp</code>, so define one in your <code>AppServiceProvider</code> or remove that entry.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">&lt;?php

use App\Mcp\Servers\ProjectServer;
use Laravel\Mcp\Facades\Mcp;

Mcp::web('/mcp/projects', ProjectServer::class)
    -&gt;middleware(['auth:sanctum', 'throttle:mcp']);</pre><p>&nbsp;</p>
<p><strong>Step 8: Open the server in MCP Inspector.</strong> Add your Sanctum token as an <code>Authorization: Bearer</code> header when the Inspector asks for connection settings.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">php artisan mcp:inspector mcp/projects</pre><p>&nbsp;</p>
<p><strong>Check.</strong> The Inspector lists <code>create-project</code> (Laravel derives the name from the class). You call it with a past date, and the tool returns your validation message instead of creating anything.</p>
<p><strong>If it fails.</strong> A 401 response means the token header is missing or the token is wrong. An empty tool list means Step 6 was skipped.</p>
<p><strong>Undo.</strong> Remove the route from <code>routes/ai.php</code>. The endpoint stops existing on the next request.</p>
<p>One thing I&#8217;d do before any of this reaches production: write the validation messages for a machine reader. When validation fails, the model reads your error text and tries again, so &#8220;The due date must be a future date in YYYY-MM-DD format&#8221; gets you a correct retry and &#8220;Invalid input&#8221; gets you a loop. (Laravel&#8217;s type handling has its own traps here. We wrote about one in <a href="https://www.macronimous.com/blog/laravel-data-type-casting-int-cast-as-str/">integers arriving as strings</a>.)</p>
<h2 id="mcp-vs-rest">MCP vs REST vs GraphQL</h2>
<p>I get asked whether MCP replaces the REST API. No. They have different callers.</p>
<table class="styled-table">
<thead>
<tr>
<th>Question</th>
<th>REST</th>
<th>GraphQL</th>
<th>MCP</th>
</tr>
</thead>
<tbody>
<tr>
<td>Who calls it?</td>
<td>Your frontend or a partner&#8217;s code</td>
<td>Your frontend</td>
<td>An AI model, through a client app</td>
</tr>
<tr>
<td>Who decides what to call?</td>
<td>A developer, at build time</td>
<td>A developer, at build time</td>
<td>The model, at run time</td>
</tr>
<tr>
<td>How does the caller learn the API?</td>
<td>Docs or an OpenAPI file</td>
<td>Schema introspection</td>
<td><code>tools/list</code>, with descriptions written for a model</td>
</tr>
<tr>
<td>Message format</td>
<td>HTTP verbs and URLs</td>
<td>A query language over HTTP</td>
<td>JSON-RPC 2.0 over STDIO or HTTP</td>
</tr>
<tr>
<td>State</td>
<td>Stateless</td>
<td>Stateless</td>
<td>Stateless since 2026-07-28</td>
</tr>
<tr>
<td>Typical endpoint count</td>
<td>Many</td>
<td>One</td>
<td>One per server</td>
</tr>
</tbody>
</table>
<p>The row that matters is the second one. With REST, a programmer read your docs and decided which endpoint to hit. With MCP, a model reads your tool descriptions and decides on the spot. So the description is part of the interface, and a vague one is a bug.</p>
<p>Don&#8217;t write the logic twice, though. Your MCP tool and your REST controller should call the same service class. If your controllers are fat and the logic lives in them, fix that first. It&#8217;s the same advice I&#8217;d give for <a href="https://www.macronimous.com/blog/mastering-microservices-in-php-a-comprehensive-guide-for-php-developers/">splitting a PHP app into services</a>, and it pays off here for the same reason.</p>
<h2 id="security">Security: what I&#8217;d lock down first</h2>
<p>An MCP tool is a function on your production app that a language model can run. You are giving a caller that doesn&#8217;t understand consequences a button. You are trusting its client to ask a human first. You are assuming nobody slipped instructions into the text it just read. Treat every argument the way you&#8217;d treat a form field from a stranger.</p>
<p>The spec lists four things a server <em>must</em> do: validate inputs, enforce access control, rate limit, and sanitize outputs. Here&#8217;s how that turns into a pre-launch list.</p>
<ul class="mac-checklist">
<li>Every web MCP route sits behind authentication middleware. No public endpoints, not even for a demo.</li>
<li>Each tool checks what <em>this user</em> may do, with a policy or gate, inside the tool. Being logged in isn&#8217;t permission.</li>
<li>Each tool validates its arguments with real rules, not just the JSON schema.</li>
<li>The route has a rate limiter. Models retry, and they retry quickly.</li>
<li>Read-only tools are marked read-only, and destructive ones are marked destructive, so clients can ask for confirmation.</li>
<li>Nothing destructive ships in version one. No delete tools, no bulk updates.</li>
<li>Every tool call is logged with the user, the tool name, and the arguments.</li>
<li>Tool output is trimmed to what the model needs. No password hashes, no internal IDs you wouldn&#8217;t put in an API response.</li>
</ul>
<p>On authentication: Laravel&#8217;s own docs recommend OAuth through Passport, since that&#8217;s what the spec documents and what the widest range of clients support. They also say that if you&#8217;re already on Sanctum, stay there until a client forces the issue. I agree with that. Don&#8217;t bolt on an OAuth server for an internal tool three people use.</p>
<p>And keep a person in the loop for anything that writes. We run an MCP server on one of our own sites that lets an AI assistant edit pages. Every edit lands as a draft, and a human publishes it. That one rule has saved us more than once. It&#8217;s the same thinking behind <a href="https://www.macronimous.com/blog/controlled-ai-coding/">controlled AI coding</a>, and behind my standing worry that <a href="https://www.macronimous.com/blog/the-code-your-ai-wants-to-delete-is-load-bearing/">the code an AI wants to delete is load-bearing</a>.</p>
<h2 id="where-id-wait">Where I&#8217;d wait</h2>
<p>I&#8217;d build an internal MCP server today. I&#8217;d be slower about a public, customer-facing one, for two reasons.</p>
<p>Both PHP packages are pre-1.0. APIs will move. The examples in this post matched the documentation on the day I checked them (October 9, 2026), and I&#8217;d bet at least one is out of date within a year. Pin versions, and read the changelog before you run <code>composer update</code>.</p>
<p>The protocol also just had its biggest revision since launch. The maintainers added a formal deprecation policy alongside it, which is a good sign, but I&#8217;d let clients and SDKs settle for a few months before signing a contract that names a spec version.</p>
<p>If you&#8217;re not on Laravel: Symfony has <code>symfony/mcp-bundle</code>, Drupal has an <code>mcp_server</code> module, and API Platform and CakePHP have integrations built on the same official SDK. For <a href="https://www.macronimous.com/blog/wordpress-7-0-ai-the-token-cost-reality-for-site-owners/">WordPress</a>, read the post I linked earlier. That&#8217;s about all I know that&#8217;s worth passing on. If you&#8217;ve shipped a PHP MCP server and something here is wrong, tell me in the comments and I&#8217;ll fix it with credit.</p>
<h2 id="faq">FAQ</h2>
<div id="mcp-php-faq">
<div class="faq-item">
<h3>Do I need Laravel to build a PHP MCP server?</h3>
<p>No. The official <code>mcp/sdk</code> package is framework-agnostic and runs in plain PHP, CodeIgniter, Symfony, or a legacy codebase. Laravel developers should use <code>laravel/mcp</code> because it plugs into validation, policies, and middleware they already have.</p>
</div>
<div class="faq-item">
<h3>Can a PHP MCP server run on shared hosting?</h3>
<p>A server that follows the stateless 2026-07-28 revision handles each call as a normal HTTP request, so it fits standard PHP hosting far better than the older session-based design did. Check that your host allows the PHP version the package needs, and that your installed SDK version supports the stateless revision.</p>
</div>
<div class="faq-item">
<h3>Does MCP replace my REST API?</h3>
<p>No. REST serves code written by developers. MCP serves AI models that choose tools at run time. Most apps will keep both, with MCP tools and REST controllers calling the same service classes.</p>
</div>
<div class="faq-item">
<h3>Which MCP spec version should a new PHP server target?</h3>
<p>Target 2026-07-28 for new work, and keep support for the previous revision (2025-11-25) while your clients catch up, because the two are not backward compatible. An SDK that speaks both is the easiest way to do that.</p>
</div>
<div class="faq-item">
<h3>How do I test a PHP MCP server?</h3>
<p>Use MCP Inspector to call tools by hand. In Laravel, run <code>php artisan mcp:inspector</code> and write unit tests with the package&#8217;s test API. For the plain SDK, start the Inspector with <code>npx @modelcontextprotocol/inspector</code> and point it at your server file.</p>
</div>
</div>
<div class="mac-cta-box">
<h3>Need a PHP or Laravel App Made Ready for AI Agents?</h3>
<p>We&#8217;ve been writing PHP since 2002, and we build MCP servers for our own sites. If you want tools exposed safely on an existing app, we can scope it with you.</p>
<p><a href="https://www.macronimous.com/services/custom-web-development/" class="mac-cta-button">Talk to Our PHP Team</a>
</div>
<p>The post <a rel="nofollow" href="https://www.macronimous.com/blog/mcp-for-php-development/">PHP MCP Server: A PHP Developer&#8217;s Guide to the Model Context Protocol</a> first appeared on <a rel="nofollow" href="https://www.macronimous.com/blog">Macronimous Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.macronimous.com/blog/mcp-for-php-development/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Google Gemini CLI for Laraval development: Your New AI Co-Pilot in PHP programming</title>
		<link>https://www.macronimous.com/blog/google-gemini-cli-for-laraval-development/</link>
					<comments>https://www.macronimous.com/blog/google-gemini-cli-for-laraval-development/#respond</comments>
		
		<dc:creator><![CDATA[Benny]]></dc:creator>
		<pubDate>Mon, 07 Jul 2025 05:58:02 +0000</pubDate>
				<category><![CDATA[web programming]]></category>
		<category><![CDATA[AI Programming]]></category>
		<category><![CDATA[Laraval Development]]></category>
		<category><![CDATA[AI programming]]></category>
		<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://www.macronimous.com/blog/?p=4796</guid>

					<description><![CDATA[<p>This is an exciting time for developers, and for a tech-focused people like us at Macronimous.com, diving into new tools like Gemini CLI for Laraval development is definitely a natural fit. Here&#8217;s a detailed blog post for Laravel developers on how Gemini CLI can revolutionize their workflow. Let&#8217;s break down what Gemini CLI is, why [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.macronimous.com/blog/google-gemini-cli-for-laraval-development/">Google Gemini CLI for Laraval development: Your New AI Co-Pilot in PHP programming</a> first appeared on <a rel="nofollow" href="https://www.macronimous.com/blog">Macronimous Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<a href="https://www.macronimous.com/blog/wp-content/uploads/2025/06/Gemini-CLI-for-Laravel-Developers.png"><img decoding="async" width="1024" height="576" class="aligncenter size-large wp-image-4798" src="https://www.macronimous.com/blog/wp-content/uploads/2025/06/Gemini-CLI-for-Laravel-Developers-1024x576.png" alt="Gemini CLI for Laravel Developers" /></a>
<p>This is an exciting time for developers, and for a tech-focused people like us at <a href="https://www.macronimous.com/">Macronimous.com</a>, diving into new tools like Gemini CLI for <a href="https://www.macronimous.com/blog/php-frameworks-we-like-laravel/">Laraval development</a> is definitely a natural fit. Here&#8217;s a detailed blog post for Laravel developers on how Gemini CLI can revolutionize their workflow.</p>
<p>Let&#8217;s break down what Gemini CLI is, why it matters for Laravel developers, what you might miss if you don&#8217;t explore it, and how to get started.</p>
<h2><strong>What is Google Gemini CLI?</strong></h2>
<p>At its core, the <strong><a href="https://blog.google/technology/developers/introducing-gemini-cli-open-source-ai-agent/" target="_blank" rel="nofollow noopener">Gemini CLI</a> is an open-source <a href="https://www.macronimous.com/blog/the-code-your-ai-wants-to-delete-is-load-bearing/">AI</a> agent that allows you to interact with Google&#8217;s Gemini models directly from your terminal.</strong> Think of your command line as an AI-powered workspace. It&#8217;s designed to understand natural language prompts and leverage the advanced capabilities of <a href="https://aistudio.google.com/welcome?utm_source=google&amp;utm_medium=cpc&amp;utm_campaign=FY25-global-DR-gsem-BKWS-1710442&amp;utm_content=text-ad-none-any-DEV_c-CRE_750056871585-ADGP_Hybrid%20%7C%20BKWS%20-%20EXA%20%7C%20Txt-Products-Gemini%202.5-KWID_43700081931154840-kwd-2325346028141&amp;utm_term=KW_gemini%202.5-ST_gemini%202.5&amp;gad_source=1&amp;gad_campaignid=21896279268&amp;gbraid=0AAAAACn9t66ZVUWrAb0_ipz6jBfq4S40z&amp;gclid=Cj0KCQjw1JjDBhDjARIsABlM2StCbDM8CW_MbUxKq586FiixcNDZrWZuhH2jF-D2LQmApcZGOGTcVNcaAl1DEALw_wcB&amp;gclsrc=aw.ds" target="_blank" rel="nofollow noopener">Gemini 2.5 Pro</a> (which boasts an impressive 1 million token context window in the free tier) to perform a wide range of tasks.</p>
<p>Key capabilities include:</p>
<ul>
<li><strong>Code Understanding and Generation:</strong> Explain complex code snippets, draft new code, generate unit tests, suggest refactorings, and even help with migrating code.</li>
<li><strong>Debugging and Troubleshooting:</strong> Analyze error messages, pinpoint root causes, and suggest effective solutions for bugs.</li>
<li><strong>File and Project Management:</strong> Use natural language to navigate, summarize, and even modify files within your project structure.</li>
<li><strong>Command Execution:</strong> Translate plain English instructions into executable shell commands.</li>
<li><strong>Content Generation:</strong> Beyond code, it can assist with general<a href="https://www.macronimous.com/blog/ai-driven-unique-content/"> content creation</a>, problem-solving, and research, grounding prompts with real-time Google Search results.</li>
<li><strong>Extensibility:</strong> Being open-source <a href="https://www.apache.org/licenses/LICENSE-2.0" target="_blank" rel="nofollow noopener">(Apache 2.0 license</a>), it supports <a href="https://modelcontextprotocol.io/introduction" target="_blank" rel="nofollow noopener">Model Context Protocol</a> (<a href="https://www.macronimous.com/blog/building-a-wordpress-mcp-server-when-the-spec-changed/">MCP</a>) servers, allowing for custom tool integrations and extending its functionality.</li>
</ul>
<p>Essentially, Gemini CLI aims to be a versatile assistant that streamlines your development workflow, making you more productive without leaving the familiar environment of your terminal.</p>
<h3><strong>Is it Required for Laravel Developers to Learn and Use Gemini CLI?</strong></h3>
<p>&#8220;Required&#8221; is a strong word in software development, as many paths lead to a successful outcome. However, for <a href="https://www.macronimous.com/blog/simplify-laravel-development-with-gitpod-a-seamless-workflow-for-developers/">Laravel developers</a> aiming for peak efficiency and modern development practices, <strong>Gemini CLI is becoming increasingly valuable and highly recommended, though not strictly mandatory.</strong></p>
<p>Here&#8217;s why:</p>
<ol>
<li><strong>Complexity of Modern Laravel:</strong> Laravel applications, especially larger ones, can involve intricate logic, multiple packages, API integrations, and complex database interactions. Navigating and understanding these can be time-consuming.</li>
<li><strong>Increased Productivity:</strong> AI tools are no longer a luxury; they are becoming productivity multipliers. Gemini CLI can automate repetitive tasks, provide instant answers, and generate boilerplate code, freeing up developers to focus on more complex, creative problem-solving.</li>
<li><strong>Staying Competitive:</strong> As AI integration becomes more common, developers who can effectively leverage these tools will have a significant edge in terms of speed, quality, and adaptability.</li>
</ol>
<p>While you <em>can</em> develop Laravel applications perfectly well without it, embracing such tools pushes you towards a more efficient and less error-prone future.</p>
<h3><strong>What Would Laravel Developers Miss if They Don&#8217;t Use Gemini CLI?</strong></h3>
<p>Choosing to forgo Gemini CLI means missing out on several significant advantages:</p>
<ul>
<li><strong>Rapid Prototyping and Boilerplate Generation:</strong> Imagine instantly generating a Laravel Livewire component with basic<a href="https://www.geeksforgeeks.org/websites-apps/crud-full-form/" target="_blank" rel="nofollow noopener"> CRUD operations</a>, or a database migration script for a new feature, just by describing it in natural language. Without Gemini CLI, these are manual tasks.</li>
<li><strong>Accelerated Debugging:</strong> Instead of meticulously tracing stack traces, you could paste an error and get intelligent suggestions, potential fixes, and even context-aware code modifications. This drastically cuts down debugging time.</li>
<li><strong>Deep Codebase Understanding:</strong> For large or legacy Laravel projects, understanding how different services, controllers, models, and views interact can be daunting. Gemini CLI, with its large context window, can analyze your entire codebase and provide summaries, architectural overviews, or explain specific <a href="https://dev.to/boma/understanding-design-patterns-with-laravel-5dci" target="_blank" rel="nofollow noopener">Laravel patterns</a> used.</li>
<li><strong>Optimized Code &amp; Best Practices:</strong> You might miss opportunities for AI-driven code reviews that suggest <a href="https://www.macronimous.com/blog/web-performance-optimization-by-cleaning-up-unnecessary-javascript/">performance improvements</a>, adherence to Laravel conventions, or security enhancements.</li>
<li><strong>Reduced Context Switching:</strong> Staying in your terminal for AI assistance, rather than switching to a browser or other applications, maintains your flow state and improves focus.</li>
<li><strong>Enhanced Learning:</strong> For junior developers, or when learning new Laravel features or packages, Gemini CLI can act as an interactive tutor, explaining concepts, providing examples, and answering questions in real-time.</li>
<li><strong>Automated Documentation:</strong> Generating doc blocks for your Laravel classes, methods, or even entire modules can be automated, ensuring your codebase remains well-documented.</li>
</ul>
<p>In essence, you&#8217;d be missing out on a powerful assistant that can significantly reduce cognitive load and development cycles.</p>
<h3><strong>Why Gemini CLI is Not Necessary for Some Developers</strong></h3>
<p>Despite its immense benefits, Gemini CLI might not be a game-changer for everyone, or at least not immediately:</p>
<ul>
<li><strong>Smaller Projects or Solo Developers (Initial Stages):</strong> For very small, simple Laravel projects or developers who prefer a strictly manual approach, the initial setup and learning curve might seem like overkill.</li>
<li><strong>Highly Specialized Workflows:</strong> Developers with deeply ingrained, highly optimized, and unique manual workflows might find adopting a new AI tool disruptive, especially if their existing setup is already extremely efficient for their specific niche.</li>
<li><strong>Reliance on Specific IDE Features:</strong> Modern IDEs like PhpStorm already offer powerful code completion, refactoring, and debugging tools. Developers who heavily rely on these integrated features might not feel the immediate need for a CLI-based AI.</li>
<li><strong>Bandwidth/Internet Dependency:</strong> While the free tier is generous, heavy reliance on any cloud-based AI tool means you&#8217;re dependent on an internet connection and Google&#8217;s service availability.</li>
<li><strong>Privacy Concerns (for some):</strong> While Google has robust privacy policies, some developers or organizations might have strict internal policies against sending proprietary code to external AI services, even if the data handling is secure.</li>
<li><strong>&#8220;Human in the Loop&#8221; Preference:</strong> Some developers simply prefer to understand and write every line of code themselves, meticulously, and might view AI generation as a shortcut that reduces their hands-on understanding.</li>
</ul>
<p>For these developers, the traditional Laravel development workflow remains perfectly viable. However, the capabilities offered by Gemini CLI are rapidly becoming a standard expectation for developer productivity.</p>
<h3><strong>How to Start Using Gemini CLI for Laravel Development</strong></h3>
<p>If you&#8217;re a Laravel developer ready to harness the power of Gemini CLI, getting started is straightforward.</p>
<ol>
<li><strong> Prerequisites:</strong></li>
</ol>
<ul>
<li><strong>Node.js (Version 18 or higher):</strong> Gemini CLI runs on Node.js. Ensure you have a recent version installed. You can check with <em>node -v.</em></li>
<li><strong>Google Account:</strong> You&#8217;ll need a personal Google account for authentication. This grants you free-tier access with generous quotas (60 requests/minute and 1,000 requests/day for Gemini 2.5 Pro). For higher limits or specific models, you can use a Google AI Studio API key.</li>
</ul>
<ol start="2">
<li><strong> Installation:</strong></li>
</ol>
<p>Open your terminal and choose one of the following installation methods:</p>
<ul>
<li><strong>Run Directly (npx):</strong> This is great for quick tests or if you don&#8217;t want a global installation.</li>
</ul>
<p>Bash</p><pre class="urvanov-syntax-highlighter-plain-tag">npx https://github.com/google-gemini/gemini-cli</pre><p></p>
<ul>
<li><strong>Global Installation (Recommended for regular use):</strong> This installs gemini as a command accessible anywhere.</li>
</ul>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">npm install -g @google/gemini-cli</pre><p></p>
<ol start="3">
<li><strong> First Run and Authentication:</strong></li>
</ol>
<p>After installation, simply type gemini in your terminal:</p><pre class="urvanov-syntax-highlighter-plain-tag">gemini</pre><p>On the first run, you&#8217;ll be prompted to:</p>
<ul>
<li><strong>Choose a color theme:</strong> Select your preferred look.</li>
<li><strong>Authenticate:</strong> Select &#8220;Login with Google&#8221; and follow the browser prompts to sign in with your Google account. This securely links your terminal to Gemini&#8217;s AI capabilities.</li>
</ul>
<ol start="4">
<li><strong> Start Prompting!</strong></li>
</ol>
<p>Once authenticated, you&#8217;ll see the gemini &gt; prompt. Now you can start interacting!</p>
<p><strong>Examples for Laravel Developers:</strong></p>
<ul>
<li><strong>Explain Laravel Code:</strong></li>
</ul>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">gemini &gt; Explain this Laravel controller method: @app/Http/Controllers/UserController.php:store</pre><p>(Use @ to reference files/folders. Gemini CLI will often auto-complete paths).</p>
<ul>
<li><strong>Generate a Model &amp; Migration:</strong></li>
</ul>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">gemini &gt; Write a Laravel migration for a `products` table with columns: name (string, unique), description (text, nullable), price (decimal), stock (integer, default 0). Also, create a Product model with fillable properties.</pre><p></p>
<ul>
<li><strong>Debug a PHP Error:</strong></li>
</ul>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">gemini &gt; I'm getting a `Target class [App\Services\PaymentService] does not exist.` error in my Laravel application. Here's my controller: @app/Http/Controllers/OrderController.php. What's wrong?</pre><p></p>
<ul>
<li><strong>Generate a Blade Component:</strong></li>
</ul>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">gemini &gt; Create a simple Blade component for displaying a success alert message. It should accept a `$message` prop.</pre><p></p>
<ul>
<li><strong>Refactor Code:</strong></li>
</ul>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">gemini &gt; Refactor this PHP code to use a more modern Laravel approach: @app/Helpers/OldHelper.php</pre><p></p>
<ul>
<li><strong>Summarize a Project Folder:</strong></li>
</ul>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">gemini &gt; Give me a summary of the `app/Models` directory and the relationships between the models.</pre><p>&nbsp;</p>
<h3><strong>Tips for Effective Usage:</strong></h3>
<ul>
<li><strong>Be Specific:</strong> The more context and detail you provide in your prompt, the better the output.</li>
<li><strong>Use </strong><strong>@</strong><strong> for Context:</strong> Leverage the @ symbol to include specific files, directories, or even parts of files in your prompt&#8217;s context.</li>
<li><strong>Review and Refine:</strong> AI-generated code is a starting point, not always a final solution. Always review, test, and refine the output to fit your exact needs and project standards.</li>
<li><strong>Explore Commands:</strong> Type /help within the Gemini CLI to see a list of available commands and shortcuts.</li>
</ul>
<h4><strong>Conclusion</strong></h4>
<p>Google Gemini CLI is a powerful addition to the developer ecosystem, offering Laravel developers an intelligent co-pilot directly in their terminal. While not strictly &#8220;required,&#8221; embracing such AI-powered tools can significantly boost productivity, enhance code quality, and make the development process more enjoyable. For a <a href="https://www.macronimous.com/services/web-development/">web</a> and <a href="https://www.macronimous.com/services/mobile-development/">mobile development</a> business like Macronimous.com, integrating tools like Gemini CLI can translate directly into faster delivery, higher quality, and a more competitive edge in the market.</p>
<p>Start experimenting today, and unlock a new dimension of efficiency in your Laravel development journey!</p>
<p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://www.macronimous.com/blog/google-gemini-cli-for-laraval-development/">Google Gemini CLI for Laraval development: Your New AI Co-Pilot in PHP programming</a> first appeared on <a rel="nofollow" href="https://www.macronimous.com/blog">Macronimous Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.macronimous.com/blog/google-gemini-cli-for-laraval-development/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
