Skip to main content
Glama
index.ts4.45 kB
/** * Configuration management for Cobalt Strike MCP Server */ import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs/promises'; import { CobaltStrikeConfig } from '../types/index.js'; const SERVICE_NAME = 'cobaltstrike-mcp'; const CONFIG_DIR = path.join(os.homedir(), '.cobaltstrike-mcp'); const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json'); // Lazy load keytar to handle cases where it fails to load let keytar: any = null; let keytarLoaded = false; async function loadKeytar(): Promise<any> { if (keytarLoaded) { return keytar; } try { // Use dynamic import for ES modules const keytarModule = await import('keytar'); keytar = keytarModule.default || keytarModule; keytarLoaded = true; return keytar; } catch (error) { // keytar failed to load (e.g., native module issue) // Will fall back to storing credentials in config file (less secure) keytarLoaded = true; // Mark as attempted to avoid repeated tries return null; } } export class ConfigManager { /** * Ensure config directory exists */ static async ensureConfigDir(): Promise<void> { try { await fs.mkdir(CONFIG_DIR, { recursive: true }); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); throw new Error(`Failed to create config directory: ${errorMsg}\n` + `Path: ${CONFIG_DIR}\n` + `Please check permissions and ensure the directory can be created.`); } } /** * Load configuration from file and keyring */ static async loadConfig(): Promise<CobaltStrikeConfig | null> { try { const configData = await fs.readFile(CONFIG_FILE, 'utf-8'); const config = JSON.parse(configData) as Partial<CobaltStrikeConfig>; if (!config.url) { return null; } let username = config.username || ''; let password = config.password || ''; // Try to load credentials from keyring if available const keytarInstance = await loadKeytar(); if (keytarInstance) { try { const keytarPassword = await keytarInstance.getPassword(SERVICE_NAME, 'password'); const keytarUsername = await keytarInstance.getPassword(SERVICE_NAME, 'username'); if (keytarPassword) password = keytarPassword; if (keytarUsername) username = keytarUsername; } catch (error) { // Keyring access failed, use config file values console.error('Warning: Failed to load credentials from keyring, using config file'); } } return { url: config.url, username: username, password: password, verifySSL: config.verifySSL !== false, }; } catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') { return null; } throw error; } } /** * Save configuration to file and keyring */ static async saveConfig(config: CobaltStrikeConfig): Promise<void> { await this.ensureConfigDir(); // Try to save credentials to keyring if available const keytarInstance = await loadKeytar(); let useKeytar = false; if (keytarInstance) { try { if (config.username) { await keytarInstance.setPassword(SERVICE_NAME, 'username', config.username); } if (config.password) { await keytarInstance.setPassword(SERVICE_NAME, 'password', config.password); } useKeytar = true; } catch (error) { console.error('Warning: Failed to save credentials to keyring, storing in config file'); // Fall through to save in config file } } // Save config to file // If keytar is not available, we store credentials in the file (less secure but functional) const configToSave: any = { url: config.url, verifySSL: config.verifySSL !== false, }; // Only store credentials in file if keytar is not available if (!useKeytar) { configToSave.username = config.username; configToSave.password = config.password; if (!keytarInstance) { console.warn('Warning: Credentials are stored in config file (keytar unavailable). This is less secure.'); } } await fs.writeFile(CONFIG_FILE, JSON.stringify(configToSave, null, 2), 'utf-8'); } /** * Get config directory path */ static getConfigDir(): string { return CONFIG_DIR; } }

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/MickeyDB/Cobalt-Strike-MCP'

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