Skip to main content
Glama
index.ts13.9 kB
#!/usr/bin/env node /** * Cobalt Strike MCP Server * Model Context Protocol server for managing Cobalt Strike operations */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, Tool, } from '@modelcontextprotocol/sdk/types.js'; import { CobaltStrikeClient } from './api/client.js'; import { ConfigManager } from './config/index.js'; import { createBeaconTools, handleBeaconTool } from './tools/beacon.js'; import { createListenerTools, handleListenerTool } from './tools/listener.js'; import { createServerTools, handleServerTool } from './tools/server.js'; import { createCredentialsTools, handleCredentialsTool } from './tools/credentials.js'; import { createTaskTools, handleTaskTool } from './tools/tasks.js'; import { createFileTools, handleFileTool } from './tools/files.js'; import { createSpawnTools, handleSpawnTool } from './tools/spawn.js'; import { createBOFTools, handleBOFTool } from './tools/bof.js'; import { createPayloadTools, handlePayloadTool } from './tools/payloads.js'; import { createDataTools, handleDataTool } from './tools/data.js'; import { createStateTools, handleStateTool } from './tools/state.js'; import { createInjectTools, handleInjectTool } from './tools/inject.js'; import { createTokenTools, handleTokenTool } from './tools/tokens.js'; import { createExecuteTools, handleExecuteTool } from './tools/execute.js'; import { createPivotingTools, handlePivotingTool } from './tools/pivoting.js'; import { createConfigTools, handleConfigTool } from './tools/config.js'; import { createElevateTools, handleElevateTool } from './tools/elevate.js'; import { createRemoteExecTools, handleRemoteExecTool } from './tools/remoteexec.js'; import { createListenerSpecificTools, handleListenerSpecificTool } from './tools/listeners-specific.js'; import { createUtilityTools, handleUtilityTool } from './tools/utilities.js'; import * as readline from 'readline'; let client: CobaltStrikeClient | null = null; /** * Initialize the Cobalt Strike client */ async function initializeClient(): Promise<void> { const config = await ConfigManager.loadConfig(); if (!config) { throw new Error( 'Configuration not found. Please set up the configuration first.\n' + 'Run: cobaltstrike-mcp --setup' ); } client = new CobaltStrikeClient(config); // Test connection (non-fatal - server will start even if connection fails) // Tools will handle connection errors when they're called try { const connected = await client.testConnection(); if (!connected) { console.error('Warning: Failed to connect to Cobalt Strike REST API. Server will start but tools may fail.'); console.error('Please check your configuration or ensure the teamserver is running.'); } } catch (error) { console.error('Warning: Could not test connection to Cobalt Strike REST API:', (error as Error).message); console.error('Server will start but tools may fail until connection is established.'); } } /** * Setup configuration interactively */ async function setupConfig(): Promise<void> { const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const question = (prompt: string): Promise<string> => { return new Promise((resolve) => { rl.question(prompt, resolve); }); }; // Cross-platform password input // Note: On Windows, password will be visible. On Unix-like systems, it will be hidden. const questionPassword = async (prompt: string): Promise<string> => { // Simple approach: use readline but warn on Windows // For better security, consider using a library like 'readline-sync' or 'inquirer' if (process.platform === 'win32') { console.log('⚠️ Warning: Password will be visible as you type on Windows.'); console.log(' Consider running this in a private terminal or use environment variables.\n'); } return new Promise((resolve) => { rl.question(prompt, (answer) => { resolve(answer); }); }); }; try { console.log('Cobalt Strike MCP Server Setup\n'); console.log('Enter your Cobalt Strike REST API configuration:\n'); const url = await question('Teamserver URL (e.g., https://teamserver.example.com:50050): '); const username = await question('Username: '); // Note: On Windows, password will be visible as you type if (process.platform === 'win32') { console.log('Note: On Windows, password input will be visible. Press Enter when done.'); } const password = await questionPassword('Password: '); const verifySSLStr = await question('Verify SSL certificates? (yes/no, default: yes): '); const verifySSL = verifySSLStr.toLowerCase() !== 'no'; await ConfigManager.saveConfig({ url: url.trim(), username: username.trim(), password: password.trim(), verifySSL, }); console.log('\nConfiguration saved successfully!'); } finally { rl.close(); } } /** * Main server implementation */ async function main() { // Handle command line arguments const args = process.argv.slice(2); if (args.includes('--setup') || args.includes('--setup-keyring')) { await setupConfig(); process.exit(0); } // Initialize client try { await initializeClient(); } catch (error) { // Only exit if configuration is missing - connection failures are non-fatal const errorMessage = (error as Error).message; if (errorMessage.includes('Configuration not found')) { console.error(`Error: ${errorMessage}`); process.exit(1); } else { // For other errors, log but continue - server can start without connection console.error(`Warning: ${errorMessage}`); console.error('Server will start but tools may fail until connection is established.'); } } if (!client) { console.error('Error: Client not initialized. Configuration may be missing.'); console.error('Run: cobaltstrike-mcp --setup'); process.exit(1); } // Create MCP server const server = new Server( { name: 'cobaltstrike-mcp', version: '0.1.0', }, { capabilities: { tools: {}, }, } ); // Register tool handlers server.setRequestHandler(ListToolsRequestSchema, async () => { const tools: Tool[] = [ ...createServerTools(client!), ...createBeaconTools(client!), ...createListenerTools(client!), ...createCredentialsTools(client!), ...createTaskTools(client!), ...createFileTools(client!), ...createSpawnTools(client!), ...createBOFTools(client!), ...createPayloadTools(client!), ...createDataTools(client!), ...createStateTools(client!), ...createInjectTools(client!), ...createTokenTools(client!), ...createExecuteTools(client!), ...createPivotingTools(client!), ...createConfigTools(client!), ...createElevateTools(client!), ...createRemoteExecTools(client!), ...createListenerSpecificTools(client!), ...createUtilityTools(client!), ]; return { tools }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { let result: string; // Route to appropriate tool handler // Check specific tools first before general patterns if (name.startsWith('get_teamserver_info') || name.startsWith('test_connection')) { result = await handleServerTool(name, args, client!); } else if (name.startsWith('get_beacon_jobs') || name.startsWith('get_beacon_c2_host_profiles') || name.startsWith('get_beacon_tokenStore')) { result = await handleStateTool(name, args, client!); } else if (name.startsWith('get_beacon_tasks_summary') || name.startsWith('get_beacon_tasks_detail')) { result = await handleTaskTool(name, args, client!); } else if (name.startsWith('list_beacons') || name.startsWith('get_beacon') || name.startsWith('execute_beacon') || name.startsWith('kill_beacon') || name.startsWith('note_beacon')) { result = await handleBeaconTool(name, args, client!); } else if (name.startsWith('list_listeners') || name.startsWith('create_listener') || name.startsWith('delete_listener')) { result = await handleListenerTool(name, args, client!); } else if (name.startsWith('list_credentials') || name.startsWith('get_credential') || name.startsWith('create_credential') || name.startsWith('delete_credential')) { result = await handleCredentialsTool(name, args, client!); } else if (name.startsWith('list_tasks') || name.startsWith('get_task')) { result = await handleTaskTool(name, args, client!); } else if (name.startsWith('beacon_')) { result = await handleFileTool(name, args, client!); } else if (name.startsWith('execute_bof')) { result = await handleBOFTool(name, args, client!); } else if (name.startsWith('spawn_')) { result = await handleSpawnTool(name, args, client!); } else if (name.startsWith('get_listener') && !name.includes('_http') && !name.includes('_https') && !name.includes('_dns') && !name.includes('_smb') && !name.includes('_tcp') && !name.includes('_externalC2') && !name.includes('_foreign') && !name.includes('_userDefined')) { result = await handleListenerSpecificTool(name, args, client!); } else if (name.startsWith('generate_') || name.startsWith('download_payload')) { result = await handlePayloadTool(name, args, client!); } else if (name.startsWith('list_') && (name.includes('screenshot') || name.includes('keystroke') || name.includes('download'))) { result = await handleDataTool(name, args, client!); } else if (name.startsWith('get_') && (name.includes('screenshot') || name.includes('keystroke') || name.includes('download'))) { result = await handleDataTool(name, args, client!); } else if (name.startsWith('set_beacon_')) { result = await handleStateTool(name, args, client!); } else if (name.startsWith('inject_')) { result = await handleInjectTool(name, args, client!); } else if (name.startsWith('execute_steal_token') || name.startsWith('execute_make_token') || name.startsWith('execute_rev2self') || name.startsWith('execute_get_system') || name.startsWith('execute_get_privs') || name.startsWith('execute_tokenStore') || name.startsWith('execute_make_token_upn')) { result = await handleTokenTool(name, args, client!); } else if (name.startsWith('execute_kill_process') || name.startsWith('execute_clipboard') || name.startsWith('execute_setenv') || name.startsWith('execute_timestomp') || name.startsWith('execute_checkin') || name.startsWith('execute_exit') || name.startsWith('execute_reg_') || name.startsWith('execute_beacon_info') || name.startsWith('execute_get_uid') || name.startsWith('execute_job_stop') || name.startsWith('execute_kerberos_') || name.startsWith('execute_powershell_import') || name.startsWith('execute_net_domain') || name.startsWith('execute_browserpivot_stop') || name.startsWith('execute_cancel_file_download') || name.startsWith('execute_socks_stop')) { result = await handleExecuteTool(name, args, client!); } else if (name.startsWith('execute_socks') || name.startsWith('execute_link') || name.startsWith('execute_unlink') || name.startsWith('execute_rportfwd')) { result = await handlePivotingTool(name, args, client!); } else if (name.startsWith('get_system_information') || name.startsWith('get_profile') || name.startsWith('update_profile') || name.startsWith('get_killdate') || name.startsWith('set_killdate') || name.startsWith('get_teamserver_ip') || name.startsWith('set_teamserver_ip') || name.startsWith('reset_data')) { result = await handleConfigTool(name, args, client!); } else if (name.startsWith('elevate_')) { result = await handleElevateTool(name, args, client!); } else if (name.startsWith('remoteExec_')) { result = await handleRemoteExecTool(name, args, client!); } else if (name.startsWith('create_listener_') || name.startsWith('get_listener_') || name.startsWith('update_listener_') || name.startsWith('delete_listener_')) { result = await handleListenerSpecificTool(name, args, client!); } else if (name.startsWith('get_artifacts') || name.startsWith('get_beacon_active_downloads') || name.startsWith('clear_beacon_command_queue') || name.startsWith('get_beacon_help') || name.startsWith('get_beacon_command_help') || name.startsWith('get_beacon_keystrokes')) { result = await handleUtilityTool(name, args, client!); } else { throw new Error(`Unknown tool: ${name}`); } return { content: [ { type: 'text', text: result, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error: ${(error as Error).message}`, }, ], isError: true, }; } }); // Connect stdio transport const transport = new StdioServerTransport(); await server.connect(transport); console.error('Cobalt Strike MCP server running on stdio'); } // Run the server main().catch((error) => { console.error('Fatal error:', error); process.exit(1); });

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