Skip to content

Commit f069108

Browse files
committed
Add eMCP scaffolding
1 parent 77adab5 commit f069108

100 files changed

Lines changed: 8734 additions & 50 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.ci/governance-lock.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"toolset_version": "1.0",
3+
"canonical_tools": [
4+
"evo.content.search",
5+
"evo.content.get",
6+
"evo.content.root_tree",
7+
"evo.content.descendants",
8+
"evo.content.ancestors",
9+
"evo.content.children",
10+
"evo.content.siblings",
11+
"evo.model.list",
12+
"evo.model.get"
13+
],
14+
"spec_version": "1.0-contract",
15+
"runtime_status": "Gate C baseline implemented (full validation pending)",
16+
"spec_public_contract_hash": "752772e83d65c41fe55bd6ddef3359a8ab04f0e3efe67d4901e79870d1967e7b",
17+
"model_allowlists_hash": "2e27381b6120a53f4adb6da3649fcc5319530da4f6e41063d7b7b0700d600731",
18+
"updated_at": "2026-03-02T14:48:22+00:00"
19+
}

.github/workflows/ci.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
pull_request:
8+
workflow_dispatch:
9+
inputs:
10+
run_runtime_integration:
11+
description: 'Run runtime integration checks against deployed environment'
12+
required: false
13+
default: false
14+
type: boolean
15+
16+
jobs:
17+
checks:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Setup PHP
24+
uses: shivammathur/setup-php@v2
25+
with:
26+
php-version: '8.4'
27+
coverage: none
28+
29+
- name: Validate composer files
30+
run: composer validate --strict
31+
32+
- name: Install dependencies
33+
run: composer install --no-interaction --prefer-dist --no-progress
34+
35+
- name: Run CI checks
36+
run: composer run ci:check
37+
38+
runtime-integration:
39+
needs: checks
40+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.run_runtime_integration == true }}
41+
runs-on: ubuntu-latest
42+
env:
43+
EMCP_INTEGRATION_ENABLED: '1'
44+
EMCP_BASE_URL: ${{ secrets.EMCP_BASE_URL }}
45+
EMCP_SERVER_HANDLE: ${{ secrets.EMCP_SERVER_HANDLE }}
46+
EMCP_API_PATH: ${{ secrets.EMCP_API_PATH }}
47+
EMCP_API_TOKEN: ${{ secrets.EMCP_API_TOKEN }}
48+
EMCP_MANAGER_PATH: ${{ secrets.EMCP_MANAGER_PATH }}
49+
EMCP_MANAGER_COOKIE: ${{ secrets.EMCP_MANAGER_COOKIE }}
50+
EMCP_DISPATCH_CHECK: ${{ secrets.EMCP_DISPATCH_CHECK }}
51+
steps:
52+
- name: Checkout
53+
uses: actions/checkout@v4
54+
55+
- name: Setup PHP
56+
uses: shivammathur/setup-php@v2
57+
with:
58+
php-version: '8.4'
59+
coverage: none
60+
61+
- name: Install dependencies
62+
run: composer install --no-interaction --prefer-dist --no-progress
63+
64+
- name: Runtime integration checks
65+
run: composer run test:integration:runtime

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
.idea
1+
.idea
2+
.DS_Store
3+
demo/

ARCHITECTURE_FREEZE_CHECKLIST.md

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,37 @@
33
Use this checklist before starting Phase 1 implementation.
44

55
## 1. Contract Completeness
6-
- [ ] `PRD.md`, `SPEC.md`, `TOOLSET.md` are mutually consistent.
7-
- [ ] Gate A/B/C boundaries are explicit and conflict-free.
8-
- [ ] Namespace governance and ecosystem extension rules are finalized.
9-
- [ ] `initialize` metadata contract is mandatory and versioned.
6+
- [x] `PRD.md`, `SPEC.md`, `TOOLSET.md` are mutually consistent.
7+
- [x] Gate A/B/C boundaries are explicit and conflict-free.
8+
- [x] Namespace governance and ecosystem extension rules are finalized.
9+
- [x] `initialize` metadata contract is mandatory and versioned.
1010

