89 lines
3.2 KiB
TypeScript
89 lines
3.2 KiB
TypeScript
import { mkdtempSync, rmSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js'
|
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
import { createManager } from '../../src/manager.js'
|
|
import { createRegistry } from '../../src/registry.js'
|
|
import { createServer, SERVER_VERSION } from '../../src/server.js'
|
|
|
|
const connectClient = async (server: McpServer): Promise<Client> => {
|
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair()
|
|
const client = new Client({ name: 'test-client', version: '0.0.0' })
|
|
await Promise.all([client.connect(clientTransport), server.connect(serverTransport)])
|
|
return client
|
|
}
|
|
|
|
describe('createServer', () => {
|
|
let dir: string
|
|
|
|
beforeEach(() => {
|
|
dir = mkdtempSync(join(tmpdir(), 'esmole-server-'))
|
|
})
|
|
|
|
afterEach(() => {
|
|
rmSync(dir, { recursive: true, force: true })
|
|
})
|
|
|
|
it('exports SERVER_VERSION', () => {
|
|
expect(SERVER_VERSION).toBe('0.1.0')
|
|
})
|
|
|
|
it('registers exactly the ten tools and names the server esmole-mcp', async () => {
|
|
const registry = createRegistry({ storePath: join(dir, 'connections.json'), env: {} })
|
|
const manager = createManager(registry)
|
|
const server = createServer(registry, manager)
|
|
const client = await connectClient(server)
|
|
const { tools } = await client.listTools()
|
|
expect(tools.map((tool) => tool.name).sort()).toEqual([
|
|
'add_connection',
|
|
'es_cluster_health',
|
|
'es_get_mapping',
|
|
'es_list_indices',
|
|
'es_request',
|
|
'es_search',
|
|
'list_connections',
|
|
'remove_connection',
|
|
'test_connection',
|
|
'update_connection'
|
|
])
|
|
expect(client.getServerVersion()?.name).toBe('esmole-mcp')
|
|
await client.close()
|
|
})
|
|
|
|
it('list_connections renders the public view of a stored connection', async () => {
|
|
const registry = createRegistry({ storePath: join(dir, 'connections.json'), env: {} })
|
|
registry.add({
|
|
name: 'prod',
|
|
type: 'elasticsearch',
|
|
host: 'es.example.com',
|
|
apiKey: 'secret-key',
|
|
scheme: 'https',
|
|
verifyTls: true,
|
|
readonly: false
|
|
})
|
|
const server = createServer(registry, createManager(registry))
|
|
const client = await connectClient(server)
|
|
const result = await client.callTool({ name: 'list_connections', arguments: {} })
|
|
const content = result.content as Array<{ type: string; text: string }>
|
|
const view = JSON.parse(content[0].text)
|
|
expect(view).toEqual([
|
|
{
|
|
name: 'prod',
|
|
type: 'elasticsearch',
|
|
scheme: 'https',
|
|
host: 'es.example.com',
|
|
port: 9200,
|
|
auth: 'apiKey',
|
|
verifyTls: true,
|
|
readonly: false,
|
|
source: 'store',
|
|
ssh: false
|
|
}
|
|
])
|
|
await client.close()
|
|
})
|
|
})
|