Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 29 additions & 1 deletion src/memory/__tests__/file-path.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,35 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { promises as fs } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { ensureMemoryFilePath, defaultMemoryPath } from '../index.js';
import { ensureMemoryFilePath, defaultMemoryPath, readPackageVersion } from '../index.js';

describe('readPackageVersion', () => {
const testDir = path.dirname(fileURLToPath(import.meta.url));
const firstCandidate = path.join(testDir, `missing-package-${Date.now()}.json`);
const fallbackPackagePath = path.join(testDir, `package-version-${Date.now()}.json`);

afterEach(async () => {
try {
await fs.unlink(fallbackPackagePath);
} catch {
// Ignore if file doesn't exist
}
});

it('reads the server version from package.json', () => {
const version = readPackageVersion();

expect(version).toMatch(/^\d+\.\d+\.\d+$/);
});

it('uses the next package.json candidate when the first path is unavailable', async () => {
await fs.writeFile(fallbackPackagePath, JSON.stringify({ version: '2026.1.26' }));

const version = readPackageVersion([firstCandidate, fallbackPackagePath]);

expect(version).toBe('2026.1.26');
});
});

describe('ensureMemoryFilePath', () => {
const testDir = path.dirname(fileURLToPath(import.meta.url));
Expand Down
32 changes: 27 additions & 5 deletions src/memory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,46 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { SubscribeRequestSchema, UnsubscribeRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
import { promises as fs } from 'fs';
import { promises as fs, readFileSync } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const currentDir = path.dirname(fileURLToPath(import.meta.url));

export function readPackageVersion(
packageJsonPaths = [
path.join(currentDir, 'package.json'),
path.join(currentDir, '..', 'package.json'),
],
): string {
for (const packageJsonPath of packageJsonPaths) {
try {
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as { version?: unknown };
if (typeof packageJson.version === 'string' && packageJson.version.length > 0) {
return packageJson.version;
}
} catch {
// Try the next candidate; source and dist resolve package.json from different directories.
}
}

throw new Error('Unable to read @modelcontextprotocol/server-memory package version');
}

// Define memory file path using environment variable with fallback
export const defaultMemoryPath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'memory.jsonl');
export const defaultMemoryPath = path.join(currentDir, 'memory.jsonl');

// Handle backward compatibility: migrate memory.json to memory.jsonl if needed
export async function ensureMemoryFilePath(): Promise<string> {
if (process.env.MEMORY_FILE_PATH) {
// Custom path provided, use it as-is (with absolute path resolution)
return path.isAbsolute(process.env.MEMORY_FILE_PATH)
? process.env.MEMORY_FILE_PATH
: path.join(path.dirname(fileURLToPath(import.meta.url)), process.env.MEMORY_FILE_PATH);
: path.join(currentDir, process.env.MEMORY_FILE_PATH);
}

// No custom path set, check for backward compatibility migration
const oldMemoryPath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'memory.json');
const oldMemoryPath = path.join(currentDir, 'memory.json');
const newMemoryPath = defaultMemoryPath;

try {
Expand Down Expand Up @@ -256,7 +278,7 @@ const RelationSchema = z.object({
// The server instance and tools exposed to Claude
const server = new McpServer({
name: "memory-server",
version: "0.6.3",
version: readPackageVersion(),
});

const RESOURCE_URI = "memory://knowledge-graph";
Expand Down
Loading