@event4u/agent-config 1.36.0 → 1.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent-src/contexts/authority/scope-mechanics.md +20 -2
- package/.agent-src/rules/scope-control.md +3 -5
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +59 -0
- package/README.md +1 -1
- package/docs/contracts/mcp-phase-1-scope.md +190 -0
- package/docs/mcp-server.md +156 -0
- package/docs/setup/mcp-server-docker.md +97 -0
- package/package.json +1 -1
- package/scripts/agent-config +29 -0
- package/scripts/mcp_server/__init__.py +13 -0
- package/scripts/mcp_server/__main__.py +12 -0
- package/scripts/mcp_server/metadata.py +75 -0
- package/scripts/mcp_server/prompts.py +305 -0
- package/scripts/mcp_server/requirements.txt +4 -0
- package/scripts/mcp_server/resources.py +201 -0
- package/scripts/mcp_server/server.py +269 -0
- package/scripts/mcp_server/tools.py +363 -0
- package/scripts/mcp_setup.sh +87 -0
- package/scripts/skill_linter.py +7 -0
|
@@ -5,8 +5,9 @@ detail behind the Hard Floor restatement, the brief-before-asking
|
|
|
5
5
|
flow for separate-branch proposals, and the failure modes / bypass
|
|
6
6
|
rules around fenced steps.
|
|
7
7
|
|
|
8
|
-
**Size budget:** ≤
|
|
9
|
-
`
|
|
8
|
+
**Size budget:** soft cap ≤ 8,000 chars (context layer, on-demand
|
|
9
|
+
loaded). The mechanics file absorbs growth so `scope-control` stays
|
|
10
|
+
under the 4,000-char kernel ceiling.
|
|
10
11
|
|
|
11
12
|
## Production, infrastructure, bulk-destructive — Hard Floor
|
|
12
13
|
|
|
@@ -40,6 +41,23 @@ permission is per-operation, this-turn. Standing autonomy directives
|
|
|
40
41
|
narrow other rules but never grant permission for items in this Hard
|
|
41
42
|
Floor subset.
|
|
42
43
|
|
|
44
|
+
## Roadmap shape — no release language
|
|
45
|
+
|
|
46
|
+
Forbidden in roadmaps / plans / tickets / any planning artifact:
|
|
47
|
+
version numbers (`v2.0`, `1.4.x`), target releases (`Q4 release`,
|
|
48
|
+
`Sprint 23`), deprecation dates tied to release calendars,
|
|
49
|
+
release-tied milestones (`launch milestone`, `GA`), and git tags
|
|
50
|
+
(`tag v1.2.0`).
|
|
51
|
+
|
|
52
|
+
Roadmaps plan **work**. Releases / tags / version pins are a
|
|
53
|
+
**separate decision** the user pins explicitly on the artifact that
|
|
54
|
+
owns release shape — changelog, release PR, tag annotation — not
|
|
55
|
+
buried inside a planning document. Authoring verbs (`create / draft /
|
|
56
|
+
write the roadmap`) authorize the planning artifact, not version
|
|
57
|
+
pinning inside it. If the user names a version in a planning
|
|
58
|
+
request, ask whether the artifact tracks the work or the release;
|
|
59
|
+
default to work.
|
|
60
|
+
|
|
43
61
|
## Brief-before-asking — separate branch / PR / worktree
|
|
44
62
|
|
|
45
63
|
If a task seems to need a separate branch or PR (spike, hotfix,
|
|
@@ -28,7 +28,7 @@ The user decides the git shape. Never improvise. Commit specifics: canonical [`c
|
|
|
28
28
|
- NEVER create / switch / delete a branch without explicit permission — includes spike, scratch, throwaway, worktree branches.
|
|
29
29
|
- NEVER create, close, reopen, or change the target of a pull request without permission.
|
|
30
30
|
- NEVER push a tag or create a release without permission.
|
|
31
|
-
- NEVER
|
|
31
|
+
- NEVER pin versions, release targets, deprecation dates, or git tags in roadmaps / plans / tickets — they plan **work**, not releases. Detail: [`scope-mechanics § Roadmap shape`](../contexts/authority/scope-mechanics.md).
|
|
32
32
|
- Task seems to need a separate branch / PR → STOP and **brief before asking** ([`scope-mechanics § Brief-before-asking`](../contexts/authority/scope-mechanics.md)).
|
|
33
33
|
- BEFORE the first commit on related work, **inventory** existing branches and open PRs. Plausible base beyond the current branch → STOP and ask with numbered options — never improvise. Commands + 4-option template + diverging-stack failure mode: [`scope-mechanics § Branch-base inventory`](../contexts/authority/scope-mechanics.md).
|
|
34
34
|
|
|
@@ -49,7 +49,7 @@ A subset is **never** autonomous, regardless of standing autonomy. Canonical: [`
|
|
|
49
49
|
|
|
50
50
|
## Kernel-rule edits — slow-rollout guarantee
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
Own PR, ≥ 24 h between merges. Autonomous mandate does not lift — soak guarantee. CI / labels / scope: [`kernel-rule-edits`](../contexts/authority/kernel-rule-edits.md).
|
|
53
53
|
|
|
54
54
|
## Decline = silence — no re-asking on the same task
|
|
55
55
|
|
|
@@ -57,11 +57,9 @@ After the user **declines** a proposal (branch switch, PR creation, tag/release,
|
|
|
57
57
|
|
|
58
58
|
## Fenced step — user-set review gates
|
|
59
59
|
|
|
60
|
-
User fences next step (*"plan only"*, *"review first"*, German equivalents) → reply is **deliverable + handoff**, never *"shall we start?"*.
|
|
61
|
-
|
|
62
60
|
```
|
|
63
61
|
USER FENCED OFF EXECUTION → DELIVER + HAND BACK.
|
|
64
62
|
NO "READY TO IMPLEMENT?" / "PHASE 1?" RE-ASK.
|
|
65
63
|
```
|
|
66
64
|
|
|
67
|
-
Fence stands until reopened
|
|
65
|
+
Fence (*"plan only"*, *"review first"*, German equivalents) stands until reopened — like `Decline = silence`. Follow-ups cover the deliverable, not its execution. Failure modes + bypass: [`scope-mechanics § Fenced step`](../contexts/authority/scope-mechanics.md).
|
package/CHANGELOG.md
CHANGED
|
@@ -318,6 +318,65 @@ our recommendation order, not its support status.
|
|
|
318
318
|
users" tension without removing any path that an existing user
|
|
319
319
|
might rely on.
|
|
320
320
|
|
|
321
|
+
## [1.37.0](https://github.com/event4u-app/agent-config/compare/1.36.1...1.37.0) (2026-05-10)
|
|
322
|
+
|
|
323
|
+
### Features
|
|
324
|
+
|
|
325
|
+
* **mcp:** add Phase 6 F3 stdio Docker bundle ([acd5e47](https://github.com/event4u-app/agent-config/commit/acd5e47a56b9fb42f57751771087c6b73759d3d5))
|
|
326
|
+
* **mcp:** add Phase 6 F1 identity metadata ([f4700ff](https://github.com/event4u-app/agent-config/commit/f4700ff1f093611220c08fba75c29d12ed57110c))
|
|
327
|
+
* **mcp:** add Phase 4 tool layer with lint_skills and chat_history_append ([fe02108](https://github.com/event4u-app/agent-config/commit/fe0210817e46f4d1710b0d96b7a176c872fc5545))
|
|
328
|
+
* **cli:** expose mcp:setup + mcp:run via ./agent-config ([bf7ff65](https://github.com/event4u-app/agent-config/commit/bf7ff65ab040b482d5f4e716a78148e95ba3bc7f))
|
|
329
|
+
* **mcp:** expose rules, guidelines, contexts as resources ([21d85c5](https://github.com/event4u-app/agent-config/commit/21d85c5142a35dade1129f835821c72944442ead))
|
|
330
|
+
* **mcp:** full skill + command coverage with pagination + hot-reload ([126c976](https://github.com/event4u-app/agent-config/commit/126c976f30e7bf3b714f8b72131b53fcc3e07878))
|
|
331
|
+
* **mcp:** add experimental stdio MCP server exposing 5 stack-agnostic skills ([8e692cf](https://github.com/event4u-app/agent-config/commit/8e692cfbdc14e67f178b11068773d50dd199b4ab))
|
|
332
|
+
|
|
333
|
+
### Bug Fixes
|
|
334
|
+
|
|
335
|
+
* **agents-md:** revert MCP pointer to keep root under 3000-char cap ([02bed8e](https://github.com/event4u-app/agent-config/commit/02bed8edb13fdcae369bac3843a836c01dc04248))
|
|
336
|
+
* **lint:** emit valid JSON when no skill/rule files changed ([caef1cb](https://github.com/event4u-app/agent-config/commit/caef1cb91def6089cad3ba3d2fd7c728b39731d0))
|
|
337
|
+
* **mcp:** relocate Phase 1 smoke transcript out of agents/roadmaps/ ([addd7c2](https://github.com/event4u-app/agent-config/commit/addd7c2ac4aa7a6527fb9e750ed38d02f1cd51bc))
|
|
338
|
+
* **mcp:** drop roadmap link from Phase 1 scope contract ([ca3c2e8](https://github.com/event4u-app/agent-config/commit/ca3c2e89b6c5ebf06cbc6a55883cf3cf1fbd015a))
|
|
339
|
+
|
|
340
|
+
### Documentation
|
|
341
|
+
|
|
342
|
+
* **contracts:** amend MCP scope contract for Phase 6 F1 + F3 ([45989c5](https://github.com/event4u-app/agent-config/commit/45989c53d6c9b361ad29b4214984db6cff8f5b5f))
|
|
343
|
+
* **contracts:** amend MCP scope contract for Phase 4 tool allowlist ([87c9622](https://github.com/event4u-app/agent-config/commit/87c9622d165d783a5b1f8c266035791cafbf3ab9))
|
|
344
|
+
* **roadmap:** mark MCP Phase 3 + Phase 5 done ([9ec9494](https://github.com/event4u-app/agent-config/commit/9ec9494be18b6634dcf4383af921b54f283c86ff))
|
|
345
|
+
* **mcp:** canonical MCP server setup guide ([4fd149f](https://github.com/event4u-app/agent-config/commit/4fd149f0b1c6e6b009d2bdd3b4ea80759e31055d))
|
|
346
|
+
* **roadmap:** mark MCP Phase 2 (B1-B5) done + extend scope contract ([5ea1c56](https://github.com/event4u-app/agent-config/commit/5ea1c56d027f432f9c950e8b35805ab91758fd26))
|
|
347
|
+
* **roadmap:** mark MCP Phase 1 (A1–A7) done + record stdio smoke transcript ([aaf8332](https://github.com/event4u-app/agent-config/commit/aaf833292aba530bdeae138fa2255b4576fe699c))
|
|
348
|
+
* **mcp:** add Phase 1 scope contract (experimental, read-only) ([2fa275e](https://github.com/event4u-app/agent-config/commit/2fa275eec70c02741b76abef2b6356c7d0d1c6a7))
|
|
349
|
+
|
|
350
|
+
### Tests
|
|
351
|
+
|
|
352
|
+
* **mcp:** cover Phase 6 F1 identity metadata ([d3f79ef](https://github.com/event4u-app/agent-config/commit/d3f79eff30f61914fe09667693b41e2ed8c29855))
|
|
353
|
+
* **mcp:** cover Phase 4 tool layer ([217c4ab](https://github.com/event4u-app/agent-config/commit/217c4ab2ed1041006e1ac3102369b8c1569f3653))
|
|
354
|
+
* **mcp:** cover Phase 2 — full coverage, pagination, hot-reload ([f93c019](https://github.com/event4u-app/agent-config/commit/f93c0199adc558119be614fadd677cf37c8c2d5a))
|
|
355
|
+
* **mcp:** make loader tests run when mcp SDK is absent ([8378621](https://github.com/event4u-app/agent-config/commit/8378621be8ec24ccba59be10c49a4384abdc335f))
|
|
356
|
+
* **mcp:** cover Phase 1 loader + import-surface guard + server handlers ([f4fee8b](https://github.com/event4u-app/agent-config/commit/f4fee8b899b0163ea2bfe7099ffa9221b70bf488))
|
|
357
|
+
|
|
358
|
+
### Chores
|
|
359
|
+
|
|
360
|
+
* **roadmap:** close road-to-mcp-server at 100%, defer F4 to distribution ([0127991](https://github.com/event4u-app/agent-config/commit/01279913f3b2a5caa1eb65f8a7b07a2f841d41af))
|
|
361
|
+
* **roadmap:** defer Phase 6 F2 to road-to-mcp-distribution ([b5e0be7](https://github.com/event4u-app/agent-config/commit/b5e0be7473296bfd5381dc1ace9bc99ae79f5090))
|
|
362
|
+
* **roadmap:** mark MCP Phase 4 (D1-D4) complete ([8c342c8](https://github.com/event4u-app/agent-config/commit/8c342c8508f17133d71528b16d727d5c3c56acfd))
|
|
363
|
+
* **mcp:** add task mcp:setup for one-line install ([ae1f6f9](https://github.com/event4u-app/agent-config/commit/ae1f6f9d355dd5a782fdadb5e67929552caab5ed))
|
|
364
|
+
* ignore .venv-mcp/ for MCP server work ([8bd44d4](https://github.com/event4u-app/agent-config/commit/8bd44d49e359021a000a989bfd7ae7f6f48800db))
|
|
365
|
+
|
|
366
|
+
Tests: 2679 (+58 since 1.36.1)
|
|
367
|
+
|
|
368
|
+
## [1.36.1](https://github.com/event4u-app/agent-config/compare/1.36.0...1.36.1) (2026-05-10)
|
|
369
|
+
|
|
370
|
+
### Refactoring
|
|
371
|
+
|
|
372
|
+
* **scope-control:** extract roadmap-shape, kernel-rule-edits, fenced-step detail to scope-mechanics ([e52c834](https://github.com/event4u-app/agent-config/commit/e52c834a672e6f24b1b7c1608e481b7f45a46054))
|
|
373
|
+
|
|
374
|
+
### Chores
|
|
375
|
+
|
|
376
|
+
* **generate-tools:** regenerate .windsurfrules for scope-control extraction ([ee7664e](https://github.com/event4u-app/agent-config/commit/ee7664ee6cd0ec5aacdf95b5e4ec1000e01a0121))
|
|
377
|
+
|
|
378
|
+
Tests: 2621 (+0 since 1.36.0)
|
|
379
|
+
|
|
321
380
|
## [1.36.0](https://github.com/event4u-app/agent-config/compare/1.35.0...1.36.0) (2026-05-10)
|
|
322
381
|
|
|
323
382
|
### Features
|
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ Install in the same project (dev-only):
|
|
|
109
109
|
npm install --save-dev @event4u/agent-memory
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
→ [Memory contract & retrieval API](docs/contracts/agent-memory-contract.md) (beta)
|
|
112
|
+
→ [Memory contract & retrieval API](docs/contracts/agent-memory-contract.md) (beta) · [Built-in MCP server](docs/mcp-server.md) (experimental — read-only access from Claude Desktop / Cursor / Zed / Continue, install with `task mcp:setup`)
|
|
113
113
|
|
|
114
114
|
---
|
|
115
115
|
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: experimental
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# MCP Server — Phase 1–6 Scope (A0 Hard Contract)
|
|
6
|
+
|
|
7
|
+
> **Status:** Active · covers Phase 1 (A1–A7) + Phase 2 (B1–B5) +
|
|
8
|
+
> Phase 3 (C1–C4) + Phase 4 (D1–D4) + Phase 6 F1/F3 of
|
|
9
|
+
> `road-to-mcp-server.md`. Phase 6 F2 (SSE transport) is deferred to
|
|
10
|
+
> [`road-to-mcp-distribution.md`](../../agents/roadmaps/road-to-mcp-distribution.md)
|
|
11
|
+
> and remains out of scope here.
|
|
12
|
+
> **Stability:** experimental — not linked from README, AGENTS.md, or
|
|
13
|
+
> `docs/architecture.md`. Internal index reference only per `STABILITY.md`.
|
|
14
|
+
|
|
15
|
+
## Purpose
|
|
16
|
+
|
|
17
|
+
Locks the **execution-safety boundary** for the MCP server through
|
|
18
|
+
Phase 2. Any code under `scripts/mcp_server/` must satisfy this
|
|
19
|
+
contract verbatim. Deviation → not Phase 1/2; promote to a follow-up
|
|
20
|
+
phase with its own design-call gate.
|
|
21
|
+
|
|
22
|
+
## In-scope (Phase 1 + Phase 2)
|
|
23
|
+
|
|
24
|
+
- Transport: **stdio**. No SSE, no HTTP, no WebSocket.
|
|
25
|
+
- MCP primitives: **`prompts/list`** + **`prompts/get`** — read-only.
|
|
26
|
+
- Source data: **`.agent-src/skills/<name>/SKILL.md`** and
|
|
27
|
+
**`.agent-src/commands/**/*.md`** (compressed projections, never the
|
|
28
|
+
uncompressed source-of-truth tree).
|
|
29
|
+
- Loaded set (Phase 2): every well-formed skill + command under
|
|
30
|
+
`.agent-src/` (Phase 1 hand-picked set retained as a smoke fixture
|
|
31
|
+
in `prompts.py::PHASE_1_SKILLS`).
|
|
32
|
+
- **Pagination** (B4): cursor-based `nextCursor` on `prompts/list`,
|
|
33
|
+
default `page_size=100`. Cursor is an opaque stringified offset.
|
|
34
|
+
- **Hot-reload** (B5): `PromptCache` re-scans on mtime / path-set
|
|
35
|
+
change before each `prompts/list` response. No background thread,
|
|
36
|
+
no inotify, no debounce — the request itself is the rate-limiter.
|
|
37
|
+
- **Frontmatter validation** (B3): entries missing `name` or
|
|
38
|
+
`description` are skipped with a stderr warning at boot; malformed
|
|
39
|
+
files do not crash the server.
|
|
40
|
+
- Process lifetime: one server per project, launched per-client by the
|
|
41
|
+
consumer (Claude Desktop, Zed, Continue) at MCP-config time.
|
|
42
|
+
|
|
43
|
+
## Out-of-scope (Phase 1 + Phase 2)
|
|
44
|
+
|
|
45
|
+
- **`tools/*` beyond the Phase 4 allowlist** — only the two
|
|
46
|
+
built-in tools listed below in *Phase 4 amendment* are reachable.
|
|
47
|
+
Any other name raises `ValueError`. `work_engine` is not exposed.
|
|
48
|
+
- **`resources/*` beyond rules / guidelines / contexts** — no model
|
|
49
|
+
outputs, no roadmaps, no chat history surfaced as resources.
|
|
50
|
+
- **Filesystem writes outside the Phase 4 write allowlist** — the only
|
|
51
|
+
writable targets are `agents/.agent-chat-history` and
|
|
52
|
+
`.agent-chat-history` under `<consumer_root>`. No log files, no
|
|
53
|
+
telemetry writes, no `.work-state.json` mutation.
|
|
54
|
+
- **Direct shell execution from `mcp_server/*`** — modules under
|
|
55
|
+
`scripts/mcp_server/` do not `import subprocess`, `os.system`, or
|
|
56
|
+
`os.popen` directly. Project helpers that internally spawn shells
|
|
57
|
+
(`skill_linter`'s `--changed` git mode, etc.) may be called only via
|
|
58
|
+
read-only wrappers that bypass those code paths.
|
|
59
|
+
- **Network egress** — the server does not call external APIs;
|
|
60
|
+
the AI Council, anthropic SDK, and openai SDK are not imported by
|
|
61
|
+
any module under `scripts/mcp_server/`.
|
|
62
|
+
- **Authentication / multi-tenancy** — single-process, single-project.
|
|
63
|
+
Multi-tenant SSE is Phase 6 (F2).
|
|
64
|
+
|
|
65
|
+
## Static guarantees enforced by tests
|
|
66
|
+
|
|
67
|
+
`tests/test_mcp_server.py` asserts the boundary at unit level:
|
|
68
|
+
|
|
69
|
+
1. `prompts/list` returns the full skills + commands set with
|
|
70
|
+
`skill.<name>` and `command.<name>` wire-name prefixes.
|
|
71
|
+
2. `prompts/get` returns a non-empty `messages[].content.text` body
|
|
72
|
+
matching the SKILL.md / command-file body (frontmatter stripped).
|
|
73
|
+
3. `prompts/get` for an unknown name raises `ValueError` (no silent
|
|
74
|
+
fallback to filesystem scan).
|
|
75
|
+
4. `scripts.mcp_server.prompts` imports cleanly without `subprocess`,
|
|
76
|
+
`os.system`, `os.popen`, or any `requests` / `httpx` call.
|
|
77
|
+
5. `prompts/list` paginates with `nextCursor` and pages do not
|
|
78
|
+
overlap.
|
|
79
|
+
6. `PromptCache` re-scans on mtime change (hot-reload).
|
|
80
|
+
7. Malformed frontmatter is skipped with an error line, not crashed.
|
|
81
|
+
|
|
82
|
+
A future regression that adds a `tools/*` handler outside the
|
|
83
|
+
allowlist or writes outside the Phase 4 write allowlist fails the
|
|
84
|
+
import-surface + behaviour assertions and the contract review in code
|
|
85
|
+
review.
|
|
86
|
+
|
|
87
|
+
## Phase 4 amendment — tool allowlist (D1–D4)
|
|
88
|
+
|
|
89
|
+
Phase 4 lifts the read-only line for **exactly** the two built-in
|
|
90
|
+
tools registered in `scripts/mcp_server/tools.py::ALLOWLIST`. Every
|
|
91
|
+
other tool name is unreachable: `tools/call` against an unlisted name
|
|
92
|
+
returns `isError=True`.
|
|
93
|
+
|
|
94
|
+
| Tool name | Mode | Side effects |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| `lint_skills` | read-only | Wraps `scripts.skill_linter.lint_file`. Never spawns `git` (no `--changed`). Returns the same JSON shape as `scripts/skill_linter.py --format json`. |
|
|
97
|
+
| `chat_history_append` | path-scoped write | Wraps `scripts.chat_history.append`. Writes are allowed only when the resolved target is `agents/.agent-chat-history` or `.agent-chat-history` under `<consumer_root>`. `dry_run=True` validates the payload without touching the filesystem. |
|
|
98
|
+
|
|
99
|
+
**Path-scoping invariant** — any tool that writes must resolve its
|
|
100
|
+
target through `_validate_in_tree_path` before the underlying writer
|
|
101
|
+
runs. Escapes (absolute paths outside the root, relative paths that
|
|
102
|
+
resolve outside, or filenames not in the write allowlist) raise
|
|
103
|
+
`ValueError` and surface as `isError=True` in `tools/call`.
|
|
104
|
+
|
|
105
|
+
**Boot-time enumeration** — `run_stdio` prints one stderr line
|
|
106
|
+
listing the registered tool names so operators see the surface at
|
|
107
|
+
launch. Adding a tool to `ALLOWLIST` is a code-review event; no
|
|
108
|
+
settings flag can enable an unlisted tool.
|
|
109
|
+
|
|
110
|
+
Additional tool tests in `tests/test_mcp_server.py`:
|
|
111
|
+
|
|
112
|
+
8. `tools/list` returns exactly the allowlisted names.
|
|
113
|
+
9. `tools/call` against a valid `dry_run` payload returns
|
|
114
|
+
`isError=False` with a JSON-serialized result.
|
|
115
|
+
10. `tools/call` with a path escape returns `isError=True` referencing
|
|
116
|
+
the escape — no exception propagates past the handler.
|
|
117
|
+
11. `tools/call` against an unknown tool name returns `isError=True`.
|
|
118
|
+
12. `scripts.mcp_server.tools` does not import `subprocess`,
|
|
119
|
+
`os.system`, `os.popen`, or any HTTP client directly.
|
|
120
|
+
|
|
121
|
+
## Phase 6 amendment — identity metadata + Docker bundle (F1, F3)
|
|
122
|
+
|
|
123
|
+
Phase 6 adds **observability** and **packaging** without changing the
|
|
124
|
+
A0 wire surface. F2 (SSE transport) is explicitly deferred — see
|
|
125
|
+
status header.
|
|
126
|
+
|
|
127
|
+
### F1 — Identity metadata
|
|
128
|
+
|
|
129
|
+
Three values surface at server boot, written to **stderr** in a single
|
|
130
|
+
`mcp-server: identity …` line (the canonical surface — the high-level
|
|
131
|
+
MCP SDK builds `serverInfo` with a fixed field set, so wire-surface
|
|
132
|
+
lift waits on SDK support):
|
|
133
|
+
|
|
134
|
+
- **`serverVersion`** — hand-maintained SemVer in
|
|
135
|
+
`scripts/mcp_server/__init__.py::__version__`. Bumps on
|
|
136
|
+
**wire-surface** changes only: new tool, new resource MIME type,
|
|
137
|
+
protocol-level break. Does **not** bump for content edits inside
|
|
138
|
+
`.agent-src/`.
|
|
139
|
+
- **`packageVersion`** — read from `package.json::version` at boot.
|
|
140
|
+
Bumps on every agent-config bundle release; build-ID semantics, not
|
|
141
|
+
a stability signal.
|
|
142
|
+
- **`skillSetSignature`** — first 12 hex chars of the SHA-256 over the
|
|
143
|
+
joined sorted `(path, mtime)` tuples of `PromptCache` and
|
|
144
|
+
`ResourceCache`. **Not a version** — a content fingerprint. Auto-
|
|
145
|
+
updates with every `task sync`; intended for cache-key /
|
|
146
|
+
reproducibility use, never for SemVer-style compatibility claims.
|
|
147
|
+
|
|
148
|
+
Implementation: `scripts/mcp_server/metadata.py`. The signature is
|
|
149
|
+
deterministic for a given snapshot of the loaded file set; any mtime
|
|
150
|
+
change invalidates it.
|
|
151
|
+
|
|
152
|
+
### F3 — Stdio Docker bundle
|
|
153
|
+
|
|
154
|
+
`docker/mcp-server/Dockerfile` ships a stdio-only image. The contract:
|
|
155
|
+
|
|
156
|
+
- **No HTTP / SSE listener** in the image. Stdio is the only wire.
|
|
157
|
+
- The image embeds `scripts/mcp_server/`, the two tool dependencies
|
|
158
|
+
(`scripts/skill_linter.py`, `scripts/chat_history.py`),
|
|
159
|
+
`.agent-src/`, `docs/guidelines/`, and `package.json`. Nothing
|
|
160
|
+
outside the COPY-listed paths reaches the runtime stage.
|
|
161
|
+
- The image runs as a non-root user (`mcp:mcp`); host volumes mounted
|
|
162
|
+
for `chat_history_append` writes must be writable by that uid/gid.
|
|
163
|
+
- The A0 contract from Phase 1–4 transfers verbatim — the import-
|
|
164
|
+
surface guard tests run identically inside and outside the image.
|
|
165
|
+
|
|
166
|
+
Operator documentation: `docs/setup/mcp-server-docker.md`. The image
|
|
167
|
+
does not introduce a new tool, resource type, or protocol surface.
|
|
168
|
+
|
|
169
|
+
### What Phase 6 explicitly does **not** add
|
|
170
|
+
|
|
171
|
+
- **No HTTP/SSE transport**, native or otherwise. F2 is deferred to
|
|
172
|
+
the successor roadmap; revival is gated on a real consumer ask, and
|
|
173
|
+
the locked design is the bridge pattern from
|
|
174
|
+
[`mcp-request-signing § Appendix`](../guidelines/agent-infra/mcp-request-signing.md#appendix--http-bridge-stdio-kernel-pattern-reference)
|
|
175
|
+
— never a native SSE server inside `scripts/mcp_server/`.
|
|
176
|
+
- **No new tools** beyond the Phase 4 allowlist.
|
|
177
|
+
- **No multi-tenancy** — the Docker image is single-tenant, one
|
|
178
|
+
process per stdio session. Multi-tenancy lives with the future
|
|
179
|
+
bridge, not the kernel.
|
|
180
|
+
|
|
181
|
+
## Revision policy
|
|
182
|
+
|
|
183
|
+
This contract is **experimental** — breaking changes are allowed in any
|
|
184
|
+
release with a CHANGELOG note. Promotion to `beta` follows the same
|
|
185
|
+
gate as Phase 1 itself: at least one shipped client renders Phase 1
|
|
186
|
+
prompts end-to-end without a contract amendment.
|
|
187
|
+
|
|
188
|
+
## See also
|
|
189
|
+
|
|
190
|
+
- [`STABILITY.md`](STABILITY.md) — stability policy for `docs/contracts/`.
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# MCP Server
|
|
2
|
+
|
|
3
|
+
> Status: **experimental** — Phase 1 + 2 + 3 shipped. No `tools/*` primitive yet (Phase 4, deferred behind a design call).
|
|
4
|
+
|
|
5
|
+
`agent-config` ships a built-in [Model Context Protocol](https://modelcontextprotocol.io)
|
|
6
|
+
server that exposes the package's read-only governance surface to MCP-aware
|
|
7
|
+
clients (Claude Desktop, Cursor, Zed, Continue, Codex via MCP). Two channels
|
|
8
|
+
coexist:
|
|
9
|
+
|
|
10
|
+
- **File projection** — `task generate-tools` writes `.claude/`, `.cursor/`,
|
|
11
|
+
`.clinerules/`, `.windsurfrules`. Used by Aider, Cline, Windsurf, Gemini CLI.
|
|
12
|
+
- **MCP server** — `scripts/mcp_server/` exposes the same content over
|
|
13
|
+
JSON-RPC. Used by clients that speak MCP natively.
|
|
14
|
+
|
|
15
|
+
The MCP server **never executes engine code, never writes files, never spawns
|
|
16
|
+
shells**. It is a read-only instructional surface — see
|
|
17
|
+
[`docs/contracts/mcp-phase-1-scope.md`](contracts/mcp-phase-1-scope.md).
|
|
18
|
+
|
|
19
|
+
## What the server exposes
|
|
20
|
+
|
|
21
|
+
| Primitive | URIs | Source | Count (this package) |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| `prompts/list` + `prompts/get` | `skill.<name>`, `command.<name>` | `.agent-src/skills/`, `.agent-src/commands/` | 174 skills + 104 commands |
|
|
24
|
+
| `resources/list` + `resources/read` | `rule://<stem>` | `.agent-src/rules/` | 60 rules |
|
|
25
|
+
| ↳ | `guideline://<relpath>` | `docs/guidelines/` | 69 guidelines |
|
|
26
|
+
| ↳ | `context://<relpath>` | `.agent-src/contexts/` | 31 contexts |
|
|
27
|
+
|
|
28
|
+
All resources are served with `mimeType: text/markdown`. Pagination is
|
|
29
|
+
cursor-based (default page size: 100). Hot-reload triggers automatically on
|
|
30
|
+
file mtime changes — edit a rule, reissue `resources/list`, see the update.
|
|
31
|
+
|
|
32
|
+
## Setup — one-line install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
task mcp:setup # maintainer / dev repo
|
|
36
|
+
./agent-config mcp:setup # consumer projects (uses the package CLI wrapper)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Either form creates `.venv-mcp/` (Python 3.11+), installs the `mcp` SDK, and
|
|
40
|
+
prints the client config snippet. Run once per checkout.
|
|
41
|
+
|
|
42
|
+
If you do not have `task` or the CLI wrapper available:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
bash scripts/mcp_setup.sh
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Running the server
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
task mcp:run # maintainer / dev repo
|
|
52
|
+
./agent-config mcp:run # consumer projects
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Both forms launch `python -m scripts.mcp_server` over stdio against the
|
|
56
|
+
local `.venv-mcp/`. Use these for ad-hoc smoke tests; long-running clients
|
|
57
|
+
(Claude Desktop, Cursor, Zed, Continue) launch the server themselves via
|
|
58
|
+
the config snippets below.
|
|
59
|
+
|
|
60
|
+
## Client configuration
|
|
61
|
+
|
|
62
|
+
### Claude Desktop
|
|
63
|
+
|
|
64
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
65
|
+
or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"agent-config": {
|
|
71
|
+
"command": "/absolute/path/to/agent-config/.venv-mcp/bin/python",
|
|
72
|
+
"args": ["-m", "scripts.mcp_server"],
|
|
73
|
+
"cwd": "/absolute/path/to/agent-config"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Restart Claude Desktop. The skills, commands, rules, guidelines, and contexts
|
|
80
|
+
appear under the connector dropdown.
|
|
81
|
+
|
|
82
|
+
### Cursor
|
|
83
|
+
|
|
84
|
+
`~/.cursor/mcp.json` (or `<repo>/.cursor/mcp.json`):
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"agent-config": {
|
|
90
|
+
"command": "/absolute/path/to/agent-config/.venv-mcp/bin/python",
|
|
91
|
+
"args": ["-m", "scripts.mcp_server"],
|
|
92
|
+
"cwd": "/absolute/path/to/agent-config"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Zed
|
|
99
|
+
|
|
100
|
+
`~/.config/zed/settings.json`:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"context_servers": {
|
|
105
|
+
"agent-config": {
|
|
106
|
+
"command": {
|
|
107
|
+
"path": "/absolute/path/to/agent-config/.venv-mcp/bin/python",
|
|
108
|
+
"args": ["-m", "scripts.mcp_server"]
|
|
109
|
+
},
|
|
110
|
+
"settings": {}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Continue (`continue.dev`)
|
|
117
|
+
|
|
118
|
+
`~/.continue/config.yaml`:
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
mcpServers:
|
|
122
|
+
- name: agent-config
|
|
123
|
+
command: /absolute/path/to/agent-config/.venv-mcp/bin/python
|
|
124
|
+
args: ["-m", "scripts.mcp_server"]
|
|
125
|
+
cwd: /absolute/path/to/agent-config
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Smoke test
|
|
129
|
+
|
|
130
|
+
After configuring a client, run a manual stdio handshake to verify the server
|
|
131
|
+
boots cleanly:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
./agent-config mcp:run < /dev/null
|
|
135
|
+
# Expect stderr: "mcp-server: loaded N prompts (0 warnings)" and
|
|
136
|
+
# "mcp-server: loaded 160 resources (0 warnings)"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Troubleshooting
|
|
140
|
+
|
|
141
|
+
| Symptom | Fix |
|
|
142
|
+
|---|---|
|
|
143
|
+
| Client shows no prompts | Confirm the `cwd` points at the repo root (where `.agent-src/` lives), not at `scripts/`. |
|
|
144
|
+
| `ModuleNotFoundError: mcp` | Re-run `task mcp:setup`. The MCP runtime is isolated in `.venv-mcp/` — the project's base Python 3.9 deliberately does not see it. |
|
|
145
|
+
| Stale prompts after editing | Hot-reload triggers on mtime; touch the file or reissue `resources/list`. |
|
|
146
|
+
| Client refuses to start the server | Check the client's log for the full command. Most clients require **absolute** paths in `command` and `cwd`. |
|
|
147
|
+
|
|
148
|
+
## Scope
|
|
149
|
+
|
|
150
|
+
- **In scope:** read-only prompts + resources, pagination, hot-reload, stdio
|
|
151
|
+
transport, free-tier client compatibility.
|
|
152
|
+
- **Out of scope (Phase 4+):** `tools/*` primitive, SSE / HTTP transport,
|
|
153
|
+
cloud distribution, signed payloads. Tracked in
|
|
154
|
+
[`agents/roadmaps/road-to-mcp-server.md`](../agents/roadmaps/road-to-mcp-server.md).
|
|
155
|
+
|
|
156
|
+
← [Architecture](architecture.md) · [MCP config generation (consumer side)](mcp.md)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# MCP server — Docker (stdio bundle)
|
|
2
|
+
|
|
3
|
+
Phase-6 F3 ships `docker/mcp-server/Dockerfile`: a stdio-only image of
|
|
4
|
+
the agent-config MCP server, pinned to the same `mcp` + `PyYAML`
|
|
5
|
+
versions the test suite runs against. No HTTP / SSE transport — that
|
|
6
|
+
lives in [`road-to-mcp-distribution.md`](../../agents/roadmaps/road-to-mcp-distribution.md)
|
|
7
|
+
under its own A0 amendment.
|
|
8
|
+
|
|
9
|
+
## Build
|
|
10
|
+
|
|
11
|
+
Build context is the **repo root**, not `docker/mcp-server/` — the
|
|
12
|
+
`COPY` lines reference paths relative to the project root.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
docker build -f docker/mcp-server/Dockerfile -t agent-config-mcp:local .
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Tag conventions:
|
|
19
|
+
|
|
20
|
+
- `:local` — your machine, current working tree
|
|
21
|
+
- `:vX.Y.Z` — pinned to `package.json::version` at release time
|
|
22
|
+
- `:latest` — most recent release (avoid in MCP client configs; pin)
|
|
23
|
+
|
|
24
|
+
## Run (stdio)
|
|
25
|
+
|
|
26
|
+
The image speaks MCP over **stdin / stdout**. `docker run` must be
|
|
27
|
+
invoked with `-i` (interactive stdin) — without it the server has
|
|
28
|
+
nothing to read and exits silently.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
docker run --rm -i agent-config-mcp:local
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
You should see, on **stderr**:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
mcp-server: loaded 278 prompts (0 warnings)
|
|
38
|
+
mcp-server: loaded 160 resources (0 warnings)
|
|
39
|
+
mcp-server: registered 2 tools: ['chat_history_append', 'lint_skills']
|
|
40
|
+
mcp-server: identity serverVersion=0.1.0 packageVersion=1.36.1 skillSetSignature=<12-hex>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The fourth line is the F1 identity surface — see
|
|
44
|
+
[`mcp-phase-1-scope.md § Phase 6`](../contracts/mcp-phase-1-scope.md)
|
|
45
|
+
for semantics.
|
|
46
|
+
|
|
47
|
+
## Wire into an MCP client
|
|
48
|
+
|
|
49
|
+
```jsonc
|
|
50
|
+
// .mcp.json (or your client's equivalent)
|
|
51
|
+
{
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"agent-config": {
|
|
54
|
+
"command": "docker",
|
|
55
|
+
"args": ["run", "--rm", "-i", "agent-config-mcp:vX.Y.Z"]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Volume mounts (`chat_history_append`)
|
|
62
|
+
|
|
63
|
+
The `chat_history_append` tool writes to
|
|
64
|
+
`agents/.agent-chat-history` **inside the container**. For writes to
|
|
65
|
+
survive container lifecycle, mount the host directory:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
docker run --rm -i \
|
|
69
|
+
-v "$(pwd)/agents/.agent-chat-history:/app/agents/.agent-chat-history" \
|
|
70
|
+
agent-config-mcp:local
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Without the mount the tool still succeeds (path-scope check passes
|
|
74
|
+
inside the container), but the appended JSONL evaporates when the
|
|
75
|
+
container exits. The `lint_skills` tool is read-only and needs no
|
|
76
|
+
mount.
|
|
77
|
+
|
|
78
|
+
## Security posture
|
|
79
|
+
|
|
80
|
+
The image inherits the A0 contract verbatim — see
|
|
81
|
+
[`mcp-phase-1-scope.md`](../contracts/mcp-phase-1-scope.md):
|
|
82
|
+
|
|
83
|
+
- No `subprocess`, `os.system`, `requests`, `httpx`, or `urllib`
|
|
84
|
+
imports anywhere on the MCP wire surface (enforced by
|
|
85
|
+
`test_no_unsafe_imports_in_*` tests).
|
|
86
|
+
- Tools allowlist is hardcoded in `scripts/mcp_server/tools.py`. The
|
|
87
|
+
container cannot grow new tools at runtime.
|
|
88
|
+
- Image runs as a non-root user (`mcp:mcp`). Mounted host paths must
|
|
89
|
+
be writable by uid/gid `999` or you'll see permission errors.
|
|
90
|
+
- No HTTP listener — there is no network attack surface. Stdin/stdout
|
|
91
|
+
only.
|
|
92
|
+
|
|
93
|
+
## Size
|
|
94
|
+
|
|
95
|
+
The runtime stage is `python:3.11-slim` + the pinned deps + the
|
|
96
|
+
`.agent-src/` content. Expect ~150-200 MB; the builder stage is
|
|
97
|
+
discarded.
|
package/package.json
CHANGED
package/scripts/agent-config
CHANGED
|
@@ -44,6 +44,10 @@ Commands:
|
|
|
44
44
|
mcp:render Render mcp.json → .cursor/mcp.json, .windsurf/mcp.json
|
|
45
45
|
(pass --claude-desktop to also write user-scope config)
|
|
46
46
|
mcp:check Dry-run mcp:render; exit non-zero if targets are stale
|
|
47
|
+
mcp:setup Create .venv-mcp/ and install the mcp SDK
|
|
48
|
+
(one-line MCP server onboarding; idempotent)
|
|
49
|
+
mcp:run Run the built-in MCP server over stdio
|
|
50
|
+
(requires `mcp:setup` first; see docs/mcp-server.md)
|
|
47
51
|
roadmap:progress Regenerate agents/roadmaps-progress.md from open roadmaps
|
|
48
52
|
roadmap:progress-check Fail if agents/roadmaps-progress.md is stale (for CI)
|
|
49
53
|
hooks:install Install the pre-commit roadmap-progress hook
|
|
@@ -97,6 +101,8 @@ Examples:
|
|
|
97
101
|
./agent-config mcp:render
|
|
98
102
|
./agent-config mcp:render --claude-desktop
|
|
99
103
|
./agent-config mcp:check
|
|
104
|
+
./agent-config mcp:setup
|
|
105
|
+
./agent-config mcp:run
|
|
100
106
|
./agent-config roadmap:progress
|
|
101
107
|
./agent-config hooks:install
|
|
102
108
|
./agent-config keys:install-anthropic
|
|
@@ -198,6 +204,27 @@ cmd_mcp_check() {
|
|
|
198
204
|
exec python3 "$script" --check "$@"
|
|
199
205
|
}
|
|
200
206
|
|
|
207
|
+
cmd_mcp_setup() {
|
|
208
|
+
local script
|
|
209
|
+
script="$(resolve_script "scripts/mcp_setup.sh")" || return 1
|
|
210
|
+
exec bash "$script" "$@"
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
# Run the built-in stdio MCP server. The server module ships inside the
|
|
214
|
+
# package (PACKAGE_ROOT/scripts/mcp_server/), but the venv is created by
|
|
215
|
+
# `mcp_setup.sh` at CWD — keeping consumer projects in control of where
|
|
216
|
+
# the SDK install lives. PYTHONPATH points at PACKAGE_ROOT so the
|
|
217
|
+
# `scripts.mcp_server` import resolves regardless of CWD.
|
|
218
|
+
cmd_mcp_run() {
|
|
219
|
+
local venv_py="$CONSUMER_ROOT/.venv-mcp/bin/python"
|
|
220
|
+
if [[ ! -x "$venv_py" ]]; then
|
|
221
|
+
echo "❌ agent-config: .venv-mcp/ not found at $CONSUMER_ROOT/.venv-mcp" >&2
|
|
222
|
+
echo " Run \`./agent-config mcp:setup\` first to create it." >&2
|
|
223
|
+
exit 1
|
|
224
|
+
fi
|
|
225
|
+
exec env PYTHONPATH="$PACKAGE_ROOT" "$venv_py" -m scripts.mcp_server "$@"
|
|
226
|
+
}
|
|
227
|
+
|
|
201
228
|
cmd_roadmap_progress() {
|
|
202
229
|
require_python3
|
|
203
230
|
local script
|
|
@@ -484,6 +511,8 @@ main() {
|
|
|
484
511
|
case "$cmd" in
|
|
485
512
|
mcp:render) cmd_mcp_render "$@" ;;
|
|
486
513
|
mcp:check) cmd_mcp_check "$@" ;;
|
|
514
|
+
mcp:setup) cmd_mcp_setup "$@" ;;
|
|
515
|
+
mcp:run) cmd_mcp_run "$@" ;;
|
|
487
516
|
roadmap:progress) cmd_roadmap_progress "$@" ;;
|
|
488
517
|
roadmap:progress-check) cmd_roadmap_progress_check "$@" ;;
|
|
489
518
|
hooks:install) cmd_hooks_install "$@" ;;
|