mem0-mcp 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/LICENSE +27 -0
- package/README.md +71 -0
- package/dist/adapters/ollama/ollama-embedder.d.ts +16 -0
- package/dist/adapters/ollama/ollama-embedder.js +132 -0
- package/dist/adapters/sqlite/sqlite-memory-store.d.ts +27 -0
- package/dist/adapters/sqlite/sqlite-memory-store.js +217 -0
- package/dist/bin/mem0-mcp.d.ts +5 -0
- package/dist/bin/mem0-mcp.js +76 -0
- package/dist/domain/errors.d.ts +7 -0
- package/dist/domain/errors.js +12 -0
- package/dist/domain/memory.types.d.ts +158 -0
- package/dist/domain/memory.types.js +115 -0
- package/dist/domain/memory.utils.d.ts +9 -0
- package/dist/domain/memory.utils.js +70 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +14 -0
- package/dist/ports/embedder.port.d.ts +12 -0
- package/dist/ports/embedder.port.js +4 -0
- package/dist/ports/memory-store.port.d.ts +19 -0
- package/dist/ports/memory-store.port.js +4 -0
- package/dist/test/mem0-mcp-server.test.d.ts +1 -0
- package/dist/test/mem0-mcp-server.test.js +122 -0
- package/dist/test/ollama-embedder.test.d.ts +1 -0
- package/dist/test/ollama-embedder.test.js +75 -0
- package/dist/test/setup-wizard.tool.test.d.ts +1 -0
- package/dist/test/setup-wizard.tool.test.js +31 -0
- package/dist/test/sqlite-memory-store.test.d.ts +1 -0
- package/dist/test/sqlite-memory-store.test.js +110 -0
- package/dist/transport/jsonrpc-stdio.d.ts +73 -0
- package/dist/transport/jsonrpc-stdio.js +230 -0
- package/dist/transport/mcp-server.d.ts +38 -0
- package/dist/transport/mcp-server.js +156 -0
- package/dist/transport/tools/health.tool.d.ts +3 -0
- package/dist/transport/tools/health.tool.js +13 -0
- package/dist/transport/tools/memory-forget.tool.d.ts +3 -0
- package/dist/transport/tools/memory-forget.tool.js +22 -0
- package/dist/transport/tools/memory-recall.tool.d.ts +3 -0
- package/dist/transport/tools/memory-recall.tool.js +22 -0
- package/dist/transport/tools/memory-search.tool.d.ts +3 -0
- package/dist/transport/tools/memory-search.tool.js +27 -0
- package/dist/transport/tools/memory-store.tool.d.ts +3 -0
- package/dist/transport/tools/memory-store.tool.js +32 -0
- package/dist/transport/tools/memory-update.tool.d.ts +3 -0
- package/dist/transport/tools/memory-update.tool.js +24 -0
- package/dist/transport/tools/setup-wizard.tool.d.ts +7 -0
- package/dist/transport/tools/setup-wizard.tool.js +35 -0
- package/dist/transport/tools/shared-schemas.d.ts +46 -0
- package/dist/transport/tools/shared-schemas.js +30 -0
- package/package.json +59 -0
- package/scripts/prepare.cjs +59 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { memorySearchInputSchema } from '../../domain/memory.types.js';
|
|
2
|
+
import { scopeJsonSchema } from './shared-schemas.js';
|
|
3
|
+
export function createMemorySearchTool(store) {
|
|
4
|
+
return {
|
|
5
|
+
name: 'memory_search',
|
|
6
|
+
description: 'Run a scoped semantic memory search using the configured Ollama embedding model.',
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: 'object',
|
|
9
|
+
properties: {
|
|
10
|
+
query: { anyOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }] },
|
|
11
|
+
scope: scopeJsonSchema,
|
|
12
|
+
kind: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
enum: ['decision', 'preference', 'summary', 'artifact_context', 'note'],
|
|
15
|
+
},
|
|
16
|
+
limit: { type: 'integer', minimum: 1, maximum: 25, default: 5 },
|
|
17
|
+
},
|
|
18
|
+
required: ['query', 'scope'],
|
|
19
|
+
additionalProperties: false,
|
|
20
|
+
},
|
|
21
|
+
handler: async (args) => {
|
|
22
|
+
const input = memorySearchInputSchema.parse(args);
|
|
23
|
+
const results = await store.searchMemory(input);
|
|
24
|
+
return { results };
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { memoryStoreInputSchema } from '../../domain/memory.types.js';
|
|
2
|
+
import { scopeJsonSchema, provenanceJsonSchema } from './shared-schemas.js';
|
|
3
|
+
export function createMemoryStoreTool(store) {
|
|
4
|
+
return {
|
|
5
|
+
name: 'memory_store',
|
|
6
|
+
description: 'Persist a scoped memory with mandatory checkpoint provenance back to SQLite.',
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: 'object',
|
|
9
|
+
properties: {
|
|
10
|
+
kind: {
|
|
11
|
+
type: 'string',
|
|
12
|
+
enum: ['decision', 'preference', 'summary', 'artifact_context', 'note'],
|
|
13
|
+
},
|
|
14
|
+
content: { type: 'string' },
|
|
15
|
+
scope: scopeJsonSchema,
|
|
16
|
+
provenance: provenanceJsonSchema,
|
|
17
|
+
metadata: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
additionalProperties: { type: 'string' },
|
|
20
|
+
default: {},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
required: ['kind', 'content', 'scope', 'provenance'],
|
|
24
|
+
additionalProperties: false,
|
|
25
|
+
},
|
|
26
|
+
handler: async (args) => {
|
|
27
|
+
const input = memoryStoreInputSchema.parse(args);
|
|
28
|
+
const memory = await store.storeMemory(input);
|
|
29
|
+
return { memory };
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { memoryUpdateInputSchema } from '../../domain/memory.types.js';
|
|
2
|
+
import { scopeJsonSchema } from './shared-schemas.js';
|
|
3
|
+
export function createMemoryUpdateTool(store) {
|
|
4
|
+
return {
|
|
5
|
+
name: 'memory_update',
|
|
6
|
+
description: 'Update an existing memory with new content or metadata.',
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: 'object',
|
|
9
|
+
properties: {
|
|
10
|
+
memoryId: { type: 'string', format: 'uuid' },
|
|
11
|
+
scope: scopeJsonSchema,
|
|
12
|
+
content: { type: 'string' },
|
|
13
|
+
metadata: { type: 'object', additionalProperties: { type: 'string' } },
|
|
14
|
+
},
|
|
15
|
+
required: ['memoryId', 'scope'],
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
},
|
|
18
|
+
handler: async (args) => {
|
|
19
|
+
const input = memoryUpdateInputSchema.parse(args);
|
|
20
|
+
const memory = await store.updateMemory(input);
|
|
21
|
+
return { memory };
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ToolDefinition } from '../mcp-server.js';
|
|
2
|
+
interface SetupWizardToolOptions {
|
|
3
|
+
embedModel: string;
|
|
4
|
+
runCommand?: (command: string, args: string[]) => Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export declare function createSetupWizardTool(options: SetupWizardToolOptions): ToolDefinition;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { getErrorMessage } from '../../domain/errors.js';
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
const emptyInputSchema = z.object({}).strict();
|
|
7
|
+
export function createSetupWizardTool(options) {
|
|
8
|
+
const runCommand = options.runCommand ?? defaultRunCommand;
|
|
9
|
+
return {
|
|
10
|
+
name: 'setup_wizard',
|
|
11
|
+
description: 'Initialize mem0 by checking dependencies and pulling the configured embedding model via Ollama.',
|
|
12
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
13
|
+
handler: async (args) => {
|
|
14
|
+
emptyInputSchema.parse(args ?? {});
|
|
15
|
+
try {
|
|
16
|
+
await runCommand('ollama', ['pull', options.embedModel]);
|
|
17
|
+
return {
|
|
18
|
+
success: true,
|
|
19
|
+
model: options.embedModel,
|
|
20
|
+
message: `Ollama model ${options.embedModel} pulled successfully.`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
return {
|
|
25
|
+
success: false,
|
|
26
|
+
model: options.embedModel,
|
|
27
|
+
message: `Failed to pull Ollama model ${options.embedModel}: ${getErrorMessage(error)}`,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
async function defaultRunCommand(command, args) {
|
|
34
|
+
await execFileAsync(command, args);
|
|
35
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared JSON Schema fragments used by multiple tool definitions.
|
|
3
|
+
* Single source of truth — eliminates duplication across tool files.
|
|
4
|
+
*/
|
|
5
|
+
export declare const scopeJsonSchema: {
|
|
6
|
+
readonly type: "object";
|
|
7
|
+
readonly properties: {
|
|
8
|
+
readonly workspace: {
|
|
9
|
+
readonly type: "string";
|
|
10
|
+
};
|
|
11
|
+
readonly project: {
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
};
|
|
14
|
+
readonly campaign: {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
};
|
|
17
|
+
readonly task: {
|
|
18
|
+
readonly type: "string";
|
|
19
|
+
};
|
|
20
|
+
readonly run: {
|
|
21
|
+
readonly type: "string";
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
readonly required: readonly ["workspace", "project"];
|
|
25
|
+
readonly additionalProperties: false;
|
|
26
|
+
};
|
|
27
|
+
export declare const provenanceJsonSchema: {
|
|
28
|
+
readonly type: "object";
|
|
29
|
+
readonly properties: {
|
|
30
|
+
readonly checkpointId: {
|
|
31
|
+
readonly type: "string";
|
|
32
|
+
};
|
|
33
|
+
readonly artifactIds: {
|
|
34
|
+
readonly type: "array";
|
|
35
|
+
readonly items: {
|
|
36
|
+
readonly type: "string";
|
|
37
|
+
};
|
|
38
|
+
readonly default: readonly [];
|
|
39
|
+
};
|
|
40
|
+
readonly note: {
|
|
41
|
+
readonly type: "string";
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
readonly required: readonly ["checkpointId"];
|
|
45
|
+
readonly additionalProperties: false;
|
|
46
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared JSON Schema fragments used by multiple tool definitions.
|
|
3
|
+
* Single source of truth — eliminates duplication across tool files.
|
|
4
|
+
*/
|
|
5
|
+
export const scopeJsonSchema = {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
workspace: { type: 'string' },
|
|
9
|
+
project: { type: 'string' },
|
|
10
|
+
campaign: { type: 'string' },
|
|
11
|
+
task: { type: 'string' },
|
|
12
|
+
run: { type: 'string' },
|
|
13
|
+
},
|
|
14
|
+
required: ['workspace', 'project'],
|
|
15
|
+
additionalProperties: false,
|
|
16
|
+
};
|
|
17
|
+
export const provenanceJsonSchema = {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
checkpointId: { type: 'string' },
|
|
21
|
+
artifactIds: {
|
|
22
|
+
type: 'array',
|
|
23
|
+
items: { type: 'string' },
|
|
24
|
+
default: [],
|
|
25
|
+
},
|
|
26
|
+
note: { type: 'string' },
|
|
27
|
+
},
|
|
28
|
+
required: ['checkpointId'],
|
|
29
|
+
additionalProperties: false,
|
|
30
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mem0-mcp",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "A dedicated mem0 MCP server with file-backed storage and Ollama embeddings.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": "dist/bin/mem0-mcp.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/**",
|
|
17
|
+
"README.md",
|
|
18
|
+
"CHANGELOG.md",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"package.json",
|
|
21
|
+
"scripts/prepare.cjs"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"prepare": "node scripts/prepare.cjs",
|
|
25
|
+
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",
|
|
26
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
27
|
+
"test": "npm run build && node --test dist/test/**/*.test.js && npm run test:prepare",
|
|
28
|
+
"test:prepare": "node --test scripts/prepare.test.cjs",
|
|
29
|
+
"mem0:mcp": "node dist/bin/mem0-mcp.js",
|
|
30
|
+
"mem0:mcp:dev": "tsx src/bin/mem0-mcp.ts",
|
|
31
|
+
"build:exe": "npm run build && pkg . --targets node18-macos-arm64,node18-macos-x64,node18-linux-x64,node18-win-x64 --out-path bin/"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"mem0",
|
|
35
|
+
"mcp",
|
|
36
|
+
"ollama",
|
|
37
|
+
"memory"
|
|
38
|
+
],
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/giulio-leone/mem0-mcp.git"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/giulio-leone/mem0-mcp/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/giulio-leone/mem0-mcp#readme",
|
|
47
|
+
"license": "BUSL-1.1",
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"better-sqlite3": "^12.8.0",
|
|
50
|
+
"zod": "^4.3.6"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
54
|
+
"@types/node": "^25.5.0",
|
|
55
|
+
"pkg": "^5.8.1",
|
|
56
|
+
"tsx": "^4.21.0",
|
|
57
|
+
"typescript": "^5.9.3"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const fs = require('node:fs');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const cp = require('node:child_process');
|
|
4
|
+
|
|
5
|
+
function resolveWithinCwd(cwd, segments) {
|
|
6
|
+
return path.join(cwd, ...segments);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function hasFile(existsSync, cwd, segments) {
|
|
10
|
+
return existsSync(resolveWithinCwd(cwd, segments));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function isDependencyInstall(cwd, initCwd) {
|
|
14
|
+
return Boolean(initCwd) && path.resolve(initCwd) !== path.resolve(cwd);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function buildMissingDistMessage(packageName) {
|
|
18
|
+
return (
|
|
19
|
+
`dist missing for ${packageName}; run npm install in ${packageName} ` +
|
|
20
|
+
'(or build it) before installing downstream consumers'
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function runPrepare(options = {}) {
|
|
25
|
+
const cwd = options.cwd ?? process.cwd();
|
|
26
|
+
const initCwd = options.initCwd ?? process.env.INIT_CWD;
|
|
27
|
+
const existsSync = options.existsSync ?? fs.existsSync;
|
|
28
|
+
const execSync = options.execSync ?? cp.execSync;
|
|
29
|
+
const log = options.log ?? console.log;
|
|
30
|
+
|
|
31
|
+
const dependencyInstall = isDependencyInstall(cwd, initCwd);
|
|
32
|
+
const hasDist = hasFile(existsSync, cwd, ['dist', 'index.js']);
|
|
33
|
+
const hasTypescript = hasFile(existsSync, cwd, ['node_modules', 'typescript', 'package.json']);
|
|
34
|
+
|
|
35
|
+
if (!dependencyInstall && hasTypescript) {
|
|
36
|
+
execSync('npm run build', {
|
|
37
|
+
cwd,
|
|
38
|
+
stdio: 'inherit',
|
|
39
|
+
});
|
|
40
|
+
return 'built';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!hasDist) {
|
|
44
|
+
throw new Error(buildMissingDistMessage('mem0-mcp'));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
log('Skipping prepare build: using existing dist for dependency install');
|
|
48
|
+
return 'skipped';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (require.main === module) {
|
|
52
|
+
runPrepare();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = {
|
|
56
|
+
buildMissingDistMessage,
|
|
57
|
+
isDependencyInstall,
|
|
58
|
+
runPrepare,
|
|
59
|
+
};
|