From 0c92dd67553616f22980edb7818592a75dde743d Mon Sep 17 00:00:00 2001 From: smartass Date: Fri, 12 Jun 2026 00:03:36 +0500 Subject: [PATCH] feat: add tool respond helpers, test harness --- src/tools/respond.ts | 13 +++++++++++++ test/unit/helpers.ts | 46 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/tools/respond.ts create mode 100644 test/unit/helpers.ts diff --git a/src/tools/respond.ts b/src/tools/respond.ts new file mode 100644 index 0000000..0fb79cc --- /dev/null +++ b/src/tools/respond.ts @@ -0,0 +1,13 @@ +import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js' + +export const ok = (payload: unknown): CallToolResult => ({ + content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] +}) + +export const fail = (message: string): CallToolResult => ({ + content: [{ type: 'text', text: message }], + isError: true +}) + +export const errorMessage = (error: unknown): string => + error instanceof Error ? error.message : String(error) diff --git a/test/unit/helpers.ts b/test/unit/helpers.ts new file mode 100644 index 0000000..a5ef1ab --- /dev/null +++ b/test/unit/helpers.ts @@ -0,0 +1,46 @@ +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 { type Mock, vi } from 'vitest' +import type { Manager } from '../../src/db/manager.js' + +export type ToolResponse = { + isError: boolean + text: string + json: () => unknown +} + +// Manager whose methods are also vitest mocks — no `as unknown as Manager` casts in tests. +export type FakeManager = Manager & { + get: Mock + invalidate: Mock + disposeAll: Mock +} + +export const fakeManager = (): FakeManager => ({ + get: vi.fn(), + invalidate: vi.fn(async () => {}), + disposeAll: vi.fn(async () => {}) +}) + +export const connectClient = async (server: McpServer): Promise => { + 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 +} + +export const callTool = async ( + client: Client, + name: string, + args: Record = {} +): Promise => { + const result = await client.callTool({ name, arguments: args }) + const content = result.content as Array<{ type: string; text: string }> + const text = content?.[0]?.text ?? '' + return { + isError: Boolean(result.isError), + text, + json: () => JSON.parse(text) + } +}