Skip to main content
Glama

n8n-MCP

by 88-888
handlers.ts8.07 kB
import { http, HttpResponse, RequestHandler } from 'msw'; import { mockWorkflows } from './data/workflows'; import { mockExecutions } from './data/executions'; import { mockCredentials } from './data/credentials'; // Base URL for n8n API (will be overridden by actual URL in tests) const API_BASE = process.env.N8N_API_URL || 'http://localhost:5678'; /** * Default handlers for n8n API endpoints * These can be overridden in specific tests using server.use() */ export const handlers: RequestHandler[] = [ // Health check endpoint http.get('*/api/v1/health', () => { return HttpResponse.json({ status: 'ok', version: '1.103.2', features: { workflows: true, executions: true, credentials: true, webhooks: true, } }); }), // Workflow endpoints http.get('*/api/v1/workflows', ({ request }) => { const url = new URL(request.url); const limit = parseInt(url.searchParams.get('limit') || '100'); const cursor = url.searchParams.get('cursor'); const active = url.searchParams.get('active'); let filtered = mockWorkflows; // Filter by active status if provided if (active !== null) { filtered = filtered.filter(w => w.active === (active === 'true')); } // Simple pagination simulation const startIndex = cursor ? parseInt(cursor) : 0; const paginatedData = filtered.slice(startIndex, startIndex + limit); const hasMore = startIndex + limit < filtered.length; const nextCursor = hasMore ? String(startIndex + limit) : null; return HttpResponse.json({ data: paginatedData, nextCursor, hasMore }); }), http.get('*/api/v1/workflows/:id', ({ params }) => { const workflow = mockWorkflows.find(w => w.id === params.id); if (!workflow) { return HttpResponse.json( { message: 'Workflow not found', code: 'NOT_FOUND' }, { status: 404 } ); } return HttpResponse.json({ data: workflow }); }), http.post('*/api/v1/workflows', async ({ request }) => { const body = await request.json() as any; // Validate required fields if (!body.name || !body.nodes || !body.connections) { return HttpResponse.json( { message: 'Validation failed', errors: { name: !body.name ? 'Name is required' : undefined, nodes: !body.nodes ? 'Nodes are required' : undefined, connections: !body.connections ? 'Connections are required' : undefined, }, code: 'VALIDATION_ERROR' }, { status: 400 } ); } const newWorkflow = { id: `workflow_${Date.now()}`, name: body.name, active: body.active || false, nodes: body.nodes, connections: body.connections, settings: body.settings || {}, tags: body.tags || [], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), versionId: '1' }; mockWorkflows.push(newWorkflow); return HttpResponse.json({ data: newWorkflow }, { status: 201 }); }), http.patch('*/api/v1/workflows/:id', async ({ params, request }) => { const workflowIndex = mockWorkflows.findIndex(w => w.id === params.id); if (workflowIndex === -1) { return HttpResponse.json( { message: 'Workflow not found', code: 'NOT_FOUND' }, { status: 404 } ); } const body = await request.json() as any; const updatedWorkflow = { ...mockWorkflows[workflowIndex], ...body, id: params.id, // Ensure ID doesn't change updatedAt: new Date().toISOString(), versionId: String(parseInt(mockWorkflows[workflowIndex].versionId) + 1) }; mockWorkflows[workflowIndex] = updatedWorkflow; return HttpResponse.json({ data: updatedWorkflow }); }), http.delete('*/api/v1/workflows/:id', ({ params }) => { const workflowIndex = mockWorkflows.findIndex(w => w.id === params.id); if (workflowIndex === -1) { return HttpResponse.json( { message: 'Workflow not found', code: 'NOT_FOUND' }, { status: 404 } ); } mockWorkflows.splice(workflowIndex, 1); return HttpResponse.json({ success: true }); }), // Execution endpoints http.get('*/api/v1/executions', ({ request }) => { const url = new URL(request.url); const limit = parseInt(url.searchParams.get('limit') || '100'); const cursor = url.searchParams.get('cursor'); const workflowId = url.searchParams.get('workflowId'); const status = url.searchParams.get('status'); let filtered = mockExecutions; // Filter by workflow ID if provided if (workflowId) { filtered = filtered.filter(e => e.workflowId === workflowId); } // Filter by status if provided if (status) { filtered = filtered.filter(e => e.status === status); } // Simple pagination simulation const startIndex = cursor ? parseInt(cursor) : 0; const paginatedData = filtered.slice(startIndex, startIndex + limit); const hasMore = startIndex + limit < filtered.length; const nextCursor = hasMore ? String(startIndex + limit) : null; return HttpResponse.json({ data: paginatedData, nextCursor, hasMore }); }), http.get('*/api/v1/executions/:id', ({ params }) => { const execution = mockExecutions.find(e => e.id === params.id); if (!execution) { return HttpResponse.json( { message: 'Execution not found', code: 'NOT_FOUND' }, { status: 404 } ); } return HttpResponse.json({ data: execution }); }), http.delete('*/api/v1/executions/:id', ({ params }) => { const executionIndex = mockExecutions.findIndex(e => e.id === params.id); if (executionIndex === -1) { return HttpResponse.json( { message: 'Execution not found', code: 'NOT_FOUND' }, { status: 404 } ); } mockExecutions.splice(executionIndex, 1); return HttpResponse.json({ success: true }); }), // Webhook endpoints (dynamic handling) http.all('*/webhook/*', async ({ request }) => { const url = new URL(request.url); const method = request.method; const body = request.body ? await request.json() : undefined; // Log webhook trigger in debug mode if (process.env.MSW_DEBUG === 'true') { console.log('[MSW] Webhook triggered:', { url: url.pathname, method, body }); } // Return success response by default return HttpResponse.json({ success: true, webhookUrl: url.pathname, method, timestamp: new Date().toISOString(), data: body }); }), // Catch-all for unhandled API routes (helps identify missing handlers) http.all('*/api/*', ({ request }) => { console.warn('[MSW] Unhandled API request:', request.method, request.url); return HttpResponse.json( { message: 'Not implemented in mock', code: 'NOT_IMPLEMENTED', path: new URL(request.url).pathname, method: request.method }, { status: 501 } ); }), ]; /** * Dynamic handler registration helpers */ export const dynamicHandlers = { /** * Add a workflow that will be returned by GET requests */ addWorkflow: (workflow: any) => { mockWorkflows.push(workflow); }, /** * Clear all mock workflows */ clearWorkflows: () => { mockWorkflows.length = 0; }, /** * Add an execution that will be returned by GET requests */ addExecution: (execution: any) => { mockExecutions.push(execution); }, /** * Clear all mock executions */ clearExecutions: () => { mockExecutions.length = 0; }, /** * Reset all mock data to initial state */ resetAll: () => { // Reset arrays to initial state (implementation depends on data modules) mockWorkflows.length = 0; mockExecutions.length = 0; mockCredentials.length = 0; } };

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/88-888/n8n-mcp'

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