Skip to main content
Glama
portel-dev

NCP - Natural Context Provider

by portel-dev
create-test-mcps.js5.46 kB
#!/usr/bin/env node /** * Create Test HTTP/SSE MCP Servers * * Quickly spin up test MCP servers with different auth types for testing */ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import express from 'express'; import chalk from 'chalk'; const TEST_SERVERS = [ { port: 3000, path: '/sse', name: 'test-public', description: 'Public test MCP (no auth)', authType: 'none', tools: ['test_tool', 'ping'] }, { port: 3001, path: '/sse', name: 'test-bearer', description: 'Bearer token auth MCP', authType: 'bearer', token: 'test-token-123', tools: ['secure_tool', 'get_data'] }, { port: 3002, path: '/sse', name: 'test-apikey', description: 'API key auth MCP', authType: 'apikey', apiKey: 'sk-test-key-456', tools: ['api_call', 'fetch_data'] } ]; console.log(chalk.bold('\n🚀 Creating Test HTTP/SSE MCP Servers\n')); const servers = []; for (const config of TEST_SERVERS) { const app = express(); // Add authentication middleware if (config.authType === 'bearer') { app.use((req, res, next) => { const auth = req.headers.authorization; if (auth !== `Bearer ${config.token}`) { return res.status(401).json({ error: 'unauthorized', message: 'Bearer token required', hint: `Use: Authorization: Bearer ${config.token}` }); } next(); }); } else if (config.authType === 'apikey') { app.use((req, res, next) => { const apiKey = req.headers['x-api-key']; if (apiKey !== config.apiKey) { return res.status(401).json({ error: 'unauthorized', message: 'API key required', hint: `Use: X-API-Key: ${config.apiKey}` }); } next(); }); } // Create MCP server const mcpServer = new Server( { name: config.name, version: '1.0.0' }, { capabilities: { tools: {} } } ); // Add tools mcpServer.setRequestHandler('tools/list', async () => ({ tools: config.tools.map(name => ({ name, description: `Test tool from ${config.name}`, inputSchema: { type: 'object', properties: { message: { type: 'string', description: 'Test message' } } } })) })); mcpServer.setRequestHandler('tools/call', async (request) => ({ content: [{ type: 'text', text: `✅ Tool ${request.params.name} executed successfully!\nAuth: ${config.authType}\nMessage: ${request.params.arguments?.message || 'none'}` }] })); // Create SSE transport const transport = new SSEServerTransport(config.path, mcpServer); app.use(transport.router); // Start server const server = app.listen(config.port, () => { const url = `http://localhost:${config.port}${config.path}`; console.log(chalk.green(`✅ ${config.name}`)); console.log(chalk.dim(` URL: ${url}`)); console.log(chalk.dim(` Auth: ${config.authType}`)); if (config.authType === 'bearer') { console.log(chalk.dim(` Token: ${config.token}`)); } else if (config.authType === 'apikey') { console.log(chalk.dim(` API Key: ${config.apiKey}`)); } console.log(chalk.dim(` Tools: ${config.tools.join(', ')}`)); console.log(''); }); servers.push({ server, config }); } // Generate CSV for batch import const csvLines = ['name,url,description']; TEST_SERVERS.forEach(config => { const url = `http://localhost:${config.port}${config.path}`; csvLines.push(`${config.name},${url},${config.description}`); }); const csvContent = csvLines.join('\n'); const { writeFileSync } = await import('fs'); writeFileSync('tests/mcp-urls-test.csv', csvContent); console.log(chalk.cyan('📄 Generated CSV: tests/mcp-urls-test.csv\n')); // Instructions console.log(chalk.bold('📋 Testing Instructions:\n')); console.log(chalk.cyan('1. Test auth detection:')); console.log(chalk.dim(' node tests/batch-import-mcps.js tests/mcp-urls-test.csv --dry-run --skip-prompts\n')); console.log(chalk.cyan('2. Test with prompts (interactive):')); console.log(chalk.dim(' node tests/batch-import-mcps.js tests/mcp-urls-test.csv --dry-run\n')); console.log(chalk.cyan('3. Actually import to test profile:')); console.log(chalk.dim(' node tests/batch-import-mcps.js tests/mcp-urls-test.csv --profile http-sse-test\n')); console.log(chalk.cyan('4. View imported MCPs:')); console.log(chalk.dim(' ncp list --profile http-sse-test\n')); console.log(chalk.cyan('5. Test discovery:')); console.log(chalk.dim(' ncp find "test" --profile http-sse-test\n')); console.log(chalk.yellow('📝 Auth Credentials:')); console.log(chalk.dim(' test-bearer: Authorization: Bearer test-token-123')); console.log(chalk.dim(' test-apikey: X-API-Key: sk-test-key-456')); console.log(chalk.dim(' test-public: No auth needed\n')); console.log(chalk.green('✨ Test servers are running!')); console.log(chalk.dim(' Press Ctrl+C to stop\n')); // Handle shutdown process.on('SIGINT', () => { console.log(chalk.yellow('\n🛑 Shutting down test servers...\n')); servers.forEach(({ server, config }) => { server.close(); console.log(chalk.dim(` Stopped: ${config.name}`)); }); console.log(chalk.green('\n✅ All servers stopped\n')); process.exit(0); });

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