UNPKG

@zerospacegg/anrubic

Version:

Anrubic - ZeroSpace.gg MCP Server for AI agents to access game data

238 lines (211 loc) 5.23 kB
// Test setup file for Anrubic MCP Server // This file provides utilities for testing MCP protocol interactions import { Readable, Writable } from "node:stream"; import { afterEach, beforeEach, mock } from "node:test"; // Global test setup beforeEach(() => { // Reset all mocks before each test mock.restoreAll(); // Reset environment variables delete process.env.NODE_ENV; }); afterEach(() => { // Clean up after each test mock.restoreAll(); }); // Helper to create mock MCP request export function createMockMCPRequest( method: string, params?: any, id: number = 1 ) { return { jsonrpc: "2.0", id, method, ...(params && { params }), }; } // Helper to create mock stdio streams for MCP server testing export function createMockStdioStreams() { const mockInput = new Readable({ read() { // Mock readable stream }, }); const mockOutput = new Writable({ write(chunk, encoding, callback) { // Store output for testing this.lastOutput = chunk.toString(); callback(); }, }); // Add a property to store the last output (mockOutput as any).lastOutput = ""; return { input: mockInput, output: mockOutput }; } // Helper to parse MCP JSON-RPC response export function parseMCPResponse(output: string) { try { const lines = output.trim().split("\n"); // Find the last line that looks like JSON for (let i = lines.length - 1; i >= 0; i--) { const line = lines[i].trim(); if (line.startsWith("{") && line.endsWith("}")) { return JSON.parse(line); } } throw new Error("No valid JSON response found"); } catch (error) { throw new Error(`Failed to parse MCP response: ${output}`); } } // Helper to send MCP request to server export function sendMCPRequest(input: Readable, request: any) { const requestStr = JSON.stringify(request) + "\n"; input.push(requestStr); input.push(null); // End the stream } // Mock iolin data for testing export const mockIolinData = { units: [ { id: "faction/grell/unit/lasher", slug: "lasher", name: "Lasher", faction: "grell", tier: "T1.5", type: "unit", inGame: true, }, { id: "faction/protectorate/unit/griffin", slug: "griffin", name: "Griffin", faction: "protectorate", tier: "T3", type: "unit", inGame: true, }, ], buildings: [ { id: "faction/grell/building/hive", slug: "hive", name: "Hive", faction: "grell", tier: "T0", type: "building", inGame: true, }, ], tags: [ { tag: "attacker", label: "Attacker", description: "Has a basic auto-attack", }, { tag: "flyer", label: "Flyer", description: "Flyer", }, { tag: "healer", label: "Healer", description: "Heals or repairs units or buildings", }, ], }; // Helper to validate MCP tool schema export function validateToolSchema(tool: any) { const requiredFields = ["name", "inputSchema"]; for (const field of requiredFields) { if (!tool[field]) { throw new Error(`Tool missing required field: ${field}`); } } // Validate inputSchema is a valid JSON schema if (typeof tool.inputSchema !== "object") { throw new Error("Tool inputSchema must be an object"); } if (tool.inputSchema.type !== "object") { throw new Error('Tool inputSchema type must be "object"'); } return true; } // Helper to validate MCP response format export function validateMCPResponse(response: any, expectedId?: number) { if (!response.jsonrpc || response.jsonrpc !== "2.0") { throw new Error("Invalid JSON-RPC version"); } if (expectedId !== undefined && response.id !== expectedId) { throw new Error(`Expected id ${expectedId}, got ${response.id}`); } if (response.error) { throw new Error(`MCP Error: ${response.error.message}`); } if (!response.result) { throw new Error("MCP response missing result"); } return true; } // Expected MCP tools that should be available export const expectedMCPTools = [ "get_tags", "get_faction_data", "fetch_entity_by_id", "all_ids", "search_entities", "compare_units", "get_tech_tree", "find_by_tags", ]; // Test data for common MCP tool calls export const testToolCalls = { get_tags: { name: "get_tags", arguments: {}, }, search_entities: { name: "search_entities", arguments: { query: "lasher", limit: 3, }, }, find_by_tags: { name: "find_by_tags", arguments: { tags: ["attacker"], matchAll: true, limit: 5, }, }, fetch_entity_by_id: { name: "fetch_entity_by_id", arguments: { id: "faction/protectorate/unit/griffin", }, }, get_faction_data: { name: "get_faction_data", arguments: { faction: "grell", }, }, }; // Console override for cleaner test output const originalConsole = { ...console }; export function suppressConsole() { global.console = { ...console, log: mock.fn(), warn: mock.fn(), error: mock.fn(), info: mock.fn(), }; } export function restoreConsole() { global.console = originalConsole; }