Цей документ описує, як eMCP інтегрує laravel/mcp в Evolution CMS.
Це реалізаційний гайд, узгоджений з PRD.md і SPEC.md.
Contract boundary:
SPEC.mdіTOOLSET.mdє нормативними.DOCS.uk.mdописує імплементацію та експлуатацію цих контрактів.OPERATIONS.mdє day-2 runbook для операторів (profiles, health checks, triage).
Status marker:
- Цільовий контракт:
SPEC 1.0-contract. - Runtime baseline в поточному репозиторії:
Gate C baseline implemented (full validation pending).
eMCP — thin Evo-native адаптер над laravel/mcp.
Базові цілі:
- зберегти upstream MCP runtime і протокол
- адаптувати реєстрацію/config/routes під архітектуру Evo
- забезпечити ACL/scopes і enterprise безпеку
- підтримати внутрішнє (manager) та зовнішнє (API) використання
Шари інтеграції:
- Protocol layer:
laravel/mcp(Server, Registrar, transports, JSON-RPC methods) - Adapter layer:
eMCPprovider, registry, middleware, publishing - API layer: опційний
sApiroute provider з JWT scopes - Async layer: опційний
sTaskworker (emcp_dispatch)
Порядок реалізації обовʼязковий:
- Gate A: web transport + manager route + manager ACL (
emcp) +initialize+tools/list+GET=405 - Gate B: API access layer (scope engine, basic rate limit,
sApiprovider) - Gate C: async (
sTaskworker, payload contract, failover, idempotency) - Gate D: security hardening + DX commands
Перший реліз — тільки Gate A.
eMCP зберігає upstream-поведінку laravel/mcp як базу:
GETна MCP transport route повертає405.POSTобробляє JSON-RPC повідомлення.MCP-Session-Idпроходить наскрізно request/response.202зберігається для no-reply notification flows.- SSE-відповідь має
text/event-stream, коли streaming увімкнено. - Upstream command surface (
make:mcp-*,mcp:start,mcp:inspector) доступний без змін.
eMCP-логіка є додатковою (ACL/scopes/policies), а не переписуванням протоколу.
sApi: зовнішня експозиція MCP endpoint через route providers і JWT scopes.sTask: async dispatch довгих MCP викликів (emcp_dispatchworker).eAi: AI runtime може споживати eMCP tools у manager/API режимі.dAi: manager-side orchestration UI може споживати стабільні eMCP tool contracts.
Правило boundary:
- eMCP надає протокол/runtime/policy контракти.
- orchestration-концепції реалізуються у пакетах-споживачах, не в ядрі eMCP.
- Згенеруй базові класи:
php artisan make:mcp-server ContentServer
php artisan make:mcp-tool HealthToolЗгенеровані класи потрапляють у core/custom/app/Mcp/....
2. Додай server entry у core/custom/config/mcp.php.
3. Перевір manager/internal виклик:
POST /{manager_prefix}/{handle}з manager-сесією і permissionemcp.
- Перевір зовнішній API виклик (якщо встановлено
sApi):
POST /{SAPI_BASE_PATH}/{SAPI_VERSION}/mcp/{handle}Authorization: Bearer <jwt>з потрібнимиmcp:*scopes.
- Опційний async режим:
queue.driver=stask+ dispatch endpoint + task progress.
Обовʼязково:
- Evolution CMS 3.5.2+
- PHP 8.3+
- Composer 2.2+
seiger/sapi1.xseiger/stask1.x
З директорії core Evo:
cd core
php artisan package:installrequire evolution-cms/emcp "*"
php artisan migrateAuto-publish може бути увімкнений інсталером, але краще явно виконати:
php 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-server.stubcore/stubs/mcp-tool.stubcore/stubs/mcp-resource.stubcore/stubs/mcp-prompt.stub
Рекомендований baseline:
Мітки по фазах:
[MVP]enable,mode.internal,route.manager_prefix,acl.permission.[Gate B+]mode.api,auth.*,rate_limit.*,limits.*,security.allow_servers,security.deny_tools,domain.*,actor.*.[Gate C+]queue.*, async/idempotency behavior.[Gate E]logging.audit_enabled, hardening/redaction tuning.
return [
'enable' => true,
'mode' => [
'internal' => true,
'api' => true,
],
'route' => [
'manager_prefix' => 'emcp',
'api_prefix' => 'mcp',
],
'auth' => [
'mode' => 'sapi_jwt',
'require_scopes' => true,
'scope_map' => [
'mcp:read' => ['initialize', 'ping', 'tools/list', 'resources/list', 'resources/read', 'prompts/list', 'prompts/get', 'completion/complete'],
'mcp:call' => ['tools/call'],
'mcp:admin' => ['admin/*'],
],
],
'acl' => [
'permission' => 'emcp',
],
'queue' => [
'driver' => 'stask',
'failover' => 'sync',
],
'rate_limit' => [
'enabled' => true,
'per_minute' => 60,
],
'limits' => [
'max_payload_kb' => 256,
'max_result_items' => 100,
'max_result_bytes' => 1048576,
],
'logging' => [
'channel' => 'emcp',
'audit_enabled' => true,
'redact_keys' => ['authorization', 'token', 'jwt', 'secret', 'cookie', 'password', 'api_key'],
],
'security' => [
'allow_servers' => ['*'],
'deny_tools' => [],
'enable_write_tools' => false,
],
'domain' => [
'content' => [
'max_depth' => 6,
'max_limit' => 100,
'max_offset' => 5000,
],
'models' => [
'max_offset' => 5000,
'allow' => [
'SiteTemplate', 'SiteTmplvar', 'SiteTmplvarContentvalue',
'SiteSnippet', 'SitePlugin', 'SiteModule', 'Category',
'User', 'UserAttribute', 'UserRole', 'Permissions', 'PermissionsGroups', 'RolePermissions',
],
],
],
'actor' => [
'mode' => 'initiator',
'service_username' => 'MCP',
'service_role' => 'MCP',
'block_login' => true,
],
];eMCP використовує цей файл як registry MCP серверів.
Приклад:
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,
],
],
];Нотатка:
content-localза замовчуванням вимкнений, щоб уникнути конфлікту дубльованих tool names зcontent.- Локальний transport вмикай лише коли конфліктні сервери вимкнені або мають різні tool names.
Правила валідації:
handleмає бути унікальнимclassмає існувати і наслідуватиLaravel\Mcp\Servertransportлишеwebабоlocal- реєструються тільки
enabled=true
Опційні per-server overrides:
scope_maplimits.max_payload_kblimits.max_result_itemsrate_limit.per_minutesecurity.deny_tools
Семантика route:
- У Gate A manager endpoint має формат
/{manager_prefix}/{handle}. servers[*].routeє route-привʼязкою web transport і зовнішньо актуальний у API mode (Gate B+).
Використовуй ці пресети, щоб швидко стартувати:
manager-only:mode.internal=true,mode.api=false- тільки manager endpoint (
/{manager_prefix}/{handle})
api-only:mode.internal=false,mode.api=true- потрібні
sApi+ JWT scopes
hybrid(рекомендований дефолт):mode.internal=true,mode.api=true- один і той самий tool contract для manager і API споживачів
Async-доповнення (для будь-якого пресету):
queue.driver=staskдля довгих викликів.queue.failover=syncдля безпечного fallback, якщоsTaskвідсутній.
Upstream Laravel MCP очікує routes/ai.php.
eMCP замінює це на config-first модель для Evo.
Мапінг:
transport=web->Mcp::web(route, class)transport=local->Mcp::local(handle, class)
Це зберігає upstream runtime behavior і відповідає архітектурі Evo-пакетів.
- Додати server entries у
core/custom/config/mcp.phpз унікальнимhandle. - Розширювати per-server policy через
scope_map,limits,rate_limit,security.deny_tools. - Додавати tools/resources/prompts через генератори (
make:mcp-*) і спільні stubs.
Канонічне джерело tool names/params/examples/errors: TOOLSET.md.
Головний доменний профіль: робота з деревом документів через SiteContent:
evo.content.searchevo.content.getevo.content.root_treeevo.content.descendantsevo.content.ancestorsevo.content.childrenevo.content.siblings
Опційні (вже реалізовані) tree tools:
evo.content.neighborsevo.content.prev_siblingsevo.content.next_siblingsevo.content.children_rangeevo.content.siblings_range
Підтримка TV входить у контракт:
with_tvsмапиться наwithTVs- структурований
tv_filtersмапиться наtvFilter - структурований
tv_orderмапиться наtvOrderBy tags_dataмапиться наtagsDataorder_by_dateмапиться наorderByDate
Обмеження безпеки:
- заборонити raw
tvFilterDSL-рядки у клієнтському payload - дозволити тільки whitelist операторів/cast
- примусово обмежувати
depth/limit/offsetчерез config
Contract-first стиль виконання:
- кожен tool call іде по pipeline
validate -> authorize -> query -> map -> paginate - один tool має відповідати одному явному handler/procedure
- приховані side-effect у transport/controller поза pipeline небажані
Профіль orchestration execution (post-MVP):
Intent -> PolicyCheck -> Task(s) -> EvidenceTrace -> ApprovalGate- дії планувальника мають бути обмежені policy-valid action set
- зв'язок intent/task/evidence має бути аудитопридатним end-to-end
Профіль model catalog (read-only за замовчуванням):
evo.model.listevo.model.get
Default allowlist моделей:
SiteTemplate,SiteTmplvar,SiteTmplvarContentvalueSiteSnippet,SitePlugin,SiteModule,CategoryUser,UserAttribute,UserRole,Permissions,PermissionsGroups,RolePermissions
Чутливі поля завжди маскуються/не віддаються:
password,cachepwd,verified_key,refresh_token,access_token,sessionid
Міграції мають створити:
- permission group:
eMCP(або спільну групу за рішенням проєкту) - permissions:
emcp(access)emcp_manage(керування)emcp_dispatch(async dispatch)
Етапи rollout:
- Gate A (MVP): обовʼязковий
emcp. - Gate B+: додати
emcp_manage. - Gate C+: додати
emcp_dispatch.
Дефолтне призначення:
- роль
1(admin) отримує всіemcp*permissions
Мінімальна політика scopes:
mcp:read:initialize,ping, list/read/get методиmcp:call:tools/callmcp:admin: admin/service дії
Правила:
- якщо
auth.require_scopes=true, перевірка scope обовʼязкова *у token scopes дає повний MCP доступ
Підтримувані режими:
sapi_jwt(default): використовує JWT атрибутиsApinone(лише для обмежених внутрішніх сценаріїв)
Контракт:
- відсутність auth-конфігурації не повинна ламати boot пакета
Під mgr middleware і permission emcp:
POST /{manager_prefix}/{server}POST /{manager_prefix}/{server}/dispatch
Правила:
GETна MCP endpoint повертає405POSTприймає JSON-RPC body- підтримується
MCP-Session-Id
Через McpRouteProvider (RouteProviderInterface):
POST /mcp/{server}POST /mcp/{server}/dispatch
Рекомендований middleware chain:
emcp.jwtemcp.scopeemcp.actoremcp.rate
McpRouteProvider прибирає upstream sapi.jwt з MCP route і використовує emcp.jwt як єдиний JWT middleware.
Error handling policy:
- transport/auth/middleware помилки -> HTTP status (
401/403/405/413/415) у non-JSON-RPC форматі. - JSON-RPC dispatch помилки -> HTTP
200+ JSON-RPCerror(-32700,-32600,-32601,-32602,-32603).
Для точного нормативного mapping і формату помилки використовуй SPEC.md.
Якщо MCP метод стрімить iterable responses, відповідь має бути:
Content-Type: text/event-stream- опційно
MCP-Session-Idу response headers
Environment notes (Gate B+):
- Nginx/Proxy: вимкнути buffering для MCP streaming маршрутів.
- PHP-FPM/FastCGI: керувати output buffering/flush, щоб події відправлялись інкрементально.
- Timeout-и proxy/FPM мають бути узгоджені з тривалими stream-викликами.
Якщо sTask встановлений, реєструється воркер:
identifier:emcp_dispatchscope:eMCPclass:EvolutionCMS\eMCP\sTask\McpDispatchWorkeractive:true
Async payload має містити:
server_handlejsonrpc_methodjsonrpc_paramsrequest_idsession_idtrace_ididempotency_keyactor_user_idinitiated_by_user_idcontext(mgr|api|cli)attemptsmax_attempts
Якщо sTask відсутній:
queue.failover=sync-> синхронне виконанняqueue.failover=fail-> контрольована помилка
Контекстні поля ідентичності:
actor_user_idinitiated_by_user_idcontexttrace_id
Стратегія резолву:
- manager mode -> поточний manager user
- sApi mode -> JWT user (
sapi.jwt.user_id) якщо є - service mode -> окремий service account (
actor.mode=service)
logging.channels.emcp (daily):
- файл:
core/storage/logs/emcp-YYYY-MM-DD.log - ротація:
LOG_DAILY_DAYS
Аудит-події мають містити:
timestamprequest_idtrace_idserver_handlemethodstatusactor_user_idcontextduration_mstask_id(для async)
Ніколи не логувати raw значення:
authorizationtokenjwtsecretcookiepasswordapi_key
Обовʼязкові мовні файли:
lang/en/global.phplang/uk/global.phplang/ru/global.php
Мінімальні ключі:
titlepermissions_grouppermission_accesspermission_managepermission_dispatcherrors.forbiddenerrors.scope_deniederrors.server_not_founderrors.invalid_payload
Очікувані upstream команди через 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
php artisan mcp:inspector content-localПеред mcp:start content-local увімкни content-local у core/custom/config/mcp.php і вимкни конфліктні сервери, якщо вони мають однакові tool names.
Доступні операційні команди eMCP:
php artisan emcp:test
php artisan emcp:list-servers
php artisan emcp:sync-workers
composer run governance:update-lock
composer run ci:check
composer run benchmark:run
composer run benchmark:leaderboard
composer run test:integration:clean-install
EMCP_INTEGRATION_ENABLED=1 EMCP_BASE_URL="https://example.org" EMCP_API_PATH="/api/v1/mcp/{server}" EMCP_API_TOKEN="<jwt>" composer run test:integration:runtime-
401/403 на API викликах: перевір JWT scopes і
auth.require_scopes. -
403 у manager: перевір, що роль має permission
emcp. -
Server not found: перевір запис у
mcp.php(enabled,handle, клас). -
Streaming не працює: перевір підтримку SSE у клієнта і proxy buffering.
-
Async dispatch не стартує: перевір встановлення
sTask, реєстрацію воркера і запущений worker process.
- Product requirements:
PRD.md - Technical contract:
SPEC.md - Canonical tool contract:
TOOLSET.md - Quick start:
README.md,README.uk.md - Deep docs:
DOCS.md,DOCS.uk.md - Execution plan:
TASKS.md - Security review:
SECURITY_CHECKLIST.md - Threat model:
THREAT_MODEL.md - Formal audit:
PLATFORM_AUDIT.md - Architecture freeze gate:
ARCHITECTURE_FREEZE_CHECKLIST.md