1111
## 2. Security Baseline
12-
- [ ] `THREAT_MODEL.md` attack trees reviewed and approved.
13-
- [ ] `SECURITY_CHECKLIST.md` mapped to planned tests.
14-
- [ ] Model field allowlist policy is complete for all allowlisted models.
15-
- [ ] Error formatter contract (`401/403/409/413/415` + `trace_id`) is fixed.
12+
- [x] `THREAT_MODEL.md` attack trees reviewed and approved.
13+
- [x] `SECURITY_CHECKLIST.md` mapped to planned tests.
14+
- [x] Model field allowlist policy is complete for all allowlisted models.
15+
- [x] Error formatter contract (`401/403/409/413/415` + `trace_id`) is fixed.
1616

1717
## 3. Runtime Governance
18-
- [ ] Tool uniqueness and handle uniqueness rules are frozen.
19-
- [ ] Rate-limit identity resolver algorithm is frozen.
20-
- [ ] Idempotency hash and conflict policy is frozen.
21-
- [ ] Streaming activation policy (`stream.enabled`) is frozen.
18+
- [x] Tool uniqueness and handle uniqueness rules are frozen.
19+
- [x] Rate-limit identity resolver algorithm is frozen.
20+
- [x] Idempotency hash and conflict policy is frozen.
21+
- [x] Streaming activation policy (`stream.enabled`) is frozen.
2222

2323
## 4. Release/BC Governance
24-
- [ ] SemVer and Public Contract Stability sections approved.
25-
- [ ] Golden fixture governance (version bump + changelog + CI guard) approved.
26-
- [ ] Deprecation policy for breaking changes approved.
27-
- [ ] Upstream compatibility policy (`laravel/mcp ^0.5.x`) approved.
24+
- [x] SemVer and Public Contract Stability sections approved.
25+
- [x] Golden fixture governance (version bump + changelog + CI guard) approved.
26+
- [x] Deprecation policy for breaking changes approved.
27+
- [x] Upstream compatibility policy (`laravel/mcp ^0.5.x`) approved.
2828

2929
## 5. Process Readiness
30-
- [ ] Formal platform audit (`PLATFORM_AUDIT.md`) approved.
31-
- [ ] Ownership assigned for platform, security, and release decisions.
32-
- [ ] Phase 1 backlog items trace to frozen contracts.
33-
- [ ] Any open architectural question has owner + resolution date.
30+
- [x] Formal platform audit (`PLATFORM_AUDIT.md`) approved.
31+
- [x] Ownership assigned for platform, security, and release decisions.
32+
- [x] Phase 1 backlog items trace to frozen contracts.
33+
- [x] Any open architectural question has owner + resolution date.
34+
35+
## Freeze Decision
36+
- Date: 2026-02-19
37+
- Status: APPROVED
38+
- Baseline: architecture contract frozen for Gate B start
39+
- Change rule: contract updates require explicit SemVer-aware version bump + changelog entry

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
## [Unreleased]
6+
- Added Gate C baseline async dispatch implementation (`/dispatch`, worker, idempotency, failover).
7+
- Added minimal security hardening baseline (security policy, redactor, audit logger).
8+
- Added governance guard tests and golden fixtures bound to `toolsetVersion`.

CONTRIBUTING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ This repository defines and implements the official MCP platform layer for Evolu
88
- Any change that affects public MCP behavior must include tests and changelog entry.
99
- Namespace governance is mandatory: third-party additions must use `vendor.domain.*`.
1010
- Breaking changes require SemVer-major planning and deprecation note.
11+
- eMCP core MUST remain orchestration-agnostic.
12+
- Planner/strategy-specific logic MUST NOT be implemented in eMCP core layer.
13+
- Orchestration concepts belong in consuming packages (for example `dAi`/`eAi`), not in core transport/policy/runtime.
1114

1215
## Pull Request Requirements
1316
- Link issue/problem statement.

