Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ff13226
chore(openmemory-js): add vitest scaffolding and fix migrate script
Apr 27, 2026
cbc8c84
test(openmemory-js): port ad-hoc tsx scripts to vitest specs
Apr 27, 2026
0220689
fix(openmemory-js): add SQL identifier and PG SSL safety helpers
Apr 27, 2026
1a196d7
fix(openmemory-js/core/db): harden TLS, identifiers, init failures, FKs
Apr 27, 2026
c60e9a1
fix(openmemory-js/core/migrate): validate identifiers and reuse SSL h…
Apr 27, 2026
c616798
fix(openmemory-js/core/vector/postgres): canonical default and valida…
Apr 27, 2026
a34a677
fix(openmemory-js/temporal_graph): backend-portable confidence decay
Apr 27, 2026
2d6d432
fix(server): fail-closed auth, tenant identity, JSON body, telemetry …
Apr 27, 2026
5ffcaf8
fix(routes): derive user_id from req.tenant, validate input, surface …
Apr 27, 2026
3c86634
fix(routes): HMAC-verify source webhooks; tenant-scope temporal facts
Apr 27, 2026
702a44d
merge: storage/DB hardening (Worktree B)
Apr 27, 2026
647147a
merge: test infrastructure (Worktree C)
Apr 27, 2026
bfa7a61
merge: HTTP/auth hardening (Worktree A)
Apr 27, 2026
40da66b
fix(openmemory-js/server): surface DbInitError as fatal exit
Apr 27, 2026
672bd90
chore(openmemory-js): apply prettier --write across src and tests
Apr 27, 2026
cc4c134
test(openmemory-js): un-skip verify spec via classifier snapshot
Apr 27, 2026
a02067c
fix(openmemory-js/temporal_graph): require user_id via options-bag
Apr 27, 2026
d71d262
fix(openmemory-js): drop JS-side tenant filter, quarantine orphans
Apr 27, 2026
6ded9e2
test(openmemory-js): pin webhook HMAC verifier behaviour
Apr 27, 2026
5344d76
chore(openmemory-js): port server.js to TypeScript and disable allowJs
Apr 27, 2026
75cb2a0
merge(openmemory-js): Phase 4 server.ts port + webhook test
Apr 27, 2026
d29c458
chore(openmemory-js): apply prettier --write to phase 2/3 additions
Apr 27, 2026
c47b858
merge: compose user_id (this PR) and project_id (#171) isolation
machj8968-lab Apr 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,615 changes: 2,373 additions & 242 deletions packages/openmemory-js/package-lock.json

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions packages/openmemory-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"build": "tsc -p tsconfig.json",
"start": "node dist/server/index.js",
"migrate": "tsx src/migrate.ts"
"migrate": "tsx src/core/migrate.ts",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"typecheck": "tsc --noEmit -p tsconfig.json"
},
"dependencies": {
"@aws-sdk/client-bedrock-runtime": "^3.932.0",
Expand All @@ -40,8 +44,10 @@
"@types/fluent-ffmpeg": "^2.1.26",
"@types/node": "^20.19.25",
"@types/pg": "^8.15.6",
"@vitest/coverage-v8": "^2.1.9",
"prettier": "^3.6.2",
"tsx": "^4.20.6",
"typescript": "^5.9.3"
"typescript": "^5.9.3",
"vitest": "^2.1.9"
}
}
6 changes: 3 additions & 3 deletions packages/openmemory-js/src/ai/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,9 @@ export async function get_graph_ctx(p: lgm_context_req) {
);
const summ = flat.length
? flat
.slice(0, lim)
.map((ln) => `- [${ln.node}] ${ln.content}`)
.join("\n")
.slice(0, lim)
.map((ln) => `- [${ln.node}] ${ln.content}`)
.join("\n")
: "";
return {
namespace: ns,
Expand Down
282 changes: 219 additions & 63 deletions packages/openmemory-js/src/ai/mcp.ts

Large diffs are not rendered by default.

90 changes: 51 additions & 39 deletions packages/openmemory-js/src/ai/mcp_tools.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { z } from "zod/v3";
import { zodToJsonSchema } from "zod-to-json-schema";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { CallToolRequestSchema, ListToolsRequestSchema, McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";

import {
CallToolRequestSchema,
ListToolsRequestSchema,
McpError,
ErrorCode,
} from "@modelcontextprotocol/sdk/types.js";

type ToolCallback = (args: any, extra?: any) => Promise<any> | any;

Expand All @@ -16,67 +20,75 @@ interface ToolDef {
export class ToolRegistry {
private tools: Map<string, ToolDef> = new Map();

tool(name: string, description: string, inputSchema: any, callback: ToolCallback) {
tool(
name: string,
description: string,
inputSchema: any,
callback: ToolCallback,
) {
this.tools.set(name, {
name,
description,
inputSchema: z.object(inputSchema),
callback
callback,
});
}

apply(server: McpServer) {


const srv = server.server;

srv.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: Array.from(this.tools.values()).map(t => {
tools: Array.from(this.tools.values()).map((t) => {
const jsonSchema = zodToJsonSchema(t.inputSchema, {
target: "jsonSchema2019-09"
target: "jsonSchema2019-09",
}) as Record<string, unknown>;


if (jsonSchema && typeof jsonSchema === 'object') {




if (jsonSchema && typeof jsonSchema === "object") {
delete jsonSchema.$schema;
}

return {
name: t.name,
description: t.description,
inputSchema: jsonSchema
inputSchema: jsonSchema,
};
})
}),
};
});

srv.setRequestHandler(CallToolRequestSchema, async (req: any, extra: any) => {
const name = req.params.name;
const tool = this.tools.get(name);
if (!tool) {
throw new McpError(ErrorCode.MethodNotFound, `Tool not found: ${name}`);
}


const args = req.params.arguments || {};
const parse = await tool.inputSchema.safeParseAsync(args);
if (!parse.success) {
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments: ${parse.error.message}`);
}

try {
return await tool.callback(parse.data, extra);
} catch (err: any) {
return {
content: [{ type: "text", text: `Error: ${err.message}` }],
isError: true
};
}
});
srv.setRequestHandler(
CallToolRequestSchema,
async (req: any, extra: any) => {
const name = req.params.name;
const tool = this.tools.get(name);
if (!tool) {
throw new McpError(
ErrorCode.MethodNotFound,
`Tool not found: ${name}`,
);
}

const args = req.params.arguments || {};
const parse = await tool.inputSchema.safeParseAsync(args);
if (!parse.success) {
throw new McpError(
ErrorCode.InvalidParams,
`Invalid arguments: ${parse.error.message}`,
);
}

try {
return await tool.callback(parse.data, extra);
} catch (err: any) {
return {
content: [
{ type: "text", text: `Error: ${err.message}` },
],
isError: true,
};
}
},
);
}
}
8 changes: 6 additions & 2 deletions packages/openmemory-js/src/core/cfg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ export const env = {
AWS_REGION: process.env.AWS_REGION || "",
AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID || "",
AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY || "",
siray_key: process.env.SIRAY_API_TOKEN || process.env.OM_SIRAY_API_TOKEN || "",
siray_key:
process.env.SIRAY_API_TOKEN || process.env.OM_SIRAY_API_TOKEN || "",
siray_base_url: str(
process.env.OM_SIRAY_BASE_URL,
"https://api.siray.ai/v1",
Expand All @@ -81,7 +82,10 @@ export const env = {
process.env.OM_METADATA_BACKEND,
"sqlite",
).toLowerCase(),
vector_backend: str(process.env.OM_VECTOR_BACKEND, "postgres").toLowerCase(),
vector_backend: str(
process.env.OM_VECTOR_BACKEND,
"postgres",
).toLowerCase(),
valkey_host: str(process.env.OM_VALKEY_HOST, "localhost"),
valkey_port: num(process.env.OM_VALKEY_PORT, 6379),
valkey_password: process.env.OM_VALKEY_PASSWORD,
Expand Down
Loading