import { registerConnectionTools } from '@dbmole/core' import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js' import * as z from 'zod' import type { EsBackend } from './es/backend.js' import { ping } from './esBackend.js' import { esFormatError } from './esError.js' import type { EsManager } from './manager.js' import type { EsRegistry } from './registry.js' import { type ConnectionConfig, connectionConfigSchema, connectionObjectSchema, defaultPort, type EsResolvedConnection, sshConfigSchema } from './schema.js' import { registerEsTools } from './tools/index.js' export const SERVER_VERSION = '0.1.1' const patchSchema = z .object({ name: z .string() .regex(/^[a-zA-Z0-9_-]+$/) .optional(), host: z.string().min(1).optional(), port: z.number().int().positive().nullable().optional(), user: z.string().min(1).nullable().optional(), password: z.string().nullable().optional(), apiKey: z.string().min(1).nullable().optional(), scheme: z.enum(['http', 'https']).optional(), verifyTls: z.boolean().optional(), readonly: z.boolean().optional(), ssh: sshConfigSchema.nullable().optional() }) .strict() const publicView = (resolved: EsResolvedConnection) => ({ name: resolved.config.name, type: resolved.config.type, scheme: resolved.config.scheme, host: resolved.config.host, port: resolved.config.port ?? defaultPort(), auth: resolved.config.apiKey ? 'apiKey' : 'basic', verifyTls: resolved.config.verifyTls, readonly: resolved.config.readonly, source: resolved.source, ssh: Boolean(resolved.config.ssh) }) export const createServer = (registry: EsRegistry, manager: EsManager): McpServer => { const server = new McpServer({ name: 'esmole-mcp', version: SERVER_VERSION }) registerConnectionTools(server, { registry, manager, fullSchema: connectionObjectSchema, parseSchema: connectionConfigSchema, patchSchema, publicView, formatError: esFormatError, ping, descriptions: { list: 'List configured Elasticsearch connections with their source layer (env/config/store). Secrets are omitted.', add: 'Add a named Elasticsearch connection to the persistent store. Auth via user/password or apiKey; optional ssh tunnel, readonly flag, scheme and verifyTls.', update: 'Patch a stored ES connection by name. Set a field to null to remove it. Only store-sourced connections can be edited.', remove: 'Remove a stored ES connection by name and drop its cached client/tunnel.', test: 'Verify an ES connection works end to end (including ssh tunnel). Reports server version and latency.' } }) registerEsTools(server, manager) return server }