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.
Генерация схем инструментов из кода. Один из самых быстрых способов создать проблемы — это написание JSON-схем для параметров инструментов вручную, что приводит к их рассинхронизации с реальной логикой валидации. PHP обладает мощными возможностями рефлексии. Анализируйте сигнатуры методов, считывайте существующие правила валидации из ваших форм или объектов команд и генерируйте схему на основе этих ограничений. Если ваш внутренний код требует корректный формат email, ваша MCP-схема должна требовать того же самого. Когда правила валидации меняются, схема обновляется автоматически. Никакого рассинхрона, никаких скрытых ошибок.
Разделяйте ошибки протокола и ошибки инструментов. У JSON-RPC есть свое пространство ошибок. Используйте его для нарушений протокола: некорректного JSON, неизвестных методов или отсутствующих ID запросов. Если инструмент выполняется правильно, но сталкивается с бизнес-проблемой, возвращайте обычный результат с флагом ошибки внутри полезной нагрузки. Если инструмент поиска клиента не находит подходящую запись, это не сбой протокола. Возврат структурированного результата, такого как {"found": false}, позволяет модели понять, что произошло, и выбрать следующий шаг. Она может попытаться выполнить более широкий поиск или попросить пользователя уточнить данные. Если же вы выбросите ошибку JSON-RPC, модель часто теряет контекст.
Планируйте длительные задачи. PHP создан для коротких запросов. Веб-запрос может прерваться по таймауту через тридцать секунд, а даже CLI-скрипты могут исчерпать память или терпение. Если инструменту требуются минуты для завершения — например, для составления большого отчета или синхронизации данных между системами — не заставляйте модель ждать. Немедленно верните идентификатор задачи. Затем предоставьте второй инструмент для проверки статуса по этому ID. Вы можете хранить прогресс в Redis, в таблице базы данных или даже в обычном файле, если объем данных невелик. Модель получает ID, проверяет статус позже и в итоге забирает готовый результат.
Безопасность, когда у модели есть ключи
Предоставление ИИ-модели доступа к инструменту — это не то же самое, что предоставление доступа человеку. Модель действует быстро, в буквальном смысле, и может неверно истолковать описания. Относитесь к каждому открытому инструменту как к риску повышения привилегий.
Агрессивно ограничивайте область действия. Никогда не открывайте универсальный инструмент run_sql. Создавайте специфические, узконаправленные инструменты, такие как find_customer_by_email или update_order_status. Модель должна иметь возможность делать только то, что вы указали, с параметрами, которые вы определили.
Разделяйте пути чтения и записи. Инструменты только для чтения несут меньший риск. Любое деструктивное действие должно быть защищено механизмом явного подтверждения или полностью вынесено на отдельный сервер. Если ваш клиент поддерживает это, требуйте подтверждения человеком перед выполнением инструмента записи.
Пишите описания инструментов так, будто это дополнительные инструкции, потому что так оно и есть. Четко указывайте, когда модель должна вызывать инструмент. Если инструмент запрашивает цены, скажите об этом. Если его следует использовать только после проверки ID клиента, заявите об этом прямо. Расплывчатые описания ведут к расплывчатому поведению.
Фильтруйте вывод. Не сериализуйте целиком модель Eloquent или сущность Doctrine и не вываливайте её в результат. Возвращайте только те поля, которые действительно нужны модели. Внутренние поля — закупочные цены, заметки сотрудников, ID базы данных, которые должны оставаться внутри — не должны передаваться по сети. Четко определяйте структуру возвращаемых данных.
Наконец, логируйте всё. Записывайте название инструмента, переданные аргументы и результат. Если модель начнет зацикливаться на дорогостоящем запросе или проверять инструменты в неожиданном порядке, логи — единственный способ это заметить.
С чего начать
Вам не нужно разрешение от мейнтейнера SDK, чтобы подключить ваше PHP-приложение к ИИ-ассистенту. Вам нужны JSON-RPC, цикл и некоторая дисциплина в работе со stdout.
Не поддавайтесь желанию перестроить весь свой API в MCP-инструменты с первого же дня. Выберите три операции только для чтения, о которых в вашей организации спрашивают чаще всего. Возможно, это проверка статуса заказа, получение сводки по клиенту или список последних счетов. Оберните их в инструменты, предоставьте через stdio и дайте использовать их одному коллеге. Наблюдайте, с чем модель справляется хорошо, а где спотыкается. Вы узнаете больше от этих трех инструментов, чем от планирования тридцати.
MCP — это мост, а не замена вашему приложению. Ваш PHP-код уже знает ваш бизнес. Протокол просто позволяет модели перейти на ту сторону и задавать вопросы.
