UNPKG

@odel/module-sdk

Version:

SDK for building Odel modules - MCP protocol over HTTP for Cloudflare Workers

101 lines 3.48 kB
/** * Testing utilities for Odel modules * * @example * ```typescript * import { testMCPCompliance, testTool, expectSuccess } from '@odel/module-sdk/testing'; * ``` */ export { testMCPCompliance } from './mcp-compliance'; export { expectSuccess, expectError } from './assertions'; /** * Create a JSON-RPC MCP request * * @param method - MCP method name (e.g., 'tools/list', 'tools/call') * @param params - Optional parameters for the method * @param id - Request ID (defaults to current timestamp) * * @example * ```typescript * const request = createMCPRequest('tools/list', { extended: true }); * const response = await worker.fetch(request, env, ctx); * ``` */ export function createMCPRequest(method, params, id) { return new Request('http://test', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: id ?? Date.now(), method, ...(params && { params }) }) }); } /** * Test a tool by calling it with given input * * @param worker - The module's ExportedHandler * @param toolName - Name of the tool to test * @param input - Input parameters for the tool * @param options - Optional configuration * @returns The parsed tool response * * @example * ```typescript * import { testTool, expectSuccess } from '@odel/module-sdk/testing'; * import worker from './src/index'; * * test('add tool works', async () => { * const result = await testTool(worker, 'add', { a: 1, b: 2 }); * expectSuccess(result); * expect(result.result).toBe(3); * }); * ``` */ export async function testTool(worker, toolName, input, options) { // Build the base request body const requestBody = { jsonrpc: '2.0', id: Date.now(), method: 'tools/call', params: { name: toolName, arguments: input } }; // Add context at the top level (not in params) if provided if (options?.context) { requestBody.context = { userId: options.context.userId || 'test-user', conversationId: options.context.conversationId, displayName: options.context.displayName || 'Test User', timestamp: options.context.timestamp || Date.now(), requestId: options.context.requestId || crypto.randomUUID(), secrets: options.context.secrets || {} }; } const request = new Request('http://test', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(requestBody) }); // Import Cloudflare test utilities - these are only available in test environment const { createExecutionContext, waitOnExecutionContext } = await import('cloudflare:test'); const ctx = createExecutionContext(); const response = await worker.fetch(request, options?.env || {}, ctx); await waitOnExecutionContext(ctx); const result = await response.json(); // Check for JSON-RPC error if (result.error) { throw new Error(`Tool execution failed: ${result.error.message}` + (result.error.data ? `\n${JSON.stringify(result.error.data, null, 2)}` : '')); } // Extract tool response from MCP envelope if (result.result?.content?.[0]?.text) { return JSON.parse(result.result.content[0].text); } throw new Error('Invalid MCP response format'); } //# sourceMappingURL=index.js.map