decibel-tools-mcp 1.0.6 → 1.0.8
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/README.md +35 -3
- package/dist/server.js +0 -0
- package/dist/tools/corpus/index.d.ts +5 -0
- package/dist/tools/corpus/index.d.ts.map +1 -0
- package/dist/tools/corpus/index.js +95 -0
- package/dist/tools/corpus/index.js.map +1 -0
- package/dist/tools/corpus.d.ts +33 -0
- package/dist/tools/corpus.d.ts.map +1 -0
- package/dist/tools/corpus.js +180 -0
- package/dist/tools/corpus.js.map +1 -0
- package/dist/tools/designer/index.d.ts +4 -0
- package/dist/tools/designer/index.d.ts.map +1 -1
- package/dist/tools/designer/index.js +177 -1
- package/dist/tools/designer/index.js.map +1 -1
- package/dist/tools/designer.d.ts +81 -0
- package/dist/tools/designer.d.ts.map +1 -1
- package/dist/tools/designer.js +304 -0
- package/dist/tools/designer.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/registry.d.ts +3 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +189 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/toolsIndex.d.ts +5 -0
- package/dist/tools/toolsIndex.d.ts.map +1 -0
- package/dist/tools/toolsIndex.js +37 -0
- package/dist/tools/toolsIndex.js.map +1 -0
- package/dist/tools/vector/index.d.ts +9 -0
- package/dist/tools/vector/index.d.ts.map +1 -0
- package/dist/tools/vector/index.js +299 -0
- package/dist/tools/vector/index.js.map +1 -0
- package/dist/tools/vector.d.ts +153 -0
- package/dist/tools/vector.d.ts.map +1 -0
- package/dist/tools/vector.js +395 -0
- package/dist/tools/vector.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
MCP server that gives AI assistants structured access to project intelligence: epics, issues, ADRs, experiments, roadmaps, and more.
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**76 tools** across 12 domains. Tested with Claude Desktop, Claude Code, and Cursor.
|
|
6
6
|
|
|
7
7
|
<a href="cursor://anysphere.cursor-deeplink/mcp/install?name=decibel-tools&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsImRlY2liZWwtdG9vbHMtbWNwIl19">
|
|
8
8
|
<img src="https://cursor.com/deeplink/mcp-install-dark.svg" alt="Add to Cursor" height="32" />
|
|
@@ -54,6 +54,33 @@ npx decibel-tools-mcp
|
|
|
54
54
|
}
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
### Claude Code
|
|
58
|
+
|
|
59
|
+
**Plugin (recommended):**
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Add the marketplace
|
|
63
|
+
/plugin marketplace add decibelsystems/decibel-tools-mcp
|
|
64
|
+
|
|
65
|
+
# Install the plugin
|
|
66
|
+
/plugin install decibel-tools@decibel-marketplace
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
This gives you slash commands like `/decibel-tools:init`, `/decibel-tools:scan`, `/decibel-tools:next`.
|
|
70
|
+
|
|
71
|
+
**Manual:** Add to `~/.claude/settings.json`:
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"decibel-tools": {
|
|
77
|
+
"command": "npx",
|
|
78
|
+
"args": ["-y", "decibel-tools-mcp"]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
57
84
|
### Claude Desktop
|
|
58
85
|
|
|
59
86
|
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
|
|
@@ -143,14 +170,18 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
143
170
|
| `oracle_next_actions` | Get recommended next actions for a project |
|
|
144
171
|
| `oracle_roadmap` | Evaluate roadmap progress against milestones |
|
|
145
172
|
|
|
146
|
-
### Designer (
|
|
147
|
-
*Design decisions and creative feedback*
|
|
173
|
+
### Designer (7 tools)
|
|
174
|
+
*Design decisions, Figma integration, and creative feedback*
|
|
148
175
|
|
|
149
176
|
| Tool | Description |
|
|
150
177
|
|------|-------------|
|
|
151
178
|
| `designer_record_design_decision` | Record a design decision |
|
|
152
179
|
| `designer_crit` | Log early creative feedback (gut reactions, hunches) |
|
|
153
180
|
| `designer_list_crits` | List crit observations, filter by area/sentiment |
|
|
181
|
+
| `designer_sync_tokens` | Sync design tokens from Figma variables |
|
|
182
|
+
| `designer_review_figma` | Review Figma component against design principles |
|
|
183
|
+
| `designer_upsert_principle` | Create or update a design principle |
|
|
184
|
+
| `designer_list_principles` | List design principles, filter by category |
|
|
154
185
|
|
|
155
186
|
### Friction (4 tools)
|
|
156
187
|
*Track recurring pain points*
|
|
@@ -252,6 +283,7 @@ Optional for cloud features:
|
|
|
252
283
|
- `SUPABASE_URL` - Supabase project URL
|
|
253
284
|
- `SUPABASE_SERVICE_KEY` - Supabase service role key
|
|
254
285
|
- `OPENAI_API_KEY` - For image generation
|
|
286
|
+
- `FIGMA_ACCESS_TOKEN` - For Figma integration (designer_sync_tokens, designer_review_figma)
|
|
255
287
|
|
|
256
288
|
## License
|
|
257
289
|
|
package/dist/server.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/corpus/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAoBvC,eAAO,MAAM,gBAAgB,EAAE,QA+C9B,CAAC;AAMF,eAAO,MAAM,gBAAgB,EAAE,QAyB9B,CAAC;AAMF,eAAO,MAAM,WAAW,EAAE,QAAQ,EAGjC,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Corpus Domain Tools
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// MCP tools for searching decibel-corpus - the shared knowledge base.
|
|
5
|
+
// Enables cross-project learning from patterns, playbooks, and field notes.
|
|
6
|
+
// ============================================================================
|
|
7
|
+
import { toolSuccess, toolError, requireFields } from '../shared/index.js';
|
|
8
|
+
import { corpusSearch, getCorpusPath, corpusExists, } from '../corpus.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Constants
|
|
11
|
+
// ============================================================================
|
|
12
|
+
const VALID_TYPES = ['pattern', 'playbook', 'field-note', 'all'];
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Corpus Search Tool
|
|
15
|
+
// ============================================================================
|
|
16
|
+
export const corpusSearchTool = {
|
|
17
|
+
definition: {
|
|
18
|
+
name: 'corpus_search',
|
|
19
|
+
description: `Search decibel-corpus for patterns, playbooks, and field notes. Use when you encounter problems that may have been solved before (DB collisions, auth patterns, deployment issues, webhook retries, etc.). Returns matching documents with snippets and relevance scores.`,
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
query: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
description: 'Search terms (e.g., "duplicate key", "advisory lock", "webhook retry", "rate limit")',
|
|
26
|
+
},
|
|
27
|
+
type: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
enum: ['pattern', 'playbook', 'field-note', 'all'],
|
|
30
|
+
description: 'Filter by content type. Patterns are reusable solutions, playbooks are step-by-step guides, field-notes are lessons learned. Default: all',
|
|
31
|
+
},
|
|
32
|
+
limit: {
|
|
33
|
+
type: 'number',
|
|
34
|
+
description: 'Maximum results to return (default: 5)',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
required: ['query'],
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
handler: async (args) => {
|
|
41
|
+
try {
|
|
42
|
+
const input = args;
|
|
43
|
+
requireFields(input, 'query');
|
|
44
|
+
if (input.type && !VALID_TYPES.includes(input.type)) {
|
|
45
|
+
throw new Error(`Invalid type: ${input.type}. Must be one of: ${VALID_TYPES.join(', ')}`);
|
|
46
|
+
}
|
|
47
|
+
// Check if corpus exists
|
|
48
|
+
if (!await corpusExists()) {
|
|
49
|
+
return toolError(`Corpus not found at ${getCorpusPath()}`, 'Clone decibel-corpus to ~/Documents/GitHub/decibel-corpus or set DECIBEL_CORPUS_PATH');
|
|
50
|
+
}
|
|
51
|
+
const result = await corpusSearch(input);
|
|
52
|
+
return toolSuccess(result);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
return toolError(err instanceof Error ? err.message : String(err));
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// Corpus Status Tool (for debugging)
|
|
61
|
+
// ============================================================================
|
|
62
|
+
export const corpusStatusTool = {
|
|
63
|
+
definition: {
|
|
64
|
+
name: 'corpus_status',
|
|
65
|
+
description: 'Check the status of decibel-corpus. Shows location and whether it exists.',
|
|
66
|
+
inputSchema: {
|
|
67
|
+
type: 'object',
|
|
68
|
+
properties: {},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
handler: async () => {
|
|
72
|
+
try {
|
|
73
|
+
const path = getCorpusPath();
|
|
74
|
+
const exists = await corpusExists();
|
|
75
|
+
return toolSuccess({
|
|
76
|
+
corpus_path: path,
|
|
77
|
+
exists,
|
|
78
|
+
hint: exists
|
|
79
|
+
? 'Corpus is available. Use corpus_search to find patterns.'
|
|
80
|
+
: 'Clone decibel-corpus to this path or set DECIBEL_CORPUS_PATH env var.',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
return toolError(err instanceof Error ? err.message : String(err));
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
// ============================================================================
|
|
89
|
+
// Export All Tools
|
|
90
|
+
// ============================================================================
|
|
91
|
+
export const corpusTools = [
|
|
92
|
+
corpusSearchTool,
|
|
93
|
+
corpusStatusTool,
|
|
94
|
+
];
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/corpus/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type CorpusContentType = 'pattern' | 'playbook' | 'field-note';
|
|
2
|
+
export interface CorpusSearchInput {
|
|
3
|
+
query: string;
|
|
4
|
+
type?: CorpusContentType | 'all';
|
|
5
|
+
limit?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface CorpusMatch {
|
|
8
|
+
id: string;
|
|
9
|
+
path: string;
|
|
10
|
+
type: CorpusContentType;
|
|
11
|
+
title: string;
|
|
12
|
+
snippet: string;
|
|
13
|
+
relevance: number;
|
|
14
|
+
}
|
|
15
|
+
export interface CorpusSearchResult {
|
|
16
|
+
matches: CorpusMatch[];
|
|
17
|
+
query: string;
|
|
18
|
+
searched: number;
|
|
19
|
+
corpus_path: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Search the decibel-corpus for patterns, playbooks, and field notes
|
|
23
|
+
*/
|
|
24
|
+
export declare function corpusSearch(input: CorpusSearchInput): Promise<CorpusSearchResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Get the corpus path for display/debugging
|
|
27
|
+
*/
|
|
28
|
+
export declare function getCorpusPath(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Check if corpus exists at the configured path
|
|
31
|
+
*/
|
|
32
|
+
export declare function corpusExists(): Promise<boolean>;
|
|
33
|
+
//# sourceMappingURL=corpus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corpus.d.ts","sourceRoot":"","sources":["../../src/tools/corpus.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,CAAC;AAEtE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAyHD;;GAEG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA6DxF;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAOrD"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Corpus Domain Logic
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Search decibel-corpus for patterns, playbooks, and field notes.
|
|
5
|
+
// Enables cross-project knowledge sharing without submodules.
|
|
6
|
+
// ============================================================================
|
|
7
|
+
import { readdir, readFile } from 'fs/promises';
|
|
8
|
+
import { join, basename } from 'path';
|
|
9
|
+
import { homedir } from 'os';
|
|
10
|
+
import { log } from '../config.js';
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Configuration
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Corpus location - configurable via environment
|
|
15
|
+
const CORPUS_PATH = process.env.DECIBEL_CORPUS_PATH
|
|
16
|
+
|| join(homedir(), 'Documents/GitHub/decibel-corpus');
|
|
17
|
+
// Map content types to directory paths within corpus
|
|
18
|
+
const TYPE_PATHS = {
|
|
19
|
+
'pattern': 'primitives/patterns',
|
|
20
|
+
'playbook': 'playbooks',
|
|
21
|
+
'field-note': 'field-notes',
|
|
22
|
+
};
|
|
23
|
+
const VALID_TYPES = ['pattern', 'playbook', 'field-note', 'all'];
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// Helpers
|
|
26
|
+
// ============================================================================
|
|
27
|
+
/**
|
|
28
|
+
* Recursively find all markdown files in a directory
|
|
29
|
+
*/
|
|
30
|
+
async function findMarkdownFiles(dir) {
|
|
31
|
+
const results = [];
|
|
32
|
+
try {
|
|
33
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
34
|
+
for (const entry of entries) {
|
|
35
|
+
const fullPath = join(dir, entry.name);
|
|
36
|
+
if (entry.isDirectory()) {
|
|
37
|
+
results.push(...await findMarkdownFiles(fullPath));
|
|
38
|
+
}
|
|
39
|
+
else if (entry.name.endsWith('.md') && !entry.name.startsWith('.')) {
|
|
40
|
+
results.push(fullPath);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Directory doesn't exist, skip silently
|
|
46
|
+
}
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Extract title from markdown content
|
|
51
|
+
* Tries YAML frontmatter first, then first H1
|
|
52
|
+
*/
|
|
53
|
+
function extractTitle(content) {
|
|
54
|
+
// Try YAML frontmatter title
|
|
55
|
+
const frontmatterMatch = content.match(/^---\n[\s\S]*?title:\s*["']?(.+?)["']?\s*\n[\s\S]*?---/);
|
|
56
|
+
if (frontmatterMatch)
|
|
57
|
+
return frontmatterMatch[1].trim();
|
|
58
|
+
// Try first H1
|
|
59
|
+
const h1Match = content.match(/^#\s+(.+)$/m);
|
|
60
|
+
if (h1Match)
|
|
61
|
+
return h1Match[1].trim();
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Extract a snippet around the first match of a term
|
|
66
|
+
*/
|
|
67
|
+
function extractSnippet(content, term) {
|
|
68
|
+
const lowerContent = content.toLowerCase();
|
|
69
|
+
const idx = lowerContent.indexOf(term.toLowerCase());
|
|
70
|
+
if (idx === -1) {
|
|
71
|
+
// Just return first 200 chars after frontmatter
|
|
72
|
+
const afterFrontmatter = content.replace(/^---\n[\s\S]*?---\n/, '');
|
|
73
|
+
const cleaned = afterFrontmatter.replace(/^#+\s+.+\n/, '').trim();
|
|
74
|
+
return cleaned.slice(0, 200).trim() + (cleaned.length > 200 ? '...' : '');
|
|
75
|
+
}
|
|
76
|
+
// Return ~100 chars around the match
|
|
77
|
+
const start = Math.max(0, idx - 50);
|
|
78
|
+
const end = Math.min(content.length, idx + 150);
|
|
79
|
+
let snippet = content.slice(start, end).trim();
|
|
80
|
+
// Clean up newlines for better display
|
|
81
|
+
snippet = snippet.replace(/\n+/g, ' ');
|
|
82
|
+
if (start > 0)
|
|
83
|
+
snippet = '...' + snippet;
|
|
84
|
+
if (end < content.length)
|
|
85
|
+
snippet = snippet + '...';
|
|
86
|
+
return snippet;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Calculate relevance score based on term matches
|
|
90
|
+
* Weights title matches higher than body matches
|
|
91
|
+
*/
|
|
92
|
+
function calculateRelevance(content, title, searchTerms) {
|
|
93
|
+
const lowerContent = content.toLowerCase();
|
|
94
|
+
const lowerTitle = (title || '').toLowerCase();
|
|
95
|
+
let relevance = 0;
|
|
96
|
+
for (const term of searchTerms) {
|
|
97
|
+
// Title matches worth 3x
|
|
98
|
+
const titleMatches = (lowerTitle.match(new RegExp(term, 'g')) || []).length;
|
|
99
|
+
relevance += titleMatches * 3;
|
|
100
|
+
// Body matches
|
|
101
|
+
const bodyMatches = (lowerContent.match(new RegExp(term, 'g')) || []).length;
|
|
102
|
+
relevance += bodyMatches;
|
|
103
|
+
}
|
|
104
|
+
return relevance;
|
|
105
|
+
}
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// Main Search Function
|
|
108
|
+
// ============================================================================
|
|
109
|
+
/**
|
|
110
|
+
* Search the decibel-corpus for patterns, playbooks, and field notes
|
|
111
|
+
*/
|
|
112
|
+
export async function corpusSearch(input) {
|
|
113
|
+
const { query, type = 'all', limit = 5 } = input;
|
|
114
|
+
if (!query || query.trim().length === 0) {
|
|
115
|
+
throw new Error('Query cannot be empty');
|
|
116
|
+
}
|
|
117
|
+
if (!VALID_TYPES.includes(type)) {
|
|
118
|
+
throw new Error(`Invalid type: ${type}. Must be one of: ${VALID_TYPES.join(', ')}`);
|
|
119
|
+
}
|
|
120
|
+
const searchTerms = query.toLowerCase().split(/\s+/).filter(t => t.length > 1);
|
|
121
|
+
const matches = [];
|
|
122
|
+
const typesToSearch = type === 'all'
|
|
123
|
+
? Object.keys(TYPE_PATHS)
|
|
124
|
+
: [type];
|
|
125
|
+
let searched = 0;
|
|
126
|
+
for (const t of typesToSearch) {
|
|
127
|
+
const dirPath = join(CORPUS_PATH, TYPE_PATHS[t]);
|
|
128
|
+
const files = await findMarkdownFiles(dirPath);
|
|
129
|
+
for (const file of files) {
|
|
130
|
+
searched++;
|
|
131
|
+
try {
|
|
132
|
+
const content = await readFile(file, 'utf-8');
|
|
133
|
+
const title = extractTitle(content) || basename(file, '.md');
|
|
134
|
+
const relevance = calculateRelevance(content, title, searchTerms);
|
|
135
|
+
if (relevance > 0) {
|
|
136
|
+
const snippet = extractSnippet(content, searchTerms[0]);
|
|
137
|
+
matches.push({
|
|
138
|
+
id: basename(file, '.md'),
|
|
139
|
+
path: file.replace(CORPUS_PATH + '/', ''),
|
|
140
|
+
type: t,
|
|
141
|
+
title,
|
|
142
|
+
snippet,
|
|
143
|
+
relevance,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
log(`Corpus: Error reading ${file}: ${err}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Sort by relevance descending, take top N
|
|
153
|
+
matches.sort((a, b) => b.relevance - a.relevance);
|
|
154
|
+
log(`Corpus: Searched ${searched} files, found ${matches.length} matches for "${query}"`);
|
|
155
|
+
return {
|
|
156
|
+
matches: matches.slice(0, limit),
|
|
157
|
+
query,
|
|
158
|
+
searched,
|
|
159
|
+
corpus_path: CORPUS_PATH,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get the corpus path for display/debugging
|
|
164
|
+
*/
|
|
165
|
+
export function getCorpusPath() {
|
|
166
|
+
return CORPUS_PATH;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Check if corpus exists at the configured path
|
|
170
|
+
*/
|
|
171
|
+
export async function corpusExists() {
|
|
172
|
+
try {
|
|
173
|
+
await readdir(CORPUS_PATH);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=corpus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corpus.js","sourceRoot":"","sources":["../../src/tools/corpus.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,5 +2,9 @@ import { ToolSpec } from '../types.js';
|
|
|
2
2
|
export declare const designerRecordDecisionTool: ToolSpec;
|
|
3
3
|
export declare const designerCritTool: ToolSpec;
|
|
4
4
|
export declare const designerListCritsTool: ToolSpec;
|
|
5
|
+
export declare const designerSyncTokensTool: ToolSpec;
|
|
6
|
+
export declare const designerReviewFigmaTool: ToolSpec;
|
|
7
|
+
export declare const designerUpsertPrincipleTool: ToolSpec;
|
|
8
|
+
export declare const designerListPrinciplesTool: ToolSpec;
|
|
5
9
|
export declare const designerTools: ToolSpec[];
|
|
6
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/designer/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/designer/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA0CvC,eAAO,MAAM,0BAA0B,EAAE,QAyCxC,CAAC;AAMF,eAAO,MAAM,gBAAgB,EAAE,QAuD9B,CAAC;AAMF,eAAO,MAAM,qBAAqB,EAAE,QA4CnC,CAAC;AAMF,eAAO,MAAM,sBAAsB,EAAE,QAqCpC,CAAC;AAMF,eAAO,MAAM,uBAAuB,EAAE,QA0CrC,CAAC;AAMF,eAAO,MAAM,2BAA2B,EAAE,QAkDzC,CAAC;AAMF,eAAO,MAAM,0BAA0B,EAAE,QA8BxC,CAAC;AAMF,eAAO,MAAM,aAAa,EAAE,QAAQ,EAQnC,CAAC"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// Tools for design decisions and creative feedback (crits).
|
|
5
5
|
// ============================================================================
|
|
6
6
|
import { toolSuccess, toolError, requireFields } from '../shared/index.js';
|
|
7
|
-
import { recordDesignDecision } from '../designer.js';
|
|
7
|
+
import { recordDesignDecision, syncTokens, reviewFigma, upsertPrinciple, listPrinciples, } from '../designer.js';
|
|
8
8
|
import { logCrit, listCrits, } from '../crit.js';
|
|
9
9
|
// ============================================================================
|
|
10
10
|
// Types
|
|
@@ -167,11 +167,187 @@ export const designerListCritsTool = {
|
|
|
167
167
|
},
|
|
168
168
|
};
|
|
169
169
|
// ============================================================================
|
|
170
|
+
// Sync Tokens Tool
|
|
171
|
+
// ============================================================================
|
|
172
|
+
export const designerSyncTokensTool = {
|
|
173
|
+
definition: {
|
|
174
|
+
name: 'designer_sync_tokens',
|
|
175
|
+
description: 'Sync design tokens from a Figma file. Fetches variables and saves them to .decibel/designer/tokens/. Requires FIGMA_ACCESS_TOKEN env var.',
|
|
176
|
+
inputSchema: {
|
|
177
|
+
type: 'object',
|
|
178
|
+
properties: {
|
|
179
|
+
projectId: {
|
|
180
|
+
type: 'string',
|
|
181
|
+
description: 'Optional project identifier. Uses default project if not specified.',
|
|
182
|
+
},
|
|
183
|
+
fileKey: {
|
|
184
|
+
type: 'string',
|
|
185
|
+
description: 'Figma file key (the part after /file/ in the URL)',
|
|
186
|
+
},
|
|
187
|
+
forceRefresh: {
|
|
188
|
+
type: 'boolean',
|
|
189
|
+
description: 'Bypass cache and fetch fresh data (default: false)',
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
required: ['fileKey'],
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
handler: async (args) => {
|
|
196
|
+
try {
|
|
197
|
+
const rawInput = args;
|
|
198
|
+
normalizeProjectId(rawInput);
|
|
199
|
+
const input = rawInput;
|
|
200
|
+
requireFields(input, 'fileKey');
|
|
201
|
+
const result = await syncTokens(input);
|
|
202
|
+
return toolSuccess(result);
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
return toolError(err instanceof Error ? err.message : String(err));
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
// ============================================================================
|
|
210
|
+
// Review Figma Tool
|
|
211
|
+
// ============================================================================
|
|
212
|
+
export const designerReviewFigmaTool = {
|
|
213
|
+
definition: {
|
|
214
|
+
name: 'designer_review_figma',
|
|
215
|
+
description: 'Review a Figma component against project design principles. Checks accessibility, consistency, and custom principles. Requires FIGMA_ACCESS_TOKEN env var.',
|
|
216
|
+
inputSchema: {
|
|
217
|
+
type: 'object',
|
|
218
|
+
properties: {
|
|
219
|
+
projectId: {
|
|
220
|
+
type: 'string',
|
|
221
|
+
description: 'Optional project identifier. Uses default project if not specified.',
|
|
222
|
+
},
|
|
223
|
+
fileKey: {
|
|
224
|
+
type: 'string',
|
|
225
|
+
description: 'Figma file key (the part after /file/ in the URL)',
|
|
226
|
+
},
|
|
227
|
+
nodeId: {
|
|
228
|
+
type: 'string',
|
|
229
|
+
description: 'Component node ID (from the URL when component is selected)',
|
|
230
|
+
},
|
|
231
|
+
scope: {
|
|
232
|
+
type: 'string',
|
|
233
|
+
enum: ['full', 'accessibility', 'consistency'],
|
|
234
|
+
description: 'Review scope: full (all checks), accessibility (a11y only), consistency (design system alignment)',
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
required: ['fileKey', 'nodeId'],
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
handler: async (args) => {
|
|
241
|
+
try {
|
|
242
|
+
const rawInput = args;
|
|
243
|
+
normalizeProjectId(rawInput);
|
|
244
|
+
const input = rawInput;
|
|
245
|
+
requireFields(input, 'fileKey', 'nodeId');
|
|
246
|
+
const result = await reviewFigma(input);
|
|
247
|
+
return toolSuccess(result);
|
|
248
|
+
}
|
|
249
|
+
catch (err) {
|
|
250
|
+
return toolError(err instanceof Error ? err.message : String(err));
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
// ============================================================================
|
|
255
|
+
// Upsert Principle Tool
|
|
256
|
+
// ============================================================================
|
|
257
|
+
export const designerUpsertPrincipleTool = {
|
|
258
|
+
definition: {
|
|
259
|
+
name: 'designer_upsert_principle',
|
|
260
|
+
description: 'Create or update a design principle. Principles are used by designer_review_figma to check components.',
|
|
261
|
+
inputSchema: {
|
|
262
|
+
type: 'object',
|
|
263
|
+
properties: {
|
|
264
|
+
projectId: {
|
|
265
|
+
type: 'string',
|
|
266
|
+
description: 'Optional project identifier. Uses default project if not specified.',
|
|
267
|
+
},
|
|
268
|
+
id: {
|
|
269
|
+
type: 'string',
|
|
270
|
+
description: 'Principle ID. If provided, updates existing. If omitted, creates new.',
|
|
271
|
+
},
|
|
272
|
+
title: {
|
|
273
|
+
type: 'string',
|
|
274
|
+
description: 'Principle title (e.g., "4px Grid System")',
|
|
275
|
+
},
|
|
276
|
+
description: {
|
|
277
|
+
type: 'string',
|
|
278
|
+
description: 'Full description of the principle',
|
|
279
|
+
},
|
|
280
|
+
category: {
|
|
281
|
+
type: 'string',
|
|
282
|
+
description: 'Category: spacing, color, typography, accessibility, etc.',
|
|
283
|
+
},
|
|
284
|
+
checks: {
|
|
285
|
+
type: 'array',
|
|
286
|
+
items: { type: 'string' },
|
|
287
|
+
description: 'Things to verify (e.g., ["spacing must be multiples of 4"])',
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
required: ['title', 'description', 'category'],
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
handler: async (args) => {
|
|
294
|
+
try {
|
|
295
|
+
const rawInput = args;
|
|
296
|
+
normalizeProjectId(rawInput);
|
|
297
|
+
const input = rawInput;
|
|
298
|
+
requireFields(input, 'title', 'description', 'category');
|
|
299
|
+
const result = await upsertPrinciple(input);
|
|
300
|
+
return toolSuccess(result);
|
|
301
|
+
}
|
|
302
|
+
catch (err) {
|
|
303
|
+
return toolError(err instanceof Error ? err.message : String(err));
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
// ============================================================================
|
|
308
|
+
// List Principles Tool
|
|
309
|
+
// ============================================================================
|
|
310
|
+
export const designerListPrinciplesTool = {
|
|
311
|
+
definition: {
|
|
312
|
+
name: 'designer_list_principles',
|
|
313
|
+
description: 'List design principles for a project, optionally filtered by category.',
|
|
314
|
+
inputSchema: {
|
|
315
|
+
type: 'object',
|
|
316
|
+
properties: {
|
|
317
|
+
projectId: {
|
|
318
|
+
type: 'string',
|
|
319
|
+
description: 'Optional project identifier. Uses default project if not specified.',
|
|
320
|
+
},
|
|
321
|
+
category: {
|
|
322
|
+
type: 'string',
|
|
323
|
+
description: 'Filter by category (e.g., "spacing", "color")',
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
handler: async (args) => {
|
|
329
|
+
try {
|
|
330
|
+
const rawInput = args;
|
|
331
|
+
normalizeProjectId(rawInput);
|
|
332
|
+
const input = rawInput;
|
|
333
|
+
const result = await listPrinciples(input);
|
|
334
|
+
return toolSuccess(result);
|
|
335
|
+
}
|
|
336
|
+
catch (err) {
|
|
337
|
+
return toolError(err instanceof Error ? err.message : String(err));
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
// ============================================================================
|
|
170
342
|
// Export All Tools
|
|
171
343
|
// ============================================================================
|
|
172
344
|
export const designerTools = [
|
|
173
345
|
designerRecordDecisionTool,
|
|
174
346
|
designerCritTool,
|
|
175
347
|
designerListCritsTool,
|
|
348
|
+
designerSyncTokensTool,
|
|
349
|
+
designerReviewFigmaTool,
|
|
350
|
+
designerUpsertPrincipleTool,
|
|
351
|
+
designerListPrinciplesTool,
|
|
176
352
|
];
|
|
177
353
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/designer/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAC/E,4DAA4D;AAC5D,+EAA+E;AAG/E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/designer/index.ts"],"names":[],"mappings":"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"}
|