Skip to main content
Glama

3GPP MCP Server

by edhijlu
install.js11.5 kB
#!/usr/bin/env node const { Command } = require('commander'); const inquirer = require('inquirer'); const chalk = require('chalk'); const ora = require('ora'); const boxen = require('boxen'); const fs = require('fs'); const path = require('path'); const { execSync, spawn } = require('child_process'); const os = require('os'); const program = new Command(); // CLI Configuration program .name('3gpp-mcp-charging') .description('3GPP Charging & Billing MCP Server - Expert guidance for telecom charging systems') .version('2.0.5'); // Available AI clients and their configuration paths const AI_CLIENTS = { claude: { name: 'Claude Desktop', configPaths: { darwin: '~/Library/Application Support/Claude/claude_desktop_config.json', win32: '%APPDATA%\\Claude\\claude_desktop_config.json', linux: '~/.config/Claude/claude_desktop_config.json' }, description: 'Anthropic Claude Desktop application' }, cursor: { name: 'Cursor IDE', configPaths: { darwin: '~/Library/Application Support/Cursor/User/globalStorage/mcp.json', win32: '%APPDATA%\\Cursor\\User\\globalStorage\\mcp.json', linux: '~/.config/Cursor/User/globalStorage/mcp.json' }, description: 'Cursor IDE with MCP support' }, vscode: { name: 'VS Code', configPaths: { darwin: '~/Library/Application Support/Code/User/settings.json', win32: '%APPDATA%\\Code\\User\\settings.json', linux: '~/.config/Code/User/settings.json' }, description: 'Visual Studio Code with MCP extension' } }; // Utility functions function getConfigPath(client, platform = os.platform()) { const configPath = AI_CLIENTS[client]?.configPaths[platform]; if (!configPath) return null; // Expand environment variables and home directory return configPath .replace(/^~/, os.homedir()) .replace(/%APPDATA%/g, process.env.APPDATA || ''); } function displayBanner() { const banner = boxen( chalk.cyan.bold('3GPP Charging & Billing MCP Server') + '\n' + chalk.gray('Expert guidance for telecom charging systems') + '\n\n' + chalk.yellow('Transform your AI into a 3GPP charging expert!'), { padding: 1, margin: 1, borderStyle: 'round', borderColor: 'cyan' } ); console.log(banner); } function detectInstalledClients() { const detected = []; const platform = os.platform(); for (const [key, client] of Object.entries(AI_CLIENTS)) { const configPath = getConfigPath(key, platform); if (configPath) { const expandedPath = configPath.replace(/^~/, os.homedir()); const dirPath = path.dirname(expandedPath); try { if (fs.existsSync(dirPath)) { detected.push({ key, name: client.name, configPath: expandedPath, exists: fs.existsSync(expandedPath) }); } } catch (error) { // Ignore errors, client not available } } } return detected; } function generateMCPConfig(serverPath, client = 'claude') { const config = { mcpServers: { "3gpp-charging": { command: "node", args: ["dist/index.js"], cwd: serverPath, description: "Expert 3GPP charging and billing guidance" } } }; if (client === 'vscode') { return { "mcp.servers": config.mcpServers }; } return config; } async function installDependencies(serverPath) { const spinner = ora('Installing dependencies...').start(); try { execSync('npm install', { cwd: serverPath, stdio: ['ignore', 'ignore', 'pipe'] }); spinner.succeed('Dependencies installed'); } catch (error) { spinner.fail('Failed to install dependencies'); throw error; } } async function buildProject(serverPath) { const spinner = ora('Building project...').start(); try { execSync('npm run build', { cwd: serverPath, stdio: ['ignore', 'ignore', 'pipe'] }); spinner.succeed('Project built successfully'); } catch (error) { spinner.fail('Failed to build project'); throw error; } } async function testServer(serverPath) { const spinner = ora('Testing MCP server...').start(); return new Promise((resolve, reject) => { const serverProcess = spawn('node', ['dist/index.js'], { cwd: serverPath, stdio: ['ignore', 'ignore', 'ignore'] }); const timeout = setTimeout(() => { serverProcess.kill(); spinner.succeed('MCP server test passed'); resolve(); }, 3000); serverProcess.on('error', (error) => { clearTimeout(timeout); spinner.fail('MCP server test failed'); reject(error); }); serverProcess.on('exit', (code) => { clearTimeout(timeout); if (code === 0) { spinner.succeed('MCP server test passed'); resolve(); } else { spinner.fail('MCP server test failed'); reject(new Error(`Server exited with code ${code}`)); } }); }); } async function writeConfig(configPath, config, client) { const dir = path.dirname(configPath); // Create directory if it doesn't exist if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } if (client === 'vscode') { // For VS Code, merge with existing settings let existingConfig = {}; if (fs.existsSync(configPath)) { try { existingConfig = JSON.parse(fs.readFileSync(configPath, 'utf8')); } catch (error) { console.log(chalk.yellow('Warning: Could not parse existing VS Code settings')); } } const mergedConfig = { ...existingConfig, ...config }; fs.writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2)); } else { // For Claude and Cursor, write MCP config fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); } } // Main installation command program .command('init') .description('Initialize 3GPP Charging MCP Server') .option('-c, --client <client>', 'Target AI client (claude, cursor, vscode)') .option('-p, --path <path>', 'Installation path') .option('-y, --yes', 'Skip interactive prompts') .action(async (options) => { try { displayBanner(); // Determine installation path const installPath = options.path || process.cwd(); console.log(chalk.blue(`📁 Installation path: ${installPath}`)); // Auto-detect available clients const detectedClients = detectInstalledClients(); if (detectedClients.length === 0 && !options.client) { console.log(chalk.yellow('Warning: No AI clients detected. You can still install and configure manually.')); } let selectedClient = options.client; let configPath = null; // Interactive client selection if not specified if (!selectedClient && !options.yes && detectedClients.length > 0) { const choices = detectedClients.map(client => ({ name: `${client.name} ${client.exists ? chalk.green('(configured)') : chalk.gray('(not configured)')}`, value: client.key })); choices.push({ name: 'Manual configuration', value: 'manual' }); const { client } = await inquirer.prompt([{ type: 'list', name: 'client', message: 'Which AI client would you like to configure?', choices }]); selectedClient = client; } // Get configuration path if (selectedClient && selectedClient !== 'manual') { const clientInfo = detectedClients.find(c => c.key === selectedClient); configPath = clientInfo?.configPath || getConfigPath(selectedClient); } // Install and build console.log(chalk.blue('\n🔧 Setting up MCP server...')); await installDependencies(installPath); await buildProject(installPath); await testServer(installPath); // Configure client if selected if (selectedClient && selectedClient !== 'manual' && configPath) { console.log(chalk.blue(`\n⚙️ Configuring ${AI_CLIENTS[selectedClient].name}...`)); const config = generateMCPConfig(installPath, selectedClient); await writeConfig(configPath, config, selectedClient); console.log(chalk.green(`Success: Configuration written to: ${configPath}`)); } // Success message const successMessage = boxen( chalk.green.bold('🎉 Installation Complete!') + '\n\n' + chalk.white('Next steps:') + '\n' + (selectedClient && selectedClient !== 'manual' ? `• Restart ${AI_CLIENTS[selectedClient].name}\n` : '• Configure your AI client manually\n') + '• Test with: "How do I implement 5G converged charging?"\n\n' + chalk.cyan('Example queries:') + '\n' + chalk.gray('• "Guide me through TS 32.290 implementation"') + '\n' + chalk.gray('• "What is the difference between CHF and OCS?"') + '\n' + chalk.gray('• "Help me design a billing integration strategy"'), { padding: 1, margin: 1, borderStyle: 'round', borderColor: 'green' } ); console.log(successMessage); if (selectedClient === 'manual' || !selectedClient) { console.log(chalk.yellow('\n📋 Manual Configuration:')); console.log(chalk.gray('Add this to your AI client\'s MCP configuration:')); console.log(JSON.stringify(generateMCPConfig(installPath), null, 2)); } } catch (error) { console.error(chalk.red('Error: Installation failed:'), error.message); process.exit(1); } }); // Serve command - run the MCP server directly program .command('serve') .description('Run the 3GPP Charging MCP Server') .action(() => { // Try multiple possible locations for the server file const possiblePaths = [ path.join(__dirname, '..', 'dist', 'index.js'), path.join(__dirname, 'dist', 'index.js'), path.resolve(__dirname, '..', 'dist', 'index.js') ]; let serverPath = null; for (const possiblePath of possiblePaths) { if (fs.existsSync(possiblePath)) { serverPath = possiblePath; break; } } if (!serverPath) { console.error(chalk.red('Error: Server files not found. Possible paths checked:')); possiblePaths.forEach(p => console.error(chalk.gray(` ${p}`))); process.exit(1); } const { ThreeGPPMCPServer } = require(serverPath); const server = new ThreeGPPMCPServer(); server.run().catch(() => process.exit(1)); }); // Info command program .command('info') .description('Show system and client information') .action(() => { displayBanner(); console.log(chalk.blue('System Information:')); console.log(`• Platform: ${os.platform()}`); console.log(`• Node.js: ${process.version}`); console.log(`• Architecture: ${os.arch()}`); console.log(chalk.blue('\nDetected AI Clients:')); const detected = detectInstalledClients(); if (detected.length === 0) { console.log(chalk.gray('• No AI clients detected')); } else { detected.forEach(client => { const status = client.exists ? chalk.green('✓ configured') : chalk.gray('○ not configured'); console.log(`• ${client.name}: ${status}`); console.log(` ${chalk.gray(client.configPath)}`); }); } }); // Parse command line arguments program.parse(); // If no command specified, show help if (!process.argv.slice(2).length) { program.outputHelp(); }

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/edhijlu/3gpp-mcp-server'

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