Якщо ви роками підтримували бізнес-логіку всередині PHP-додатків, перегляд туторіалів з Model Context Protocol може здатися спробою зазирнути за зачинені двері. Майже кожен посібник передбачає використання TypeScript або Python. У них описують офіційні SDK, встановлення через npm та pip-пакети. Це залишає величезну кількість бізнес-даних — записи клієнтів, історію замовлень, системи інвентаризації — у PHP-кодобазах, які здаються невидимими для поточної хвилі інструментів ШІ.

Гарна новина полягає в тому, що для MCP не потрібні ці SDK. MCP — це не бібліотека. Це протокол передачі даних (wire protocol). Якщо ваше середовище виконання (runtime) може зчитувати рядок тексту зі стандартного вводу, парсити JSON і записувати JSON назад, воно може спілкуватися за цим протоколом. PHP робить саме це ще задовго до появи LLM.

Що насправді являє собою MCP

MCP розшифровується як Model Context Protocol. За своєю суттю це відкритий стандарт для підключення ШІ-асистентів до даних, інструментів та зовнішніх API. Замість того, щоб створювати кастомну інтеграцію для кожного асистента чи моделі, ви створюєте один відповідний стандарту інтерфейс. Будь-який клієнт, який розуміє MCP, зможе спілкуватися з вашим сервером, не знаючи нічого про PHP, Laravel чи вашу конкретну схему бази даних.

Під капотом MCP використовує JSON-RPC 2.0. Це означає, що кожен запит — це простий JSON-об'єкт, що містить назву методу, параметри та ID. Сервер відповідає іншим JSON-об'єктом, який містить або результат, або помилку.

Сервер надає три примітиви:

  • Інструменти (Tools): Дії, які може викликати модель. Інструмент може робити запит до бази даних, оновлювати статус або викликати сторонній API.
  • Ресурси (Resources): Статичні або напівстатичні дані, на які модель може посилатися через URI. Думайте про файли, конфігураційні документи або довідкові набори даних.
  • Промпти (Prompts): Попередньо визначені шаблони, які допомагають користувачеві взаємодіяти з системою.

Важливо пам'ятати про різницю в управлінні. Інструменти контролюються моделлю. Асистент сам вирішує, коли їх викликати. Ресурси контролюються додатком. Сервер вирішує, які дані доступні, а модель просто читає те, що їй пропонують. Правильне розмежування цих понять робить вашу архітектуру передбачуваною. Ви ж не хочете, щоб модель шукала ресурси, які мали б бути інструментами, або навпаки.

Як працює транспорт

MCP визначає два методи транспортування, і ваш вибір вплине на те, як ви будете писати PHP-частину.

stdio — найпростіший варіант. MCP-клієнт запускає ваш PHP-скрипт як підпроцес. Клієнт записує повідомлення JSON-RPC у стандартний ввід (stdin) вашого скрипта, а ваш скрипт записує відповіді у стандартний вивід (stdout). Тут немає сокетів, які потрібно керувати, портів, які потрібно відкривати, або заголовків автентифікації, які потрібно парсити. Якщо ваш інструмент і клієнт знаходяться на одній машині, це зазвичай найкращий варіант для старту.

Робота через stdio накладає два суворі правила на ваш PHP-процес. По-перше, ваш додаток ніколи не повинен записувати дані, що не належать до протоколу, у stdout. Якщо ви виведете через echo налагоджувальне повідомлення або дозволите PHP-попередженню (notice) просочитися у вивід, ви зламаєте парсер клієнта. Перенаправте все логування та діагностику у stderr. По-друге, повністю вимкніть буферизацію виводу. PHP любить буферизувати stdout, особливо в контекстах CGI або веб-запитів, але навіть CLI-скрипти можуть утримувати дані. Очищуйте (flush) кожну відповідь негайно. Якщо ви використовуєте потоки, встановіть stream_set_write_buffer(STDOUT, 0) або вимкніть неявну буферизацію, щоб клієнт отримав символ нового рядка миттєво після вашої відправки.

