@allpepper/memory-bank-mcp
Version:
MCP server for remote management of project memory banks
207 lines (206 loc) • 7.75 kB
JavaScript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js";
import { FileHandler } from "./services/FileHandler.js";
import { CORE_FILES, } from "./types.js";
const DEFAULT_CONFIG = {
rootPath: process.env.MEMORY_BANK_ROOT || "/memory-bank",
};
const memoryBankTools = {
list_projects: {
name: "list_projects",
description: "List all projects in the memory bank",
inputSchema: {
type: "object",
properties: {},
required: [],
},
},
list_project_files: {
name: "list_project_files",
description: "List all files within a specific project",
inputSchema: {
type: "object",
properties: {
projectName: { type: "string" },
},
required: ["projectName"],
},
},
memory_bank_read: {
name: "memory_bank_read",
description: "Read a memory bank file for a specific project",
inputSchema: {
type: "object",
properties: {
projectName: { type: "string" },
fileName: {
type: "string",
enum: CORE_FILES,
},
},
required: ["projectName", "fileName"],
},
},
memory_bank_write: {
name: "memory_bank_write",
description: "Create a new memory bank file for a specific project",
inputSchema: {
type: "object",
properties: {
projectName: { type: "string" },
fileName: {
type: "string",
enum: CORE_FILES,
},
content: { type: "string" },
},
required: ["projectName", "fileName", "content"],
},
},
memory_bank_update: {
name: "memory_bank_update",
description: "Update an existing memory bank file for a specific project",
inputSchema: {
type: "object",
properties: {
projectName: { type: "string" },
fileName: {
type: "string",
enum: CORE_FILES,
},
content: { type: "string" },
},
required: ["projectName", "fileName", "content"],
},
},
};
export class MemoryBankServer {
server;
fileHandler;
constructor(config = {}) {
const finalConfig = { ...DEFAULT_CONFIG, ...config };
this.fileHandler = new FileHandler(finalConfig);
this.server = new Server({
name: "memory-bank",
version: "0.1.0",
}, {
capabilities: {
tools: {
memory_bank_read: memoryBankTools.memory_bank_read,
memory_bank_write: memoryBankTools.memory_bank_write,
memory_bank_update: memoryBankTools.memory_bank_update,
list_projects: memoryBankTools.list_projects,
list_project_files: memoryBankTools.list_project_files,
},
},
});
this.setupToolHandlers();
this.server.onerror = (error) => console.error("[MCP Error]", error);
process.on("SIGINT", async () => {
await this.server.close();
process.exit(0);
});
}
validateArgs(args) {
const validatedArgs = args;
// TODO: Validate args for future requirements
return validatedArgs;
}
setupToolHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
memoryBankTools.memory_bank_read,
memoryBankTools.memory_bank_write,
memoryBankTools.memory_bank_update,
memoryBankTools.list_projects,
memoryBankTools.list_project_files,
],
}));
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (!args || typeof args !== "object") {
throw new McpError(ErrorCode.InvalidParams, "No arguments provided");
}
try {
let command;
switch (name) {
case "list_projects": {
command = {
operation: "list_projects",
};
break;
}
case "list_project_files": {
const { projectName } = args;
command = {
operation: "list_project_files",
projectName,
};
break;
}
case "memory_bank_read": {
const readArgs = this.validateArgs(args);
command = {
operation: "read",
projectName: readArgs.projectName,
fileName: readArgs.fileName,
};
break;
}
case "memory_bank_write": {
const writeArgs = this.validateArgs(args);
command = {
operation: "write",
projectName: writeArgs.projectName,
fileName: writeArgs.fileName,
content: writeArgs.content,
};
break;
}
case "memory_bank_update": {
const updateArgs = this.validateArgs(args);
command = {
operation: "update",
projectName: updateArgs.projectName,
fileName: updateArgs.fileName,
content: updateArgs.content,
};
break;
}
default:
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
}
const result = await this.fileHandler.handleCommand(command);
if (!result.success) {
throw new McpError(ErrorCode.InternalError, result.error || "Unknown error");
}
return {
content: [
{
type: "text",
text: result.content || "Operation completed successfully",
},
],
isError: false,
};
}
catch (error) {
if (error instanceof McpError) {
throw error;
}
throw new McpError(ErrorCode.InternalError, `Operation failed: ${error instanceof Error ? error.message : "Unknown error"}`);
}
});
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error("Memory Bank MCP server running on stdio");
}
}
// Start the server when loaded through npx
const server = new MemoryBankServer();
server.run().catch(console.error);
export default MemoryBankServer;