memorandum-mcp 0.1.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/LICENSE +674 -0
- package/README.md +237 -0
- package/README.ru.md +237 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.js +63 -0
- package/dist/config.js.map +1 -0
- package/dist/document-store.d.ts +145 -0
- package/dist/document-store.js +682 -0
- package/dist/document-store.js.map +1 -0
- package/dist/document-tools.d.ts +10 -0
- package/dist/document-tools.js +101 -0
- package/dist/document-tools.js.map +1 -0
- package/dist/document-types.d.ts +147 -0
- package/dist/document-types.js +125 -0
- package/dist/document-types.js.map +1 -0
- package/dist/embedder.d.ts +55 -0
- package/dist/embedder.js +152 -0
- package/dist/embedder.js.map +1 -0
- package/dist/embedding-queue.d.ts +66 -0
- package/dist/embedding-queue.js +152 -0
- package/dist/embedding-queue.js.map +1 -0
- package/dist/errors.d.ts +26 -0
- package/dist/errors.js +46 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +147 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +12 -0
- package/dist/logger.js +22 -0
- package/dist/logger.js.map +1 -0
- package/dist/semantic-index.d.ts +126 -0
- package/dist/semantic-index.js +427 -0
- package/dist/semantic-index.js.map +1 -0
- package/dist/semantic-tools.d.ts +10 -0
- package/dist/semantic-tools.js +80 -0
- package/dist/semantic-tools.js.map +1 -0
- package/dist/semantic-types.d.ts +161 -0
- package/dist/semantic-types.js +101 -0
- package/dist/semantic-types.js.map +1 -0
- package/dist/store.d.ts +130 -0
- package/dist/store.js +389 -0
- package/dist/store.js.map +1 -0
- package/dist/tools.d.ts +15 -0
- package/dist/tools.js +104 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +97 -0
- package/dist/types.js +88 -0
- package/dist/types.js.map +1 -0
- package/dist/vector-store.d.ts +85 -0
- package/dist/vector-store.js +241 -0
- package/dist/vector-store.js.map +1 -0
- package/package.json +50 -0
package/dist/embedder.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { existsSync, rmSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Manages loading and running a HuggingFace feature-extraction model
|
|
5
|
+
* to produce vector embeddings from text.
|
|
6
|
+
*/
|
|
7
|
+
export class Embedder {
|
|
8
|
+
static MAX_INPUT_CHARS = 2000;
|
|
9
|
+
modelId;
|
|
10
|
+
dtype;
|
|
11
|
+
logger;
|
|
12
|
+
pipeline = null;
|
|
13
|
+
loading = null;
|
|
14
|
+
unavailable = false;
|
|
15
|
+
failureReason = null;
|
|
16
|
+
/**
|
|
17
|
+
* @param modelId - HuggingFace model identifier (e.g. "intfloat/multilingual-e5-small").
|
|
18
|
+
* @param dtype - Data type for the model weights (e.g. "fp32", "q8").
|
|
19
|
+
* @param logger - Pino logger instance.
|
|
20
|
+
*/
|
|
21
|
+
constructor(modelId, dtype, logger) {
|
|
22
|
+
this.modelId = modelId;
|
|
23
|
+
this.dtype = dtype;
|
|
24
|
+
this.logger = logger;
|
|
25
|
+
}
|
|
26
|
+
/** Whether the embedding pipeline has been successfully loaded. */
|
|
27
|
+
get isLoaded() { return this.pipeline != null; }
|
|
28
|
+
/** Whether the embedding pipeline is currently being loaded. */
|
|
29
|
+
get isLoading() { return this.loading != null; }
|
|
30
|
+
/** Whether the model failed to load and is permanently unavailable. */
|
|
31
|
+
get isUnavailable() { return this.unavailable; }
|
|
32
|
+
/** The error message explaining why the model is unavailable, or null. */
|
|
33
|
+
get unavailableReason() { return this.failureReason; }
|
|
34
|
+
/**
|
|
35
|
+
* Resets internal state, loads the pipeline, and retries after clearing
|
|
36
|
+
* the model cache if a corrupted-cache error is detected.
|
|
37
|
+
*/
|
|
38
|
+
async repairAndLoad() {
|
|
39
|
+
this.pipeline = null;
|
|
40
|
+
this.loading = null;
|
|
41
|
+
this.unavailable = false;
|
|
42
|
+
this.failureReason = null;
|
|
43
|
+
try {
|
|
44
|
+
await this.getPipeline();
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
if (!this.isCorruptedCacheError(err))
|
|
48
|
+
throw err;
|
|
49
|
+
this.logger.warn({ model: this.modelId, error: err instanceof Error ? err.message : String(err) }, 'Corrupted model cache detected, deleting cache and retrying');
|
|
50
|
+
await this.deleteModelCache();
|
|
51
|
+
this.pipeline = null;
|
|
52
|
+
this.loading = null;
|
|
53
|
+
this.unavailable = false;
|
|
54
|
+
this.failureReason = null;
|
|
55
|
+
await this.getPipeline();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Embeds a search query, applying E5 "query:" prefix when applicable.
|
|
60
|
+
* @param text - The query text to embed.
|
|
61
|
+
* @returns The embedding vector.
|
|
62
|
+
*/
|
|
63
|
+
async embedQuery(text) {
|
|
64
|
+
return this.embed(this.formatQuery(text));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Embeds a passage of text, applying E5 "passage:" prefix when applicable.
|
|
68
|
+
* @param text - The passage text to embed.
|
|
69
|
+
* @returns The embedding vector.
|
|
70
|
+
*/
|
|
71
|
+
async embedPassage(text) {
|
|
72
|
+
return this.embed(this.formatPassage(text));
|
|
73
|
+
}
|
|
74
|
+
get isE5Model() {
|
|
75
|
+
return this.modelId.toLowerCase().includes('e5');
|
|
76
|
+
}
|
|
77
|
+
formatQuery(text) {
|
|
78
|
+
return this.isE5Model ? `query: ${text}` : text;
|
|
79
|
+
}
|
|
80
|
+
formatPassage(text) {
|
|
81
|
+
return this.isE5Model ? `passage: ${text}` : text;
|
|
82
|
+
}
|
|
83
|
+
truncateText(text) {
|
|
84
|
+
if (text.length <= Embedder.MAX_INPUT_CHARS)
|
|
85
|
+
return text;
|
|
86
|
+
return text.slice(0, Embedder.MAX_INPUT_CHARS);
|
|
87
|
+
}
|
|
88
|
+
async embed(text) {
|
|
89
|
+
const pipe = await this.getPipeline();
|
|
90
|
+
const truncated = this.truncateText(text);
|
|
91
|
+
const output = await pipe(truncated, { pooling: 'mean', normalize: true });
|
|
92
|
+
return output.tolist()[0];
|
|
93
|
+
}
|
|
94
|
+
async getPipeline() {
|
|
95
|
+
if (this.pipeline)
|
|
96
|
+
return this.pipeline;
|
|
97
|
+
if (this.unavailable)
|
|
98
|
+
throw new Error('Embedding model is unavailable');
|
|
99
|
+
if (this.loading)
|
|
100
|
+
return this.loading;
|
|
101
|
+
this.loading = this.initPipeline();
|
|
102
|
+
try {
|
|
103
|
+
this.pipeline = await this.loading;
|
|
104
|
+
return this.pipeline;
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
this.failureReason = err instanceof Error ? err.message : String(err);
|
|
108
|
+
this.unavailable = true;
|
|
109
|
+
this.logger.error({ model: this.modelId, error: this.failureReason }, 'Embedding model failed to load');
|
|
110
|
+
throw err;
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
this.loading = null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
isCorruptedCacheError(err) {
|
|
117
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
118
|
+
return msg.includes('Protobuf parsing failed') || msg.includes('invalid model');
|
|
119
|
+
}
|
|
120
|
+
async deleteModelCache() {
|
|
121
|
+
try {
|
|
122
|
+
const { env } = await import('@huggingface/transformers');
|
|
123
|
+
const cacheBase = String(env.cacheDir || '');
|
|
124
|
+
if (!cacheBase)
|
|
125
|
+
return;
|
|
126
|
+
const modelCacheDir = join(cacheBase, this.modelId);
|
|
127
|
+
if (existsSync(modelCacheDir)) {
|
|
128
|
+
rmSync(modelCacheDir, { recursive: true, force: true });
|
|
129
|
+
this.logger.info({ path: modelCacheDir }, 'Deleted corrupted model cache');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (deleteErr) {
|
|
133
|
+
this.logger.warn({ error: deleteErr instanceof Error ? deleteErr.message : String(deleteErr) }, 'Failed to delete model cache');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async initPipeline() {
|
|
137
|
+
const { pipeline, env } = await import('@huggingface/transformers');
|
|
138
|
+
env.allowRemoteModels = true;
|
|
139
|
+
const extractor = await pipeline('feature-extraction', this.modelId, {
|
|
140
|
+
dtype: this.dtype,
|
|
141
|
+
device: 'cpu',
|
|
142
|
+
progress_callback: (progress) => {
|
|
143
|
+
if (progress.status === 'downloading' && progress.file) {
|
|
144
|
+
this.logger.info({ file: progress.file, progress: progress.progress?.toFixed(1) }, 'Downloading embedding model');
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
this.logger.info({ model: this.modelId, dtype: this.dtype }, 'Embedding model loaded');
|
|
149
|
+
return extractor;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=embedder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedder.js","sourceRoot":"","sources":["../src/embedder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Logger } from 'pino';
|
|
2
|
+
import type { Embedder } from './embedder.js';
|
|
3
|
+
import type { VectorStore } from './vector-store.js';
|
|
4
|
+
import type { EmbeddingQueueItem } from './semantic-types.js';
|
|
5
|
+
/** Configuration options for the embedding queue. */
|
|
6
|
+
export interface EmbeddingQueueConfig {
|
|
7
|
+
/** Delay in milliseconds before processing a batch after the last enqueue. */
|
|
8
|
+
debounceMs: number;
|
|
9
|
+
/** Maximum number of pending items before a batch is triggered immediately. */
|
|
10
|
+
maxQueueSize: number;
|
|
11
|
+
/** Maximum retry attempts before marking an embedding as permanently failed. */
|
|
12
|
+
maxRetries: number;
|
|
13
|
+
}
|
|
14
|
+
/** Summary of a completed embedding batch. */
|
|
15
|
+
export interface BatchResult {
|
|
16
|
+
/** Number of items successfully embedded and stored. */
|
|
17
|
+
succeeded: number;
|
|
18
|
+
/** Number of items that failed during embedding. */
|
|
19
|
+
failed: number;
|
|
20
|
+
/** Number of items skipped (discarded or permanently failed). */
|
|
21
|
+
skipped: number;
|
|
22
|
+
/** Wall-clock time of the batch in milliseconds. */
|
|
23
|
+
durationMs: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Debounced queue that batches embedding requests and processes them
|
|
27
|
+
* sequentially through the Embedder, persisting results to the VectorStore.
|
|
28
|
+
*/
|
|
29
|
+
export declare class EmbeddingQueue {
|
|
30
|
+
private readonly embedder;
|
|
31
|
+
private readonly vectorStore;
|
|
32
|
+
private readonly logger;
|
|
33
|
+
private readonly config;
|
|
34
|
+
private pending;
|
|
35
|
+
private processingIds;
|
|
36
|
+
private discardedIds;
|
|
37
|
+
private timer;
|
|
38
|
+
private processing;
|
|
39
|
+
private processingPromise;
|
|
40
|
+
constructor(embedder: Embedder, vectorStore: VectorStore, logger: Logger, config: EmbeddingQueueConfig);
|
|
41
|
+
/**
|
|
42
|
+
* Adds an item to the queue. Triggers an immediate batch if the queue
|
|
43
|
+
* reaches maxQueueSize, otherwise resets the debounce timer.
|
|
44
|
+
* @param item - The item to enqueue for embedding.
|
|
45
|
+
*/
|
|
46
|
+
enqueue(item: EmbeddingQueueItem): void;
|
|
47
|
+
/**
|
|
48
|
+
* Removes an item from the pending queue. If the item is currently being
|
|
49
|
+
* processed, marks it as discarded so its result will be ignored.
|
|
50
|
+
* @param id - The identifier of the item to remove.
|
|
51
|
+
*/
|
|
52
|
+
dequeue(id: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* Processes all pending items immediately, waiting for any in-flight
|
|
55
|
+
* batch to complete first.
|
|
56
|
+
* @returns The result of the flushed batch.
|
|
57
|
+
*/
|
|
58
|
+
flush(): Promise<BatchResult>;
|
|
59
|
+
/** Cancels any pending timer and clears the queue. */
|
|
60
|
+
dispose(): void;
|
|
61
|
+
private resetTimer;
|
|
62
|
+
private cancelTimer;
|
|
63
|
+
private triggerBatch;
|
|
64
|
+
private waitForProcessing;
|
|
65
|
+
private processBatch;
|
|
66
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debounced queue that batches embedding requests and processes them
|
|
3
|
+
* sequentially through the Embedder, persisting results to the VectorStore.
|
|
4
|
+
*/
|
|
5
|
+
export class EmbeddingQueue {
|
|
6
|
+
embedder;
|
|
7
|
+
vectorStore;
|
|
8
|
+
logger;
|
|
9
|
+
config;
|
|
10
|
+
pending = new Map();
|
|
11
|
+
processingIds = new Set();
|
|
12
|
+
discardedIds = new Set();
|
|
13
|
+
timer = null;
|
|
14
|
+
processing = false;
|
|
15
|
+
processingPromise = null;
|
|
16
|
+
constructor(embedder, vectorStore, logger, config) {
|
|
17
|
+
this.embedder = embedder;
|
|
18
|
+
this.vectorStore = vectorStore;
|
|
19
|
+
this.logger = logger;
|
|
20
|
+
this.config = config;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Adds an item to the queue. Triggers an immediate batch if the queue
|
|
24
|
+
* reaches maxQueueSize, otherwise resets the debounce timer.
|
|
25
|
+
* @param item - The item to enqueue for embedding.
|
|
26
|
+
*/
|
|
27
|
+
enqueue(item) {
|
|
28
|
+
this.pending.set(item.id, item);
|
|
29
|
+
this.vectorStore.clearFailure(item.id);
|
|
30
|
+
if (this.pending.size >= this.config.maxQueueSize) {
|
|
31
|
+
this.cancelTimer();
|
|
32
|
+
this.triggerBatch();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
this.resetTimer();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Removes an item from the pending queue. If the item is currently being
|
|
39
|
+
* processed, marks it as discarded so its result will be ignored.
|
|
40
|
+
* @param id - The identifier of the item to remove.
|
|
41
|
+
*/
|
|
42
|
+
dequeue(id) {
|
|
43
|
+
this.pending.delete(id);
|
|
44
|
+
if (this.processingIds.has(id))
|
|
45
|
+
this.discardedIds.add(id);
|
|
46
|
+
this.vectorStore.clearFailure(id);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Processes all pending items immediately, waiting for any in-flight
|
|
50
|
+
* batch to complete first.
|
|
51
|
+
* @returns The result of the flushed batch.
|
|
52
|
+
*/
|
|
53
|
+
async flush() {
|
|
54
|
+
this.cancelTimer();
|
|
55
|
+
if (this.pending.size === 0 && !this.processing) {
|
|
56
|
+
return { succeeded: 0, failed: 0, skipped: 0, durationMs: 0 };
|
|
57
|
+
}
|
|
58
|
+
if (this.processing)
|
|
59
|
+
await this.waitForProcessing();
|
|
60
|
+
if (this.pending.size === 0) {
|
|
61
|
+
return { succeeded: 0, failed: 0, skipped: 0, durationMs: 0 };
|
|
62
|
+
}
|
|
63
|
+
return this.processBatch();
|
|
64
|
+
}
|
|
65
|
+
/** Cancels any pending timer and clears the queue. */
|
|
66
|
+
dispose() {
|
|
67
|
+
this.cancelTimer();
|
|
68
|
+
this.pending.clear();
|
|
69
|
+
}
|
|
70
|
+
resetTimer() {
|
|
71
|
+
this.cancelTimer();
|
|
72
|
+
const delay = this.config.debounceMs === 0 ? 0 : this.config.debounceMs;
|
|
73
|
+
this.timer = setTimeout(() => {
|
|
74
|
+
this.timer = null;
|
|
75
|
+
this.triggerBatch();
|
|
76
|
+
}, delay);
|
|
77
|
+
this.timer.unref();
|
|
78
|
+
}
|
|
79
|
+
cancelTimer() {
|
|
80
|
+
if (this.timer !== null) {
|
|
81
|
+
clearTimeout(this.timer);
|
|
82
|
+
this.timer = null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
triggerBatch() {
|
|
86
|
+
if (this.processing || this.pending.size === 0)
|
|
87
|
+
return;
|
|
88
|
+
this.processBatch().catch((err) => {
|
|
89
|
+
this.logger.error({ error: err instanceof Error ? err.message : String(err) }, 'Batch processing failed');
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
async waitForProcessing() {
|
|
93
|
+
if (this.processingPromise)
|
|
94
|
+
await this.processingPromise;
|
|
95
|
+
}
|
|
96
|
+
async processBatch() {
|
|
97
|
+
const start = Date.now();
|
|
98
|
+
this.processing = true;
|
|
99
|
+
const batch = new Map(this.pending);
|
|
100
|
+
this.pending.clear();
|
|
101
|
+
this.processingIds = new Set(batch.keys());
|
|
102
|
+
this.discardedIds.clear();
|
|
103
|
+
let succeeded = 0, failed = 0, skipped = 0;
|
|
104
|
+
const processPromise = (async () => {
|
|
105
|
+
for (const [id, item] of batch) {
|
|
106
|
+
const failureRecord = this.vectorStore.getFailedEmbeddings()[id];
|
|
107
|
+
if (failureRecord && failureRecord.status === 'failed') {
|
|
108
|
+
skipped++;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const vector = await this.embedder.embedPassage(item.textToEmbed);
|
|
113
|
+
if (this.discardedIds.has(id)) {
|
|
114
|
+
skipped++;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const entry = {
|
|
118
|
+
id, vector, source: item.source,
|
|
119
|
+
metadata: item.metadata, indexedAt: Date.now(),
|
|
120
|
+
};
|
|
121
|
+
this.vectorStore.upsert(entry);
|
|
122
|
+
this.vectorStore.clearFailure(id);
|
|
123
|
+
succeeded++;
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
127
|
+
this.vectorStore.recordFailure(id, errorMsg, this.config.maxRetries);
|
|
128
|
+
failed++;
|
|
129
|
+
this.logger.warn({ id, error: errorMsg }, 'Embedding failed for item');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (succeeded > 0 || failed > 0)
|
|
133
|
+
await this.vectorStore.save();
|
|
134
|
+
})();
|
|
135
|
+
this.processingPromise = processPromise;
|
|
136
|
+
try {
|
|
137
|
+
await processPromise;
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
this.processing = false;
|
|
141
|
+
this.processingIds.clear();
|
|
142
|
+
this.discardedIds.clear();
|
|
143
|
+
this.processingPromise = null;
|
|
144
|
+
}
|
|
145
|
+
const durationMs = Date.now() - start;
|
|
146
|
+
this.logger.info({ succeeded, failed, skipped, durationMs, remaining: this.pending.size }, 'Embedding batch completed');
|
|
147
|
+
if (this.pending.size > 0)
|
|
148
|
+
this.resetTimer();
|
|
149
|
+
return { succeeded, failed, skipped, durationMs };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=embedding-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-queue.js","sourceRoot":"","sources":["../src/embedding-queue.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error types for Memorandum MCP server.
|
|
3
|
+
*/
|
|
4
|
+
/** Base error class for all Memorandum domain errors. */
|
|
5
|
+
export declare class MemorandumError extends Error {
|
|
6
|
+
readonly code: string;
|
|
7
|
+
readonly details?: Record<string, unknown>;
|
|
8
|
+
/**
|
|
9
|
+
* @param code - Machine-readable error code (e.g. "not_found").
|
|
10
|
+
* @param message - Human-readable error description.
|
|
11
|
+
* @param details - Optional structured metadata about the error.
|
|
12
|
+
*/
|
|
13
|
+
constructor(code: string, message: string, details?: Record<string, unknown>);
|
|
14
|
+
/** Serialize this error into an MCP-compatible plain object. */
|
|
15
|
+
toMcpError(): Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Convert an error to an MCP-compatible error response.
|
|
19
|
+
*/
|
|
20
|
+
export declare function toMcpErrorResponse(error: unknown): {
|
|
21
|
+
content: Array<{
|
|
22
|
+
type: 'text';
|
|
23
|
+
text: string;
|
|
24
|
+
}>;
|
|
25
|
+
isError: true;
|
|
26
|
+
};
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error types for Memorandum MCP server.
|
|
3
|
+
*/
|
|
4
|
+
/** Base error class for all Memorandum domain errors. */
|
|
5
|
+
export class MemorandumError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
details;
|
|
8
|
+
/**
|
|
9
|
+
* @param code - Machine-readable error code (e.g. "not_found").
|
|
10
|
+
* @param message - Human-readable error description.
|
|
11
|
+
* @param details - Optional structured metadata about the error.
|
|
12
|
+
*/
|
|
13
|
+
constructor(code, message, details) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'MemorandumError';
|
|
16
|
+
this.code = code;
|
|
17
|
+
this.details = details;
|
|
18
|
+
}
|
|
19
|
+
/** Serialize this error into an MCP-compatible plain object. */
|
|
20
|
+
toMcpError() {
|
|
21
|
+
return {
|
|
22
|
+
error: this.code,
|
|
23
|
+
message: this.message,
|
|
24
|
+
...(this.details ? { details: this.details } : {}),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Convert an error to an MCP-compatible error response.
|
|
30
|
+
*/
|
|
31
|
+
export function toMcpErrorResponse(error) {
|
|
32
|
+
if (error instanceof MemorandumError) {
|
|
33
|
+
return {
|
|
34
|
+
content: [{ type: 'text', text: JSON.stringify(error.toMcpError()) }],
|
|
35
|
+
isError: true,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (error instanceof Error) {
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: 'text', text: JSON.stringify({ error: 'internal_error', message: error.message }) }],
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,yDAAyD;AACzD,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAAS;IACb,OAAO,CAA2B;IAE3C;;;;OAIG;IACH,YAAY,IAAY,EAAE,OAAe,EAAE,OAAiC;QAC1E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,gEAAgE;IAChE,UAAU;QACR,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,IAAI;YAChB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD,CAAC;IACJ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAI/C,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;QACrC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;YAC9E,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YAC/G,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,CAAC;AACd,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Memorandum — MCP server with persistent memory.
|
|
4
|
+
*
|
|
5
|
+
* Two memory types:
|
|
6
|
+
* - Facts: short key-value records with LRU expiration
|
|
7
|
+
* - Documents: structured storage with metadata and semantic search
|
|
8
|
+
*/
|
|
9
|
+
import { createRequire } from 'node:module';
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { join, dirname } from 'node:path';
|
|
12
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
13
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
14
|
+
import { loadConfig } from './config.js';
|
|
15
|
+
import { createLogger } from './logger.js';
|
|
16
|
+
import { MemoryStore } from './store.js';
|
|
17
|
+
import { DocumentStore } from './document-store.js';
|
|
18
|
+
import { VectorStore } from './vector-store.js';
|
|
19
|
+
import { Embedder } from './embedder.js';
|
|
20
|
+
import { SemanticIndex } from './semantic-index.js';
|
|
21
|
+
import { EmbeddingQueue } from './embedding-queue.js';
|
|
22
|
+
import { registerMemoryTools } from './tools.js';
|
|
23
|
+
import { registerDocumentTools } from './document-tools.js';
|
|
24
|
+
import { registerSemanticTools } from './semantic-tools.js';
|
|
25
|
+
const _require = createRequire(import.meta.url);
|
|
26
|
+
const { version } = _require('../package.json');
|
|
27
|
+
/**
|
|
28
|
+
* Ensure .memorandum/.gitignore exists with cache/ exclusion.
|
|
29
|
+
*/
|
|
30
|
+
function ensureGitignore(storageDir) {
|
|
31
|
+
const gitignorePath = join(storageDir, '.gitignore');
|
|
32
|
+
const cacheEntry = 'cache/';
|
|
33
|
+
if (!existsSync(storageDir)) {
|
|
34
|
+
mkdirSync(storageDir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
if (!existsSync(gitignorePath)) {
|
|
37
|
+
writeFileSync(gitignorePath, `${cacheEntry}\n`, 'utf-8');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const content = readFileSync(gitignorePath, 'utf-8');
|
|
41
|
+
if (!content.includes(cacheEntry)) {
|
|
42
|
+
writeFileSync(gitignorePath, `${content.trimEnd()}\n${cacheEntry}\n`, 'utf-8');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function main() {
|
|
46
|
+
const storageDir = process.env.MEMORANDUM_STORAGE_DIR || '.memorandum';
|
|
47
|
+
const logLevel = process.env.MEMORANDUM_LOG_LEVEL || 'info';
|
|
48
|
+
const logger = createLogger(logLevel);
|
|
49
|
+
const { config, paths } = loadConfig(storageDir);
|
|
50
|
+
logger.info({ version, storageDir: paths.storageDir }, 'Memorandum starting');
|
|
51
|
+
// Ensure storage directories
|
|
52
|
+
if (!existsSync(paths.storageDir))
|
|
53
|
+
mkdirSync(paths.storageDir, { recursive: true });
|
|
54
|
+
const factsDir = dirname(paths.factsPath);
|
|
55
|
+
if (!existsSync(factsDir))
|
|
56
|
+
mkdirSync(factsDir, { recursive: true });
|
|
57
|
+
// Initialize MCP server
|
|
58
|
+
const server = new McpServer({
|
|
59
|
+
name: 'memorandum',
|
|
60
|
+
version,
|
|
61
|
+
});
|
|
62
|
+
// Initialize stores
|
|
63
|
+
const store = new MemoryStore(config, paths, logger);
|
|
64
|
+
await store.load();
|
|
65
|
+
const documentStore = new DocumentStore(config, paths, logger);
|
|
66
|
+
documentStore.loadIndex();
|
|
67
|
+
// Component references for teardown
|
|
68
|
+
let vectorStore;
|
|
69
|
+
let semanticIndex;
|
|
70
|
+
let embeddingQueue;
|
|
71
|
+
// Sync callback
|
|
72
|
+
const syncFn = async () => {
|
|
73
|
+
const savedStores = [];
|
|
74
|
+
let flushedEmbeddings = 0;
|
|
75
|
+
if (embeddingQueue) {
|
|
76
|
+
const result = await embeddingQueue.flush();
|
|
77
|
+
flushedEmbeddings = result.succeeded;
|
|
78
|
+
}
|
|
79
|
+
if (vectorStore) {
|
|
80
|
+
const written = await vectorStore.save();
|
|
81
|
+
if (written)
|
|
82
|
+
savedStores.push('vectors');
|
|
83
|
+
}
|
|
84
|
+
const docsWritten = documentStore.saveIndex();
|
|
85
|
+
if (docsWritten)
|
|
86
|
+
savedStores.push('documents');
|
|
87
|
+
const factsWritten = await store.save();
|
|
88
|
+
if (factsWritten)
|
|
89
|
+
savedStores.push('facts');
|
|
90
|
+
return { flushed_embeddings: flushedEmbeddings, saved_stores: savedStores };
|
|
91
|
+
};
|
|
92
|
+
// Register fact tools
|
|
93
|
+
registerMemoryTools(server, store, logger, syncFn);
|
|
94
|
+
// Register document tools
|
|
95
|
+
registerDocumentTools(server, documentStore, logger);
|
|
96
|
+
// Semantic search initialization
|
|
97
|
+
if (config.semantic_enabled) {
|
|
98
|
+
const embedder = new Embedder(config.semantic_model, config.semantic_model_dtype, logger);
|
|
99
|
+
const indexPath = join(paths.cachePath, 'vector-index.json');
|
|
100
|
+
const dimensions = 384; // e5-small default
|
|
101
|
+
vectorStore = new VectorStore(indexPath, config.semantic_model, dimensions, logger);
|
|
102
|
+
semanticIndex = new SemanticIndex(embedder, vectorStore, logger);
|
|
103
|
+
await semanticIndex.initialize();
|
|
104
|
+
semanticIndex.setMemoryStore(store);
|
|
105
|
+
semanticIndex.setDocumentStore(documentStore);
|
|
106
|
+
await semanticIndex.pruneOrphans();
|
|
107
|
+
embeddingQueue = new EmbeddingQueue(embedder, vectorStore, logger, {
|
|
108
|
+
debounceMs: config.semantic_debounce_seconds * 1000,
|
|
109
|
+
maxQueueSize: config.semantic_max_queue_size,
|
|
110
|
+
maxRetries: config.semantic_max_retries,
|
|
111
|
+
});
|
|
112
|
+
semanticIndex.setEmbeddingQueue(embeddingQueue);
|
|
113
|
+
semanticIndex.enqueueMissing();
|
|
114
|
+
documentStore.setSemanticIndex(semanticIndex);
|
|
115
|
+
store.setSemanticIndex(semanticIndex);
|
|
116
|
+
registerSemanticTools(server, semanticIndex, logger);
|
|
117
|
+
ensureGitignore(paths.storageDir);
|
|
118
|
+
}
|
|
119
|
+
// Start autosave
|
|
120
|
+
const intervalMs = config.autosave_interval_seconds * 1000;
|
|
121
|
+
store.startAutosave(intervalMs);
|
|
122
|
+
// Graceful shutdown
|
|
123
|
+
const teardown = async () => {
|
|
124
|
+
logger.info('Shutting down...');
|
|
125
|
+
if (embeddingQueue) {
|
|
126
|
+
await embeddingQueue.flush();
|
|
127
|
+
embeddingQueue.dispose();
|
|
128
|
+
}
|
|
129
|
+
if (vectorStore)
|
|
130
|
+
await vectorStore.save();
|
|
131
|
+
documentStore.saveIndex();
|
|
132
|
+
store.stopAutosave();
|
|
133
|
+
await store.save();
|
|
134
|
+
logger.info('Shutdown complete');
|
|
135
|
+
};
|
|
136
|
+
process.on('SIGINT', () => { teardown().then(() => process.exit(0)); });
|
|
137
|
+
process.on('SIGTERM', () => { teardown().then(() => process.exit(0)); });
|
|
138
|
+
// Start MCP transport
|
|
139
|
+
const transport = new StdioServerTransport();
|
|
140
|
+
await server.connect(transport);
|
|
141
|
+
logger.info({ tools: 10, semantic: config.semantic_enabled }, 'Memorandum ready');
|
|
142
|
+
}
|
|
143
|
+
main().catch((err) => {
|
|
144
|
+
console.error('Fatal error:', err);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger setup for Memorandum MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Uses pino with stderr transport (stdout is reserved for MCP protocol).
|
|
5
|
+
*/
|
|
6
|
+
import pino from 'pino';
|
|
7
|
+
/**
|
|
8
|
+
* Create a pino logger that writes to stderr.
|
|
9
|
+
* @param level - Log level (default: "info").
|
|
10
|
+
* @returns Configured pino logger instance.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createLogger(level?: string): pino.Logger;
|