@softspark/ai-toolkit 3.1.0 → 3.2.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.
@@ -0,0 +1,158 @@
1
+ ---
2
+ title: "PRD: MCP Context Trim v4.0 — Local Proxy with Description Compression"
3
+ category: planning
4
+ service: ai-toolkit
5
+ tags:
6
+ - mcp
7
+ - proxy
8
+ - tool-descriptions
9
+ - jsonrpc
10
+ - tokens
11
+ - v4
12
+ doc_type: plan
13
+ status: proposed
14
+ created: "2026-05-04"
15
+ last_updated: "2026-05-04"
16
+ completion: "0%"
17
+ target_milestone: "v4.0"
18
+ predecessor:
19
+ - "kb/history/completed/output-token-discipline-plan-20260504.md"
20
+ - "kb/history/completed/f2-mcp-trim-spike-20260504.md"
21
+ description: "Local MCP proxy server that compresses tool descriptions before they reach the model. Carved out of the v3.2.0 output-token-discipline plan (Feature 2), deferred after the 2026-05-04 spike showed Claude Code hooks cannot modify tools/list metadata. Targets ~8-15k token reduction per session for users with many MCP servers."
22
+ ---
23
+
24
+ # PRD: MCP Context Trim v4.0
25
+
26
+ **Status:** Proposed
27
+ **Target milestone:** v4.0
28
+ **Carved out of:** [`output-token-discipline-plan-20260504.md`](../history/completed/output-token-discipline-plan-20260504.md) (was Feature 2)
29
+ **Spike basis:** [`f2-mcp-trim-spike-20260504.md`](../history/completed/f2-mcp-trim-spike-20260504.md)
30
+
31
+ ## Problem
32
+
33
+ MCP server tool descriptions are injected into every model turn's system prompt. With ~100 tools across 7 typical servers, descriptions consume 8–15k tokens per turn — pure overhead, paid every message. Examples observed in users' configs:
34
+
35
+ - `dart-mcp-server` — ~30 tools with multi-paragraph descriptions
36
+ - `filesystem` — verbose paths and example sections
37
+ - `pencil` — "IMPORTANT" stanzas repeated across tools
38
+ - `jira-mcp` — long `Use this tool to…` boilerplate
39
+
40
+ The v3.2.0 output-discipline plan attempted to solve this with a hook-based trimmer. The spike conducted 2026-05-04 proved Claude Code hooks do not expose `tools/list` metadata or the system-prompt tool catalog. The only viable architecture is a local MCP proxy.
41
+
42
+ ## Goal
43
+
44
+ Reduce MCP-description overhead by ≥40% per server, with **zero** loss of parameter schemas, required fields, or discrimination signals (`not`, `never`, `only`, `except`, `unless`).
45
+
46
+ ## Non-goals
47
+
48
+ - Modifying tool **call** behavior (only descriptions)
49
+ - Compressing user-facing prompts or completions
50
+ - Replacing or rewriting upstream MCP servers
51
+ - Touching MCP servers we do not control
52
+
53
+ ## Architecture
54
+
55
+ ### Proxy topology
56
+
57
+ ```
58
+ Claude Code ──stdio──▶ ai-toolkit MCP proxy ──stdio/SSE──▶ upstream MCP server
59
+
60
+ └─ rewrites tools/list response
61
+ passes through tools/call unchanged
62
+ ```
63
+
64
+ One proxy process per upstream server, supervised by `ai-toolkit mcp-trim daemon` (or equivalent). User's `~/.claude/.mcp.json` is rewritten by `ai-toolkit install` (opt-in) to point Claude Code at the proxy instead of upstream — proxy reads the original target from a sidecar config.
65
+
66
+ ### Required components
67
+
68
+ | Component | Purpose |
69
+ |-----------|---------|
70
+ | `scripts/mcp_proxy_server.py` | JSON-RPC 2.0 proxy. Reads stdin, forwards to upstream over stdio or SSE, intercepts `tools/list` response, rewrites descriptions. Stdlib-only. |
71
+ | `scripts/mcp_description_trimmer.py` | Pure function library: `trim(description: str) → str`. Reused from heuristics below. Stdlib-only. |
72
+ | `scripts/mcp_proxy_config.py` | Reads `~/.softspark/ai-toolkit/mcp-proxy/servers.json`, validates upstream targets, generates supervisord/launchd config. |
73
+ | `app/hooks/mcp-proxy-health.sh` | SessionStart hook — verifies all configured proxies responsive; fall through (warn, do not block) if any down. |
74
+ | `app/skills/mcp-trim/SKILL.md` | Knowledge skill: how to enable, opt out, audit savings. |
75
+ | `bin/ai-toolkit-mcp-trim` | CLI: `enable`, `disable`, `status`, `audit` (per-server token savings report). |
76
+ | `tests/test_mcp_proxy.bats` | Integration tests with mock upstream MCP servers. |
77
+ | `tests/test_mcp_trimmer.bats` | Unit tests for description trim heuristics on captured fixtures. |
78
+
79
+ ### Compression heuristics (from spike)
80
+
81
+ Applied to each tool description in `tools/list` response:
82
+
83
+ - Drop example sections >40 chars
84
+ - Collapse `Use this server to…` / `Use this tool to…` boilerplate to minimum form preserving intent
85
+ - Drop duplicate occurrences of tool name in its own description
86
+ - **Preserve bytewise:** `inputSchema.properties[*].description`, `required`, `enum` values, URL/path identifiers
87
+ - **Never strip:** the words `not`, `never`, `only`, `except`, `unless` — these carry "when NOT to use" signals
88
+ - Target: ≥40% length reduction, 0% schema loss
89
+
90
+ ### Failure modes & rollback
91
+
92
+ | Scenario | Behavior |
93
+ |----------|----------|
94
+ | Proxy crashes mid-session | `mcp-proxy-health.sh` detects on next SessionStart, prints warning, suggests `ai-toolkit mcp-trim disable <server>` |
95
+ | Upstream MCP server changes its tool catalog | Proxy passes through unchanged tools (no cached schema), warns once if a tool's description was previously trimmed |
96
+ | Trimmer produces malformed JSON | Proxy falls through to upstream response unchanged, logs to `~/.softspark/ai-toolkit/mcp-proxy/error.log` |
97
+ | User wants to bypass | `AI_TOOLKIT_MCP_TRIM_DISABLE=1` env var → proxies pass everything through unchanged |
98
+ | User wants to fully uninstall | `ai-toolkit mcp-trim disable` reverts `~/.claude/.mcp.json` to original upstream targets |
99
+
100
+ ### Migration of existing user `.mcp.json`
101
+
102
+ `ai-toolkit mcp-trim enable` does:
103
+
104
+ 1. Backup `~/.claude/.mcp.json` → `~/.softspark/ai-toolkit/mcp-proxy/.mcp.json.bak.<timestamp>`
105
+ 2. Read each server entry, store in `~/.softspark/ai-toolkit/mcp-proxy/servers.json`
106
+ 3. Rewrite each entry to point at the local proxy (with sidecar `target` field)
107
+ 4. Spawn supervisor (per-OS: launchd on macOS, systemd on Linux, scheduled task on Windows)
108
+ 5. Verify each upstream reachable via proxy, abort + restore backup on any failure
109
+
110
+ ## Out-of-scope decisions (rejected mid-spike)
111
+
112
+ | Option | Why rejected |
113
+ |--------|--------------|
114
+ | Pre-install rewrite of `.mcp.json` only | MCP spec sources descriptions from server runtime, not config — wouldn't take effect |
115
+ | Source-side forks of MCP servers | Doesn't help users with custom servers; high maintenance |
116
+ | F2-lite observability tool | User decision 2026-05-04: tracking token waste without trimming is half-value; do the full thing in v4.0 |
117
+ | Hook-based interception | Spike proved hooks cannot reach `tools/list` |
118
+
119
+ ## Success criteria
120
+
121
+ - ≥40% description-length reduction per server on the captured fixture set (jira, filesystem, dart, pencil)
122
+ - Deep-equal `inputSchema` between trimmed and upstream — zero schema regression
123
+ - Proxy adds <50ms per `tools/list` call (one-time per session)
124
+ - Proxy adds <5ms per `tools/call` (passthrough overhead)
125
+ - Round-trip correctness: every tool callable via proxy returns byte-identical result vs direct call
126
+ - Zero MCP-skill regressions in `npm test` after enabling proxy in CI
127
+ - Rollback (`ai-toolkit mcp-trim disable`) restores byte-identical original `.mcp.json`
128
+
129
+ ## Open questions
130
+
131
+ 1. Process supervision per-OS — launchd / systemd / scheduled-task wrappers, or a built-in `ai-toolkit-mcp-trimd` daemon binary?
132
+ 2. SSE-mode upstreams (e.g., rag-mcp at `http://localhost:8081/mcp/sse`) — proxy listens on SSE locally too, or stdio-only with internal SSE client?
133
+ 3. Description rewrites — static dictionary of "boilerplate phrases to drop" (faster, deterministic) vs LLM-based summarizer (more aggressive, less predictable)? Recommend static for v4.0, LLM as v4.1 stretch.
134
+ 4. Config path — `~/.softspark/ai-toolkit/mcp-proxy/` (matches existing convention) or `~/.claude/mcp-proxy/` (closer to MCP config)? Recommend the former.
135
+ 5. Telemetry — does this become an opt-in metric in `/briefing --tokens` ("MCP descriptions: 12.3k → 7.2k, saved 5.1k per turn")? Recommend yes.
136
+
137
+ ## Pre-mortem (failure scenarios to design against)
138
+
139
+ 1. **Proxy gets out of sync with upstream** — upstream adds a new tool, proxy doesn't know how to compress it → passthrough that tool's description unchanged, log warning
140
+ 2. **Compression breaks tool discriminability** — model picks wrong tool because trimmed description lost the "use only when X" qualifier → the `not/never/only/except/unless` blacklist must be exhaustive; add per-server allowlists for false positives
141
+ 3. **Multi-process race on `.mcp.json` rewrite** — two `ai-toolkit install` invocations clobber each other → file lock during enable/disable
142
+ 4. **Proxy supervisor fails to start on user's machine** — different distro / no systemd → ai-toolkit doctor must detect and report; degrade to "MCP proxy unavailable, falling through" with no functionality loss
143
+ 5. **User has custom MCP server we don't recognize** — must work without per-server schema; default heuristics must be safe enough for arbitrary servers
144
+
145
+ ## Estimate
146
+
147
+ - Architecture spike + working proxy prototype: 2 days
148
+ - Production proxy + supervisor + config + CLI: 3 days
149
+ - Test suite + fixtures + CI integration: 2 days
150
+ - Documentation + migration guide + release notes: 1 day
151
+
152
+ **Total: ~8 working days** (1.5–2 weeks calendar time at typical pace)
153
+
154
+ ## Status
155
+
156
+ | Date | Status | Author |
157
+ |------|--------|--------|
158
+ | 2026-05-04 | PRD drafted from spike conclusions, carved out of v3.2.0 plan | claude |
@@ -3,10 +3,10 @@ title: "SOP: Release Verification"
3
3
  category: procedures
