@andespindola/brainlink 0.1.0-alpha.6 → 0.1.0-alpha.7
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.md +1 -1
- package/README.md +22 -37
- package/dist/mcp/main.js +10 -0
- package/dist/mcp/server.js +59 -0
- package/dist/mcp/tools.js +166 -0
- package/docs/AGENT_USAGE.md +29 -10
- package/docs/ARCHITECTURE.md +5 -7
- package/package.json +7 -3
package/AGENTS.md
CHANGED
|
@@ -86,7 +86,7 @@ npm run dev -- watch --vault ./vault
|
|
|
86
86
|
Start MCP over stdio:
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
|
-
npm run dev
|
|
89
|
+
npm run dev:mcp
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
Automation-facing CLI commands support `--json`. When invoking through `npm`, use `npm run --silent dev -- ...` so stdout remains valid JSON.
|
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ Markdown is the source of truth. `.brainlink/brainlink.db` is only a rebuildable
|
|
|
64
64
|
- Agent namespaces under `agents/<agent-id>/`.
|
|
65
65
|
- CLI with machine-readable `--json` output.
|
|
66
66
|
- Short CLI alias: `blink`.
|
|
67
|
-
-
|
|
67
|
+
- Built-in MCP stdio server for agent tool integration.
|
|
68
68
|
- Local HTTP API.
|
|
69
69
|
- Realtime graph UI with agent selector and colored knowledge groups.
|
|
70
70
|
|
|
@@ -330,50 +330,36 @@ This allows `coding-agent` and `research-agent` to both have a note named `Archi
|
|
|
330
330
|
|
|
331
331
|
## MCP Server Integration
|
|
332
332
|
|
|
333
|
-
Brainlink
|
|
334
|
-
|
|
335
|
-
An MCP server can use Brainlink by spawning `blink` or `brainlink` as a subprocess and reading `--json` output. This keeps Brainlink decoupled from any specific MCP SDK while still making it usable by MCP-compatible agents.
|
|
336
|
-
|
|
337
|
-
Minimum integration contract:
|
|
333
|
+
Brainlink ships a stdio MCP server with the npm package:
|
|
338
334
|
|
|
339
335
|
```bash
|
|
340
|
-
|
|
341
|
-
blink add "Decision Title" --agent "$BLINK_AGENT" --content "Durable memory. #decision"
|
|
342
|
-
blink index
|
|
336
|
+
brainlink-mcp
|
|
343
337
|
```
|
|
344
338
|
|
|
345
|
-
Example
|
|
346
|
-
|
|
347
|
-
```js
|
|
348
|
-
import { execFile } from 'node:child_process'
|
|
349
|
-
import { promisify } from 'node:util'
|
|
350
|
-
|
|
351
|
-
const execFileAsync = promisify(execFile)
|
|
339
|
+
Example MCP client configuration:
|
|
352
340
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
agent,
|
|
361
|
-
'--mode',
|
|
362
|
-
'hybrid',
|
|
363
|
-
'--json'
|
|
364
|
-
])
|
|
365
|
-
|
|
366
|
-
return JSON.parse(stdout)
|
|
341
|
+
```json
|
|
342
|
+
{
|
|
343
|
+
"mcpServers": {
|
|
344
|
+
"brainlink": {
|
|
345
|
+
"command": "brainlink-mcp"
|
|
346
|
+
}
|
|
347
|
+
}
|
|
367
348
|
}
|
|
368
349
|
```
|
|
369
350
|
|
|
370
|
-
|
|
351
|
+
Available tools:
|
|
352
|
+
|
|
353
|
+
- `brainlink_context`: read indexed context for a task or question.
|
|
354
|
+
- `brainlink_search`: search indexed notes.
|
|
355
|
+
- `brainlink_add_note`: write durable Markdown memory and reindex.
|
|
356
|
+
- `brainlink_index`: rebuild the vault index.
|
|
357
|
+
- `brainlink_validate`: validate broken links and orphan notes.
|
|
358
|
+
- `brainlink_graph`: read indexed graph nodes and links.
|
|
359
|
+
- `brainlink_broken_links`: list unresolved wiki links.
|
|
360
|
+
- `brainlink_orphans`: list disconnected notes.
|
|
371
361
|
|
|
372
|
-
|
|
373
|
-
- `brainlink_search`: calls `blink search ... --json`.
|
|
374
|
-
- `brainlink_add_note`: calls `blink add ... --json`, then `blink index`.
|
|
375
|
-
- `brainlink_graph`: calls `blink graph ... --json`.
|
|
376
|
-
- `brainlink_validate`: calls `blink validate ... --json`.
|
|
362
|
+
The same linking rule applies through MCP: `brainlink_context` is read-only, and real graph links require Markdown notes with explicit `[[wiki links]]` followed by indexing.
|
|
377
363
|
|
|
378
364
|
## Graph UI
|
|
379
365
|
|
|
@@ -708,7 +694,6 @@ Detailed notes:
|
|
|
708
694
|
- Semantic search uses SQLite embedding buckets to narrow candidates before cosine scoring.
|
|
709
695
|
- `embeddingProvider` currently supports `local` and `none`.
|
|
710
696
|
- Link resolution is title-based inside each agent namespace, with `shared` as fallback.
|
|
711
|
-
- No embedded MCP server is shipped; MCP integration is done by external servers wrapping the CLI.
|
|
712
697
|
- HTTP API is local and unauthenticated.
|
|
713
698
|
- Watch mode depends on the platform filesystem watcher.
|
|
714
699
|
|
package/dist/mcp/main.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { createBrainlinkMcpServer } from './server.js';
|
|
4
|
+
const server = createBrainlinkMcpServer();
|
|
5
|
+
const transport = new StdioServerTransport();
|
|
6
|
+
server.connect(transport).catch((error) => {
|
|
7
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8
|
+
console.error(message);
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { addNoteInputSchema, addNoteTool, brokenLinksInputSchema, brokenLinksTool, contextInputSchema, contextTool, graphInputSchema, graphTool, indexInputSchema, indexTool, orphansInputSchema, orphansTool, searchInputSchema, searchTool, validateInputSchema, validateTool } from './tools.js';
|
|
6
|
+
const readPackageVersion = () => {
|
|
7
|
+
const packagePath = join(dirname(fileURLToPath(import.meta.url)), '../../package.json');
|
|
8
|
+
const metadata = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
9
|
+
return metadata.version ?? '0.0.0';
|
|
10
|
+
};
|
|
11
|
+
export const createBrainlinkMcpServer = () => {
|
|
12
|
+
const server = new McpServer({
|
|
13
|
+
name: 'brainlink',
|
|
14
|
+
title: 'Brainlink',
|
|
15
|
+
version: readPackageVersion(),
|
|
16
|
+
description: 'Local-first Markdown memory tools for AI agents.'
|
|
17
|
+
});
|
|
18
|
+
server.registerTool('brainlink_context', {
|
|
19
|
+
title: 'Build Brainlink Context',
|
|
20
|
+
description: 'Read indexed Brainlink memory for a task or question. This is read-only and does not create graph links.',
|
|
21
|
+
inputSchema: contextInputSchema
|
|
22
|
+
}, contextTool);
|
|
23
|
+
server.registerTool('brainlink_search', {
|
|
24
|
+
title: 'Search Brainlink Memory',
|
|
25
|
+
description: 'Search indexed Brainlink notes with FTS, semantic or hybrid retrieval.',
|
|
26
|
+
inputSchema: searchInputSchema
|
|
27
|
+
}, searchTool);
|
|
28
|
+
server.registerTool('brainlink_add_note', {
|
|
29
|
+
title: 'Add Brainlink Note',
|
|
30
|
+
description: 'Write durable Markdown memory, then reindex the vault. Include explicit [[wiki links]] for connected graph memory.',
|
|
31
|
+
inputSchema: addNoteInputSchema
|
|
32
|
+
}, addNoteTool);
|
|
33
|
+
server.registerTool('brainlink_index', {
|
|
34
|
+
title: 'Index Brainlink Vault',
|
|
35
|
+
description: 'Rebuild the local Brainlink index from Markdown notes.',
|
|
36
|
+
inputSchema: indexInputSchema
|
|
37
|
+
}, indexTool);
|
|
38
|
+
server.registerTool('brainlink_validate', {
|
|
39
|
+
title: 'Validate Brainlink Vault',
|
|
40
|
+
description: 'Validate indexed graph health, including broken links and orphan notes.',
|
|
41
|
+
inputSchema: validateInputSchema
|
|
42
|
+
}, validateTool);
|
|
43
|
+
server.registerTool('brainlink_graph', {
|
|
44
|
+
title: 'Read Brainlink Graph',
|
|
45
|
+
description: 'Read indexed graph nodes and wiki-link edges.',
|
|
46
|
+
inputSchema: graphInputSchema
|
|
47
|
+
}, graphTool);
|
|
48
|
+
server.registerTool('brainlink_broken_links', {
|
|
49
|
+
title: 'List Brainlink Broken Links',
|
|
50
|
+
description: 'List unresolved indexed wiki links.',
|
|
51
|
+
inputSchema: brokenLinksInputSchema
|
|
52
|
+
}, brokenLinksTool);
|
|
53
|
+
server.registerTool('brainlink_orphans', {
|
|
54
|
+
title: 'List Brainlink Orphans',
|
|
55
|
+
description: 'List indexed notes without incoming or outgoing graph links.',
|
|
56
|
+
inputSchema: orphansInputSchema
|
|
57
|
+
}, orphansTool);
|
|
58
|
+
return server;
|
|
59
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getBrokenLinksReport, getOrphansReport, validateVault } from '../application/analyze-vault.js';
|
|
3
|
+
import { addNote } from '../application/add-note.js';
|
|
4
|
+
import { buildContextPackage } from '../application/build-context.js';
|
|
5
|
+
import { getGraph } from '../application/get-graph.js';
|
|
6
|
+
import { indexVault } from '../application/index-vault.js';
|
|
7
|
+
import { searchKnowledge } from '../application/search-knowledge.js';
|
|
8
|
+
import { sanitizeSearchMode } from '../infrastructure/config.js';
|
|
9
|
+
import { loadBrainlinkConfig } from '../infrastructure/config.js';
|
|
10
|
+
import { assertVaultAllowed } from '../infrastructure/file-system-vault.js';
|
|
11
|
+
const positiveInteger = (fallback) => z
|
|
12
|
+
.number()
|
|
13
|
+
.int()
|
|
14
|
+
.positive()
|
|
15
|
+
.optional()
|
|
16
|
+
.transform((value) => value ?? fallback);
|
|
17
|
+
const vaultInput = {
|
|
18
|
+
vault: z.string().min(1).optional().describe('Vault directory. Omit to use the configured Brainlink default vault.')
|
|
19
|
+
};
|
|
20
|
+
const agentInput = {
|
|
21
|
+
agent: z.string().min(1).optional().describe('Agent memory namespace. Omit to read shared/default indexed memory.')
|
|
22
|
+
};
|
|
23
|
+
const searchModeInput = {
|
|
24
|
+
mode: z.enum(['fts', 'semantic', 'hybrid']).optional().describe('Search mode. Defaults to the Brainlink config value.')
|
|
25
|
+
};
|
|
26
|
+
const resolveVault = async (vault) => {
|
|
27
|
+
const config = await loadBrainlinkConfig();
|
|
28
|
+
return assertVaultAllowed(vault ?? config.vault, config.allowedVaults);
|
|
29
|
+
};
|
|
30
|
+
const jsonResult = (value) => ({
|
|
31
|
+
content: [
|
|
32
|
+
{
|
|
33
|
+
type: 'text',
|
|
34
|
+
text: JSON.stringify(value, null, 2)
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
structuredContent: value
|
|
38
|
+
});
|
|
39
|
+
export const contextInputSchema = {
|
|
40
|
+
...vaultInput,
|
|
41
|
+
...agentInput,
|
|
42
|
+
...searchModeInput,
|
|
43
|
+
query: z.string().min(1).describe('Task or question to retrieve Brainlink context for.'),
|
|
44
|
+
limit: positiveInteger(12).describe('Maximum search results before context selection.'),
|
|
45
|
+
tokens: positiveInteger(2000).describe('Maximum estimated context tokens.')
|
|
46
|
+
};
|
|
47
|
+
export const searchInputSchema = {
|
|
48
|
+
...vaultInput,
|
|
49
|
+
...agentInput,
|
|
50
|
+
...searchModeInput,
|
|
51
|
+
query: z.string().min(1).describe('Search query.'),
|
|
52
|
+
limit: positiveInteger(10).describe('Maximum result count.')
|
|
53
|
+
};
|
|
54
|
+
export const addNoteInputSchema = {
|
|
55
|
+
...vaultInput,
|
|
56
|
+
title: z.string().min(1).describe('Markdown note title.'),
|
|
57
|
+
content: z
|
|
58
|
+
.string()
|
|
59
|
+
.min(1)
|
|
60
|
+
.describe('Durable Markdown memory. Include explicit [[wiki links]] and #tags when the memory should be connected.'),
|
|
61
|
+
agent: z.string().min(1).optional().default('shared').describe('Agent memory namespace. Defaults to shared.'),
|
|
62
|
+
allowSensitive: z.boolean().optional().default(false).describe('Allow content that looks like a secret.')
|
|
63
|
+
};
|
|
64
|
+
export const indexInputSchema = {
|
|
65
|
+
...vaultInput
|
|
66
|
+
};
|
|
67
|
+
export const validateInputSchema = {
|
|
68
|
+
...vaultInput,
|
|
69
|
+
...agentInput
|
|
70
|
+
};
|
|
71
|
+
export const graphInputSchema = {
|
|
72
|
+
...vaultInput,
|
|
73
|
+
...agentInput
|
|
74
|
+
};
|
|
75
|
+
export const brokenLinksInputSchema = {
|
|
76
|
+
...vaultInput,
|
|
77
|
+
...agentInput
|
|
78
|
+
};
|
|
79
|
+
export const orphansInputSchema = {
|
|
80
|
+
...vaultInput,
|
|
81
|
+
...agentInput
|
|
82
|
+
};
|
|
83
|
+
export const contextTool = async (input) => {
|
|
84
|
+
const vault = await resolveVault(input.vault);
|
|
85
|
+
const config = await loadBrainlinkConfig();
|
|
86
|
+
const mode = sanitizeSearchMode(input.mode, config.defaultSearchMode);
|
|
87
|
+
const contextPackage = await buildContextPackage(vault, input.query, input.limit, input.tokens, input.agent, mode);
|
|
88
|
+
return jsonResult({
|
|
89
|
+
vault,
|
|
90
|
+
agent: input.agent,
|
|
91
|
+
mode,
|
|
92
|
+
...contextPackage
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
export const searchTool = async (input) => {
|
|
96
|
+
const vault = await resolveVault(input.vault);
|
|
97
|
+
const config = await loadBrainlinkConfig();
|
|
98
|
+
const mode = sanitizeSearchMode(input.mode, config.defaultSearchMode);
|
|
99
|
+
const results = await searchKnowledge(vault, input.query, input.limit, input.agent, mode);
|
|
100
|
+
return jsonResult({
|
|
101
|
+
vault,
|
|
102
|
+
agent: input.agent,
|
|
103
|
+
query: input.query,
|
|
104
|
+
limit: input.limit,
|
|
105
|
+
mode,
|
|
106
|
+
results
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
export const addNoteTool = async (input) => {
|
|
110
|
+
const vault = await resolveVault(input.vault);
|
|
111
|
+
const path = await addNote(vault, input.title, input.content, input.agent, {
|
|
112
|
+
allowSensitive: input.allowSensitive
|
|
113
|
+
});
|
|
114
|
+
const index = await indexVault(vault);
|
|
115
|
+
return jsonResult({
|
|
116
|
+
vault,
|
|
117
|
+
title: input.title,
|
|
118
|
+
agent: input.agent,
|
|
119
|
+
path,
|
|
120
|
+
index
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
export const indexTool = async (input) => {
|
|
124
|
+
const vault = await resolveVault(input.vault);
|
|
125
|
+
const result = await indexVault(vault);
|
|
126
|
+
return jsonResult({
|
|
127
|
+
vault,
|
|
128
|
+
...result
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
export const validateTool = async (input) => {
|
|
132
|
+
const vault = await resolveVault(input.vault);
|
|
133
|
+
const validation = await validateVault(vault, input.agent);
|
|
134
|
+
return jsonResult({
|
|
135
|
+
vault,
|
|
136
|
+
agent: input.agent,
|
|
137
|
+
...validation
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
export const graphTool = async (input) => {
|
|
141
|
+
const vault = await resolveVault(input.vault);
|
|
142
|
+
const graph = await getGraph(vault, input.agent);
|
|
143
|
+
return jsonResult({
|
|
144
|
+
vault,
|
|
145
|
+
agent: input.agent,
|
|
146
|
+
...graph
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
export const brokenLinksTool = async (input) => {
|
|
150
|
+
const vault = await resolveVault(input.vault);
|
|
151
|
+
const brokenLinks = await getBrokenLinksReport(vault, input.agent);
|
|
152
|
+
return jsonResult({
|
|
153
|
+
vault,
|
|
154
|
+
agent: input.agent,
|
|
155
|
+
brokenLinks
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
export const orphansTool = async (input) => {
|
|
159
|
+
const vault = await resolveVault(input.vault);
|
|
160
|
+
const orphans = await getOrphansReport(vault, input.agent);
|
|
161
|
+
return jsonResult({
|
|
162
|
+
vault,
|
|
163
|
+
agent: input.agent,
|
|
164
|
+
orphans
|
|
165
|
+
});
|
|
166
|
+
};
|
package/docs/AGENT_USAGE.md
CHANGED
|
@@ -431,19 +431,38 @@ blink watch --vault ./vault
|
|
|
431
431
|
|
|
432
432
|
This process watches Markdown files and rebuilds the index after changes.
|
|
433
433
|
|
|
434
|
-
### Use From
|
|
434
|
+
### Use From MCP
|
|
435
435
|
|
|
436
|
-
Brainlink
|
|
436
|
+
Brainlink ships a stdio MCP server:
|
|
437
437
|
|
|
438
|
-
|
|
438
|
+
```bash
|
|
439
|
+
brainlink-mcp
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Example MCP client configuration:
|
|
443
|
+
|
|
444
|
+
```json
|
|
445
|
+
{
|
|
446
|
+
"mcpServers": {
|
|
447
|
+
"brainlink": {
|
|
448
|
+
"command": "brainlink-mcp"
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
Available MCP tools:
|
|
439
455
|
|
|
440
|
-
- `brainlink_context
|
|
441
|
-
- `brainlink_search
|
|
442
|
-
- `brainlink_add_note
|
|
443
|
-
- `
|
|
444
|
-
- `brainlink_validate
|
|
456
|
+
- `brainlink_context`
|
|
457
|
+
- `brainlink_search`
|
|
458
|
+
- `brainlink_add_note`
|
|
459
|
+
- `brainlink_index`
|
|
460
|
+
- `brainlink_validate`
|
|
461
|
+
- `brainlink_graph`
|
|
462
|
+
- `brainlink_broken_links`
|
|
463
|
+
- `brainlink_orphans`
|
|
445
464
|
|
|
446
|
-
|
|
465
|
+
MCP clients can pass `vault` and `agent` arguments per tool call. Set `BRAINLINK_ALLOWED_VAULTS` when exposing Brainlink to an external agent process so a tool cannot pass arbitrary vault paths:
|
|
447
466
|
|
|
448
467
|
```bash
|
|
449
468
|
export BRAINLINK_ALLOWED_VAULTS="/absolute/path/to/project-vault"
|
|
@@ -531,6 +550,6 @@ Weak retrieval usually means:
|
|
|
531
550
|
|
|
532
551
|
- Search supports FTS, local semantic embeddings, SQLite semantic buckets and hybrid ranking.
|
|
533
552
|
- Local embeddings are deterministic and provider-free; remote embedding providers are not implemented yet.
|
|
534
|
-
- MCP integration is
|
|
553
|
+
- MCP integration is available through the `brainlink-mcp` stdio server.
|
|
535
554
|
- HTTP API is local and unauthenticated.
|
|
536
555
|
- Watch mode depends on platform filesystem watcher behavior.
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -167,20 +167,18 @@ HTTP request
|
|
|
167
167
|
|
|
168
168
|
The HTTP API is local-first and unauthenticated. It is meant for local agents, browser UI, and development workflows.
|
|
169
169
|
|
|
170
|
-
##
|
|
170
|
+
## MCP Flow
|
|
171
171
|
|
|
172
|
-
Brainlink
|
|
172
|
+
Brainlink includes a stdio MCP server for agent integrations.
|
|
173
173
|
|
|
174
174
|
```txt
|
|
175
175
|
MCP client
|
|
176
|
-
->
|
|
177
|
-
-> child_process execFile("blink", ["context", ..., "--json"])
|
|
178
|
-
-> Brainlink CLI
|
|
176
|
+
-> brainlink-mcp
|
|
179
177
|
-> application use case
|
|
180
|
-
->
|
|
178
|
+
-> MCP tool result
|
|
181
179
|
```
|
|
182
180
|
|
|
183
|
-
|
|
181
|
+
The MCP adapter stays thin. It validates tool inputs, resolves the configured vault and calls the same application use cases used by the CLI.
|
|
184
182
|
|
|
185
183
|
## Link Resolution
|
|
186
184
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andespindola/brainlink",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.7",
|
|
4
4
|
"description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
],
|
|
26
26
|
"bin": {
|
|
27
27
|
"brainlink": "dist/cli/main.js",
|
|
28
|
-
"blink": "dist/cli/main.js"
|
|
28
|
+
"blink": "dist/cli/main.js",
|
|
29
|
+
"brainlink-mcp": "dist/mcp/main.js"
|
|
29
30
|
},
|
|
30
31
|
"files": [
|
|
31
32
|
"dist",
|
|
@@ -44,6 +45,7 @@
|
|
|
44
45
|
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
45
46
|
"build": "npm run clean && tsc -p tsconfig.json",
|
|
46
47
|
"dev": "tsx src/cli/main.ts",
|
|
48
|
+
"dev:mcp": "tsx src/mcp/main.ts",
|
|
47
49
|
"test": "vitest run --config vitest.config.ts",
|
|
48
50
|
"check": "npm run build && npm run test",
|
|
49
51
|
"benchmark:large": "tsx src/benchmarks/large-vault.ts",
|
|
@@ -51,8 +53,10 @@
|
|
|
51
53
|
"pack:smoke": "npm pack --dry-run"
|
|
52
54
|
},
|
|
53
55
|
"dependencies": {
|
|
56
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
54
57
|
"better-sqlite3": "^12.9.0",
|
|
55
|
-
"commander": "^14.0.2"
|
|
58
|
+
"commander": "^14.0.2",
|
|
59
|
+
"zod": "^4.3.6"
|
|
56
60
|
},
|
|
57
61
|
"devDependencies": {
|
|
58
62
|
"@types/better-sqlite3": "^7.6.13",
|