Skip to main content
Glama
portel-dev

NCP - Natural Context Provider

by portel-dev
mcp-error-parser.test.ts7.71 kB
/** * Tests for MCP Error Parser */ import { MCPErrorParser } from '../src/utils/mcp-error-parser.js'; describe('MCPErrorParser', () => { let parser: MCPErrorParser; beforeEach(() => { parser = new MCPErrorParser(); }); describe('API Key Detection', () => { it('should detect ELEVENLABS_API_KEY requirement', () => { const stderr = 'Error: ELEVENLABS_API_KEY is required'; const needs = parser.parseError('elevenlabs', stderr, 1); expect(needs).toHaveLength(1); expect(needs[0].type).toBe('api_key'); expect(needs[0].variable).toBe('ELEVENLABS_API_KEY'); expect(needs[0].sensitive).toBe(true); }); it('should detect GITHUB_TOKEN missing', () => { const stderr = 'Error: GITHUB_TOKEN not set'; const needs = parser.parseError('github', stderr, 1); expect(needs).toHaveLength(1); expect(needs[0].type).toBe('api_key'); expect(needs[0].variable).toBe('GITHUB_TOKEN'); }); it('should detect multiple API keys', () => { const stderr = ` Error: OPENAI_API_KEY is required Warning: ANTHROPIC_API_KEY must be set `; const needs = parser.parseError('test', stderr, 1); expect(needs).toHaveLength(2); expect(needs[0].variable).toBe('OPENAI_API_KEY'); expect(needs[1].variable).toBe('ANTHROPIC_API_KEY'); }); }); describe('Command Argument Detection', () => { it('should detect filesystem directory requirement', () => { const stderr = 'Usage: mcp-server-filesystem [allowed-directory]...'; const needs = parser.parseError('filesystem', stderr, 1); expect(needs).toHaveLength(1); expect(needs[0].type).toBe('command_arg'); expect(needs[0].variable).toBe('allowed-directory'); }); it('should detect required path from usage', () => { const stderr = 'Usage: mcp-server <path>'; const needs = parser.parseError('test', stderr, 1); expect(needs).toHaveLength(1); expect(needs[0].type).toBe('command_arg'); expect(needs[0].variable).toBe('path'); }); it('should detect "requires at least one" pattern', () => { const stderr = 'Error: requires at least one directory'; const needs = parser.parseError('test', stderr, 1); expect(needs).toHaveLength(1); expect(needs[0].type).toBe('command_arg'); expect(needs[0].variable).toBe('required-path'); }); it('should not duplicate path requirements from Usage and "requires at least one"', () => { const stderr = `Usage: mcp-server-filesystem [allowed-directory] [additional-directories...] At least one directory must be provided by EITHER method for the server to operate.`; const needs = parser.parseError('filesystem', stderr, 1); // Should only detect ONE requirement (from Usage), not two expect(needs).toHaveLength(1); expect(needs[0].type).toBe('command_arg'); expect(needs[0].variable).toBe('allowed-directory'); }); it('should detect multiple path arguments for clone/copy MCPs', () => { const stderr = 'Usage: mcp-server-clone <source-directory> <destination-directory>'; const needs = parser.parseError('clone', stderr, 1); // Should detect BOTH source and destination expect(needs).toHaveLength(2); expect(needs[0].type).toBe('command_arg'); expect(needs[0].variable).toBe('source-directory'); expect(needs[1].type).toBe('command_arg'); expect(needs[1].variable).toBe('destination-directory'); }); }); describe('Environment Variable Detection', () => { it('should detect generic env var requirement', () => { const stderr = 'Error: DATABASE_URL environment variable is required'; const needs = parser.parseError('test', stderr, 1); expect(needs).toHaveLength(1); expect(needs[0].type).toBe('env_var'); expect(needs[0].variable).toBe('DATABASE_URL'); }); it('should skip common false positives', () => { const stderr = 'Error: HTTP request failed, ERROR code 500'; const needs = parser.parseError('test', stderr, 1); expect(needs).toHaveLength(0); }); it('should mark password-related vars as sensitive', () => { const stderr = 'Error: DATABASE_PASSWORD is required'; const needs = parser.parseError('test', stderr, 1); expect(needs).toHaveLength(1); expect(needs[0].type).toBe('env_var'); expect(needs[0].sensitive).toBe(true); }); }); describe('Package Missing Detection', () => { it('should detect npm 404 error', () => { const stderr = 'npm error 404 Not Found - GET https://registry.npmjs.org/@modelcontextprotocol/server-browserbase'; const needs = parser.parseError('browserbase', stderr, 1); expect(needs).toHaveLength(1); expect(needs[0].type).toBe('package_missing'); }); it('should detect registry not found', () => { const stderr = 'Error: ENOTFOUND registry.npmjs.org'; const needs = parser.parseError('test', stderr, 1); expect(needs).toHaveLength(1); expect(needs[0].type).toBe('package_missing'); }); it('should skip other patterns if package is missing', () => { const stderr = ` npm error 404 Package not found Error: API_KEY is required `; const needs = parser.parseError('test', stderr, 1); // Should only return package_missing, skip API_KEY detection expect(needs).toHaveLength(1); expect(needs[0].type).toBe('package_missing'); }); }); describe('Path Detection', () => { it('should detect missing config file', () => { const stderr = 'Error: cannot find config.json'; const needs = parser.parseError('test', stderr, 1); expect(needs).toHaveLength(1); expect(needs[0].type).toBe('command_arg'); expect(needs[0].variable).toBe('config.json'); }); it('should detect missing directory', () => { const stderr = 'Error: no such file or directory /path/to/dir'; const needs = parser.parseError('test', stderr, 1); expect(needs.length).toBeGreaterThan(0); expect(needs[0].type).toBe('command_arg'); }); }); describe('Summary Generation', () => { it('should generate summary for multiple needs', () => { const needs = [ { type: 'api_key' as const, variable: 'OPENAI_API_KEY', description: 'test', prompt: 'test', sensitive: true, extractedFrom: 'test' }, { type: 'env_var' as const, variable: 'DATABASE_URL', description: 'test', prompt: 'test', sensitive: false, extractedFrom: 'test' }, { type: 'command_arg' as const, variable: 'path', description: 'test', prompt: 'test', sensitive: false, extractedFrom: 'test' } ]; const summary = parser.generateSummary(needs); expect(summary).toContain('1 API key'); expect(summary).toContain('1 env var'); expect(summary).toContain('1 argument'); }); it('should handle no configuration needs', () => { const summary = parser.generateSummary([]); expect(summary).toBe('No configuration issues detected.'); }); it('should show package missing message', () => { const needs = [{ type: 'package_missing' as const, variable: '', description: 'test', prompt: 'test', sensitive: false, extractedFrom: 'test' }]; const summary = parser.generateSummary(needs); expect(summary).toContain('Package not found'); }); }); });

Latest Blog Posts

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/portel-dev/ncp'

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