4
4
  service: ai-toolkit
5
5
  tags: [sop, verification, release, smoke-test, install, update, qa, provenance, sarif]
6
- version: "1.4.1"
6
+ version: "1.4.2"
7
7
  created: "2026-04-08"
8
- last_updated: "2026-04-28"
9
- description: "End-to-end smoke test after installing or updating @softspark/ai-toolkit — verifies CLI, install, doctor, validation, tests, eject, npm provenance attestation, SARIF audit, and per-skill permissions. Reflects the v2.8.0 supply-chain standard. v1.3.0 added the single-run npm test discipline; v1.4.0 adds v3.0.0 deep-coverage checks (--profile full, --codex-skills, breaking-change surfaces, idempotence, registry drift, live-JSON parse) and refreshes stale thresholds."
8
+ last_updated: "2026-04-29"
9
+ description: "End-to-end smoke test after installing or updating @softspark/ai-toolkit — verifies CLI, install, doctor, validation, tests, eject, npm provenance attestation, SARIF audit, and per-skill permissions. Reflects the v2.8.0 supply-chain standard. v1.3.0 added the single-run npm test discipline; v1.4.0 adds v3.0.0 deep-coverage checks (--profile full, --codex-skills, breaking-change surfaces, idempotence, registry drift, live-JSON parse) and refreshes stale thresholds. v1.4.2 makes the Phase 9.4 idempotence check deterministic by sorting file paths before hashing."
10
10
  ---
