If you have spent years maintaining business logic inside PHP applications, watching Model Context Protocol tutorials can feel like standing outside a locked door. Nearly every guide assumes TypeScript or Python. They walk through official SDKs, npm installs, and pip packages. That leaves an enormous amount of business data—customer records, order histories, inventory systems—sitting in PHP codebases that look invisible to the current wave of AI tooling.

The good news is that nothing about MCP requires those SDKs. MCP is not a library. It is a wire protocol. If your runtime can read a line of text from standard input, parse JSON, and write JSON back out, it can speak the protocol. PHP has been doing exactly that since long before LLMs existed.

What MCP Actually Is

MCP stands for Model Context Protocol. At its core, it is an open standard for connecting AI assistants to data, tools, and external APIs. Instead of building a custom integration for every assistant or model, you build one compliant interface. Any client that understands MCP can then talk to your server without knowing anything about PHP, Laravel, or your specific database schema.

Underneath, MCP uses JSON-RPC 2.0. That means every request is a simple JSON object containing a method name, parameters, and an ID. The server responds with another JSON object carrying either a result or an error.

A server exposes three primitives:

  • Tools: Actions the model can invoke. A tool might query a database, update a status, or call a third-party API.
  • Resources: Static or semi-static data the model can reference through a URI. Think of files, configuration documents, or reference datasets.
  • Prompts: Predefined templates that help the user interact with the system.

There is an important control distinction to remember. Tools are model-controlled. The assistant decides when to call one. Resources are application-controlled. The server decides what data is available and the model simply reads what is offered. Getting this right keeps your architecture predictable. You do not want a model hunting for resources that should have been tools, or vice versa.

How the Transport Works

MCP defines two transport methods, and your choice shapes how you write the PHP side.

stdio is the simplest. The MCP client launches your PHP script as a subprocess. The client writes JSON-RPC messages to your script’s standard input, and your script writes responses to standard output. There are no sockets to manage, no ports to open, and no authentication headers to parse. If your tool and your client live on the same machine, this is usually the right place to start.

Running over stdio imposes two strict rules on your PHP process. First, your application must never write non-protocol data to stdout. If you echo a debug statement or let a PHP notice leak through, you will break the client’s parser. Route all logging and diagnostics to stderr. Second, disable output buffering entirely. PHP likes to buffer stdout, especially in CGI or web contexts, but even CLI scripts can hold data. Flush every response immediately. If you are using streams, set stream_set_write_buffer(STDOUT, 0) or turn off implicit buffering so the client receives the newline the instant you send it.

Streamable HTTP works differently. Your PHP application runs as a persistent HTTP endpoint, usually reached via POST requests. This is useful when the server lives on a different host, or when you want a long-running daemon that multiple clients can reach. In PHP, this typically means running under RoadRunner, FrankenPHP, or a similar process manager rather than the traditional request-response cycle that dies after every call.

Building It in PHP

You do not need a framework to start. A minimal MCP server in PHP is a loop reading from STDIN, decoding JSON, dispatching to a handler, and encoding the result.

while ($line = fgets(STDIN)) {
    $request = json_decode($line, true);
    // route to tool or resource handler
    // write JSON-RPC response to STDOUT
}

Inside that loop, the real work is building interfaces that make sense to a model.

Genereer tool-schema's vanuit code. Een van de snelste manieren om problemen te veroorzaken, is het handmatig schrijven van JSON-schema's voor je tool-parameters, waardoor ze uit de pas gaan lopen met je werkelijke validatielogica. PHP heeft uitgebreide reflectie-mogelijkheden. Inspecteer je methodesignaturen, lees bestaande validatieregels uit je formulieren of command-objecten en genereer het schema op basis van die beperkingen. Als je interne code een geldig e-mailformaat vereist, moet je MCP-schema hetzelfde aangeven. Wanneer validatieregels veranderen, wordt het schema automatisch bijgewerkt. Geen afwijkingen, geen stille fouten.

