Skip to main content
Glama
cli.ts4.69 kB
#!/usr/bin/env node import { Command } from 'commander'; import path from 'path'; import { OpenAPIMCPServer } from './server'; import { ServerConfig } from './types'; const program = new Command(); program .name('specbridge') .description('Bridge OpenAPI specifications to MCP tools - automatically generates tools from OpenAPI specs') .version('1.0.0') .option( '--specs <path>', 'Path to directory containing OpenAPI spec files', process.cwd() ) .option( '--port <number>', 'Port number for HTTP transport (enables HTTP mode)', (val: any) => parseInt(val, 10) ) .option( '--transport <type>', 'Transport type: stdio or httpStream', 'stdio' ) .action(async (options: any) => { try { // Debug: log raw options without breaking JSON protocol const specsPath = path.resolve(options.specs || process.cwd()); const config: ServerConfig = { specsPath, port: options.port, transportType: options.transport as 'stdio' | 'httpStream' }; // Validate transport configuration if (config.transportType === 'httpStream' && !config.port) { console.error('Error: --port is required when using httpStream transport'); process.exit(1); } const server = new OpenAPIMCPServer(config); // Handle graceful shutdown const shutdown = async () => { console.log('\nShutting down...'); await server.stop(); process.exit(0); }; process.on('SIGINT', shutdown); process.on('SIGTERM', shutdown); // Start the server await server.start(); } catch (error) { console.error('Failed to start server:', error); process.exit(1); } }); // Add a command to list loaded specs (useful for debugging) program .command('list') .description('List all loaded OpenAPI specifications and their tools') .option('--specs <path>', 'Path to directory containing OpenAPI spec files', process.cwd()) .action(async (options: any) => { try { // Debug: log raw options without breaking JSON protocol const specsPath = path.resolve(options.specs || process.cwd()); const config: ServerConfig = { specsPath }; const server = new OpenAPIMCPServer(config); // We need to start the server briefly to load specs await server.start(); const specs = server.getLoadedSpecs(); const authConfig = server.getAuthConfig(); console.log('\n=== Specbridge Status ===\n'); console.log(`Specs Directory: ${config.specsPath}`); console.log(`Loaded Specifications: ${specs.length}`); if (specs.length === 0) { console.log('\nNo OpenAPI specifications found.'); console.log('Add .json, .yaml, or .yml files to the specs directory.'); } else { for (const spec of specs) { console.log(`\n📋 ${spec.apiName.toUpperCase()}`); console.log(` File: ${path.basename(spec.filePath)}`); console.log(` Base URL: ${spec.tools[0]?.baseUrl || 'N/A'}`); console.log(` Tools: ${spec.tools.length}`); if (authConfig[spec.apiName]) { const auth = authConfig[spec.apiName]; console.log(` Auth: ${auth.type} ${auth.type === 'apiKey' ? `(${auth.headerName})` : ''}`); } else { console.log(` Auth: None configured`); } if (spec.tools.length > 0) { console.log(' Available tools:'); for (const tool of spec.tools.slice(0, 5)) { // Show first 5 tools console.log(` • ${tool.name} - ${tool.description}`); } if (spec.tools.length > 5) { console.log(` ... and ${spec.tools.length - 5} more`); } } } } console.log('\n=== Authentication Configuration ===\n'); const authKeys = Object.keys(authConfig); if (authKeys.length === 0) { console.log('No authentication configured.'); console.log('Add a .env file with credentials like:'); console.log(' PETSTORE_API_KEY=your_key_here'); console.log(' GITHUB_TOKEN=your_token_here'); } else { for (const apiName of authKeys) { const auth = authConfig[apiName]; console.log(`🔐 ${apiName.toUpperCase()}: ${auth.type}`); } } await server.stop(); } catch (error) { console.error('Failed to list specs:', error); process.exit(1); } }); if (require.main === module) { program.parse(); }

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/TBosak/specbridge'

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