eMCP — інтеграційний шар Evolution CMS для laravel/mcp.
Пакет адаптує Laravel MCP під runtime Evo:
- Evo-native publish конфігів
- доступ через manager ACL і sApi scopes
- опційне async виконання через sTask
- без залежності від Laravel app skeleton
- Evo domain MCP tools для дерева документів (
SiteContent+ TVs)
Реалізація стартує з жорсткого MVP gate:
- web transport
- manager mode
initialize+tools/list
Стиль дизайну:
- contract-first (
TOOLSET.md+ валідатори) - декларативний config-first реєстр серверів (
config/mcp.php) - явний handler pipeline (
validate -> authorize -> query -> map -> paginate)
Повний технічний опис: DOCS.uk.md (UA) і DOCS.md (EN).
Канонічний публічний tool contract: TOOLSET.md.
Versioning і BC policy: PRD.md (розділ API Stability Policy).
Операційний runbook: OPERATIONS.md.
- Evolution CMS 3.5.2+
- PHP 8.3+
- Composer 2.2+
seiger/sapi1.x (встановлюється як залежність)seiger/stask1.x (встановлюється як залежність)
З директорії core вашого Evo:
cd core
php artisan package:installrequire evolution-cms/emcp "*"
php artisan migratephp artisan vendor:publish --provider="EvolutionCMS\\eMCP\\eMCPServiceProvider" --tag=emcp-config
php artisan vendor:publish --provider="EvolutionCMS\\eMCP\\eMCPServiceProvider" --tag=emcp-mcp-config
php artisan vendor:publish --provider="EvolutionCMS\\eMCP\\eMCPServiceProvider" --tag=emcp-stubsПісля publish:
core/custom/config/cms/settings/eMCP.phpcore/custom/config/mcp.phpcore/stubs/mcp-*.stub
Базовий контракт нейтральний до конкретної концепції і спирається спочатку на стандартний Laravel MCP.
- Створи класи MCP server/tool:
php artisan make:mcp-server ContentServer
php artisan make:mcp-tool HealthToolЗгенеровані класи створюються у core/custom/app/Mcp/....
- Зареєструй сервер у
core/custom/config/mcp.php(servers[]). - Перевір manager/internal route:
POST /{manager_prefix}/{handle}з manager-сесією і permissionemcp.
- Увімкни зовнішній API режим (якщо встановлено
sApi):
- залиш
mode.api=trueуcore/custom/config/cms/settings/eMCP.php - викликай
POST /{SAPI_BASE_PATH}/{SAPI_VERSION}/mcp/{handle}з Bearer JWT і потрібнимиmcp:*scopes. - JWT можна отримати через
POST /{SAPI_BASE_PATH}/{SAPI_VERSION}/token(sApi token endpoint).
- Опційний async:
- встанови
queue.driver=stask, перевір наявністьsTask, використовуй dispatch endpoint для довгих задач.
Це короткий спосіб зрозуміти eMCP як продукт, а не просто набір файлів.
- Матеріальна причина: з чого воно складається (жорсткі межі):
- protocol/runtime від
laravel/mcp - Evo adapter layer (
ServiceProvider, registry, routes, middleware, publish) - опційні інтеграції доступу та async (
sApi,sTask) - канонічні контракти (
SPEC.md,TOOLSET.md)
- Формальна причина: яка форма робить це продуктом (а не компонентами):
- єдиний execution contract від запиту до аудованої відповіді
- єдина policy-модель доступу manager/API (
ACL + scopes + limits) - версійований публічний tool contract для споживачів екосистеми
- стабільна extension-модель для сторонніх пакетів
- Рушійна причина: що приводить систему в рух (workflow + triggers):
- внутрішній тригер: manager MCP виклик (
/{manager_prefix}/{handle}) - зовнішній тригер: API MCP виклик (
/{SAPI_BASE_PATH}/{SAPI_VERSION}/mcp/{handle}) - async тригер: dispatch у воркер
sTaskдля довгих операцій - життєвий тригер: install/publish/register/test
- Цільова причина: заради чого це зроблено саме так:
- зберегти семантику Laravel MCP без розривів
- зробити інтеграцію з Evo явною та операційно простою
- підтримати внутрішнє і зовнішнє використання MCP одночасно
- дати нейтральний фундамент для різних orchestration-концепцій поверх eMCP
- теорія множин: CMS-дані моделюються як ієрархія множин (site -> nodes -> attributes)
- Пеано/індукція: workflow моделюється як послідовність станів і переходів
- межі Геделя: самореферентні rule-системи потребують жорстких меж між runtime і meta-level
Практичний висновок:
- eMCP лишається contract/runtime шаром
- orchestration-логіка виноситься у пакети-споживачі
- policy/audit/human-gate запобігають небезпечним рекурсивним петлям
Для Gate A використовуй manager endpoint /{manager_prefix}/{server_handle} (за замовчуванням: /emcp/content).
Gate A захищений manager ACL, тому перевірка виконується з manager-сесією користувача, який має permission emcp.
- Перевірити, що
GETна MCP endpoint повертає405:
curl -i -X GET http://localhost/<MANAGER_PREFIX>/<SERVER_HANDLE> \
-H 'Cookie: evo_session=<MANAGER_SESSION_COOKIE>'- Перевірити
initializeJSON-RPC:
curl -i -X POST http://localhost/<MANAGER_PREFIX>/<SERVER_HANDLE> \
-H 'Cookie: evo_session=<MANAGER_SESSION_COOKIE>' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":"init-1","method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"smoke","version":"1.0.0"}}}'Очікування:
- HTTP
200для валідногоinitialize. - У відповіді присутній
MCP-Session-Id. - На
GETстабільно повертається405.
На відміну від стандартного routes/ai.php у Laravel, в eMCP сервери реєструються з конфігу.
Приклад core/custom/config/mcp.php:
return [
'redirect_domains' => ['*'],
'servers' => [
[
'handle' => 'content',
'transport' => 'web',
'route' => '/mcp/content',
'class' => EvolutionCMS\eMCP\Servers\ContentServer::class,
'enabled' => true,
'auth' => 'sapi_jwt',
'scopes' => ['mcp:read', 'mcp:call'],
],
[
'handle' => 'content-local',
'transport' => 'local',
'class' => EvolutionCMS\eMCP\Servers\ContentServer::class,
'enabled' => false,
],
],
];Нотатки:
- У Gate A manager endpoint лишається
/{manager_prefix}/{handle}(наприклад/emcp/content). servers[*].routeвикористовується при реєстрації web transport і стає зовнішньо релевантним у API mode (Gate B+).content-localза замовчуванням вимкнений, щоб уникнути конфлікту дубльованих tool names зcontent.
- Внутрішній доступ (manager): permission
emcp - API доступ (через sApi): JWT scopes (
mcp:read,mcp:call,mcp:admin) - Domain read tools (
evo.content.*,evo.model.*) за замовчуванням read-only
eMCP є MCP platform layer для екосистеми Evo:
LaravelMcp: upstream протокол/рантайм (зберігаємо як є).sApi: зовнішній API kernel + JWT + route-provider discovery.sTask: async виконання через worker/task модель і прогрес.eAi: AI runtime може викликати MCP tools через manager або API режим.dAi: manager-side orchestration UI споживає eMCP tools як стабільний контракт.
Це дає нейтральну декларативну основу: один MCP фундамент для різних orchestration-концепцій.
- Реалізовано зараз:
evo.content.search|get|root_tree|descendants|ancestors|children|siblings - Опційні (вже реалізовані):
evo.content.neighbors|prev_siblings|next_siblings|children_range|siblings_range - TV-aware запити через структуровані
with_tvs,tv_filters,tv_order evo.model.list|getреалізовано з явним per-model allowlist projection і додатковим sensitive blacklist захистом
Команди з Laravel MCP (через eMCP adapter):
php artisan make:mcp-server ContentServer
php artisan make:mcp-tool ListResourcesTool
php artisan make:mcp-resource DocsResource
php artisan make:mcp-prompt SummaryPrompt
php artisan mcp:start content-localДля mcp:start content-local спочатку увімкни content-local у core/custom/config/mcp.php і вимкни конфліктні сервери, якщо вони мають однакові tool names.
Операційні команди eMCP:
php artisan emcp:testphp artisan emcp:list-serversphp artisan emcp:sync-workerscomposer run governance:update-lockcomposer run ci:checkcomposer run benchmark:runcomposer run benchmark:leaderboardcomposer run test:integration:clean-install
Якщо перевіряєш цей репозиторій напряму:
composer run check
make test
composer run ci:check
make benchmark
make leaderboardЦі перевірки валідовують composer.json і виконують PHP syntax lint по всіх файлах пакета.
One-click демо + повна MCP перевірка:
make demo-allЦя ціль встановлює demo Evo, запускає php -S, видає sApi JWT, виконує php artisan emcp:test, а потім composer run test з увімкненою HTTP runtime integration перевіркою.
Після виконання детальні докази записуються у:
demo/logs.md(masked token, MCP payload-и, HTTP статуси, відповіді, manual verification команди, а також negative probes: 401/403/413/415/409/429 і sanity check дляevo.model.get(User))demo/logs.mdтакож містить локальний proof для lifecyclesTask(queued -> completed) черезphp artisan stask:workerу demo runtime./tmp/emcp-demo-php-server.log(лог PHP built-in server)
Якщо під час інсталяції потрібна GitHub авторизація API, передай токен через ENV (як у evolution):
GITHUB_PAT=ghp_xxx make demo-allТакож підтримуються GITHUB_TOKEN і GH_TOKEN.
Ручні приклади MCP читання content (ті самі виклики, що пишуться у demo/logs.md):
# список tools
curl -sS -H 'Content-Type: application/json' -H 'Authorization: Bearer <TOKEN>' \
-d '{"jsonrpc":"2.0","id":"tools-1","method":"tools/list","params":{}}' \
'http://127.0.0.1:8787/api/v1/mcp/content'
# читання content з БД
curl -sS -H 'Content-Type: application/json' -H 'Authorization: Bearer <TOKEN>' \
-d '{"jsonrpc":"2.0","id":"search-1","method":"tools/call","params":{"name":"evo.content.search","arguments":{"limit":3,"offset":0}}}' \
'http://127.0.0.1:8787/api/v1/mcp/content'
# читання одного документа
curl -sS -H 'Content-Type: application/json' -H 'Authorization: Bearer <TOKEN>' \
-d '{"jsonrpc":"2.0","id":"get-1","method":"tools/call","params":{"name":"evo.content.get","arguments":{"id":1}}}' \
'http://127.0.0.1:8787/api/v1/mcp/content'Опційна runtime integration перевірка (проти розгорнутого середовища):
EMCP_INTEGRATION_ENABLED=1 \
EMCP_BASE_URL="https://example.org" \
EMCP_API_PATH="/api/v1/mcp/{server}" \
EMCP_API_TOKEN="<jwt>" \
EMCP_SERVER_HANDLE="content" \
EMCP_DISPATCH_CHECK=1 \
composer run test:integration:runtimeCI release примітка:
.github/workflows/ci.ymlзапускаєdemo-runtime-proof,runtime-integrationіmigration-matrix(sqlite/mysql/pgsql) на push уrelease/*.- Для RC/release merge треба увімкнути branch protection і позначити ці jobs як required checks.
Якщо queue.driver=stask і sTask встановлений, довгі MCP виклики виконуються через воркер emcp_dispatch.
Якщо sTask відсутній — fallback визначається queue.failover (sync або fail).
- Зберігайте секрети у
.envабоcore/custom/config/*. - Аудит-логи мають маскувати токени/секрети.
- Для production увімкніть allowlist серверів і denylist tools.
- deny-by-default для manager/API без явних прав.
security.enable_write_tools=falseза замовчуванням.- Redaction чутливих ключів у логах обов'язковий.
- Для API (Gate B+) обов'язкові scopes (
mcp:read|call|admin). - Ліміти
depth/limit/payloadмають бути увімкнені.
Security release checklist: SECURITY_CHECKLIST.md.
Threat model: THREAT_MODEL.md.
Architecture freeze: ARCHITECTURE_FREEZE_CHECKLIST.md.
MIT (LICENSE).