DOCS.md

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ It is the implementation-oriented guide aligned with `PRD.md` and `SPEC.md`.
66
Contract boundary:
77
- `SPEC.md` and `TOOLSET.md` are normative.
88
- `DOCS.md` describes how to implement and operate those contracts.
9+
- `OPERATIONS.md` is the day-2 operator runbook (profiles, health checks, triage).
10+
11+
Status marker:
12+
- Contract target: `SPEC 1.0-contract`.
13+
- Runtime baseline in current repository: `Gate C baseline implemented (full validation pending)`.
914

1015
## 1) Overview
1116
`eMCP` is a thin Evo-native adapter around `laravel/mcp`.
@@ -32,6 +37,43 @@ Implementation order is mandatory:
3237

3338
Minimal first release is Gate A only.
3439

40+
## 2.1) Laravel MCP Parity Contract
41+
eMCP keeps upstream `laravel/mcp` behavior as the baseline:
42+
- `GET` on MCP transport route returns `405`.
43+
- `POST` processes JSON-RPC messages.
44+
- `MCP-Session-Id` is passed through request/response.
45+
- `202` is preserved for no-reply notification flows.
46+
- SSE transport response uses `text/event-stream` when streaming is enabled.
47+
- Upstream command surface (`make:mcp-*`, `mcp:start`, `mcp:inspector`) remains available.
48+
49+
eMCP-specific logic is additive (ACL/scopes/policies), not a protocol rewrite.
50+
51+
## 2.2) Ecosystem Interop Map
52+
- `sApi`: external exposure for MCP endpoints through route providers and JWT scopes.
53+
- `sTask`: async dispatch for long-running MCP calls (`emcp_dispatch` worker).
54+
- `eAi`: AI runtime can consume eMCP tools in manager or API mode.
55+
- `dAi`: manager orchestration UI can consume stable eMCP tool contracts.
56+
57+
Boundary rule:
58+
- eMCP provides protocol/runtime/policy contracts.
59+
- orchestration concepts live in consuming packages, not in eMCP core.
60+
61+
## 2.3) Fast Path: One MCP Server, Internal + External
62+
1. Generate primitives:
63+
```bash
64+
php artisan make:mcp-server ContentServer
65+
php artisan make:mcp-tool HealthTool
66+
```
67+
Generated classes are placed under `core/custom/app/Mcp/...`.
68+
2. Register server entry in `core/custom/config/mcp.php`.
69+
3. Verify manager/internal call:
70+
- `POST /{manager_prefix}/{handle}` with manager session and `emcp` permission.
71+
4. Verify external API call (with `sApi` installed):
72+
- `POST /{SAPI_BASE_PATH}/{SAPI_VERSION}/mcp/{handle}`
73+
- `Authorization: Bearer <jwt>` with required `mcp:*` scopes.
74+
5. Optional async mode:
75+
- `queue.driver=stask` + dispatch endpoint + task progress tracking.
76+
3577
## User Guide
3678

