@hasna/mementos 0.14.40 → 0.14.41
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 +2 -1
- package/README.md +12 -0
- package/dist/cli/index.js +6 -0
- package/dist/index.js +6 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/mcp/http.d.ts +17 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +202 -78
- package/dist/server/index.js +8 -2
- package/package.json +2 -2
package/LICENSE
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
Apache License
|
|
2
3
|
Version 2.0, January 2004
|
|
3
4
|
http://www.apache.org/licenses/
|
|
@@ -175,7 +176,7 @@
|
|
|
175
176
|
|
|
176
177
|
END OF TERMS AND CONDITIONS
|
|
177
178
|
|
|
178
|
-
Copyright
|
|
179
|
+
Copyright 2026 Hasna, Inc.
|
|
179
180
|
|
|
180
181
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
181
182
|
you may not use this file except in compliance with the License.
|
package/README.md
CHANGED
|
@@ -25,6 +25,18 @@ mementos-mcp
|
|
|
25
25
|
|
|
26
26
|
116 tools available.
|
|
27
27
|
|
|
28
|
+
## HTTP mode
|
|
29
|
+
|
|
30
|
+
Run a shared Streamable HTTP MCP server (stateless, `127.0.0.1` only):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
mementos-mcp --http
|
|
34
|
+
# or: MCP_HTTP=1 mementos-mcp
|
|
35
|
+
# default port: 8824 (override with --port or MCP_HTTP_PORT)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Endpoints: `GET /health`, `POST /mcp` (Streamable HTTP).
|
|
39
|
+
|
|
28
40
|
## REST API
|
|
29
41
|
|
|
30
42
|
```bash
|
package/dist/cli/index.js
CHANGED
|
@@ -64425,6 +64425,9 @@ import chalk19 from "chalk";
|
|
|
64425
64425
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, readdirSync, writeFileSync as writeFileSync2, unlinkSync, cpSync as cpSync2 } from "fs";
|
|
64426
64426
|
import { homedir as homedir3 } from "os";
|
|
64427
64427
|
import { basename, dirname as dirname3, join as join5, resolve as resolve13 } from "path";
|
|
64428
|
+
function isInMemoryDb2(path) {
|
|
64429
|
+
return path === ":memory:" || path.startsWith("file::memory:");
|
|
64430
|
+
}
|
|
64428
64431
|
var DEFAULT_CONFIG = {
|
|
64429
64432
|
default_scope: "private",
|
|
64430
64433
|
default_category: "knowledge",
|
|
@@ -64596,6 +64599,9 @@ function getDbPath2() {
|
|
|
64596
64599
|
}
|
|
64597
64600
|
const envDbPath = process.env["HASNA_MEMENTOS_DB_PATH"] ?? process.env["MEMENTOS_DB_PATH"];
|
|
64598
64601
|
if (envDbPath) {
|
|
64602
|
+
if (isInMemoryDb2(envDbPath)) {
|
|
64603
|
+
return envDbPath;
|
|
64604
|
+
}
|
|
64599
64605
|
const resolved = resolve13(envDbPath);
|
|
64600
64606
|
ensureDir2(dirname3(resolved));
|
|
64601
64607
|
return resolved;
|
package/dist/index.js
CHANGED
|
@@ -55359,6 +55359,9 @@ function logSearchQuery(query, resultCount, agentId, projectId, db) {
|
|
|
55359
55359
|
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, readdirSync, writeFileSync as writeFileSync2, unlinkSync, cpSync as cpSync2 } from "fs";
|
|
55360
55360
|
import { homedir as homedir2 } from "os";
|
|
55361
55361
|
import { basename, dirname as dirname2, join as join3, resolve as resolve2 } from "path";
|
|
55362
|
+
function isInMemoryDb2(path) {
|
|
55363
|
+
return path === ":memory:" || path.startsWith("file::memory:");
|
|
55364
|
+
}
|
|
55362
55365
|
var DEFAULT_CONFIG = {
|
|
55363
55366
|
default_scope: "private",
|
|
55364
55367
|
default_category: "knowledge",
|
|
@@ -55530,6 +55533,9 @@ function getDbPath2() {
|
|
|
55530
55533
|
}
|
|
55531
55534
|
const envDbPath = process.env["HASNA_MEMENTOS_DB_PATH"] ?? process.env["MEMENTOS_DB_PATH"];
|
|
55532
55535
|
if (envDbPath) {
|
|
55536
|
+
if (isInMemoryDb2(envDbPath)) {
|
|
55537
|
+
return envDbPath;
|
|
55538
|
+
}
|
|
55533
55539
|
const resolved = resolve2(envDbPath);
|
|
55534
55540
|
ensureDir2(dirname2(resolved));
|
|
55535
55541
|
return resolved;
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAA+B,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAA+B,MAAM,UAAU,CAAC;AAU5E,eAAO,MAAM,cAAc,EAAE,cA4B5B,CAAC;AA4DF,wBAAgB,UAAU,IAAI,cAAc,CAwC3C;AAwED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAMhD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAQ1D;AAED,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAOvC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAmDlC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export declare const MCP_HTTP_SERVICE_NAME = "mementos";
|
|
3
|
+
export declare const DEFAULT_MCP_HTTP_PORT = 8867;
|
|
4
|
+
export declare function isHttpMode(argv?: string[], env?: NodeJS.ProcessEnv): boolean;
|
|
5
|
+
export declare function isStdioMode(argv?: string[], env?: NodeJS.ProcessEnv): boolean;
|
|
6
|
+
export declare function resolveMcpHttpPort(argv?: string[], env?: NodeJS.ProcessEnv): number;
|
|
7
|
+
export type McpHttpServerHandle = {
|
|
8
|
+
port: number;
|
|
9
|
+
host: string;
|
|
10
|
+
close: () => Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
export declare function startMcpHttpServer(buildServer: () => McpServer, options?: {
|
|
13
|
+
port?: number;
|
|
14
|
+
host?: string;
|
|
15
|
+
serviceName?: string;
|
|
16
|
+
}): Promise<McpHttpServerHandle>;
|
|
17
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,eAAO,MAAM,qBAAqB,aAAa,CAAC;AAChD,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C,wBAAgB,UAAU,CACxB,IAAI,GAAE,MAAM,EAAiB,EAC7B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAET;AAED,wBAAgB,WAAW,CACzB,IAAI,GAAE,MAAM,EAAiB,EAC7B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAET;AAED,wBAAgB,kBAAkB,CAChC,IAAI,GAAE,MAAM,EAAiB,EAC7B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CASR;AAoBD,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,SAAS,EAC5B,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,OAAO,CAAC,mBAAmB,CAAC,CAwE9B"}
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@
|
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
/** Exported so other modules can push channel notifications via the underlying Server. */
|
|
4
4
|
export declare let mcpServer: McpServer | null;
|
|
5
|
+
export declare function buildServer(): McpServer;
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/mcp/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA6CpE,0FAA0F;AAC1F,eAAO,IAAI,SAAS,EAAE,SAAS,GAAG,IAAW,CAAC;AAqB9C,wBAAgB,WAAW,IAAI,SAAS,CA4EvC"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -14668,6 +14668,9 @@ var init_export_v1 = __esm(() => {
|
|
|
14668
14668
|
import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync3, readdirSync as readdirSync2, writeFileSync as writeFileSync2, unlinkSync, cpSync as cpSync2 } from "fs";
|
|
14669
14669
|
import { homedir as homedir2 } from "os";
|
|
14670
14670
|
import { basename as basename2, dirname as dirname4, join as join6, resolve as resolve3 } from "path";
|
|
14671
|
+
function isInMemoryDb2(path) {
|
|
14672
|
+
return path === ":memory:" || path.startsWith("file::memory:");
|
|
14673
|
+
}
|
|
14671
14674
|
function deepMerge(target, source) {
|
|
14672
14675
|
const result = { ...target };
|
|
14673
14676
|
for (const key of Object.keys(source)) {
|
|
@@ -14774,6 +14777,9 @@ function getDbPath2() {
|
|
|
14774
14777
|
}
|
|
14775
14778
|
const envDbPath = process.env["HASNA_MEMENTOS_DB_PATH"] ?? process.env["MEMENTOS_DB_PATH"];
|
|
14776
14779
|
if (envDbPath) {
|
|
14780
|
+
if (isInMemoryDb2(envDbPath)) {
|
|
14781
|
+
return envDbPath;
|
|
14782
|
+
}
|
|
14777
14783
|
const resolved = resolve3(envDbPath);
|
|
14778
14784
|
ensureDir2(dirname4(resolved));
|
|
14779
14785
|
return resolved;
|
|
@@ -68285,74 +68291,174 @@ function registerConsolidationTools(server) {
|
|
|
68285
68291
|
});
|
|
68286
68292
|
}
|
|
68287
68293
|
|
|
68294
|
+
// src/mcp/http.ts
|
|
68295
|
+
import { createServer } from "http";
|
|
68296
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
68297
|
+
var MCP_HTTP_SERVICE_NAME = "mementos";
|
|
68298
|
+
var DEFAULT_MCP_HTTP_PORT = 8867;
|
|
68299
|
+
function isStdioMode(argv = process.argv, env = process.env) {
|
|
68300
|
+
return argv.includes("--stdio") || env.MCP_STDIO === "1";
|
|
68301
|
+
}
|
|
68302
|
+
function resolveMcpHttpPort(argv = process.argv, env = process.env) {
|
|
68303
|
+
const portIdx = argv.indexOf("--port");
|
|
68304
|
+
if (portIdx !== -1 && argv[portIdx + 1]) {
|
|
68305
|
+
return parsePort(argv[portIdx + 1], "--port");
|
|
68306
|
+
}
|
|
68307
|
+
if (env.MCP_HTTP_PORT) {
|
|
68308
|
+
return parsePort(env.MCP_HTTP_PORT, "MCP_HTTP_PORT");
|
|
68309
|
+
}
|
|
68310
|
+
return DEFAULT_MCP_HTTP_PORT;
|
|
68311
|
+
}
|
|
68312
|
+
function parsePort(raw, source) {
|
|
68313
|
+
const parsed = Number(raw);
|
|
68314
|
+
if (!Number.isInteger(parsed) || parsed < 0 || parsed > 65535) {
|
|
68315
|
+
throw new Error(`Invalid ${source} value "${raw}". Expected 0-65535.`);
|
|
68316
|
+
}
|
|
68317
|
+
return parsed;
|
|
68318
|
+
}
|
|
68319
|
+
async function readJsonBody(req) {
|
|
68320
|
+
const chunks = [];
|
|
68321
|
+
for await (const chunk of req) {
|
|
68322
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
68323
|
+
}
|
|
68324
|
+
const text3 = Buffer.concat(chunks).toString("utf8");
|
|
68325
|
+
if (!text3)
|
|
68326
|
+
return;
|
|
68327
|
+
return JSON.parse(text3);
|
|
68328
|
+
}
|
|
68329
|
+
async function startMcpHttpServer(buildServer, options) {
|
|
68330
|
+
const host = options?.host ?? "127.0.0.1";
|
|
68331
|
+
const requestedPort = options?.port ?? resolveMcpHttpPort();
|
|
68332
|
+
const serviceName = options?.serviceName ?? MCP_HTTP_SERVICE_NAME;
|
|
68333
|
+
const httpServer = createServer(async (req, res) => {
|
|
68334
|
+
try {
|
|
68335
|
+
const url2 = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
68336
|
+
if (req.method === "GET" && url2.pathname === "/health") {
|
|
68337
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
68338
|
+
res.end(JSON.stringify({ status: "ok", name: serviceName }));
|
|
68339
|
+
return;
|
|
68340
|
+
}
|
|
68341
|
+
if (url2.pathname !== "/mcp") {
|
|
68342
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
68343
|
+
res.end("Not Found");
|
|
68344
|
+
return;
|
|
68345
|
+
}
|
|
68346
|
+
const server = buildServer();
|
|
68347
|
+
const transport = new StreamableHTTPServerTransport({
|
|
68348
|
+
sessionIdGenerator: undefined
|
|
68349
|
+
});
|
|
68350
|
+
await server.connect(transport);
|
|
68351
|
+
let parsedBody;
|
|
68352
|
+
if (req.method === "POST") {
|
|
68353
|
+
parsedBody = await readJsonBody(req);
|
|
68354
|
+
}
|
|
68355
|
+
await transport.handleRequest(req, res, parsedBody);
|
|
68356
|
+
res.on("close", () => {
|
|
68357
|
+
transport.close();
|
|
68358
|
+
server.close();
|
|
68359
|
+
});
|
|
68360
|
+
} catch (error40) {
|
|
68361
|
+
console.error(`[${serviceName}-mcp] HTTP error:`, error40);
|
|
68362
|
+
if (!res.headersSent) {
|
|
68363
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
68364
|
+
res.end(JSON.stringify({
|
|
68365
|
+
jsonrpc: "2.0",
|
|
68366
|
+
error: { code: -32603, message: "Internal server error" },
|
|
68367
|
+
id: null
|
|
68368
|
+
}));
|
|
68369
|
+
}
|
|
68370
|
+
}
|
|
68371
|
+
});
|
|
68372
|
+
await new Promise((resolve6, reject) => {
|
|
68373
|
+
httpServer.once("error", reject);
|
|
68374
|
+
httpServer.listen(requestedPort, host, () => resolve6());
|
|
68375
|
+
});
|
|
68376
|
+
const addr = httpServer.address();
|
|
68377
|
+
const port = typeof addr === "object" && addr ? addr.port : requestedPort;
|
|
68378
|
+
console.error(`[${serviceName}-mcp] Streamable HTTP listening on http://${host}:${port}/mcp`);
|
|
68379
|
+
return {
|
|
68380
|
+
port,
|
|
68381
|
+
host,
|
|
68382
|
+
close: () => new Promise((resolve6, reject) => {
|
|
68383
|
+
httpServer.close((err) => err ? reject(err) : resolve6());
|
|
68384
|
+
})
|
|
68385
|
+
};
|
|
68386
|
+
}
|
|
68387
|
+
|
|
68288
68388
|
// src/mcp/index.ts
|
|
68289
68389
|
import { createRequire } from "module";
|
|
68290
68390
|
var _require = createRequire(import.meta.url);
|
|
68291
68391
|
var _pkg = _require("../../package.json");
|
|
68292
68392
|
var mcpServer = null;
|
|
68293
|
-
var server = new McpServer({
|
|
68294
|
-
name: "mementos",
|
|
68295
|
-
version: _pkg.version
|
|
68296
|
-
}, {
|
|
68297
|
-
capabilities: {
|
|
68298
|
-
experimental: { "claude/channel": {} }
|
|
68299
|
-
},
|
|
68300
|
-
instructions: `Mementos is the persistent memory layer for AI agents. It stores, searches, and manages memories across sessions and projects.
|
|
68301
|
-
|
|
68302
|
-
When running with --dangerously-load-development-channels, mementos will proactively push relevant memories into your conversation via channel notifications. These appear as <channel source="mementos"> tags. They contain memories activated by your current task context \u2014 use them to inform your work. You don't need to call memory_inject when auto-inject is active.`
|
|
68303
|
-
});
|
|
68304
|
-
mcpServer = server;
|
|
68305
68393
|
function hasFlag(...flags) {
|
|
68306
68394
|
return process.argv.some((arg) => flags.includes(arg));
|
|
68307
68395
|
}
|
|
68308
68396
|
function printHelp() {
|
|
68309
68397
|
process.stdout.write(`Usage: mementos-mcp [options]
|
|
68310
68398
|
|
|
68311
|
-
Mementos MCP server (stdio transport)
|
|
68399
|
+
Mementos MCP server (stdio transport by default)
|
|
68312
68400
|
|
|
68313
68401
|
Options:
|
|
68402
|
+
--http Serve MCP over Streamable HTTP (127.0.0.1)
|
|
68403
|
+
--port <number> HTTP port (default: 8824, env: MCP_HTTP_PORT)
|
|
68314
68404
|
-h, --help Show help
|
|
68315
68405
|
-V, --version Show version
|
|
68316
68406
|
`);
|
|
68317
68407
|
}
|
|
68318
|
-
|
|
68319
|
-
|
|
68320
|
-
|
|
68321
|
-
|
|
68322
|
-
|
|
68323
|
-
|
|
68324
|
-
|
|
68325
|
-
|
|
68326
|
-
|
|
68327
|
-
|
|
68328
|
-
|
|
68329
|
-
|
|
68330
|
-
|
|
68331
|
-
|
|
68332
|
-
|
|
68333
|
-
|
|
68334
|
-
|
|
68335
|
-
|
|
68336
|
-
|
|
68337
|
-
|
|
68338
|
-
|
|
68339
|
-
|
|
68340
|
-
|
|
68341
|
-
|
|
68342
|
-
|
|
68343
|
-
|
|
68344
|
-
server
|
|
68345
|
-
|
|
68346
|
-
|
|
68347
|
-
|
|
68348
|
-
server
|
|
68349
|
-
|
|
68350
|
-
|
|
68351
|
-
|
|
68352
|
-
server
|
|
68353
|
-
|
|
68354
|
-
|
|
68355
|
-
|
|
68408
|
+
function buildServer() {
|
|
68409
|
+
const server = new McpServer({
|
|
68410
|
+
name: "mementos",
|
|
68411
|
+
version: _pkg.version
|
|
68412
|
+
}, {
|
|
68413
|
+
capabilities: {
|
|
68414
|
+
experimental: { "claude/channel": {} }
|
|
68415
|
+
},
|
|
68416
|
+
instructions: `Mementos is the persistent memory layer for AI agents. It stores, searches, and manages memories across sessions and projects.
|
|
68417
|
+
|
|
68418
|
+
When running with --dangerously-load-development-channels, mementos will proactively push relevant memories into your conversation via channel notifications. These appear as <channel source="mementos"> tags. They contain memories activated by your current task context \u2014 use them to inform your work. You don't need to call memory_inject when auto-inject is active.`
|
|
68419
|
+
});
|
|
68420
|
+
registerMemoryCrudTools(server);
|
|
68421
|
+
registerMemoryHistoryTools(server);
|
|
68422
|
+
registerMemoryHealthTools(server);
|
|
68423
|
+
registerMemoryValidationTools(server);
|
|
68424
|
+
registerMemorySearchTools(server);
|
|
68425
|
+
registerMemoryLifecycleTools(server);
|
|
68426
|
+
registerMemorySyncTools(server);
|
|
68427
|
+
registerMemoryStatsTools(server);
|
|
68428
|
+
registerMemoryAuditTools(server);
|
|
68429
|
+
registerMemoryIoTools(server);
|
|
68430
|
+
registerMemoryInjectTools(server);
|
|
68431
|
+
registerEntityTools(server);
|
|
68432
|
+
registerRelationTools(server);
|
|
68433
|
+
registerGraphQueryTools(server);
|
|
68434
|
+
registerAgentTools(server);
|
|
68435
|
+
registerProjectTools(server);
|
|
68436
|
+
registerBulkTools(server);
|
|
68437
|
+
registerLockTools(server);
|
|
68438
|
+
registerFocusTools(server);
|
|
68439
|
+
registerHookTools(server);
|
|
68440
|
+
registerSynthesisTools(server);
|
|
68441
|
+
registerAutoMemoryTools(server);
|
|
68442
|
+
registerSessionTools(server);
|
|
68443
|
+
registerUtilityTools(server);
|
|
68444
|
+
registerSystemTools(server);
|
|
68445
|
+
registerMementosStorageTools(server);
|
|
68446
|
+
registerConsolidationTools(server);
|
|
68447
|
+
server.resource("memories", "mementos://memories", { description: "All active memories", mimeType: "application/json" }, async () => {
|
|
68448
|
+
const memories = listMemories({ status: "active", limit: 1000 });
|
|
68449
|
+
return { contents: [{ uri: "mementos://memories", text: JSON.stringify(memories, null, 2), mimeType: "application/json" }] };
|
|
68450
|
+
});
|
|
68451
|
+
server.resource("agents", "mementos://agents", { description: "All registered agents", mimeType: "application/json" }, async () => {
|
|
68452
|
+
const agents = listAgents();
|
|
68453
|
+
return { contents: [{ uri: "mementos://agents", text: JSON.stringify(agents, null, 2), mimeType: "application/json" }] };
|
|
68454
|
+
});
|
|
68455
|
+
server.resource("projects", "mementos://projects", { description: "All registered projects", mimeType: "application/json" }, async () => {
|
|
68456
|
+
const projects = listProjects();
|
|
68457
|
+
return { contents: [{ uri: "mementos://projects", text: JSON.stringify(projects, null, 2), mimeType: "application/json" }] };
|
|
68458
|
+
});
|
|
68459
|
+
mcpServer = server;
|
|
68460
|
+
return server;
|
|
68461
|
+
}
|
|
68356
68462
|
async function ensureRestServerRunning() {
|
|
68357
68463
|
try {
|
|
68358
68464
|
const res = await fetch("http://127.0.0.1:19428/api/memories?limit=0", {
|
|
@@ -68378,6 +68484,16 @@ async function ensureRestServerRunning() {
|
|
|
68378
68484
|
} catch {}
|
|
68379
68485
|
}
|
|
68380
68486
|
}
|
|
68487
|
+
async function prepareMcpRuntime() {
|
|
68488
|
+
try {
|
|
68489
|
+
const warning = getPrimaryMachineStartupWarning(getDatabase());
|
|
68490
|
+
if (warning) {
|
|
68491
|
+
console.warn(`[mementos-mcp] ${warning}`);
|
|
68492
|
+
}
|
|
68493
|
+
} catch {}
|
|
68494
|
+
await ensureRestServerRunning();
|
|
68495
|
+
loadWebhooksFromDb();
|
|
68496
|
+
}
|
|
68381
68497
|
async function main() {
|
|
68382
68498
|
if (hasFlag("--help", "-h")) {
|
|
68383
68499
|
printHelp();
|
|
@@ -68388,37 +68504,45 @@ async function main() {
|
|
|
68388
68504
|
`);
|
|
68389
68505
|
return;
|
|
68390
68506
|
}
|
|
68391
|
-
|
|
68392
|
-
|
|
68393
|
-
|
|
68394
|
-
|
|
68395
|
-
|
|
68396
|
-
|
|
68397
|
-
|
|
68398
|
-
|
|
68399
|
-
|
|
68400
|
-
|
|
68401
|
-
|
|
68402
|
-
|
|
68403
|
-
|
|
68404
|
-
|
|
68405
|
-
|
|
68406
|
-
|
|
68407
|
-
|
|
68408
|
-
|
|
68507
|
+
await prepareMcpRuntime();
|
|
68508
|
+
if (isStdioMode()) {
|
|
68509
|
+
const server = buildServer();
|
|
68510
|
+
const transport = new StdioServerTransport;
|
|
68511
|
+
await server.connect(transport);
|
|
68512
|
+
const autoProject = detectProject();
|
|
68513
|
+
startAutoInject({
|
|
68514
|
+
server,
|
|
68515
|
+
project_id: autoProject?.id,
|
|
68516
|
+
project_name: autoProject?.name,
|
|
68517
|
+
cwd: process.cwd()
|
|
68518
|
+
}).catch(() => {});
|
|
68519
|
+
process.on("SIGINT", () => {
|
|
68520
|
+
stopAutoInject();
|
|
68521
|
+
process.exit(0);
|
|
68522
|
+
});
|
|
68523
|
+
process.on("SIGTERM", () => {
|
|
68524
|
+
stopAutoInject();
|
|
68525
|
+
process.exit(0);
|
|
68526
|
+
});
|
|
68527
|
+
return;
|
|
68528
|
+
}
|
|
68529
|
+
const handle = await startMcpHttpServer(buildServer, {
|
|
68530
|
+
port: resolveMcpHttpPort()
|
|
68531
|
+
});
|
|
68409
68532
|
process.on("SIGINT", () => {
|
|
68410
|
-
|
|
68411
|
-
process.exit(0);
|
|
68533
|
+
handle.close().finally(() => process.exit(0));
|
|
68412
68534
|
});
|
|
68413
68535
|
process.on("SIGTERM", () => {
|
|
68414
|
-
|
|
68415
|
-
|
|
68536
|
+
handle.close().finally(() => process.exit(0));
|
|
68537
|
+
});
|
|
68538
|
+
}
|
|
68539
|
+
if (import.meta.main) {
|
|
68540
|
+
main().catch((error40) => {
|
|
68541
|
+
console.error("MCP server error:", error40);
|
|
68542
|
+
process.exit(1);
|
|
68416
68543
|
});
|
|
68417
68544
|
}
|
|
68418
|
-
main().catch((error40) => {
|
|
68419
|
-
console.error("MCP server error:", error40);
|
|
68420
|
-
process.exit(1);
|
|
68421
|
-
});
|
|
68422
68545
|
export {
|
|
68423
|
-
mcpServer
|
|
68546
|
+
mcpServer,
|
|
68547
|
+
buildServer
|
|
68424
68548
|
};
|
package/dist/server/index.js
CHANGED
|
@@ -5954,7 +5954,7 @@ __export(exports_database, {
|
|
|
5954
5954
|
});
|
|
5955
5955
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, cpSync as cpSync2 } from "fs";
|
|
5956
5956
|
import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
|
|
5957
|
-
function
|
|
5957
|
+
function isInMemoryDb2(path) {
|
|
5958
5958
|
return path === ":memory:" || path.startsWith("file::memory:");
|
|
5959
5959
|
}
|
|
5960
5960
|
function findNearestMementosDb(startDir) {
|
|
@@ -6011,7 +6011,7 @@ function getDbPath2() {
|
|
|
6011
6011
|
return join3(home, ".hasna", "mementos", "mementos.db");
|
|
6012
6012
|
}
|
|
6013
6013
|
function ensureDir2(filePath) {
|
|
6014
|
-
if (
|
|
6014
|
+
if (isInMemoryDb2(filePath))
|
|
6015
6015
|
return;
|
|
6016
6016
|
const dir = dirname2(resolve2(filePath));
|
|
6017
6017
|
if (!existsSync2(dir)) {
|
|
@@ -55997,6 +55997,9 @@ import { join as join5, resolve as resolve4, sep } from "path";
|
|
|
55997
55997
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, unlinkSync, cpSync } from "fs";
|
|
55998
55998
|
import { homedir } from "os";
|
|
55999
55999
|
import { basename, dirname, join, resolve } from "path";
|
|
56000
|
+
function isInMemoryDb(path) {
|
|
56001
|
+
return path === ":memory:" || path.startsWith("file::memory:");
|
|
56002
|
+
}
|
|
56000
56003
|
function findFileWalkingUp(filename) {
|
|
56001
56004
|
let dir = process.cwd();
|
|
56002
56005
|
while (true) {
|
|
@@ -56063,6 +56066,9 @@ function getDbPath() {
|
|
|
56063
56066
|
}
|
|
56064
56067
|
const envDbPath = process.env["HASNA_MEMENTOS_DB_PATH"] ?? process.env["MEMENTOS_DB_PATH"];
|
|
56065
56068
|
if (envDbPath) {
|
|
56069
|
+
if (isInMemoryDb(envDbPath)) {
|
|
56070
|
+
return envDbPath;
|
|
56071
|
+
}
|
|
56066
56072
|
const resolved = resolve(envDbPath);
|
|
56067
56073
|
ensureDir(dirname(resolved));
|
|
56068
56074
|
return resolved;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/mementos",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.41",
|
|
4
4
|
"description": "Universal memory system for AI agents - CLI + MCP server + library API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"build": "bun run clean && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk && bun build src/server/index.ts --outdir dist/server --target bun && bun build src/index.ts src/storage.ts --outdir dist --target bun && bun build src/sdk/index.ts --outdir dist/sdk --target bun && tsc --emitDeclarationOnly --outDir dist",
|
|
36
36
|
"prepare": "bun run build",
|
|
37
37
|
"typecheck": "tsc --noEmit",
|
|
38
|
-
"test": "bun test",
|
|
38
|
+
"test": "bun test --isolate --timeout=10000",
|
|
39
39
|
"dev:cli": "bun run src/cli/index.tsx",
|
|
40
40
|
"dev:mcp": "bun run src/mcp/index.ts",
|
|
41
41
|
"dev:serve": "bun run src/server/index.ts",
|