11
11
 
12
12
  # SOP: Release Verification
@@ -382,10 +382,13 @@ grep -q "\\.gemini/settings\\.json hooks" /tmp/aitk-breaking.log && echo "OK: Ge
382
382
 
383
383
  ```bash
384
384
  D=/tmp/aitk-idem-${RANDOM} && mkdir -p "$D" && cd "$D" && git init -q
385
+ # Sort file paths before hashing — find traversal order follows inode order,
386
+ # which can shift between runs even when content is byte-identical, producing
387
+ # false FAIL signals.
385
388
  ai-toolkit install --local --editors cursor,gemini --profile full >/dev/null 2>&1
386
- SHA1=$(find .cursor .gemini -type f -exec shasum {} + | shasum | awk '{print $1}')
389
+ SHA1=$(find .cursor .gemini -type f -print0 | LC_ALL=C sort -z | xargs -0 shasum | shasum | awk '{print $1}')
387
390
  ai-toolkit install --local --editors cursor,gemini --profile full >/dev/null 2>&1
388
- SHA2=$(find .cursor .gemini -type f -exec shasum {} + | shasum | awk '{print $1}')
391
+ SHA2=$(find .cursor .gemini -type f -print0 | LC_ALL=C sort -z | xargs -0 shasum | shasum | awk '{print $1}')
389
392
  [ "$SHA1" = "$SHA2" ] && echo "OK: idempotent" || echo "FAIL: install is not idempotent"
390
393
  ```