3779
## 3) Requirements
@@ -122,6 +164,8 @@ return [
122164

123165
'limits' => [
124166
'max_payload_kb' => 256,
167+
'max_result_items' => 100,
168+
'max_result_bytes' => 1048576,
125169
],
126170

127171
'logging' => [
@@ -143,6 +187,7 @@ return [
143187
'max_offset' => 5000,
144188
],
145189
'models' => [
190+
'max_offset' => 5000,
146191
'allow' => [
147192
'SiteTemplate', 'SiteTmplvar', 'SiteTmplvarContentvalue',
148193
'SiteSnippet', 'SitePlugin', 'SiteModule', 'Category',
@@ -176,21 +221,25 @@ return [
176221
'handle' => 'content',
177222
'transport' => 'web',
178223
'route' => '/mcp/content',
179-
'class' => App\Mcp\Servers\ContentServer::class,
224+
'class' => EvolutionCMS\eMCP\Servers\ContentServer::class,
180225
'enabled' => true,
181226
'auth' => 'sapi_jwt',
182227
'scopes' => ['mcp:read', 'mcp:call'],
183228
],
184229
[
185230
'handle' => 'content-local',
186231
'transport' => 'local',
187-
'class' => App\Mcp\Servers\ContentServer::class,
188-
'enabled' => true,
232+
'class' => EvolutionCMS\eMCP\Servers\ContentServer::class,
233+
'enabled' => false,
189234
],
190235
],
191236
];
192237
```
193238

239+
Note:
240+
- `content-local` is disabled by default to avoid duplicate tool-name registration conflicts with `content`.
241+
- Enable local transport only when conflicting server entries are disabled or use non-overlapping tool names.
242+
194243
Validation rules:
195244
- `handle` must be unique
196245
- `class` must exist and extend `Laravel\Mcp\Server`
@@ -208,6 +257,23 @@ Route semantics:
208257
- Gate A manager endpoint is `/{manager_prefix}/{handle}`.
209258
- `servers[*].route` is the web transport route binding and is externally relevant in API mode (Gate B+).
210259

260+
## 6.3 Configuration Presets (Practical)
261+
Use these presets to reduce setup friction:
262+
263+
- `manager-only`:
264+
- `mode.internal=true`, `mode.api=false`
265+
- use manager endpoint only (`/{manager_prefix}/{handle}`)
266+
- `api-only`:
267+
- `mode.internal=false`, `mode.api=true`
268+
- require `sApi` + JWT scopes
269+
- `hybrid` (recommended default):
270+
- `mode.internal=true`, `mode.api=true`
271+
- same tool contract available for manager and API consumers
272+
273+
Async add-on (any preset):
274+
- `queue.driver=stask` for long-running calls.
275+
- `queue.failover=sync` for resilient fallback on installations without `sTask`.
276+
211277
## 7) Server Registration Model
212278
Upstream Laravel MCP expects `routes/ai.php`.
213279
`eMCP` replaces this with config-first registration for Evo.
@@ -254,6 +320,16 @@ Safety constraints:
254320
- allow only approved operators/casts
255321
- enforce `depth/limit/offset` caps from config
256322

323+
Contract-first execution style:
324+
- each tool call follows `validate -> authorize -> query -> map -> paginate`
325+
- one tool should map to one explicit handler/procedure
326+
- hidden query/policy side effects outside the pipeline are discouraged
327+
328+
Orchestration execution profile (post-MVP):
329+
- `Intent -> PolicyCheck -> Task(s) -> EvidenceTrace -> ApprovalGate`
330+
- planner actions should be constrained by policy-valid action sets
331+
- intent/task/evidence linkage should be auditable end-to-end
332+
257333
Model catalog profile (read-only by default):
258334
- `evo.model.list`
259335
- `evo.model.get`
@@ -324,11 +400,13 @@ Via `McpRouteProvider` (`RouteProviderInterface`):
324400
- `POST /mcp/{server}/dispatch`
325401

326402
Recommended middleware chain:
327-
- `sapi.jwt`
403+
- `emcp.jwt`
328404
- `emcp.scope`
329405
- `emcp.actor`
330406
- `emcp.rate`
331407

408+
`McpRouteProvider` removes upstream `sapi.jwt` from MCP routes and uses `emcp.jwt` as the single JWT middleware.
409+
332410
Error handling policy:
333411
- transport/auth/middleware failures -> HTTP status (`401/403/405/413/415`) with non-JSON-RPC error body.
334412
- JSON-RPC dispatch failures -> HTTP `200` + JSON-RPC `error` (`-32700`, `-32600`, `-32601`, `-32602`, `-32603`).
@@ -445,12 +523,17 @@ php artisan mcp:start content-local
445523
php artisan mcp:inspector content-local
446524
```
447525

448-
Planned eMCP operational commands:
526+
Before `mcp:start content-local`, enable `content-local` in `core/custom/config/mcp.php` and disable conflicting server entries if they expose identical tool names.
527+
528+
Available eMCP operational commands:
449529

450530
```bash
451531
php artisan emcp:test
452-
php artisan emcp:sync-workers
453532
php artisan emcp:list-servers
533+
php artisan emcp:sync-workers
534+
composer run governance:update-lock
535+
composer run ci:check
536+
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
454537
```
455538

456539
## 16) Troubleshooting

0 commit comments

Comments
 (0)