Skip to main content
Glama
mcp_uri_validation.test.js11.4 kB
/** * MCP URI Scheme Validation Tests for krep-mcp-server * * These tests specifically focus on validating compliance with MCP URI schemes * including edge cases, special character handling, and encoding requirements. */ const request = require('supertest'); const path = require('path'); const fs = require('fs'); const { URL } = require('url'); const { getFixturePath, SAMPLE_TEXT } = require('../utils'); // Import the server const app = require('../../src/index'); // Import SDK for testing URI parsing const sdkIntegration = require('../../sdk-integration'); describe('MCP URI Scheme Validation', () => { describe('URI Structure Compliance', () => { it('should support search:// URI scheme with basic parameters', async () => { const searchPath = getFixturePath('sample.txt'); const pattern = 'pattern'; // Format a compliant search URI const uri = `search://${searchPath}?pattern=${pattern}`; // Test via SDK integration const client = new sdkIntegration.KrepMcpClient(); const params = client.parseUri(uri); // Verify URI parsing results expect(params.scheme).toBe('search'); expect(params.path).toBe(searchPath); expect(params.pattern).toBe(pattern); expect(params.caseSensitive).toBe(true); // Default expect(params.threads).toBe(4); // Default expect(params.countOnly).toBe(false); // Default // Verify server correctly handles the URI const response = await request(app) .get(`/mcp/search/${searchPath}?pattern=${pattern}`); expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); }); it('should support match:// URI scheme with basic parameters', async () => { const text = 'Hello world'; const pattern = 'world'; // Format a compliant match URI const uri = `match://${text}?pattern=${pattern}`; // Test via SDK integration const client = new sdkIntegration.KrepMcpClient(); const params = client.parseUri(uri); // Verify URI parsing results expect(params.scheme).toBe('match'); expect(params.text).toBe(text); expect(params.pattern).toBe(pattern); // Verify server correctly handles the URI const response = await request(app) .get(`/mcp/match/${encodeURIComponent(text)}?pattern=${pattern}`); expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); }); }); describe('Parameter Encoding and Handling', () => { it('should handle URL encoded special characters in patterns', async () => { // Special characters in pattern const specialPattern = 'patt+ern[0-9]?'; const encodedPattern = encodeURIComponent(specialPattern); const searchPath = getFixturePath('sample.txt'); const uri = `search://${searchPath}?pattern=${encodedPattern}`; // Verify SDK correctly decodes pattern const client = new sdkIntegration.KrepMcpClient(); const params = client.parseUri(uri); expect(params.pattern).toBe(specialPattern); // Verify server correctly handles encoded pattern const response = await request(app) .get(`/mcp/search/${searchPath}?pattern=${encodedPattern}`); expect(response.status).toBe(200); expect(response.body).toHaveProperty('pattern', specialPattern); }); it('should handle URL encoded spaces in file paths', async () => { // Create a temporary file with spaces in name const tempFileName = 'test file with spaces.txt'; const tempFilePath = path.join(__dirname, '../fixtures', tempFileName); try { // Create the test file fs.writeFileSync(tempFilePath, 'This is a test pattern'); // Encode path for URI const encodedPath = encodeURIComponent(tempFilePath); const pattern = 'test'; const uri = `search://${encodedPath}?pattern=${pattern}`; // Test URI parsing via SDK const client = new sdkIntegration.KrepMcpClient(); const params = client.parseUri(uri); // Encoded path should be properly decoded expect(params.path).toBe(tempFilePath); // Verify server correctly handles the path const response = await request(app) .get(`/mcp/search/${encodeURIComponent(tempFilePath)}?pattern=${pattern}`); expect(response.status).toBe(200); } finally { // Clean up try { fs.unlinkSync(tempFilePath); } catch (error) { // Ignore cleanup errors } } }); it('should handle complex parameter combinations', async () => { const searchPath = getFixturePath('sample.txt'); const pattern = 'pattern\\d+'; const encodedPattern = encodeURIComponent(pattern); // Complex URI with all parameters const uri = `search://${searchPath}?pattern=${encodedPattern}&case=false&threads=8&count=true`; // Verify SDK correctly parses all parameters const client = new sdkIntegration.KrepMcpClient(); const params = client.parseUri(uri); expect(params.pattern).toBe(pattern); expect(params.caseSensitive).toBe(false); expect(params.threads).toBe(8); expect(params.countOnly).toBe(true); // Verify server correctly handles all parameters const response = await request(app) .get(`/mcp/search/${searchPath}?pattern=${encodedPattern}&case=false&threads=8&count=true`); expect(response.status).toBe(200); expect(response.body.performance).toHaveProperty('caseSensitive', false); expect(response.body.performance).toHaveProperty('threads', 8); }); }); describe('URI Edge Cases', () => { it('should handle empty pattern parameter gracefully', async () => { const searchPath = getFixturePath('sample.txt'); const uri = `search://${searchPath}?pattern=`; // Verify SDK behavior const client = new sdkIntegration.KrepMcpClient(); const params = client.parseUri(uri); expect(params.pattern).toBe(''); // Server should return a 400 for empty pattern const response = await request(app) .get(`/mcp/search/${searchPath}?pattern=`); expect(response.status).toBe(400); expect(response.body).toHaveProperty('error'); }); it('should handle URIs missing required parameters', async () => { const searchPath = getFixturePath('sample.txt'); // URI missing pattern parameter const uri = `search://${searchPath}`; // Verify SDK behavior const client = new sdkIntegration.KrepMcpClient(); const params = client.parseUri(uri); expect(params.pattern).toBe(''); // Server should return a 400 for missing pattern const response = await request(app) .get(`/mcp/search/${searchPath}`); expect(response.status).toBe(400); expect(response.body).toHaveProperty('error'); }); it('should handle path parameters with unusual characters', async () => { // Path with various special characters const pattern = 'test'; const characters = '!@#$%^&()_+-={}[];,.'; const tempFileName = `test${characters}.txt`; const tempFilePath = path.join(__dirname, '../fixtures', tempFileName); try { // Create the test file fs.writeFileSync(tempFilePath, 'This is a test pattern'); // Encode path for URI const encodedPath = encodeURIComponent(tempFilePath); const uri = `search://${encodedPath}?pattern=${pattern}`; // Test URI parsing via SDK const client = new sdkIntegration.KrepMcpClient(); const params = client.parseUri(uri); // Verify server handling const response = await request(app) .post('/search') .send({ pattern, path: tempFilePath }); expect(response.status).toBe(200); } finally { // Clean up try { fs.unlinkSync(tempFilePath); } catch (error) { // Ignore cleanup errors } } }); it('should handle extremely long URIs', async () => { const searchPath = getFixturePath('sample.txt'); // Create a very long pattern (1000+ characters) const longPattern = 'a'.repeat(1000); const encodedPattern = encodeURIComponent(longPattern); // Long URI const uri = `search://${searchPath}?pattern=${encodedPattern}`; // Verify SDK can parse long URIs const client = new sdkIntegration.KrepMcpClient(); const params = client.parseUri(uri); expect(params.pattern.length).toBe(1000); // Server might have limitations with extremely long URIs // This test is more focused on SDK handling }); }); describe('MCP URI Execution', () => { it('should handle URIs with the file:// prefix in paths', async () => { const searchPath = getFixturePath('sample.txt'); const fileUriPath = `file://${searchPath}`; const pattern = 'pattern'; // SDK should strip file:// prefix if present const uri = `search://${fileUriPath}?pattern=${pattern}`; const client = new sdkIntegration.KrepMcpClient(); try { const params = client.parseUri(uri); expect(params.path).toContain(searchPath); // The server itself should still work with the path const response = await request(app) .post('/search') .send({ pattern, path: fileUriPath }); // Server should either handle it or return an error, but not crash expect(response.status).toBeDefined(); } catch (error) { // If URI parsing fails, that's okay - some implementations might reject nested schemes expect(error).toBeDefined(); } }); it('should validate boolean parameters correctly', async () => { const searchPath = getFixturePath('sample.txt'); const pattern = 'pattern'; // Test various boolean parameter forms const testCases = [ { uri: `search://${searchPath}?pattern=${pattern}&case=true`, expected: true }, { uri: `search://${searchPath}?pattern=${pattern}&case=false`, expected: false }, { uri: `search://${searchPath}?pattern=${pattern}&case=1`, expected: true }, // Non-"false" = true { uri: `search://${searchPath}?pattern=${pattern}&case=0`, expected: true }, // Non-"false" = true { uri: `search://${searchPath}?pattern=${pattern}&case=yes`, expected: true }, { uri: `search://${searchPath}?pattern=${pattern}&case=no`, expected: true }, { uri: `search://${searchPath}?pattern=${pattern}`, expected: true } // Default ]; const client = new sdkIntegration.KrepMcpClient(); for (const testCase of testCases) { const params = client.parseUri(testCase.uri); expect(params.caseSensitive).toBe(testCase.expected); } }); }); });

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/bmorphism/krep-mcp-server'

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