eMCP is the Evolution CMS integration layer for laravel/mcp.
It adapts Laravel MCP to Evo runtime with:
- Evo-native config publishing
- manager ACL and sApi scope controls
- optional async dispatch through sTask
- no Laravel app skeleton requirement
- Evo domain MCP tools for document tree (
SiteContent+ TVs)
Implementation starts with a strict MVP gate:
- web transport
- manager mode
initialize+tools/list
If you need full architecture and contracts, see DOCS.md (EN) or DOCS.uk.md (UA).
Public canonical tool contract: TOOLSET.md.
Versioning and BC policy: PRD.md (API Stability Policy section).
- Evolution CMS 3.5.2+
- PHP 8.4+
- Composer 2.2+
Optional:
seiger/sapifor external MCP API accessseiger/staskfor async MCP dispatchlaravel/passportfor OAuth-compatible mode
From your Evo core directory:
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-stubsPublished files:
core/custom/config/cms/settings/eMCP.phpcore/custom/config/mcp.phpcore/stubs/mcp-*.stub
For Gate A, use manager endpoint /{manager_prefix}/{server_handle} (default: /emcp/content).
Gate A is manager ACL protected, so run checks as a logged-in manager with emcp permission (session cookie required).
- Verify
GETreturns405on MCP endpoint:
curl -i -X GET http://localhost/<MANAGER_PREFIX>/<SERVER_HANDLE> \
-H 'Cookie: evo_session=<MANAGER_SESSION_COOKIE>'- Verify JSON-RPC
initialize:
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"}}}'Expected:
- HTTP
200for validinitialize. MCP-Session-Idpresent in response headers.- stable HTTP
405onGET.
Unlike Laravel default routes/ai.php, eMCP registers servers from config.
Example in core/custom/config/mcp.php:
return [
'redirect_domains' => ['*'],
'servers' => [
[
'handle' => 'content',
'transport' => 'web',
'route' => '/mcp/content',
'class' => App\Mcp\Servers\ContentServer::class,
'enabled' => true,
'auth' => 'sapi_jwt',
'scopes' => ['mcp:read', 'mcp:call'],
],
[
'handle' => 'content-local',
'transport' => 'local',
'class' => App\Mcp\Servers\ContentServer::class,
'enabled' => true,
],
],
];Notes:
- Gate A manager endpoint is still
/{manager_prefix}/{handle}(for example/emcp/content). servers[*].routeis used by web transport registration and becomes externally relevant in API mode (Gate B+).
- Manager/internal access: Evo permission
emcp - API access (via sApi): JWT scopes (
mcp:read,mcp:call,mcp:admin) - Optional Passport mode:
mcp:usecompatibility when Passport is installed - Domain reads (
evo.content.*,evo.model.*) are read-only by default
evo.content.search|get|root_tree|descendants|ancestors|children|siblings- Post-MVP:
evo.content.neighbors|prev_siblings|next_siblings|children_range|siblings_range - TV-aware queries via structured
with_tvs,tv_filters,tv_order evo.model.list|getfor allowlisted Evo models with sensitive-field masking
From Laravel MCP (available via 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-localPlanned eMCP operational commands:
php artisan emcp:testphp artisan emcp:sync-workersphp artisan emcp:list-servers
If queue.driver=stask and sTask is installed, eMCP can run long MCP calls via worker emcp_dispatch.
If sTask is missing, fallback behavior follows queue.failover (sync or fail).
- Keep secrets in
.envorcore/custom/config/*. - Audit logs must redact tokens/secrets.
- Use tool denylist and server allowlist for production hardening.
- deny-by-default for manager/API without explicit access.
security.enable_write_tools=falseby default.- sensitive key redaction in logs is mandatory.
- API scope checks (
mcp:read|call|admin) are required in Gate B+. depth/limit/payloadlimits should stay enabled.
Security release checklist: SECURITY_CHECKLIST.md.
Threat model: THREAT_MODEL.md.
Architecture freeze: ARCHITECTURE_FREEZE_CHECKLIST.md.
MIT (LICENSE).