@abarcenas/ai-workflow-template 1.23.0 β 1.26.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/.agents/instructions/agent-skill.instructions.md +18 -20
- package/.agents/instructions/agent.instructions.md +111 -570
- package/.agents/instructions/ai-prompt-engineering-safety.instructions.md +3 -3
- package/.agents/instructions/instructions.instructions.md +6 -7
- package/.agents/instructions/learned-knowledge.instructions.md +17 -41
- package/.agents/instructions/memory-bank.instructions.md +125 -17
- package/.agents/instructions/memory-schema.instructions.md +75 -0
- package/.agents/instructions/prompt.instructions.md +25 -30
- package/.agents/instructions/task-implementation.instructions.md +12 -5
- package/.agents/skills/architecture-blueprint-generator/SKILL.md +63 -18
- package/.agents/skills/context-map/SKILL.md +27 -4
- package/.agents/skills/conventional-commit/SKILL.md +2 -2
- package/.agents/skills/github-issues/SKILL.md +2 -2
- package/.agents/skills/graphify-framework-aware/SKILL.md +133 -0
- package/.agents/skills/graphify-framework-aware/references/framework-registry.md +95 -0
- package/.agents/skills/graphify-framework-aware/scripts/fw-exclude.py +425 -0
- package/.agents/skills/memory-search/SKILL.md +69 -0
- package/.agents/skills/microsoft-docs/SKILL.md +1 -1
- package/.agents/skills/polygot-test-agent/SKILL.md +0 -1
- package/.agents/skills/prompt-builder/SKILL.md +15 -14
- package/.husky/post-merge +10 -0
- package/.husky/pre-commit +2 -0
- package/AGENTS.md +54 -0
- package/README.md +177 -3
- package/memory-bank/.vocabulary.json +52 -0
- package/opencode.mcp.example.json +8 -1
- package/package.json +25 -5
- package/scripts/mcp-memory-server.js +243 -0
- package/scripts/memory-cli.js +110 -0
- package/scripts/memory-index.js +512 -0
- package/scripts/normalize-memory.js +349 -0
- package/scripts/sync.test.js +12 -0
- package/scripts/validate-memory-schema.js +190 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# π€ AI Workflow Template
|
|
2
2
|
|
|
3
|
-
**Publishable AI workflow starter pack for
|
|
3
|
+
**Publishable AI workflow starter pack for OpenCode** β Auto-syncing, version-managed, npm-distributed agent configuration suite with vector search memory.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -12,12 +12,18 @@ This isn't a one-off template to cloneβit's a **live npm package** that distri
|
|
|
12
12
|
|
|
13
13
|
- βοΈ **27+ Specialized AI Skills** - Reusable, task-based workflows (`.agents/skills/`)
|
|
14
14
|
- π§ **Smart Agent Frameworks** - Plan Mode, Implementation Plans, Research Spikes (`.agents/agents/`)
|
|
15
|
+
- π **Multi-Agent Orchestrator** β Dynamic pipeline builder with 10+ specialized sub-agents
|
|
16
|
+
- π§ͺ **TDD Orchestrator** β Strict REDβGREENβREFACTOR/VERIFY test-driven pipeline (90% coverage gate)
|
|
15
17
|
- π **Framework Instructions** - Technology-specific guidance (`.agents/instructions/`)
|
|
16
18
|
- π¬ **Prompt Templates** - Ready-to-use prompt blueprints (`.agents/prompts/`)
|
|
19
|
+
- π§ **Memory Bank** β Persistent project context across AI sessions with semantic search
|
|
20
|
+
- π **Vector Memory Search** β sqlite-vec powered semantic search (token-efficient, zero deps)
|
|
17
21
|
- πββοΈ **Caveman Mode** - Ultra-compressed communication for token efficiency
|
|
18
|
-
-
|
|
22
|
+
- π **Playwright Testing** - Automated E2E testing with MCP integration
|
|
23
|
+
- β‘ **Vitest Unit Testing** β Fast unit tests with v8 coverage (β₯90% threshold)
|
|
19
24
|
- π¦ **Version Auto-Bumping** - Husky-managed semantic versioning
|
|
20
25
|
- π **Auto-Publishing** - npm publish on merge to `main`
|
|
26
|
+
- πΊοΈ **graphify Knowledge Graph** β Queryable code-level relationship mapping
|
|
21
27
|
|
|
22
28
|
---
|
|
23
29
|
|
|
@@ -158,6 +164,7 @@ Some agents require MCP servers configured in `opencode.mcp.json` (copy from `op
|
|
|
158
164
|
- π `create-implementation-plan` - Structured task planning
|
|
159
165
|
- βοΈ `create-readme` - Automated README generation
|
|
160
166
|
- π― `context-map` - File relevance mapping
|
|
167
|
+
- π§ `graphify` - Codebase knowledge graph generation
|
|
161
168
|
|
|
162
169
|
### Development Tools
|
|
163
170
|
- π `playwright-explore-website` / `playwright-generate-test` - Browser automation
|
|
@@ -179,6 +186,140 @@ Some agents require MCP servers configured in `opencode.mcp.json` (copy from `op
|
|
|
179
186
|
|
|
180
187
|
---
|
|
181
188
|
|
|
189
|
+
### π§ Knowledge Graph (graphify)
|
|
190
|
+
|
|
191
|
+
Turns any folder of code, docs, papers, images, or videos into a **queryable knowledge graph** with community detection, interactive HTML visualization, and GraphRAG-ready JSON.
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Build a knowledge graph for the current directory
|
|
195
|
+
/graphify
|
|
196
|
+
|
|
197
|
+
# Build for a specific path
|
|
198
|
+
/graphify <path>
|
|
199
|
+
|
|
200
|
+
# Query an existing graph
|
|
201
|
+
/graphify query "How does authentication work?"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### Prerequisites
|
|
205
|
+
|
|
206
|
+
- **Python 3.10+** β required runtime
|
|
207
|
+
- **`graphifyy` Python package** β `pip install graphifyy` or `uv tool install graphifyy`
|
|
208
|
+
- **Optional: Gemini API key** (`GEMINI_API_KEY` or `GOOGLE_API_KEY`) β enables faster semantic extraction; without it, graphify falls back to Claude subagents
|
|
209
|
+
|
|
210
|
+
> π [GitHub: safishamsi/graphify](https://github.com/safishamsi/graphify) β full docs, examples, and source
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
### π§ͺ TDD Orchestrator β Test-Driven Development Pipeline
|
|
215
|
+
|
|
216
|
+
The project enforces a strict **Test-Driven Development** methodology through a specialized orchestrator that runs the **RED β GREEN β REFACTOR/VERIFY** cycle:
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
implementer (PLAN) β unit-testerβ₯ (RED) β coderβ₯ (GREEN) β unit-tester (VERIFY) β reviewer β tracker
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
| Step | Agent | Phase | Description |
|
|
223
|
+
|------|-------|-------|-------------|
|
|
224
|
+
| 1 | Implementer | PLAN | Creates implementation plan with parallel test/code batch tables |
|
|
225
|
+
| 2 | Unit Tester | RED | Writes FAILING tests first β defines expected behavior before any code exists |
|
|
226
|
+
| 3 | Coder | GREEN | Writes MINIMAL production code to pass all tests β no extra features |
|
|
227
|
+
| 4 | Unit Tester | VERIFY | Runs full suite, enforces β₯90% coverage threshold |
|
|
228
|
+
| 5 | Reviewer | REFACTOR | Audits tests + implementation for quality, security, patterns |
|
|
229
|
+
| 6 | Tracker | DOCUMENT | Records pipeline results to `docs/tracker-log.md` |
|
|
230
|
+
|
|
231
|
+
**Key TDD rules enforced:**
|
|
232
|
+
- Tests are ALWAYS written first (RED phase) β no implementation until tests exist
|
|
233
|
+
- Coverage gate: if <90%, loop back to RED phase (up to 3 iterations)
|
|
234
|
+
- Every test suite tracked in `memory-bank/tasks/`
|
|
235
|
+
- Lessons learned persisted to `.agents/instructions/learned-knowledge.instructions.md`
|
|
236
|
+
|
|
237
|
+
**How to invoke:**
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
@orchestrator Add user authentication with login/logout endpoints
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
The TDD orchestrator uses `subagent_type "tdd-orchestrator"` and auto-selects the strict TDD pipeline when testable code changes are requested.
|
|
244
|
+
|
|
245
|
+
### π§ Memory Bank β Persistent Project Context with Vector Search
|
|
246
|
+
|
|
247
|
+
The memory bank preserves project knowledge across AI sessions, preventing context loss after resets. **New: semantic vector search** lets agents query project memory without loading all files into context β saving thousands of tokens per session.
|
|
248
|
+
|
|
249
|
+
#### Architecture
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
Markdown files (git-committed) Vector Index (.gitignore'd)
|
|
253
|
+
ββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββ
|
|
254
|
+
memory-bank/ memory-bank/.index/
|
|
255
|
+
βββ activeContext.md βββ memory.db β sqlite-vec + better-sqlite3
|
|
256
|
+
βββ progress.md β
|
|
257
|
+
βββ systemPatterns.md β rebuilt from .md files
|
|
258
|
+
βββ ... βΌ on demand
|
|
259
|
+
memory_search("tdd orchestrator")
|
|
260
|
+
β top 5 relevant chunks (~500 tokens)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Source of truth:** Markdown files (git-versioned, human-readable).
|
|
264
|
+
**Search index:** `sqlite-vec` vector database (disposable, rebuildable, never committed).
|
|
265
|
+
|
|
266
|
+
#### MCP Tools (OpenCode)
|
|
267
|
+
|
|
268
|
+
| Tool | Purpose |
|
|
269
|
+
|---|---|
|
|
270
|
+
| `memory_search` | Semantic search across memory-bank + docs (query + topK) |
|
|
271
|
+
| `memory_update` | Incremental sync β only changed files (~2 seconds) |
|
|
272
|
+
| `memory_rebuild` | Full rebuild from markdown files (rare β clone/corruption) |
|
|
273
|
+
| `memory_get` | Read a specific memory file by name |
|
|
274
|
+
| `memory_stats` | Index statistics (vector count, DB size) |
|
|
275
|
+
|
|
276
|
+
#### File Structure
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
projectbrief.md β productContext.md / systemPatterns.md / techContext.md β activeContext.md β progress.md / tasks/
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
| File | Purpose |
|
|
283
|
+
|------|---------|
|
|
284
|
+
| `memory-bank/projectbrief.md` | Core requirements, goals, and scope |
|
|
285
|
+
| `memory-bank/productContext.md` | Problem solved, UX goals |
|
|
286
|
+
| `memory-bank/systemPatterns.md` | Architecture, design patterns, component relationships |
|
|
287
|
+
| `memory-bank/techContext.md` | Technologies, dev setup, constraints |
|
|
288
|
+
| `memory-bank/activeContext.md` | Current focus, recent changes, next steps |
|
|
289
|
+
| `memory-bank/progress.md` | What works, what's left, known issues |
|
|
290
|
+
| `memory-bank/tasks/` | Per-task tracking with `_index.md` |
|
|
291
|
+
|
|
292
|
+
#### Document Schema
|
|
293
|
+
|
|
294
|
+
All memory-bank files use YAML frontmatter for search indexing:
|
|
295
|
+
|
|
296
|
+
```yaml
|
|
297
|
+
---
|
|
298
|
+
id: activeContext
|
|
299
|
+
title: "Active Context"
|
|
300
|
+
updated: 2026-07-23
|
|
301
|
+
tags: [orchestrator, bootstrap, tdd]
|
|
302
|
+
entities: [vitest, graphify, memory-bank]
|
|
303
|
+
category: context
|
|
304
|
+
---
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
See `memory-bank/.vocabulary.json` for the controlled vocabulary (user-extensible).
|
|
308
|
+
|
|
309
|
+
**Auto-normalization:** `npm install` runs `normalize-memory.js` to add frontmatter to existing files.
|
|
310
|
+
**Pre-commit validation:** Husky hook rejects commits with invalid frontmatter.
|
|
311
|
+
|
|
312
|
+
**Task commands:** `add task`, `update task [ID]`, `show tasks [filter]`
|
|
313
|
+
|
|
314
|
+
#### Token Efficiency
|
|
315
|
+
|
|
316
|
+
| Approach | Tokens per session |
|
|
317
|
+
|---|---|
|
|
318
|
+
| Read all memory files | ~5,000β15,000+ |
|
|
319
|
+
| Semantic search | ~500β2,000 (top 3β5 chunks) |
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
182
323
|
## π¦ Versioning
|
|
183
324
|
|
|
184
325
|
Husky automatically bumps versions on every commit:
|
|
@@ -219,10 +360,43 @@ npm run sync -- --dry-run
|
|
|
219
360
|
# Test package creation
|
|
220
361
|
npm pack --json
|
|
221
362
|
|
|
222
|
-
# Run Playwright tests
|
|
363
|
+
# Run Playwright E2E tests
|
|
223
364
|
npm test
|
|
365
|
+
|
|
366
|
+
# Run unit tests (Vitest)
|
|
367
|
+
npm run test:unit
|
|
368
|
+
|
|
369
|
+
# Run unit tests with coverage (90% threshold)
|
|
370
|
+
npm run test:unit:coverage
|
|
371
|
+
|
|
372
|
+
# Watch mode for unit tests
|
|
373
|
+
npm run test:unit:watch
|
|
374
|
+
|
|
375
|
+
# βββ Memory Bank (Vector Search) βββ
|
|
376
|
+
|
|
377
|
+
# Build the vector search index (one-time, ~8 min for 5K files)
|
|
378
|
+
npm run memory:rebuild
|
|
379
|
+
|
|
380
|
+
# Incremental update (seconds β only changed files)
|
|
381
|
+
npm run memory:update
|
|
382
|
+
|
|
383
|
+
# Search project memory
|
|
384
|
+
npm run memory:search "tdd orchestrator status"
|
|
385
|
+
|
|
386
|
+
# Normalize document frontmatter (runs automatically on install)
|
|
387
|
+
npm run memory:normalize
|
|
224
388
|
```
|
|
225
389
|
|
|
390
|
+
### Testing
|
|
391
|
+
|
|
392
|
+
| Type | Framework | Command | Coverage |
|
|
393
|
+
|------|-----------|---------|----------|
|
|
394
|
+
| E2E | Playwright | `npm test` | β |
|
|
395
|
+
| Unit | Vitest | `npm run test:unit` | `npm run test:unit:coverage` (β₯90%) |
|
|
396
|
+
|
|
397
|
+
- **E2E tests** live in `tests/*.spec.ts` β browser automation via Playwright
|
|
398
|
+
- **Unit tests** live in `scripts/*.test.{js,ts}` β component tests via Vitest with v8 coverage
|
|
399
|
+
|
|
226
400
|
---
|
|
227
401
|
|
|
228
402
|
## π Updating the Shared Template
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"categories": {
|
|
3
|
+
"brief": "Project scope, goals (projectbrief.md)",
|
|
4
|
+
"product": "Product context, UX goals (productContext.md)",
|
|
5
|
+
"architecture": "System patterns, design decisions, component relationships",
|
|
6
|
+
"tech": "Technology stack, dev setup, constraints",
|
|
7
|
+
"context": "Current focus, recent changes, next steps (activeContext.md)",
|
|
8
|
+
"progress": "What works, what's left, known issues (progress.md)",
|
|
9
|
+
"task": "Individual task tracking (tasks/TASK*.md)",
|
|
10
|
+
"decision": "ADR-style architecture/technical decisions"
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
"tags": {
|
|
14
|
+
"agent_roles": [
|
|
15
|
+
"designer", "architect", "researcher", "coder", "implementer",
|
|
16
|
+
"tester", "reviewer", "tracker", "deployer", "orchestrator"
|
|
17
|
+
],
|
|
18
|
+
"workflow": [
|
|
19
|
+
"bootstrap", "setup", "configuration", "migration", "refactor",
|
|
20
|
+
"tdd", "feature-pipeline", "onboarding", "normalization",
|
|
21
|
+
"research", "spike", "implementation"
|
|
22
|
+
],
|
|
23
|
+
"memory_ops": [
|
|
24
|
+
"decision", "discovery", "status-update", "task-plan", "retrospective"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
"entity_patterns": {
|
|
29
|
+
"vitest": ["vitest", "vitest\\.config", "@vitest\\/coverage"],
|
|
30
|
+
"playwright": ["playwright", "@playwright", "browser.*test"],
|
|
31
|
+
"graphify": ["graphify", "knowledge graph", "graph\\.json"],
|
|
32
|
+
"memory-bank": ["memory-bank", "memory bank", "activeContext", "systemPatterns"],
|
|
33
|
+
"husky": ["husky", "pre-commit", "git hook"],
|
|
34
|
+
"tdd-orchestrator": ["tdd orchestrator", "RED.*GREEN.*REFACTOR"],
|
|
35
|
+
"mcp-server": ["mcp", "modelcontextprotocol", "stdio", "mcp server"],
|
|
36
|
+
"sqlite-vec": ["sqlite-vec", "sqlite.vec", "better-sqlite3"],
|
|
37
|
+
"transformers.js": ["@xenova\\/transformers", "transformers\\.js", "all-MiniLM"],
|
|
38
|
+
"opencode": ["opencode", "OpenCode", "open code"],
|
|
39
|
+
"npm": ["npm", "npm package", "npm install"]
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
"file_category_map": {
|
|
43
|
+
"projectbrief": "brief",
|
|
44
|
+
"productContext": "product",
|
|
45
|
+
"systemPatterns": "architecture",
|
|
46
|
+
"techContext": "tech",
|
|
47
|
+
"activeContext": "context",
|
|
48
|
+
"progress": "progress"
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
"doc_types": ["spike", "architecture", "configuration", "orchestrator-log", "tracker-log", "decision"]
|
|
52
|
+
}
|
|
@@ -53,12 +53,19 @@
|
|
|
53
53
|
"type": "remote",
|
|
54
54
|
"url": "https://your-mcp-server.com/mcp",
|
|
55
55
|
"enabled": false
|
|
56
|
+
},
|
|
57
|
+
"memory-bank": {
|
|
58
|
+
"type": "local",
|
|
59
|
+
"command": ["node", "scripts/mcp-memory-server.js"],
|
|
60
|
+
"enabled": true
|
|
56
61
|
}
|
|
57
62
|
},
|
|
58
63
|
"permission": {
|
|
59
64
|
"ddg-search_*": "allow",
|
|
60
65
|
"github_*": "allow",
|
|
61
66
|
"mcp-everything_*": "allow",
|
|
62
|
-
"
|
|
67
|
+
"angular-cli_*": "allow",
|
|
68
|
+
"playwright_*": "allow",
|
|
69
|
+
"memory-bank_*": "allow"
|
|
63
70
|
}
|
|
64
71
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abarcenas/ai-workflow-template",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "A comprehensive template repository for AI-assisted development workflows using
|
|
3
|
+
"version": "1.26.0",
|
|
4
|
+
"description": "A comprehensive template repository for AI-assisted development workflows using OpenCode. Provides structured agent pipelines, TDD orchestrator, memory bank with vector search, skills, prompts, and coding standards distributed as an npm package.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "playwright test",
|
|
@@ -9,9 +9,16 @@
|
|
|
9
9
|
"test:ui": "playwright test --ui",
|
|
10
10
|
"test:debug": "playwright test --debug",
|
|
11
11
|
"test:report": "playwright show-report",
|
|
12
|
+
"test:unit": "vitest run",
|
|
13
|
+
"test:unit:coverage": "vitest run --coverage",
|
|
14
|
+
"test:unit:watch": "vitest",
|
|
12
15
|
"prepare": "husky",
|
|
13
16
|
"sync": "node ./scripts/sync.js",
|
|
14
|
-
"postinstall": "node ./scripts/sync.js"
|
|
17
|
+
"postinstall": "node ./scripts/sync.js && node ./scripts/normalize-memory.js",
|
|
18
|
+
"memory:search": "node ./scripts/memory-cli.js search",
|
|
19
|
+
"memory:rebuild": "node ./scripts/memory-cli.js rebuild",
|
|
20
|
+
"memory:update": "node ./scripts/memory-cli.js update",
|
|
21
|
+
"memory:normalize": "node ./scripts/normalize-memory.js"
|
|
15
22
|
},
|
|
16
23
|
"repository": {
|
|
17
24
|
"type": "git",
|
|
@@ -31,13 +38,26 @@
|
|
|
31
38
|
"scripts/",
|
|
32
39
|
".opencode/agents/",
|
|
33
40
|
".opencode/commands/",
|
|
41
|
+
".husky/",
|
|
42
|
+
"memory-bank/.vocabulary.json",
|
|
34
43
|
"AGENTS.md",
|
|
35
44
|
"opencode.mcp.example.json",
|
|
36
|
-
"skills-lock.json"
|
|
45
|
+
"skills-lock.json",
|
|
46
|
+
".husky/post-merge"
|
|
37
47
|
],
|
|
38
48
|
"devDependencies": {
|
|
39
49
|
"@playwright/test": "^1.59.1",
|
|
50
|
+
"@vitest/coverage-v8": "^4.1.8",
|
|
40
51
|
"dotenv": "^17.4.2",
|
|
41
|
-
"husky": "^9.0.0"
|
|
52
|
+
"husky": "^9.0.0",
|
|
53
|
+
"vitest": "^4.1.8"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"better-sqlite3": "^12.11.0",
|
|
57
|
+
"sqlite-vec": "^0.1.9",
|
|
58
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
59
|
+
},
|
|
60
|
+
"optionalDependencies": {
|
|
61
|
+
"@xenova/transformers": "^2.17.0"
|
|
42
62
|
}
|
|
43
63
|
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* mcp-memory-server.js β MCP server exposing memory-bank tools to OpenCode.
|
|
5
|
+
*
|
|
6
|
+
* Provides: memory_search, memory_rebuild, memory_get
|
|
7
|
+
* Uses stdio transport β OpenCode spawns this as a child process.
|
|
8
|
+
*
|
|
9
|
+
* Configuration (opencode.json):
|
|
10
|
+
* "memory-bank": {
|
|
11
|
+
* "type": "local",
|
|
12
|
+
* "command": ["node", "scripts/mcp-memory-server.js"],
|
|
13
|
+
* "enabled": true
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
18
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
19
|
+
import {
|
|
20
|
+
CallToolRequestSchema,
|
|
21
|
+
ListToolsRequestSchema,
|
|
22
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
23
|
+
import { search, rebuildIndex, incrementalUpdate, getFile, getStats } from './memory-index.js';
|
|
24
|
+
|
|
25
|
+
const VALID_FILES = [
|
|
26
|
+
'activeContext', 'systemPatterns', 'techContext',
|
|
27
|
+
'productContext', 'progress', 'projectbrief',
|
|
28
|
+
'tracker-log', 'architecture-context', 'orchestrator-log',
|
|
29
|
+
'spike-vector-db-memory', 'playwright-mcp-configuration',
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const server = new Server(
|
|
33
|
+
{
|
|
34
|
+
name: 'memory-bank',
|
|
35
|
+
version: '1.0.0',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
capabilities: {
|
|
39
|
+
tools: {},
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// ββ List tools βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
45
|
+
|
|
46
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
47
|
+
tools: [
|
|
48
|
+
{
|
|
49
|
+
name: 'memory_search',
|
|
50
|
+
description:
|
|
51
|
+
'Semantic search across the project memory bank (activeContext, systemPatterns, progress, decisions, tasks). ' +
|
|
52
|
+
'Returns ranked chunks with source file and similarity score. ' +
|
|
53
|
+
'Use this instead of reading all memory files to save tokens.',
|
|
54
|
+
inputSchema: {
|
|
55
|
+
type: 'object',
|
|
56
|
+
properties: {
|
|
57
|
+
query: {
|
|
58
|
+
type: 'string',
|
|
59
|
+
description: 'Natural language query about project context, decisions, or status',
|
|
60
|
+
},
|
|
61
|
+
topK: {
|
|
62
|
+
type: 'number',
|
|
63
|
+
default: 5,
|
|
64
|
+
description: 'Number of results to return (1-20)',
|
|
65
|
+
},
|
|
66
|
+
sourceFile: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
description: 'Optional: filter to a specific memory file (e.g., "activeContext", "systemPatterns")',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
required: ['query'],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'memory_rebuild',
|
|
76
|
+
description:
|
|
77
|
+
'Full rebuild of the memory vector index from memory-bank/*.md and docs/*.md files. ' +
|
|
78
|
+
'Re-indexes every file regardless of change. ' +
|
|
79
|
+
'Use memory_update instead for faster incremental sync (only changed files). ' +
|
|
80
|
+
'The index is disposable β rebuilding is safe.',
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: 'object',
|
|
83
|
+
properties: {},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'memory_update',
|
|
88
|
+
description:
|
|
89
|
+
'Incremental update β only re-indexes files whose content changed (SHA-256 content hash). ' +
|
|
90
|
+
'Much faster than memory_rebuild for daily use (~2 seconds vs minutes). ' +
|
|
91
|
+
'Run this after completing tasks, writing to memory-bank, or after git pull.',
|
|
92
|
+
inputSchema: {
|
|
93
|
+
type: 'object',
|
|
94
|
+
properties: {},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: 'memory_get',
|
|
99
|
+
description:
|
|
100
|
+
'Read the full content of a specific memory file by name. ' +
|
|
101
|
+
'Use when you need the complete file, not just search snippets.',
|
|
102
|
+
inputSchema: {
|
|
103
|
+
type: 'object',
|
|
104
|
+
properties: {
|
|
105
|
+
file: {
|
|
106
|
+
type: 'string',
|
|
107
|
+
description: 'File ID without extension. One of: ' + VALID_FILES.join(', '),
|
|
108
|
+
enum: VALID_FILES,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
required: ['file'],
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'memory_stats',
|
|
116
|
+
description: 'Get statistics about the memory index (vector count, file count, database size).',
|
|
117
|
+
inputSchema: {
|
|
118
|
+
type: 'object',
|
|
119
|
+
properties: {},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
}));
|
|
124
|
+
|
|
125
|
+
// ββ Handle tool calls ββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
126
|
+
|
|
127
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
128
|
+
const { name, arguments: args } = request.params;
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
switch (name) {
|
|
132
|
+
case 'memory_search': {
|
|
133
|
+
const results = await search(args.query, {
|
|
134
|
+
topK: args.topK || 5,
|
|
135
|
+
sourceFile: args.sourceFile || undefined,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (results.length === 0) {
|
|
139
|
+
return {
|
|
140
|
+
content: [{
|
|
141
|
+
type: 'text',
|
|
142
|
+
text: 'No results found. The index may be empty. Try running memory_rebuild first.',
|
|
143
|
+
}],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const formatted = results
|
|
148
|
+
.map((r, i) =>
|
|
149
|
+
`### Result ${i + 1} (score: ${r.score})\n` +
|
|
150
|
+
`**File:** \`${r.source_file}\`\n\n${r.content}`
|
|
151
|
+
)
|
|
152
|
+
.join('\n\n---\n\n');
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
content: [{ type: 'text', text: formatted }],
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
case 'memory_rebuild': {
|
|
160
|
+
const result = await rebuildIndex();
|
|
161
|
+
return {
|
|
162
|
+
content: [{
|
|
163
|
+
type: 'text',
|
|
164
|
+
text: `Index rebuilt successfully.\n` +
|
|
165
|
+
`- Chunks indexed: ${result.indexed}\n` +
|
|
166
|
+
`- Chunks skipped (unchanged): ${result.skipped}\n` +
|
|
167
|
+
`- Total vectors: ${result.stats.totalVectors}\n` +
|
|
168
|
+
`- Total files: ${result.stats.totalFiles}\n` +
|
|
169
|
+
`- DB size: ${result.stats.dbSize}`,
|
|
170
|
+
}],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
case 'memory_update': {
|
|
175
|
+
const result = await incrementalUpdate();
|
|
176
|
+
return {
|
|
177
|
+
content: [{
|
|
178
|
+
type: 'text',
|
|
179
|
+
text: `Index updated incrementally.\n` +
|
|
180
|
+
`- Chunks re-indexed: ${result.indexed}\n` +
|
|
181
|
+
`- Chunks cached (unchanged): ${result.skipped}\n` +
|
|
182
|
+
(result.changed.length > 0
|
|
183
|
+
? `- Changed files: ${result.changed.join(', ')}\n`
|
|
184
|
+
: '- No files changed.\n') +
|
|
185
|
+
`- Total vectors: ${(await getStats()).totalVectors}`,
|
|
186
|
+
}],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
case 'memory_get': {
|
|
191
|
+
const content = getFile(args.file);
|
|
192
|
+
if (!content) {
|
|
193
|
+
return {
|
|
194
|
+
content: [{
|
|
195
|
+
type: 'text',
|
|
196
|
+
text: `File not found: ${args.file}.md. Available files: ${VALID_FILES.join(', ')}`,
|
|
197
|
+
}],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
content: [{ type: 'text', text: content }],
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
case 'memory_stats': {
|
|
206
|
+
const stats = getStats();
|
|
207
|
+
return {
|
|
208
|
+
content: [{
|
|
209
|
+
type: 'text',
|
|
210
|
+
text: `**Memory Index Stats**\n` +
|
|
211
|
+
`- Total vectors: ${stats.totalVectors}\n` +
|
|
212
|
+
`- Total files indexed: ${stats.totalFiles}\n` +
|
|
213
|
+
`- Database size: ${stats.dbSize}`,
|
|
214
|
+
}],
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
default:
|
|
219
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
220
|
+
}
|
|
221
|
+
} catch (err) {
|
|
222
|
+
return {
|
|
223
|
+
content: [{
|
|
224
|
+
type: 'text',
|
|
225
|
+
text: `Error: ${err.message}`,
|
|
226
|
+
}],
|
|
227
|
+
isError: true,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// ββ Start server βββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
233
|
+
|
|
234
|
+
async function main() {
|
|
235
|
+
const transport = new StdioServerTransport();
|
|
236
|
+
await server.connect(transport);
|
|
237
|
+
console.error('[memory-bank-mcp] Server started via stdio transport');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
main().catch((err) => {
|
|
241
|
+
console.error('[memory-bank-mcp] Fatal error:', err);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
});
|