Skip to main content
Glama

Curupira

by drzln
tool_handlers.test.ts20.4 kB
/** * Integration Tests for Enhanced Tool Handlers * Tests comprehensive tool execution against a real Chrome instance */ import { describe, test, expect, beforeAll, afterAll, beforeEach } from 'vitest' import { Server } from '@modelcontextprotocol/sdk/server/index.js' import { setupComprehensiveToolHandlers } from '../../src/mcp/tools/comprehensive.js' import { ChromeManager } from '../../src/chrome/manager.js' import type { SessionId } from '@curupira/shared/types' // Mock MCP server for testing class MockMCPServer { private toolHandlers: Map<string, Function> = new Map() private tools: any[] = [] setRequestHandler(schema: any, handler: Function) { if (schema.method === 'tools/list') { this.toolHandlers.set('tools/list', handler) } else if (schema.method === 'tools/call') { this.toolHandlers.set('tools/call', handler) } } async listTools() { const handler = this.toolHandlers.get('tools/list') if (handler) { const result = await handler({}) this.tools = result.tools return result } return { tools: [] } } async callTool(name: string, args: any) { const handler = this.toolHandlers.get('tools/call') if (handler) { return await handler({ params: { name, arguments: args } }) } throw new Error(`No handler for tool: ${name}`) } getTools() { return this.tools } } // Test Chrome setup utility class TestChromeSetup { private chromeManager: ChromeManager private sessionId: SessionId | null = null constructor() { this.chromeManager = ChromeManager.getInstance() } async setup(): Promise<SessionId> { await this.chromeManager.initialize({ host: 'localhost', port: 9222, secure: false }) this.sessionId = await this.chromeManager.createSession() return this.sessionId } async navigate(url: string): Promise<void> { if (!this.sessionId) { throw new Error('Chrome session not initialized') } const client = this.chromeManager.getClient() await client.send('Page.navigate', { url }, this.sessionId) // Wait for navigation to complete await new Promise(resolve => setTimeout(resolve, 1500)) } async cleanup(): Promise<void> { if (this.sessionId) { await this.chromeManager.closeSession(this.sessionId) } await this.chromeManager.disconnect() } getSessionId(): SessionId { if (!this.sessionId) { throw new Error('Chrome session not initialized') } return this.sessionId } } describe('Enhanced Tool Handlers Integration', () => { let chromeSetup: TestChromeSetup let sessionId: SessionId let mockServer: MockMCPServer beforeAll(async () => { chromeSetup = new TestChromeSetup() sessionId = await chromeSetup.setup() // Setup mock MCP server with comprehensive tool handlers mockServer = new MockMCPServer() setupComprehensiveToolHandlers(mockServer as any) // Initialize tools list await mockServer.listTools() }, 30000) afterAll(async () => { await chromeSetup.cleanup() }) beforeEach(async () => { // Navigate to a test page for each test await chromeSetup.navigate('data:text/html,<html><head><title>Test Page</title></head><body><h1 id="header">Test Content</h1><p class="content">Sample text</p><button onclick="console.log(\'clicked\')">Click me</button></body></html>') }) describe('Tool Discovery', () => { test('should list all comprehensive tools', async () => { const result = await mockServer.listTools() expect(result).toBeDefined() expect(result).toHaveProperty('tools') expect(Array.isArray(result.tools)).toBe(true) expect(result.tools.length).toBeGreaterThan(40) // Should have 40+ tools // Check for specific tool categories const toolNames = result.tools.map((tool: any) => tool.name) // Basic tools expect(toolNames).toContain('navigate') expect(toolNames).toContain('screenshot') expect(toolNames).toContain('eval') expect(toolNames).toContain('inspect') // Enhanced CDP tools expect(toolNames).toContain('cdp_evaluate') expect(toolNames).toContain('cdp_screenshot') expect(toolNames).toContain('cdp_navigate') // DOM tools expect(toolNames).toContain('dom_find_element') expect(toolNames).toContain('dom_get_attributes') expect(toolNames).toContain('dom_click_element') // React tools expect(toolNames).toContain('react_find_component') expect(toolNames).toContain('react_inspect_props') // State management tools expect(toolNames).toContain('zustand_inspect_store') expect(toolNames).toContain('xstate_inspect_actor') expect(toolNames).toContain('apollo_inspect_cache') // Performance tools expect(toolNames).toContain('performance_start_profiling') expect(toolNames).toContain('performance_stop_profiling') // Network tools expect(toolNames).toContain('network_mock_request') expect(toolNames).toContain('network_throttle') // Console tools expect(toolNames).toContain('console_clear') expect(toolNames).toContain('console_execute') // Connectivity tools expect(toolNames).toContain('connectivity_test') expect(toolNames).toContain('connectivity_websocket_test') expect(toolNames).toContain('connectivity_cors_test') }) test('should have proper tool schemas', async () => { const result = await mockServer.listTools() const tools = result.tools // Check that each tool has required properties for (const tool of tools) { expect(tool).toHaveProperty('name') expect(tool).toHaveProperty('description') expect(tool).toHaveProperty('inputSchema') expect(typeof tool.name).toBe('string') expect(typeof tool.description).toBe('string') expect(typeof tool.inputSchema).toBe('object') expect(tool.inputSchema).toHaveProperty('type') expect(tool.inputSchema.type).toBe('object') expect(tool.inputSchema).toHaveProperty('properties') expect(tool.inputSchema).toHaveProperty('required') expect(Array.isArray(tool.inputSchema.required)).toBe(true) // All tools should require sessionId expect(tool.inputSchema.required).toContain('sessionId') expect(tool.inputSchema.properties).toHaveProperty('sessionId') } }) }) describe('Basic Chrome Tools', () => { test('should execute navigate tool', async () => { const result = await mockServer.callTool('navigate', { url: 'data:text/html,<html><body><h1>Navigated Page</h1></body></html>', sessionId }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) expect(result.content[0]).toHaveProperty('type') expect(result.content[0].type).toBe('text') }) test('should execute screenshot tool', async () => { const result = await mockServer.callTool('screenshot', { sessionId, fullPage: false }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute eval tool', async () => { const result = await mockServer.callTool('eval', { expression: '2 + 2', sessionId }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute inspect tool', async () => { const result = await mockServer.callTool('inspect', { selector: '#header', sessionId }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) }) describe('Enhanced CDP Tools', () => { test('should execute cdp_evaluate tool', async () => { const result = await mockServer.callTool('cdp_evaluate', { expression: 'document.title', sessionId, returnByValue: true }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute cdp_screenshot tool', async () => { const result = await mockServer.callTool('cdp_screenshot', { sessionId, format: 'png', quality: 80 }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute cdp_navigate tool', async () => { const result = await mockServer.callTool('cdp_navigate', { url: 'data:text/html,<html><body><h1>CDP Navigate Test</h1></body></html>', sessionId }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute cdp_reload tool', async () => { const result = await mockServer.callTool('cdp_reload', { sessionId, ignoreCache: true }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) }) describe('DOM Tools', () => { test('should execute dom_find_element tool', async () => { const result = await mockServer.callTool('dom_find_element', { sessionId, selector: 'h1' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute dom_get_attributes tool', async () => { const result = await mockServer.callTool('dom_get_attributes', { sessionId, nodeId: 1 }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute dom_click_element tool', async () => { const result = await mockServer.callTool('dom_click_element', { sessionId, nodeId: 1 }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute dom_type_text tool', async () => { const result = await mockServer.callTool('dom_type_text', { sessionId, text: 'Hello World' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) }) describe('React Tools', () => { test('should execute react_find_component tool', async () => { const result = await mockServer.callTool('react_find_component', { sessionId, componentName: 'App' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) expect(result.content[0]).toHaveProperty('text') }) test('should execute react_inspect_props tool', async () => { const result = await mockServer.callTool('react_inspect_props', { sessionId, componentId: 'component-1' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute react_inspect_state tool', async () => { const result = await mockServer.callTool('react_inspect_state', { sessionId, componentId: 'component-1' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute react_inspect_hooks tool', async () => { const result = await mockServer.callTool('react_inspect_hooks', { sessionId, componentId: 'component-1' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) }) describe('State Management Tools', () => { test('should execute zustand_inspect_store tool', async () => { const result = await mockServer.callTool('zustand_inspect_store', { sessionId, storeId: 'store-1' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) expect(result.content[0]).toHaveProperty('text') expect(result.content[0].text).toContain('Zustand') }) test('should execute xstate_inspect_actor tool', async () => { const result = await mockServer.callTool('xstate_inspect_actor', { sessionId, actorId: 'actor-1' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) expect(result.content[0]).toHaveProperty('text') expect(result.content[0].text).toContain('XState') }) test('should execute apollo_inspect_cache tool', async () => { const result = await mockServer.callTool('apollo_inspect_cache', { sessionId }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) expect(result.content[0]).toHaveProperty('text') expect(result.content[0].text).toContain('Apollo') }) }) describe('Performance Tools', () => { test('should execute performance_start_profiling tool', async () => { const result = await mockServer.callTool('performance_start_profiling', { sessionId, duration: 5 }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) expect(result.content[0]).toHaveProperty('text') expect(result.content[0].text).toContain('Performance') }) test('should execute performance_stop_profiling tool', async () => { const result = await mockServer.callTool('performance_stop_profiling', { sessionId }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) }) describe('Network Tools', () => { test('should execute network_mock_request tool', async () => { const result = await mockServer.callTool('network_mock_request', { sessionId, url: 'https://api.example.com/test', method: 'GET', status: 200, body: '{"success": true}' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute network_throttle tool', async () => { const result = await mockServer.callTool('network_throttle', { sessionId, downloadThroughput: 100000, uploadThroughput: 50000, latency: 100 }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) }) describe('Console Tools', () => { test('should execute console_clear tool', async () => { const result = await mockServer.callTool('console_clear', { sessionId }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute console_execute tool', async () => { const result = await mockServer.callTool('console_execute', { sessionId, command: 'console.log("Hello from MCP tool")' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) }) describe('Connectivity Tools', () => { test('should execute connectivity_test tool', async () => { const result = await mockServer.callTool('connectivity_test', { sessionId, url: 'https://httpbin.org/get' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute connectivity_websocket_test tool', async () => { const result = await mockServer.callTool('connectivity_websocket_test', { sessionId, url: 'wss://echo.websocket.org' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) test('should execute connectivity_cors_test tool', async () => { const result = await mockServer.callTool('connectivity_cors_test', { sessionId, url: 'https://httpbin.org/get', origin: 'https://example.com' }) expect(result).toBeDefined() expect(result).toHaveProperty('content') expect(Array.isArray(result.content)).toBe(true) }) }) describe('Error Handling', () => { test('should handle unknown tool names', async () => { await expect(async () => { await mockServer.callTool('unknown_tool', { sessionId }) }).rejects.toThrow() }) test('should handle missing required parameters', async () => { // Most tools require sessionId const result = await mockServer.callTool('eval', { expression: '2 + 2' // Missing sessionId }) expect(result).toBeDefined() expect(result).toHaveProperty('isError') expect(result.isError).toBe(true) }) test('should handle invalid session IDs', async () => { const result = await mockServer.callTool('eval', { expression: '2 + 2', sessionId: 'invalid-session-id' }) expect(result).toBeDefined() expect(result).toHaveProperty('isError') expect(result.isError).toBe(true) }) test('should handle malformed expressions', async () => { const result = await mockServer.callTool('eval', { expression: 'invalid javascript syntax }{', sessionId }) expect(result).toBeDefined() expect(result).toHaveProperty('isError') expect(result.isError).toBe(true) }) }) describe('Tool Categories', () => { test('should properly categorize tools by prefix', async () => { const tools = mockServer.getTools() // Check CDP tools const cdpTools = tools.filter((tool: any) => tool.name.startsWith('cdp_')) expect(cdpTools.length).toBeGreaterThan(5) // Check DOM tools const domTools = tools.filter((tool: any) => tool.name.startsWith('dom_')) expect(domTools.length).toBeGreaterThan(3) // Check React tools const reactTools = tools.filter((tool: any) => tool.name.startsWith('react_')) expect(reactTools.length).toBeGreaterThan(3) // Check state management tools const stateTools = tools.filter((tool: any) => tool.name.startsWith('zustand_') || tool.name.startsWith('xstate_') || tool.name.startsWith('apollo_') ) expect(stateTools.length).toBeGreaterThan(2) // Check performance tools const perfTools = tools.filter((tool: any) => tool.name.startsWith('performance_')) expect(perfTools.length).toBeGreaterThan(1) // Check network tools const networkTools = tools.filter((tool: any) => tool.name.startsWith('network_')) expect(networkTools.length).toBeGreaterThan(1) // Check console tools const consoleTools = tools.filter((tool: any) => tool.name.startsWith('console_')) expect(consoleTools.length).toBeGreaterThan(1) // Check connectivity tools const connectivityTools = tools.filter((tool: any) => tool.name.startsWith('connectivity_')) expect(connectivityTools.length).toBeGreaterThan(2) }) }) })

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/drzln/curupira'

If you have feedback or need assistance with the MCP directory API, please join our Discord server