MCP Memory Server
by ebailey78
#!/usr/bin/env node
import { spawn } from 'child_process';
import path from 'path';
import fs from 'fs';
// Create test memory directories if they don't exist
const testMemoryDir = './test-memory';
const testCustomDir = './test-custom-memory';
// Remove test-custom-memory directory if it exists
if (fs.existsSync(testCustomDir)) {
fs.rmSync(testCustomDir, { recursive: true, force: true });
console.log(`Removed existing directory: ${testCustomDir}`);
}
// Create test memory directories
const dirs = [
testMemoryDir,
`${testMemoryDir}/entities`,
`${testMemoryDir}/concepts`,
`${testMemoryDir}/sessions`
];
for (const dir of dirs) {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
console.log(`Created directory: ${dir}`);
}
}
// Start the MCP server
const server = spawn('node', ['./dist/index.js'], {
env: { ...process.env, MEMORY_DIR: testMemoryDir },
stdio: ['pipe', 'pipe', process.stderr]
});
// Track the current memory directory
let currentMemoryDir = testMemoryDir;
// Handle server output
server.stdout.on('data', (data) => {
try {
const response = JSON.parse(data.toString().trim());
console.log('Server response:', JSON.stringify(response, null, 2));
// Process the response
if (response.type === 'list_tools_response') {
console.log(`\nFound ${response.tools.length} tools\n`);
// Test building a memory store
sendRequest({
id: '2',
type: 'call_tool',
tool_name: 'build_memory_store',
tool_input: {
directory: testCustomDir,
overwrite: true
}
});
} else if (response.type === 'call_tool_response') {
if (response.content[0].text && response.content[0].text.includes('Memory store successfully built')) {
console.log(`\nMemory store built successfully\n`);
// Verify the directory structure
if (fs.existsSync(testCustomDir) &&
fs.existsSync(`${testCustomDir}/entities`) &&
fs.existsSync(`${testCustomDir}/concepts`) &&
fs.existsSync(`${testCustomDir}/sessions`) &&
fs.existsSync(`${testCustomDir}/metadata.json`) &&
fs.existsSync(`${testCustomDir}/index.json`) &&
fs.existsSync(`${testCustomDir}/README.md`)) {
console.log('Directory structure verified successfully!');
// Update the memory directory for the server
currentMemoryDir = testCustomDir;
// Restart the server with the new memory directory
server.kill();
// Wait for the server to exit before restarting
server.on('close', () => {
console.log('Restarting server with new memory directory...');
// Start a new server with the custom memory directory
const newServer = spawn('node', ['./dist/index.js'], {
env: { ...process.env, MEMORY_DIR: currentMemoryDir },
stdio: ['pipe', 'pipe', process.stderr]
});
// Replace the old server with the new one
Object.assign(server, newServer);
// Wait for the new server to initialize
setTimeout(() => {
// Test creating a memory
sendRequest({
id: '3',
type: 'call_tool',
tool_name: 'create_memory',
tool_input: {
title: 'Test Memory',
type: 'concept',
tags: ['test', 'example'],
content: 'This is a test memory created by the test script.'
}
});
}, 2000);
});
} else {
console.error('Directory structure verification failed!');
server.kill();
process.exit(1);
}
} else if (response.content[0].text && response.content[0].text.includes('Memory created with ID:')) {
// Extract memory ID
const memoryId = response.content[0].text.split('Memory created with ID: ')[1];
console.log(`\nCreated memory with ID: ${memoryId}\n`);
// Verify the memory file was created in the custom directory
setTimeout(() => {
const memoryFile = `${currentMemoryDir}/concepts/${memoryId}.md`;
if (fs.existsSync(memoryFile)) {
console.log(`Memory file verified: ${memoryFile}`);
// Test searching memories
sendRequest({
id: '4',
type: 'call_tool',
tool_name: 'search_memories',
tool_input: {
query: 'test'
}
});
} else {
console.error(`Memory file not found: ${memoryFile}`);
server.kill();
process.exit(1);
}
}, 500);
} else if (response.content[0].json) {
console.log('\nSearch results found. Test completed successfully!\n');
// Clean up and exit
server.kill();
process.exit(0);
}
}
} catch (error) {
console.error('Error processing server output:', error);
console.error('Raw output:', data.toString());
}
});
// Handle errors
server.on('error', (error) => {
console.error('Server error:', error);
process.exit(1);
});
// Handle server exit
server.on('close', (code) => {
console.log(`Server exited with code ${code}`);
});
// Send a request to the server
function sendRequest(request) {
console.log('Sending request:', JSON.stringify(request, null, 2));
server.stdin.write(JSON.stringify(request) + '\n');
}
// Start by listing tools after a delay to allow server initialization
setTimeout(() => {
sendRequest({
id: '1',
type: 'list_tools'
});
}, 2000);