UNPKG

kuzu-mcp-server

Version:

A Model Context Protocol (MCP) server for Kuzu graph databases. Enables LLMs like Claude to execute Cypher queries and analyze graph data with path invariance support.

230 lines (206 loc) 7.12 kB
/** * setup-with-callback.js - Initialize the Kuzu database with schema and sample data * This version includes the required progress callback function */ const kuzu = require('kuzu'); const path = require('path'); const fs = require('fs'); // Process command line arguments for database path const args = process.argv.slice(2); let dbPath; if (args.length === 0) { const envDbPath = process.env.KUZU_DB_PATH; if (envDbPath) { dbPath = envDbPath; } else { dbPath = path.join(__dirname, 'kuzu_data'); console.log(`No path provided, using default: ${dbPath}`); } } else { dbPath = args[0]; } // Create directory if it doesn't exist if (!fs.existsSync(dbPath)) { fs.mkdirSync(dbPath, { recursive: true }); console.log(`Created database directory: ${dbPath}`); } // Initialize database console.log(`Initializing Kuzu database at: ${dbPath}`); const db = new kuzu.Database(dbPath, 0, true, false); // 3rd param: create if not exists const conn = new kuzu.Connection(db); // Progress callback function const progressCallback = (pipelineProgress, numPipelinesFinished, numPipelines) => { // Can use this to show progress if desired // console.log(`Progress: ${pipelineProgress}, Finished: ${numPipelinesFinished}/${numPipelines}`); }; // Schema creation helper function with progress callback const executeQuery = async (query, params = {}) => { try { console.log(`Executing: ${query}`); const result = await conn.query(query, progressCallback); const rows = await result.getAll(); result.close(); return rows; } catch (error) { console.error(`Error executing query: ${query}`); console.error(error); throw error; } }; // Main setup function async function setupDatabase() { try { // Create node tables await executeQuery(` CREATE NODE TABLE IF NOT EXISTS Person ( id INT64 PRIMARY KEY, name STRING, age INT64, occupation STRING ) `); await executeQuery(` CREATE NODE TABLE IF NOT EXISTS Location ( id INT64 PRIMARY KEY, name STRING, type STRING, latitude DOUBLE, longitude DOUBLE ) `); await executeQuery(` CREATE NODE TABLE IF NOT EXISTS Concept ( id INT64 PRIMARY KEY, name STRING, description STRING, field STRING ) `); // Create relationship tables await executeQuery(` CREATE REL TABLE IF NOT EXISTS KNOWS ( FROM Person TO Person, since STRING, strength FLOAT ) `); await executeQuery(` CREATE REL TABLE IF NOT EXISTS LIVES_IN ( FROM Person TO Location, since STRING, is_primary BOOLEAN ) `); await executeQuery(` CREATE REL TABLE IF NOT EXISTS VISITED ( FROM Person TO Location, date STRING, purpose STRING ) `); await executeQuery(` CREATE REL TABLE IF NOT EXISTS UNDERSTANDS ( FROM Person TO Concept, proficiency INT64, learned_date STRING ) `); await executeQuery(` CREATE REL TABLE IF NOT EXISTS RELATED_TO ( FROM Concept TO Concept, relationship_type STRING, strength FLOAT ) `); // Check if we have any data const personQuery = await executeQuery(`MATCH (p:Person) RETURN COUNT(*) as count`); const personCount = personQuery && personQuery[0] ? personQuery[0].count : 0; console.log(`Person count: ${personCount}`); // Insert sample data if empty if (personCount === 0) { console.log('Inserting sample data...'); // Insert Persons await executeQuery(` CREATE (p:Person {id: 1, name: 'Alice', age: 30, occupation: 'Data Scientist'}) `); await executeQuery(` CREATE (p:Person {id: 2, name: 'Bob', age: 28, occupation: 'Software Engineer'}) `); await executeQuery(` CREATE (p:Person {id: 3, name: 'Charlie', age: 35, occupation: 'Mathematician'}) `); // Insert Locations await executeQuery(` CREATE (l:Location {id: 1, name: 'San Francisco', type: 'City', latitude: 37.7749, longitude: -122.4194}) `); await executeQuery(` CREATE (l:Location {id: 2, name: 'New York', type: 'City', latitude: 40.7128, longitude: -74.0060}) `); await executeQuery(` CREATE (l:Location {id: 3, name: 'Berkeley', type: 'University', latitude: 37.8719, longitude: -122.2585}) `); // Insert Concepts await executeQuery(` CREATE (c:Concept {id: 1, name: 'Category Theory', description: 'Mathematical study of abstract structures', field: 'Mathematics'}) `); await executeQuery(` CREATE (c:Concept {id: 2, name: 'Path Invariance', description: 'Property where outcomes remain consistent regardless of the specific path taken', field: 'Computer Science'}) `); await executeQuery(` CREATE (c:Concept {id: 3, name: 'Graph Database', description: 'Database that uses graph structures for semantic queries', field: 'Computer Science'}) `); // Create relationships await executeQuery(` MATCH (a:Person {id: 1}), (b:Person {id: 2}) CREATE (a)-[r:KNOWS {since: '2020', strength: 0.8}]->(b) `); await executeQuery(` MATCH (a:Person {id: 2}), (b:Person {id: 3}) CREATE (a)-[r:KNOWS {since: '2018', strength: 0.9}]->(b) `); await executeQuery(` MATCH (a:Person {id: 1}), (l:Location {id: 1}) CREATE (a)-[r:LIVES_IN {since: '2019', is_primary: true}]->(l) `); await executeQuery(` MATCH (a:Person {id: 2}), (l:Location {id: 2}) CREATE (a)-[r:LIVES_IN {since: '2015', is_primary: true}]->(l) `); await executeQuery(` MATCH (a:Person {id: 3}), (l:Location {id: 3}) CREATE (a)-[r:VISITED {date: '2023-05-15', purpose: 'Conference'}]->(l) `); await executeQuery(` MATCH (a:Person {id: 1}), (c:Concept {id: 1}) CREATE (a)-[r:UNDERSTANDS {proficiency: 4, learned_date: '2022-01-10'}]->(c) `); await executeQuery(` MATCH (a:Person {id: 3}), (c:Concept {id: 2}) CREATE (a)-[r:UNDERSTANDS {proficiency: 5, learned_date: '2021-07-22'}]->(c) `); await executeQuery(` MATCH (c1:Concept {id: 1}), (c2:Concept {id: 2}) CREATE (c1)-[r:RELATED_TO {relationship_type: 'Foundation', strength: 0.7}]->(c2) `); } console.log('Database setup completed successfully'); } catch (error) { console.error('Error during database setup:', error); process.exit(1); } } // Run the setup setupDatabase() .then(() => { console.log('Setup completed successfully, listing tables...'); return conn.query('CALL show_tables() RETURN *', progressCallback) .then(res => res.getAll()) .then(tables => { console.log('Tables in database:', tables); process.exit(0); }); }) .catch(error => { console.error('Setup failed:', error); process.exit(1); });