Skip to main content
Glama

MCP Smart Filesystem Server

by lofcz
test-interactive.js•6.57 kB
/** * Interactive test script for MCP filesystem server * Run: node test-interactive.js * * Available commands: * list - List tools * dirs - List allowed directories * ls [path] - List directory (default: .) * read <path> [start_line] - Read file * search <pattern> - Search code * find <pattern> - Find files * info <path> - Get file info * exit - Exit */ import { spawn } from 'child_process'; import readline from 'readline'; // Start the server const serverPath = process.argv[2] || process.cwd(); console.log(`šŸš€ Starting MCP server with allowed directory: ${serverPath}\n`); const server = spawn('node', ['dist/index.js', serverPath]); let messageId = 1; let waitingForResponse = false; // Handle server output server.stdout.on('data', (data) => { const lines = data.toString().trim().split('\n'); for (const line of lines) { try { const json = JSON.parse(line); console.log('\nšŸ“„ RESPONSE:'); console.log(JSON.stringify(json, null, 2)); } catch { console.log('\nšŸ“„ RAW:', line); } } waitingForResponse = false; rl.prompt(); }); server.stderr.on('data', (data) => { console.log('šŸ”§', data.toString().trim()); }); server.on('close', (code) => { console.log(`\nāŒ Server exited with code ${code}`); process.exit(code); }); // Send a request function sendRequest(method, params = {}) { const request = { jsonrpc: '2.0', id: messageId++, method: method, params: params }; server.stdin.write(JSON.stringify(request) + '\n'); waitingForResponse = true; } // Setup interactive CLI const rl = readline.createInterface({ input: process.stdin, output: process.stdout, prompt: '\n> ' }); console.log('=== Interactive MCP Filesystem Test ==='); console.log('Type "help" for available commands\n'); // Initialize the server first setTimeout(() => { sendRequest('initialize', { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'test-client', version: '1.0.0' } }); setTimeout(() => { console.log('\nāœ… Server initialized! Type commands below:'); rl.prompt(); }, 500); }, 500); rl.on('line', (line) => { const input = line.trim(); if (!input) { rl.prompt(); return; } const parts = input.split(/\s+/); const cmd = parts[0].toLowerCase(); switch (cmd) { case 'help': console.log('\nAvailable commands:'); console.log(' list - List available tools'); console.log(' dirs - List allowed directories'); console.log(' ls [path] - List directory (default: .)'); console.log(' read <path> [line] - Read file (optionally from line)'); console.log(' search <pattern> - Search code with pattern'); console.log(' find <pattern> - Find files by name pattern'); console.log(' info <path> - Get file info'); console.log(' exit - Exit'); rl.prompt(); break; case 'list': console.log('\nšŸ“¤ Requesting tools list...'); sendRequest('tools/list'); break; case 'dirs': console.log('\nšŸ“¤ Requesting allowed directories...'); sendRequest('tools/call', { name: 'list_allowed_directories', arguments: {} }); break; case 'ls': const lsPath = parts[1] || '.'; console.log(`\nšŸ“¤ Listing directory: ${lsPath}`); sendRequest('tools/call', { name: 'list_directory', arguments: { path: lsPath } }); break; case 'read': if (!parts[1]) { console.log('āŒ Usage: read <path> [start_line]'); rl.prompt(); break; } const readPath = parts[1]; const startLine = parts[2] ? parseInt(parts[2]) : 0; console.log(`\nšŸ“¤ Reading file: ${readPath} (from line ${startLine})`); sendRequest('tools/call', { name: 'read_file', arguments: { path: readPath, start_line: startLine } }); break; case 'search': if (!parts[1]) { console.log('āŒ Usage: search [-s] <pattern>'); console.log(' Note: Case-insensitive by default (LLM-friendly)'); console.log(' Examples: search class.*ChatRequest (matches any case)'); console.log(' search enum.*llmproviders (finds LLmProviders)'); console.log(' search -s PublicClass (case-sensitive)'); rl.prompt(); break; } // Check for -i flag (case-insensitive is default, but explicit -i is still supported) let caseInsensitive = true; // Default to true for LLM-friendly behavior let searchParts = parts.slice(1); if (searchParts[0] === '-s') { // -s for case-sensitive (opposite of default) caseInsensitive = false; searchParts = searchParts.slice(1); } // Remove surrounding quotes if present let pattern = searchParts.join(' ').replace(/^["']|["']$/g, ''); console.log(`\nšŸ“¤ Searching for: ${pattern}${caseInsensitive ? ' (case-insensitive)' : ' (case-sensitive)'}`); sendRequest('tools/call', { name: 'search_code', arguments: { pattern: pattern, contextLines: 2, caseInsensitive: caseInsensitive } }); break; case 'find': if (!parts[1]) { console.log('āŒ Usage: find <pattern>'); rl.prompt(); break; } const findPattern = parts[1]; console.log(`\nšŸ“¤ Finding files: ${findPattern}`); sendRequest('tools/call', { name: 'find_files', arguments: { pattern: findPattern } }); break; case 'info': if (!parts[1]) { console.log('āŒ Usage: info <path>'); rl.prompt(); break; } const infoPath = parts[1]; console.log(`\nšŸ“¤ Getting file info: ${infoPath}`); sendRequest('tools/call', { name: 'get_file_info', arguments: { path: infoPath } }); break; case 'exit': case 'quit': console.log('\nšŸ‘‹ Goodbye!'); server.kill(); process.exit(0); break; default: console.log(`āŒ Unknown command: ${cmd}. Type "help" for available commands.`); rl.prompt(); } }); rl.on('close', () => { server.kill(); process.exit(0); }); // Handle Ctrl+C process.on('SIGINT', () => { console.log('\n\nšŸ‘‹ Shutting down...'); server.kill(); process.exit(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/lofcz/mcp-filesystem-smart'

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