UNPKG

@niledatabase/nile-mcp-server

Version:
146 lines (145 loc) 7.1 kB
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { createDatabase, listDatabases, getDatabase, deleteDatabase, getConnectionString, executeSQL, createDatabaseSchema, getDatabaseSchema, deleteDatabaseSchema, getConnectionStringSchema, executeSqlSchema, createTenant, deleteTenant, listTenants, createTenantSchema, deleteTenantSchema, listTenantsSchema, listResources, readResource, listResourcesSchema, readResourceSchema } from './tools.js'; import { log } from './logger.js'; export class NileMcpServer extends McpServer { constructor(options) { super({ name: 'nile-mcp-server', version: '1.0.0', capabilities: { tools: true } }); this.baseUrl = 'https://global.thenile.dev'; log.info('Initializing Nile MCP Server', { workspaceSlug: options.workspaceSlug, baseUrl: this.baseUrl }); this.apiKey = options.apiKey; this.workspaceSlug = options.workspaceSlug; this.toolContext = { apiKey: this.apiKey, workspaceSlug: this.workspaceSlug, baseUrl: this.baseUrl }; this.setupTools(); log.info('Tools initialized successfully'); // Add request handler logging const server = this['server']; if (server && typeof server.handleRequest === 'function') { const originalHandleRequest = server.handleRequest.bind(server); server.handleRequest = async (request, extra) => { log.debug('MCP Server handling request', { method: request.method, params: request.params, id: request.id, registeredTools: Object.keys(this['_registeredTools'] || {}), toolsEnabled: this['capabilities']?.tools, requestType: request.method === 'tools.call' ? 'Tool Call' : request.method }); if (request.method === 'tools.call') { const toolName = request.params?.name; const toolArgs = request.params?.arguments; log.debug('Tool call details', { toolName, toolArgs, toolExists: this['_registeredTools']?.[toolName] !== undefined, toolSchema: this['_registeredTools']?.[toolName]?.schema }); } try { const result = await originalHandleRequest(request, extra); log.debug('MCP Server request handled successfully', { method: request.method, id: request.id, result }); return result; } catch (error) { log.error('MCP Server request handling error', { method: request.method, id: request.id, error: error instanceof Error ? { message: error.message, stack: error.stack, name: error.name } : error }); throw error; } }; } } async connect(transport) { log.info('Connecting to transport...'); log.debug('Transport details:', { type: transport.constructor.name, transport }); await super.connect(transport); log.info('Connected successfully'); } async close() { log.info('Closing server connection...'); await super.close(); log.info('Server connection closed'); } setupTools() { log.info('Setting up tools...'); // Database Management this.tool('list-resources', 'Lists all tables and their descriptions in the specified database', listResourcesSchema.shape, (args) => { log.debug('Tool list-resources called with args:', args); return listResources(args, this.toolContext); }); this.tool('create-database', 'Creates a new Nile database', createDatabaseSchema.shape, (args) => { log.debug('Tool create-database called with args:', args); return createDatabase(args, this.toolContext); }); this.tool('list-databases', 'Lists all databases in the workspace', {}, () => { log.debug('Tool list-databases called'); return listDatabases(this.toolContext); }); this.tool('get-database', 'Gets details of a specific database', getDatabaseSchema.shape, (args) => { log.debug('Tool get-database called with args:', args); return getDatabase(args, this.toolContext); }); this.tool('delete-database', 'Deletes a database', deleteDatabaseSchema.shape, (args) => { log.debug('Tool delete-database called with args:', args); return deleteDatabase(args, this.toolContext); }); // Connection Management this.tool('get-connection-string', 'Gets a PostgreSQL connection string with fresh credentials', getConnectionStringSchema.shape, (args) => { log.debug('Tool get-connection-string called with args:', args); return getConnectionString(args, this.toolContext); }); // SQL Query Execution this.tool('execute-sql', 'Executes a SQL query on a Nile database', executeSqlSchema.shape, (args) => { log.debug('Tool execute-sql called with args:', args); return executeSQL(args, this.toolContext); }); // Tenant Management this.tool('create-tenant', 'Creates a new tenant in the specified database', createTenantSchema.shape, (args) => { log.debug('Tool create-tenant called with args:', args); return createTenant(args, this.toolContext); }); this.tool('delete-tenant', 'Deletes a tenant from the specified database', deleteTenantSchema.shape, (args) => { log.debug('Tool delete-tenant called with args:', args); return deleteTenant(args, this.toolContext); }); this.tool('list-tenants', 'Lists all tenants in the specified database', listTenantsSchema.shape, (args) => { log.debug('Tool list-tenants called with args:', args); return listTenants(args, this.toolContext); }); // Resource Management this.tool('read-resource', 'Gets detailed schema information for a specific table', readResourceSchema.shape, (args) => { log.debug('Tool read-resource called with args:', args); return readResource(args, this.toolContext); }); // Log registered tools log.debug('Registered tools:', { tools: Object.keys(this['_registeredTools'] || {}) }); log.info('All tools registered successfully'); } }