UNPKG

signoz-mcp-server

Version:

Model Context Protocol server for SigNoz observability platform

256 lines • 9.67 kB
#!/usr/bin/env node "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = require("commander"); const chalk_1 = __importDefault(require("chalk")); const ora_1 = __importDefault(require("ora")); const inquirer_1 = __importDefault(require("inquirer")); const fs_1 = require("fs"); const path_1 = require("path"); const os_1 = require("os"); const program = new commander_1.Command(); const CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), '.signoz-mcp'); const CONFIG_FILE = (0, path_1.join)(CONFIG_DIR, 'config.json'); function ensureConfigDir() { if (!(0, fs_1.existsSync)(CONFIG_DIR)) { (0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true }); } } function saveConfig(config) { ensureConfigDir(); (0, fs_1.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2)); } function loadConfig() { try { if ((0, fs_1.existsSync)(CONFIG_FILE)) { return JSON.parse(require('fs').readFileSync(CONFIG_FILE, 'utf8')); } } catch (error) { console.error(chalk_1.default.red('Error loading config:'), error); } return null; } async function validateSigNozConnection(url, token) { const spinner = (0, ora_1.default)('Validating SigNoz connection...').start(); try { const axios = require('axios'); const apiUrl = url.endsWith('/') ? url.slice(0, -1) : url; const response = await axios.get(`${apiUrl}/api/v1/version`, { headers: { 'SIGNOZ-API-KEY': token, 'Content-Type': 'application/json' }, timeout: 10000 }); if (response.status === 200) { spinner.succeed(chalk_1.default.green('āœ… Connection validated successfully!')); console.log(chalk_1.default.blue(`šŸ“Š SigNoz Version: ${response.data.version || 'Unknown'}`)); console.log(chalk_1.default.blue(`šŸ¢ Enterprise: ${response.data.ee ? 'Yes' : 'No'}`)); return true; } } catch (error) { spinner.fail(chalk_1.default.red('āŒ Connection validation failed')); if (error.response) { console.error(chalk_1.default.red(`HTTP ${error.response.status}: ${error.response.statusText}`)); if (error.response.status === 401) { console.error(chalk_1.default.yellow('šŸ’” Check your API token - it might be invalid or expired')); } else if (error.response.status === 404) { console.error(chalk_1.default.yellow('šŸ’” Check your URL - the SigNoz API endpoint might be wrong')); } } else if (error.code === 'ECONNREFUSED') { console.error(chalk_1.default.yellow('šŸ’” Connection refused - check if SigNoz is running and accessible')); } else { console.error(chalk_1.default.red(`Error: ${error.message}`)); } return false; } return false; } function generateMcpConfig(config) { return { mcpServers: { signoz: { command: "npx", args: ["signoz-mcp-server"], env: { SIGNOZ_URL: config.url, SIGNOZ_TOKEN: config.token } } } }; } program .name('signoz-mcp') .description('CLI tool to configure SigNoz MCP Server') .version('1.0.0'); program .command('configure') .description('Configure SigNoz MCP Server connection') .option('-u, --url <url>', 'SigNoz instance URL') .option('-t, --token <token>', 'SigNoz API token') .option('-n, --name <name>', 'Configuration name (optional)') .option('--no-validate', 'Skip connection validation') .action(async (options) => { console.log(chalk_1.default.blue.bold('šŸš€ SigNoz MCP Server Configuration\n')); let { url, token, name } = options; const validate = options.validate !== false; // Interactive prompts if parameters not provided if (!url || !token) { const answers = await inquirer_1.default.prompt([ { type: 'input', name: 'url', message: 'Enter your SigNoz instance URL:', default: url || 'http://localhost:3301', validate: (input) => { try { new URL(input); return true; } catch { return 'Please enter a valid URL (e.g., http://localhost:3301 or https://your-signoz.com)'; } } }, { type: 'password', name: 'token', message: 'Enter your SigNoz API token:', default: token, validate: (input) => input.length > 0 || 'API token is required' }, { type: 'input', name: 'name', message: 'Configuration name (optional):', default: name || 'default' } ]); url = answers.url; token = answers.token; name = answers.name; } // Normalize URL url = url.replace(/\/+$/, ''); // Remove trailing slashes const config = { url, token, name: name || 'default', description: `SigNoz instance at ${url}` }; // Validate connection if requested if (validate) { const isValid = await validateSigNozConnection(url, token); if (!isValid) { console.log(chalk_1.default.yellow('\nāš ļø Connection validation failed. You can still save the configuration.')); const { proceed } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'proceed', message: 'Do you want to save the configuration anyway?', default: false } ]); if (!proceed) { console.log(chalk_1.default.red('Configuration cancelled.')); process.exit(1); } } } // Save configuration try { saveConfig(config); console.log(chalk_1.default.green('āœ… Configuration saved successfully!')); console.log(chalk_1.default.blue(`šŸ“ Config location: ${CONFIG_FILE}`)); // Generate Claude Desktop config const mcpConfig = generateMcpConfig(config); console.log(chalk_1.default.yellow('\nšŸ“‹ Add this to your Claude Desktop config:')); console.log(chalk_1.default.gray(JSON.stringify(mcpConfig, null, 2))); console.log(chalk_1.default.green('\nšŸŽ‰ Setup complete! You can now use the SigNoz MCP server in Claude.')); } catch (error) { console.error(chalk_1.default.red('āŒ Failed to save configuration:'), error); process.exit(1); } }); program .command('test') .description('Test SigNoz connection with saved configuration') .action(async () => { const config = loadConfig(); if (!config) { console.error(chalk_1.default.red('āŒ No configuration found. Run "signoz-mcp configure" first.')); process.exit(1); } console.log(chalk_1.default.blue(`šŸ” Testing connection to: ${config.url}`)); const isValid = await validateSigNozConnection(config.url, config.token); if (isValid) { console.log(chalk_1.default.green('\nāœ… Connection test successful!')); } else { console.log(chalk_1.default.red('\nāŒ Connection test failed.')); process.exit(1); } }); program .command('show-config') .description('Display current configuration') .action(() => { const config = loadConfig(); if (!config) { console.error(chalk_1.default.red('āŒ No configuration found. Run "signoz-mcp configure" first.')); process.exit(1); } console.log(chalk_1.default.blue.bold('šŸ“‹ Current SigNoz MCP Configuration:\n')); console.log(chalk_1.default.gray('Name:'), config.name); console.log(chalk_1.default.gray('URL:'), config.url); console.log(chalk_1.default.gray('Token:'), config.token.replace(/./g, '*').slice(0, -4) + config.token.slice(-4)); console.log(chalk_1.default.gray('Description:'), config.description); console.log(chalk_1.default.gray('Config file:'), CONFIG_FILE); }); program .command('reset') .description('Reset configuration') .action(async () => { const { confirm } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'confirm', message: 'Are you sure you want to reset the configuration?', default: false } ]); if (confirm) { try { if ((0, fs_1.existsSync)(CONFIG_FILE)) { require('fs').unlinkSync(CONFIG_FILE); console.log(chalk_1.default.green('āœ… Configuration reset successfully!')); } else { console.log(chalk_1.default.yellow('āš ļø No configuration found to reset.')); } } catch (error) { console.error(chalk_1.default.red('āŒ Failed to reset configuration:'), error); process.exit(1); } } }); // Handle the case when used as MCP server if (process.argv.length === 2) { // No arguments provided, start as MCP server require('./index'); } else { program.parse(); } //# sourceMappingURL=cli.js.map