Skip to main content
Glama

n8n-MCP

by 88-888
ai-tool-validation.test.tsβ€’12.5 kB
/** * Integration Tests: AI Tool Validation * * Tests AI tool node validation against real n8n instance. * Covers HTTP Request Tool, Code Tool, Vector Store Tool, Workflow Tool, Calculator Tool. */ import { describe, it, expect, beforeEach, afterEach, afterAll } from 'vitest'; import { createTestContext, TestContext, createTestWorkflowName } from '../n8n-api/utils/test-context'; import { getTestN8nClient } from '../n8n-api/utils/n8n-client'; import { N8nApiClient } from '../../../src/services/n8n-api-client'; import { cleanupOrphanedWorkflows } from '../n8n-api/utils/cleanup-helpers'; import { createMcpContext } from '../n8n-api/utils/mcp-context'; import { InstanceContext } from '../../../src/types/instance-context'; import { handleValidateWorkflow } from '../../../src/mcp/handlers-n8n-manager'; import { getNodeRepository, closeNodeRepository } from '../n8n-api/utils/node-repository'; import { NodeRepository } from '../../../src/database/node-repository'; import { ValidationResponse } from '../n8n-api/types/mcp-responses'; import { createHTTPRequestToolNode, createCodeToolNode, createVectorStoreToolNode, createWorkflowToolNode, createCalculatorToolNode, createAIWorkflow } from './helpers'; describe('Integration: AI Tool Validation', () => { let context: TestContext; let client: N8nApiClient; let mcpContext: InstanceContext; let repository: NodeRepository; beforeEach(async () => { context = createTestContext(); client = getTestN8nClient(); mcpContext = createMcpContext(); repository = await getNodeRepository(); }); afterEach(async () => { await context.cleanup(); }); afterAll(async () => { await closeNodeRepository(); if (!process.env.CI) { await cleanupOrphanedWorkflows(); } }); // ====================================================================== // HTTP Request Tool Tests // ====================================================================== describe('HTTP Request Tool', () => { it('should detect missing toolDescription', async () => { const httpTool = createHTTPRequestToolNode({ name: 'HTTP Request Tool', toolDescription: '', // Missing url: 'https://api.example.com/data', method: 'GET' }); const workflow = createAIWorkflow( [httpTool], {}, { name: createTestWorkflowName('HTTP Tool - No Description'), tags: ['mcp-integration-test', 'ai-validation'] } ); const created = await client.createWorkflow(workflow); context.trackWorkflow(created.id!); const response = await handleValidateWorkflow( { id: created.id }, repository, mcpContext ); expect(response.success).toBe(true); const data = response.data as ValidationResponse; expect(data.valid).toBe(false); expect(data.errors).toBeDefined(); const errorCodes = data.errors!.map(e => e.details?.code || e.code); expect(errorCodes).toContain('MISSING_TOOL_DESCRIPTION'); }); it('should detect missing URL', async () => { const httpTool = createHTTPRequestToolNode({ name: 'HTTP Request Tool', toolDescription: 'Fetches data from API', url: '', // Missing method: 'GET' }); const workflow = createAIWorkflow( [httpTool], {}, { name: createTestWorkflowName('HTTP Tool - No URL'), tags: ['mcp-integration-test', 'ai-validation'] } ); const created = await client.createWorkflow(workflow); context.trackWorkflow(created.id!); const response = await handleValidateWorkflow( { id: created.id }, repository, mcpContext ); expect(response.success).toBe(true); const data = response.data as ValidationResponse; expect(data.valid).toBe(false); expect(data.errors).toBeDefined(); const errorCodes = data.errors!.map(e => e.details?.code || e.code); expect(errorCodes).toContain('MISSING_URL'); }); it('should validate valid HTTP Request Tool', async () => { const httpTool = createHTTPRequestToolNode({ name: 'HTTP Request Tool', toolDescription: 'Fetches weather data from the weather API', url: 'https://api.weather.com/current', method: 'GET' }); const workflow = createAIWorkflow( [httpTool], {}, { name: createTestWorkflowName('HTTP Tool - Valid'), tags: ['mcp-integration-test', 'ai-validation'] } ); const created = await client.createWorkflow(workflow); context.trackWorkflow(created.id!); const response = await handleValidateWorkflow( { id: created.id }, repository, mcpContext ); expect(response.success).toBe(true); const data = response.data as ValidationResponse; expect(data.valid).toBe(true); expect(data.errors).toBeUndefined(); }); }); // ====================================================================== // Code Tool Tests // ====================================================================== describe('Code Tool', () => { it('should detect missing code', async () => { const codeTool = createCodeToolNode({ name: 'Code Tool', toolDescription: 'Processes data with custom logic', code: '' // Missing }); const workflow = createAIWorkflow( [codeTool], {}, { name: createTestWorkflowName('Code Tool - No Code'), tags: ['mcp-integration-test', 'ai-validation'] } ); const created = await client.createWorkflow(workflow); context.trackWorkflow(created.id!); const response = await handleValidateWorkflow( { id: created.id }, repository, mcpContext ); expect(response.success).toBe(true); const data = response.data as ValidationResponse; expect(data.valid).toBe(false); expect(data.errors).toBeDefined(); const errorCodes = data.errors!.map(e => e.details?.code || e.code); expect(errorCodes).toContain('MISSING_CODE'); }); it('should validate valid Code Tool', async () => { const codeTool = createCodeToolNode({ name: 'Code Tool', toolDescription: 'Calculates the sum of two numbers', code: 'return { sum: Number(a) + Number(b) };' }); const workflow = createAIWorkflow( [codeTool], {}, { name: createTestWorkflowName('Code Tool - Valid'), tags: ['mcp-integration-test', 'ai-validation'] } ); const created = await client.createWorkflow(workflow); context.trackWorkflow(created.id!); const response = await handleValidateWorkflow( { id: created.id }, repository, mcpContext ); expect(response.success).toBe(true); const data = response.data as ValidationResponse; expect(data.valid).toBe(true); expect(data.errors).toBeUndefined(); }); }); // ====================================================================== // Vector Store Tool Tests // ====================================================================== describe('Vector Store Tool', () => { it('should detect missing toolDescription', async () => { const vectorTool = createVectorStoreToolNode({ name: 'Vector Store Tool', toolDescription: '' // Missing }); const workflow = createAIWorkflow( [vectorTool], {}, { name: createTestWorkflowName('Vector Tool - No Description'), tags: ['mcp-integration-test', 'ai-validation'] } ); const created = await client.createWorkflow(workflow); context.trackWorkflow(created.id!); const response = await handleValidateWorkflow( { id: created.id }, repository, mcpContext ); expect(response.success).toBe(true); const data = response.data as ValidationResponse; expect(data.valid).toBe(false); expect(data.errors).toBeDefined(); const errorCodes = data.errors!.map(e => e.details?.code || e.code); expect(errorCodes).toContain('MISSING_TOOL_DESCRIPTION'); }); it('should validate valid Vector Store Tool', async () => { const vectorTool = createVectorStoreToolNode({ name: 'Vector Store Tool', toolDescription: 'Searches documentation in vector database' }); const workflow = createAIWorkflow( [vectorTool], {}, { name: createTestWorkflowName('Vector Tool - Valid'), tags: ['mcp-integration-test', 'ai-validation'] } ); const created = await client.createWorkflow(workflow); context.trackWorkflow(created.id!); const response = await handleValidateWorkflow( { id: created.id }, repository, mcpContext ); expect(response.success).toBe(true); const data = response.data as ValidationResponse; expect(data.valid).toBe(true); expect(data.errors).toBeUndefined(); }); }); // ====================================================================== // Workflow Tool Tests // ====================================================================== describe('Workflow Tool', () => { it('should detect missing workflowId', async () => { const workflowTool = createWorkflowToolNode({ name: 'Workflow Tool', toolDescription: 'Executes a sub-workflow', workflowId: '' // Missing }); const workflow = createAIWorkflow( [workflowTool], {}, { name: createTestWorkflowName('Workflow Tool - No ID'), tags: ['mcp-integration-test', 'ai-validation'] } ); const created = await client.createWorkflow(workflow); context.trackWorkflow(created.id!); const response = await handleValidateWorkflow( { id: created.id }, repository, mcpContext ); expect(response.success).toBe(true); const data = response.data as ValidationResponse; expect(data.valid).toBe(false); expect(data.errors).toBeDefined(); const errorCodes = data.errors!.map(e => e.details?.code || e.code); expect(errorCodes).toContain('MISSING_WORKFLOW_ID'); }); it('should validate valid Workflow Tool', async () => { const workflowTool = createWorkflowToolNode({ name: 'Workflow Tool', toolDescription: 'Processes customer data through validation workflow', workflowId: '123' }); const workflow = createAIWorkflow( [workflowTool], {}, { name: createTestWorkflowName('Workflow Tool - Valid'), tags: ['mcp-integration-test', 'ai-validation'] } ); const created = await client.createWorkflow(workflow); context.trackWorkflow(created.id!); const response = await handleValidateWorkflow( { id: created.id }, repository, mcpContext ); expect(response.success).toBe(true); const data = response.data as ValidationResponse; expect(data.valid).toBe(true); expect(data.errors).toBeUndefined(); }); }); // ====================================================================== // Calculator Tool Tests // ====================================================================== describe('Calculator Tool', () => { it('should validate Calculator Tool (no configuration needed)', async () => { const calcTool = createCalculatorToolNode({ name: 'Calculator' }); const workflow = createAIWorkflow( [calcTool], {}, { name: createTestWorkflowName('Calculator Tool - Valid'), tags: ['mcp-integration-test', 'ai-validation'] } ); const created = await client.createWorkflow(workflow); context.trackWorkflow(created.id!); const response = await handleValidateWorkflow( { id: created.id }, repository, mcpContext ); expect(response.success).toBe(true); const data = response.data as ValidationResponse; // Calculator has no required configuration expect(data.valid).toBe(true); expect(data.errors).toBeUndefined(); }); }); });

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