Skip to main content
Glama
interactive-cli.ts5.79 kB
#!/usr/bin/env tsx import { spawn } from 'child_process'; import { createInterface } from 'readline'; import path from 'path'; /** * Interactive CLI for humans to test MCP server * Shows exact MCP protocol responses */ async function interactiveCLI() { console.log('='.repeat(80)); console.log('🎮 PEEKABOO MCP - INTERACTIVE HUMAN CLI'); console.log('='.repeat(80)); console.log(); const rl = createInterface({ input: process.stdin, output: process.stdout, prompt: 'peekaboo> ' }); // Get root directory console.log('Enter root directory (or press Enter for current):'); rl.prompt(); let rootDir = process.cwd(); let mcpProcess: any = null; rl.on('line', async (line) => { const input = line.trim(); if (!mcpProcess && rootDir === process.cwd()) { // First input is the root directory rootDir = input || process.cwd(); console.log(`\n✅ Using root: ${rootDir}\n`); // Start MCP server process mcpProcess = spawn('tsx', ['src/index.ts'], { env: { ...process.env, PEEKABOO_ROOT: rootDir }, stdio: 'pipe' }); mcpProcess.stderr.on('data', (data: Buffer) => { if (data.toString().includes('server started')) { showHelp(); rl.prompt(); } }); return; } const [cmd, ...args] = input.split(' '); switch (cmd) { case 'help': case 'h': showHelp(); break; case 'list': case 'ls': await runTest('list', rootDir); break; case 'read': if (args.length === 0) { console.log('Usage: read <file-path>'); } else { await runTest('read', rootDir, args.join(' ')); } break; case 'search': if (args.length === 0) { console.log('Usage: search <pattern>'); console.log('Examples: *.ts, **/*.json, src/**/*.js'); } else { await runTest('search', rootDir, args.join(' ')); } break; case 'grep': if (args.length === 0) { console.log('Usage: grep <text> [file-pattern]'); } else { await runTest('grep', rootDir, args[0], args[1]); } break; case 'quit': case 'q': if (mcpProcess) { mcpProcess.kill(); } process.exit(0); default: if (input) { console.log('Unknown command. Type "help" for commands.'); } } rl.prompt(); }); rl.on('close', () => { if (mcpProcess) { mcpProcess.kill(); } process.exit(0); }); } function showHelp() { console.log('\nCOMMANDS:'); console.log(' list, ls - List all files and directories'); console.log(' read <path> - Read a specific file'); console.log(' search <pattern> - Search files by name (e.g., *.ts)'); console.log(' grep <text> [pattern] - Search for text in files'); console.log(' help, h - Show this help'); console.log(' quit, q - Exit\n'); } async function runTest(command: string, rootDir: string, ...args: string[]) { console.log('\n' + '='.repeat(60)); // Create a test script for the command let testScript = ` import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; const transport = new StdioClientTransport({ command: 'tsx', args: ['src/index.ts'], env: { ...process.env, PEEKABOO_ROOT: '${rootDir}', PEEKABOO_RECURSIVE: 'true', PEEKABOO_MAX_DEPTH: '10' } }); const client = new Client({ name: 'cli-test', version: '1.0.0' }, { capabilities: {} }); await client.connect(transport); `; switch (command) { case 'list': testScript += ` const resources = await client.listResources(); console.log('Found ' + resources.resources.length + ' items:\\n'); resources.resources.forEach(r => { const icon = r.mimeType === 'inode/directory' ? '📁' : '📄'; const size = r.metadata?.size ? ' (' + r.metadata.size + ' bytes)' : ''; console.log(icon + ' ' + r.name + ' [' + r.mimeType + ']' + size); }); console.log('\\nRAW RESPONSE (first 3 items):'); console.log(JSON.stringify(resources.resources.slice(0, 3), null, 2)); `; break; case 'read': const filePath = args[0]; const uri = filePath.startsWith('file://') ? filePath : `file://${path.join(rootDir, filePath.startsWith('/') ? filePath.slice(1) : filePath)}`; testScript += ` try { const content = await client.readResource({ uri: '${uri}' }); console.log('FILE CONTENT:'); console.log(content.contents[0].text); console.log('\\nMCP RESPONSE:'); console.log(JSON.stringify(content, null, 2).substring(0, 300) + '...'); } catch (error) { console.log('Error: ' + error.message); } `; break; case 'search': testScript += ` const result = await client.callTool({ name: 'search_path', arguments: { pattern: '${args[0]}' } }); console.log(result.content[0].text); `; break; case 'grep': testScript += ` const result = await client.callTool({ name: 'search_content', arguments: { query: '${args[0]}', ${args[1] ? `include: '${args[1]}',` : ''} ignoreCase: true } }); console.log(result.content[0].text); `; break; } testScript += ` await client.close(); `; // Run the test const proc = spawn('tsx', ['--eval', testScript], { stdio: 'inherit', env: process.env }); await new Promise(resolve => proc.on('close', resolve)); console.log('='.repeat(60) + '\n'); } // Start the CLI interactiveCLI().catch(console.error);

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/davstr1/peekabooMCP'

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