UNPKG

falkordb-mcpserver

Version:

Model Context Protocol server for FalkorDB graph databases - enables AI assistants to query and manage graph data using natural language

207 lines (206 loc) 7.74 kB
import { z } from 'zod'; import { falkorDBService } from '../services/falkordb.service.js'; import { redisService } from '../services/redis.service.js'; import { logger } from '../services/logger.service.js'; import { AppError, CommonErrors } from '../errors/AppError.js'; function registerQueryGraphTool(server) { server.registerTool("query_graph", { title: "Query Graph", description: "Run a OpenCypher query on a graph", inputSchema: { graphName: z.string().describe("The name of the graph to query"), query: z.string().describe("The OpenCypher query to run"), }, }, async ({ graphName, query }) => { try { if (!graphName?.trim()) { throw new AppError(CommonErrors.INVALID_INPUT, 'Graph name is required and cannot be empty', true); } if (!query?.trim()) { throw new AppError(CommonErrors.INVALID_INPUT, 'Query is required and cannot be empty', true); } const result = await falkorDBService.executeQuery(graphName, query); await logger.debug('Query tool executed successfully', { graphName }); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } catch (error) { await logger.error('Query tool execution failed', error instanceof Error ? error : new Error(String(error)), { graphName, query }); throw error; } }); } function registerListGraphsTool(server) { // Register list_graphs tool server.registerTool("list_graphs", { title: "List Graphs", description: "List all graphs available to query", inputSchema: {}, }, async () => { try { const result = await falkorDBService.listGraphs(); await logger.debug('List graphs tool executed', { count: result.length }); return { content: [{ type: "text", text: result.join("\n"), }] }; } catch (error) { await logger.error('List graphs tool execution failed', error instanceof Error ? error : new Error(String(error))); throw error; } }); } function registerDeleteGraphTool(server) { // Register delete_graph tool server.registerTool("delete_graph", { title: "Delete Graph", description: "Delete a graph from the database", inputSchema: { graphName: z.string().describe("The name of the graph to delete"), }, }, async ({ graphName }) => { try { if (!graphName?.trim()) { throw new AppError(CommonErrors.INVALID_INPUT, 'Graph name is required and cannot be empty', true); } await falkorDBService.deleteGraph(graphName); await logger.info('Delete graph tool executed successfully', { graphName }); return { content: [{ type: "text", text: `Graph ${graphName} deleted` }] }; } catch (error) { await logger.error('Delete graph tool execution failed', error instanceof Error ? error : new Error(String(error)), { graphName }); throw error; } }); } function registerListKeysTool(server) { server.registerTool("list_keys", { title: "List Keys", description: "List all keys in Redis", inputSchema: {}, }, async () => { try { const keys = await redisService.listKeys(); await logger.debug('List keys tool executed', { count: keys.length }); return { content: [{ type: "text", text: keys.join("\n"), }] }; } catch (error) { await logger.error('List keys tool execution failed', error instanceof Error ? error : new Error(String(error))); throw error; } }); } function registerSetKeyTool(server) { // Register set_key tool server.registerTool("set_key", { title: "Set Key", description: "Set a key in Redis", inputSchema: { key: z.string().describe("The key to set"), value: z.string().describe("The value to set"), }, }, async ({ key, value }) => { try { if (!key?.trim()) { throw new AppError(CommonErrors.INVALID_INPUT, 'Key is required and cannot be empty', true); } if (value === undefined || value === null) { throw new AppError(CommonErrors.INVALID_INPUT, 'Value is required', true); } await redisService.set(key, value); await logger.debug('Set key tool executed successfully', { key }); return { content: [{ type: "text", text: `Key ${key} set to ${value}` }] }; } catch (error) { await logger.error('Set key tool execution failed', error instanceof Error ? error : new Error(String(error)), { key }); throw error; } }); } function registerGetKeyTool(server) { // Register get_key tool server.registerTool("get_key", { title: "Get Key", description: "Get a key from Redis", inputSchema: { key: z.string().describe("The key to get."), }, }, async ({ key }) => { try { if (!key?.trim()) { throw new AppError(CommonErrors.INVALID_INPUT, 'Key is required and cannot be empty', true); } const value = await redisService.get(key); await logger.debug('Get key tool executed successfully', { key, hasValue: value !== null }); return { content: [{ type: "text", text: `Key ${key} is ${value ?? 'null (not found)'}` }] }; } catch (error) { await logger.error('Get key tool execution failed', error instanceof Error ? error : new Error(String(error)), { key }); throw error; } }); } function registerDeleteKeyTool(server) { server.registerTool("delete_key", { title: "Delete Key", description: "Delete a key from Redis", inputSchema: { key: z.string().describe("The key to delete"), }, }, async ({ key }) => { try { if (!key?.trim()) { throw new AppError(CommonErrors.INVALID_INPUT, 'Key is required and cannot be empty', true); } await redisService.delete(key); await logger.debug('Delete key tool executed successfully', { key }); return { content: [{ type: "text", text: `Key ${key} deleted` }] }; } catch (error) { await logger.error('Delete key tool execution failed', error instanceof Error ? error : new Error(String(error)), { key }); throw error; } }); } export default function registerAllTools(server) { // Register query_graph tool registerQueryGraphTool(server); registerListGraphsTool(server); registerDeleteGraphTool(server); registerSetKeyTool(server); registerGetKeyTool(server); registerDeleteKeyTool(server); registerListKeysTool(server); }