Streamable HTTP працює інакше. Ваш PHP-додаток працює як постійна HTTP-точка входу (endpoint), до якої зазвичай звертаються через POST-запити. Це корисно, коли сервер знаходиться на іншому хості або коли ви хочете створити довготривалий демон, до якого зможуть звертатися кілька клієнтів. У PHP це зазвичай означає запуск під керуванням RoadRunner, FrankenPHP або подібного менеджера процесів, а не використання традиційного циклу запит-відповідь, який завершується після кожного виклику.

Створення на PHP

Для старту вам не потрібен фреймворк. Мінімальний MCP-сервер на PHP — це цикл, який зчитує дані зі STDIN, декодує JSON, передає їх обробнику та кодує результат.

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

Всередині цього циклу справжня робота полягає у створенні інтерфейсів, які будуть зрозумілими для моделі.

Generate tool schemas from code. One of the fastest ways to cause trouble is hand-writing JSON Schemas for your tool parameters and letting them drift out of sync with your actual validation logic. PHP has rich reflection capabilities. Inspect your method signatures, read existing validation rules from your forms or command objects, and generate the schema from those constraints. If your internal code requires a valid email format, your MCP schema should say the same thing. When validation rules change, the schema updates automatically. No drift, no silent failures.

Separate protocol errors from tool errors. JSON-RPC has its own error space. Use it for broken protocol: malformed JSON, unknown methods, or missing request IDs. When a tool executes correctly but encounters a business problem, return a normal result with an error flag inside the payload. If a customer lookup tool finds no matching record, that is not a protocol crash. Returning a structured result like {"found": false} lets the model understand what happened and choose the next step. It might try a broader search, or it might ask the user for clarification. If you throw a JSON-RPC error instead, the model often loses context.

Plan for long-running work. PHP is built for short requests. A web request might time out in thirty seconds, and even CLI scripts can exhaust memory or patience. If a tool needs minutes to finish—perhaps it compiles a large report or syncs data across systems—do not make the model wait. Return a job identifier immediately. Then expose a second tool for checking status by that ID. You can store progress in Redis, a database table, or even a flat file if the volume is low. The model receives the ID, checks back later, and eventually picks up the completed result.

Security When the Model Has Keys

Giving an AI model access to a tool is not like giving it to a human user. A model acts fast, literally, and it can misinterpret descriptions. Treat every exposed tool as a privilege escalation risk.

Limit scope aggressively. Never expose a generic run_sql tool. Build specific, narrow tools like find_customer_by_email or update_order_status. The model should only be able to do exactly what you name, with parameters you have defined.

Separate read and write paths. Read-only tools carry lower risk. Put any destructive action behind an explicit confirmation mechanism, or restrict it to a second server entirely. If your client supports it, require a human approval step before a write tool executes.

Write tool descriptions as if they are additional instructions, because they are. Be precise about when the model should call a tool. If a tool looks up pricing, say so. If it should only be used after verifying the customer ID, state that clearly. Vague descriptions lead to vague behavior.

Filter your output. Do not serialize an entire Eloquent model or Doctrine entity and dump it into the result. Return only the fields the model actually needs. Internal fields—cost prices, employee notes, database IDs that should stay internal—have no business crossing the wire. Be explicit about your return shape.

Finally, log everything. Record the tool name, the arguments passed, and the outcome. If a model starts looping on an expensive query or probing tools in an unexpected order, your logs are the only way you will see it.

Where to Start

You do not need permission from an SDK maintainer to connect your PHP application to an AI assistant. You need JSON-RPC, a loop, and some discipline around stdout.

Resist the urge to rebuild your entire API as MCP tools on day one. Pick three read-only operations that someone in your organization actually asks about repeatedly. Maybe it is checking an order status, pulling a customer summary, or listing recent invoices. Wrap those as tools, serve them over stdio, and let one colleague use them. Watch what the model does well and where it stumbles. You will learn more from those three tools than you will from planning thirty.

MCP is a bridge, not a replacement for your application. Your PHP code already knows your business. The protocol just lets the model cross over and ask it questions.