Scheid protocolfouten van toolfouten. JSON-RPC heeft zijn eigen foutruimte. Gebruik deze voor een defect protocol: ongeldige JSON, onbekende methoden of ontbrekende request-ID's. Wanneer een tool correct wordt uitgevoerd maar een zakelijk probleem tegenkomt, retourneer dan een normaal resultaat met een error-vlag in de payload. Als een tool voor klantopzoeking geen overeenkomend record vindt, is dat geen protocolcrash. Het retourneren van een gestructureerd resultaat zoals {"found": false} zorgt ervoor dat het model begrijpt wat er is gebeurd en de volgende stap kan kiezen. Het kan een bredere zoekopdracht proberen of de gebruiker om verduidelijking vragen. Als je in plaats daarvan een JSON-RPC-fout gooit, verliest het model vaak de context.

Plan voor langlopende taken. PHP is gebouwd voor korte verzoeken. Een webverzoek kan na dertig seconden een timeout geven, en zelfs CLI-scripts kunnen het geheugen of het geduld uitputten. Als een tool er minuten over doet om klaar te zijn — bijvoorbeeld omdat het een groot rapport compileert of gegevens tussen systemen synchroniseert — laat het model dan niet wachten. Retourneer onmiddellijk een job-identifier. Stel vervolgens een tweede tool beschikbaar om de status via die ID te controleren. Je kunt de voortgang opslaan in Redis, een database-tabel of zelfs een plat bestand als het volume laag is. Het model ontvangt de ID, komt later terug en haalt uiteindelijk het voltooide resultaat op.

Beveiliging wanneer het model sleutels heeft

Een AI-model toegang geven tot een tool is niet hetzelfde als toegang geven aan een menselijke gebruiker. Een model handelt snel, letterlijk, en kan beschrijvingen verkeerd interpreteren. Behandel elke blootgestelde tool als een risico op privilege escalation.

Beperk de scope agressief. Stel nooit een generieke run_sql-tool bloot. Bouw specifieke, nauwe tools zoals find_customer_by_email of update_order_status. Het model moet alleen precies kunnen doen wat je benoemt, met de parameters die je hebt gedefinieerd.

Scheid lees- en schrijfpaden. Read-only tools brengen een lager risico met zich mee. Plaats elke destructieve actie achter een expliciet bevestigingsmechanisme, of beperk deze volledig tot een tweede server. Als je client het ondersteunt, vereis dan een menselijke goedkeuringsstap voordat een write-tool wordt uitgevoerd.

Schrijf tool-beschrijvingen alsof het extra instructies zijn, want dat zijn ze ook. Wees nauwkeurig over wanneer het model een tool moet aanroepen. Als een tool prijzen opzoekt, zeg dat dan. Als het alleen gebruikt mag worden na het verifiëren van het klant-ID, vermeld dat dan duidelijk. Vage beschrijvingen leiden tot vaag gedrag.

Filter je output. Serialiseer niet een heel Eloquent-model of een Doctrine-entity en dump dit in het resultaat. Retourneer alleen de velden die het model daadwerkelijk nodig heeft. Interne velden — inkoopprijzen, notities van medewerkers, database-ID's die intern moeten blijven — horen niet over de lijn te gaan. Wees expliciet over de vorm van je retourwaarde.

Log tot slot alles. Registreer de naam van de tool, de meegegeven argumenten en de uitkomst. Als een model in een loop terechtkomt bij een dure query of tools op een onverwachte volgorde verkent, zijn je logs de enige manier om dit te zien.

Waar te beginnen

Je hebt geen toestemming nodig van een SDK-onderhouder om je PHP-applicatie te verbinden met een AI-assistent. Je hebt JSON-RPC nodig, een loop en wat discipline rondom stdout.

Weersta de drang om op dag één je hele API te herbouwen als MCP-tools. Kies drie read-only operaties waar iemand in je organisatie daadwerkelijk herhaaldelijk naar vraagt. Misschien is het het controleren van een bestelstatus, het ophalen van een klantoverzicht of het op een rij zetten van recente facturen. Verpak deze als tools, serveer ze via stdio en laat een collega ze gebruiken. Kijk wat het model goed doet en waar het struikelt. Je zult meer leren van die drie tools dan van het plannen van dertig.

MCP is een brug, geen vervanging voor je applicatie. Je PHP-code kent je business al. Het protocol zorgt er alleen voor dat het model kan oversteken en vragen kan stellen.