Files
dbmole-mcp/packages/esmole-mcp/src/server.ts
T

74 lines
2.9 KiB
TypeScript

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<ConnectionConfig, EsBackend>(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
}