391
394
 
@@ -186,8 +186,8 @@ Three tiers determine how to approach a task:
186
186
  | Type | Field | Invocation | Count |
187
187
  |------|-------|-----------|-------|
188
188
  | Task | `disable-model-invocation: true` | User via `/skill` only | 32 |
189
- | Hybrid | (neither) | User via `/skill` + agent knowledge | 31 |
190
- | Knowledge | `user-invocable: false` | Claude auto-loads | 49 |
189
+ | Hybrid | (neither) | User via `/skill` + agent knowledge | 32 |
190
+ | Knowledge | `user-invocable: false` | Claude auto-loads | 48 |
191
191
 
192
192
  ## Multi-Agent Execution
193
193
 
@@ -62,7 +62,7 @@ Task skills execute a specific action. Invoked via slash commands. `disable-mode
62
62
  | **seo-validate** | `/seo-validate` | medium | Scan codebase for SEO issues: W3C semantics, meta/OG tags, Schema.org, hreflang, Core Web Vitals (LCP/INP/CLS), resource hints, GEO, SPA/SSG/CSR crawlability, technical SEO, accessibility-for-SEO. Framework-aware (Next/Nuxt/Astro/Gatsby/SvelteKit/Remix/Angular/Vue/static HTML). |
63
63
  | **mcp-builder** | `/mcp-builder` | high | Build production-grade MCP servers using the 4-phase methodology (research, implement, test, evaluate). TypeScript/Python, stdio/streamable-http. |
64
64
 
65
- ## Hybrid Skills (31)
65
+ ## Hybrid Skills (32)
66
66
 
67
67
  Hybrid skills combine slash-command invocation with domain knowledge that agents reference.
68
68
 
@@ -99,6 +99,7 @@ Hybrid skills combine slash-command invocation with domain knowledge that agents
99
99
  | **persona** | `/persona` | low | Switch engineering persona at runtime (backend-lead, frontend-lead, devops-eng, junior-dev) |
100
100
  | **council** | `/council` | high | 4-perspective decision evaluation (Advocate, Critic, Pragmatist, User-Proxy) with synthesis and confidence-rated recommendation. Tier 1, orchestrator, `context: fork`. |
101
101
  | **introspect** | `/introspect` | medium | Agent self-debugging: classify failure pattern, suggest smallest recovery action, emit structured introspection report |
102
+ | **brand-voice** | `/brand-voice` | medium | Anti-trope list, voice principles, LLM rhetoric prevention; output modes (`concise` ≤60% tokens, `strict` ≤40%) governing conversational responses. |
102
103
 
103
104
  ### `/workflow` types
104
105
 
@@ -120,7 +121,7 @@ Hybrid skills combine slash-command invocation with domain knowledge that agents
120
121
  | `application-deploy` | 3 | Deploy → smoke test → release notes |
121
122
  | `proactive-troubleshooting` | 4 | Investigate → check perf → preventive fix → docs |
122
123
 
123
- ## Knowledge Skills - Development (16)
124
+ ## Knowledge Skills - Development (15)
124
125
 
125
126
  | Skill | Directory | Domain |
126
127
  |-------|-----------|--------|
@@ -139,7 +140,6 @@ Hybrid skills combine slash-command invocation with domain knowledge that agents
139
140
  | **ruby-patterns** | `skills/ruby-patterns/` | Blocks, Rails conventions, RSpec, ActiveRecord |
140
141
  | **design-engineering** | `skills/design-engineering/` | UI polish, animation craft, easing, transforms, accessibility |
141
142
  | **documentation-standards** | `skills/documentation-standards/` | KB document conventions, frontmatter validation, category taxonomy |
142
- | **brand-voice** | `skills/brand-voice/` | Anti-trope list, voice principles, LLM rhetoric prevention |
143
143
 
144
144
  ## Knowledge Skills - Infrastructure (6)
145
145