Memory Cache MCP Server
by ibproduct
- build
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ErrorCode, ListResourcesRequestSchema, ListToolsRequestSchema, McpError, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
import { CacheManager } from './CacheManager.js';
class MemoryCacheServer {
constructor() {
this.server = new Server({
name: 'charly-memory-cache-server',
version: '0.1.0',
}, {
capabilities: {
resources: {},
tools: {},
},
});
this.cacheManager = new CacheManager();
this.setupResourceHandlers();
this.setupToolHandlers();
// Error handling
this.server.onerror = (error) => console.error('[MCP Error]', error);
process.on('SIGINT', async () => {
await this.close();
process.exit(0);
});
}
setupResourceHandlers() {
// List available resources
this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [
{
uri: 'cache://stats',
name: 'Cache Statistics',
mimeType: 'application/json',
description: 'Real-time cache performance metrics',
},
],
}));
// Handle resource reads
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
if (request.params.uri === 'cache://stats') {
return {
contents: [
{
uri: request.params.uri,
mimeType: 'application/json',
text: JSON.stringify(this.cacheManager.getStats(), null, 2),
},
],
};
}
throw new McpError(ErrorCode.InvalidRequest, `Unknown resource: ${request.params.uri}`);
});
}
setupToolHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'store_data',
description: 'Store data in the cache with optional TTL',
inputSchema: {
type: 'object',
properties: {
key: {
type: 'string',
description: 'Unique identifier for the cached data',
},
value: {
type: 'any',
description: 'Data to cache',
},
ttl: {
type: 'number',
description: 'Time-to-live in seconds (optional)',
},
},
required: ['key', 'value'],
},
},
{
name: 'retrieve_data',
description: 'Retrieve data from the cache',
inputSchema: {
type: 'object',
properties: {
key: {
type: 'string',
description: 'Key of the cached data to retrieve',
},
},
required: ['key'],
},
},
{
name: 'clear_cache',
description: 'Clear specific or all cache entries',
inputSchema: {
type: 'object',
properties: {
key: {
type: 'string',
description: 'Specific key to clear (optional - clears all if not provided)',
},
},
},
},
{
name: 'get_cache_stats',
description: 'Get cache statistics',
inputSchema: {
type: 'object',
properties: {},
},
},
],
}));
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
switch (request.params.name) {
case 'store_data': {
const { key, value, ttl } = request.params.arguments;
this.cacheManager.set(key, value, ttl);
return {
content: [
{
type: 'text',
text: `Successfully stored data with key: ${key}`,
},
],
};
}
case 'retrieve_data': {
const { key } = request.params.arguments;
const value = this.cacheManager.get(key);
if (value === undefined) {
return {
content: [
{
type: 'text',
text: `No data found for key: ${key}`,
},
],
isError: true,
};
}
return {
content: [
{
type: 'text',
text: JSON.stringify(value, null, 2),
},
],
};
}
case 'clear_cache': {
const { key } = request.params.arguments;
if (key) {
const success = this.cacheManager.delete(key);
return {
content: [
{
type: 'text',
text: success
? `Successfully cleared cache entry: ${key}`
: `No cache entry found for key: ${key}`,
},
],
};
}
else {
this.cacheManager.clear();
return {
content: [
{
type: 'text',
text: 'Successfully cleared all cache entries',
},
],
};
}
}
case 'get_cache_stats': {
const stats = this.cacheManager.getStats();
return {
content: [
{
type: 'text',
text: JSON.stringify(stats, null, 2),
},
],
};
}
default:
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
}
}
catch (error) {
return {
content: [
{
type: 'text',
text: error instanceof Error ? error.message : String(error),
},
],
isError: true,
};
}
});
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('Memory Cache MCP server running on stdio');
}
async close() {
this.cacheManager.destroy();
await this.server.close();
}
}
const server = new MemoryCacheServer();
server.run().catch(console.error);