Skip to main content
Glama

n8n-MCP

by 88-888
llm-chain-validation.test.tsβ€’10.6 kB
/** * Integration Tests: Basic LLM Chain Validation * * Tests Basic LLM Chain validation against real n8n instance. */ 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 { createBasicLLMChainNode, createLanguageModelNode, createMemoryNode, createAIConnection, mergeConnections, createAIWorkflow } from './helpers'; import { WorkflowNode } from '../../../src/types/n8n-api'; describe('Integration: Basic LLM Chain 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(); } }); // ====================================================================== // TEST 1: Missing Language Model // ====================================================================== it('should detect missing language model', async () => { const llmChain = createBasicLLMChainNode({ name: 'Basic LLM Chain', promptType: 'define', text: 'Test prompt' }); const workflow = createAIWorkflow( [llmChain], {}, // No connections { name: createTestWorkflowName('LLM Chain - Missing Model'), 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_LANGUAGE_MODEL'); }); // ====================================================================== // TEST 2: Missing Prompt Text (promptType=define) // ====================================================================== it('should detect missing prompt text', async () => { const languageModel = createLanguageModelNode('openai', { name: 'OpenAI Chat Model' }); const llmChain = createBasicLLMChainNode({ name: 'Basic LLM Chain', promptType: 'define', text: '' // Empty prompt text }); const workflow = createAIWorkflow( [languageModel, llmChain], createAIConnection('OpenAI Chat Model', 'Basic LLM Chain', 'ai_languageModel'), { name: createTestWorkflowName('LLM Chain - Missing Prompt'), 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_PROMPT_TEXT'); }); // ====================================================================== // TEST 3: Valid Complete LLM Chain // ====================================================================== it('should validate complete LLM Chain', async () => { const languageModel = createLanguageModelNode('openai', { name: 'OpenAI Chat Model' }); const llmChain = createBasicLLMChainNode({ name: 'Basic LLM Chain', promptType: 'define', text: 'You are a helpful assistant. Answer the following: {{ $json.question }}' }); const workflow = createAIWorkflow( [languageModel, llmChain], createAIConnection('OpenAI Chat Model', 'Basic LLM Chain', 'ai_languageModel'), { name: createTestWorkflowName('LLM Chain - 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(); expect(data.summary.errorCount).toBe(0); }); // ====================================================================== // TEST 4: LLM Chain with Memory // ====================================================================== it('should validate LLM Chain with memory', async () => { const languageModel = createLanguageModelNode('anthropic', { name: 'Anthropic Chat Model' }); const memory = createMemoryNode({ name: 'Window Buffer Memory', contextWindowLength: 10 }); const llmChain = createBasicLLMChainNode({ name: 'Basic LLM Chain', promptType: 'auto' }); const workflow = createAIWorkflow( [languageModel, memory, llmChain], mergeConnections( createAIConnection('Anthropic Chat Model', 'Basic LLM Chain', 'ai_languageModel'), createAIConnection('Window Buffer Memory', 'Basic LLM Chain', 'ai_memory') ), { name: createTestWorkflowName('LLM Chain - With Memory'), 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(); }); // ====================================================================== // TEST 5: LLM Chain with Multiple Language Models (Error) // ====================================================================== it('should detect multiple language models', async () => { const languageModel1 = createLanguageModelNode('openai', { id: 'model-1', name: 'OpenAI Chat Model 1' }); const languageModel2 = createLanguageModelNode('anthropic', { id: 'model-2', name: 'Anthropic Chat Model' }); const llmChain = createBasicLLMChainNode({ name: 'Basic LLM Chain', promptType: 'define', text: 'Test prompt' }); const workflow = createAIWorkflow( [languageModel1, languageModel2, llmChain], mergeConnections( createAIConnection('OpenAI Chat Model 1', 'Basic LLM Chain', 'ai_languageModel'), createAIConnection('Anthropic Chat Model', 'Basic LLM Chain', 'ai_languageModel') // ERROR: multiple models ), { name: createTestWorkflowName('LLM Chain - Multiple Models'), 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('MULTIPLE_LANGUAGE_MODELS'); }); // ====================================================================== // TEST 6: LLM Chain with Tools (Error - not supported) // ====================================================================== it('should detect tools connection (not supported)', async () => { const languageModel = createLanguageModelNode('openai', { name: 'OpenAI Chat Model' }); // Manually create a tool node const toolNode: WorkflowNode = { id: 'tool-1', name: 'Calculator', type: '@n8n/n8n-nodes-langchain.toolCalculator', typeVersion: 1, position: [250, 400], parameters: {} }; const llmChain = createBasicLLMChainNode({ name: 'Basic LLM Chain', promptType: 'define', text: 'Calculate something' }); const workflow = createAIWorkflow( [languageModel, toolNode, llmChain], mergeConnections( createAIConnection('OpenAI Chat Model', 'Basic LLM Chain', 'ai_languageModel'), createAIConnection('Calculator', 'Basic LLM Chain', 'ai_tool') // ERROR: tools not supported ), { name: createTestWorkflowName('LLM Chain - With Tools'), 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('TOOLS_NOT_SUPPORTED'); const errorMessages = data.errors!.map(e => e.message).join(' '); expect(errorMessages).toMatch(/AI Agent/i); // Should suggest using AI Agent }); });

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