Skip to main content
Glama

NSAF MCP Server

index.ts8.74 kB
#!/usr/bin/env node import { spawn } from 'child_process'; import { join } from 'path'; import * as fs from 'fs'; import * as readline from 'readline'; // Determine the path to the NSAF Python project // First check if it's specified via environment variable // Then check if it's in the same directory as the script // Then check if it's in the parent directory (for global installs) function findNsafProjectPath(): string { // Check environment variable first if (process.env.NSAF_PROJECT_PATH && fs.existsSync(join(process.env.NSAF_PROJECT_PATH, 'main.py'))) { return process.env.NSAF_PROJECT_PATH; } // Check current directory if (fs.existsSync(join('./', 'main.py'))) { return './'; } // Check directory where the script is located const scriptDir = __dirname; if (fs.existsSync(join(scriptDir, 'main.py'))) { return scriptDir; } // Check parent directory of script (for npm global installs) const parentDir = join(scriptDir, '..'); if (fs.existsSync(join(parentDir, 'main.py'))) { return parentDir; } // Check two levels up (for npm global installs with nested structure) const grandparentDir = join(scriptDir, '..', '..'); if (fs.existsSync(join(grandparentDir, 'main.py'))) { return grandparentDir; } // Default to current directory with a warning console.error('Warning: NSAF main.py not found. Using current directory.'); return './'; } const NSAF_PROJECT_PATH = findNsafProjectPath(); console.error(`Using NSAF project path: ${NSAF_PROJECT_PATH}`); /** * Execute a Python script from the NSAF project */ async function executePythonScript(scriptPath: string, args: string[] = []): Promise<string> { return new Promise((resolve, reject) => { const pythonProcess = spawn('python', [scriptPath, ...args], { cwd: NSAF_PROJECT_PATH, }); let stdout = ''; let stderr = ''; pythonProcess.stdout.on('data', (data) => { stdout += data.toString(); }); pythonProcess.stderr.on('data', (data) => { stderr += data.toString(); }); pythonProcess.on('close', (code) => { if (code !== 0) { reject(new Error(`Python script exited with code ${code}: ${stderr}`)); } else { resolve(stdout); } }); }); } /** * Simplified MCP Server for NSAF */ class SimplifiedMCPServer { private rl: readline.Interface; constructor() { this.rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false }); process.on('SIGINT', () => { this.rl.close(); process.exit(0); }); } async run() { console.error('NSAF MCP server running...'); this.rl.on('line', async (line) => { try { const request = JSON.parse(line); const response = await this.handleRequest(request); console.log(JSON.stringify(response)); } catch (error) { console.error('Error handling request:', error); console.log(JSON.stringify({ jsonrpc: '2.0', id: null, error: { code: -32603, message: error instanceof Error ? error.message : String(error) } })); } }); } private async handleRequest(request: any): Promise<any> { if (!request.method) { return { jsonrpc: '2.0', id: request.id, error: { code: -32601, message: 'Method not found' } }; } switch (request.method) { case 'list_tools': return this.handleListTools(request); case 'call_tool': return this.handleCallTool(request); default: return { jsonrpc: '2.0', id: request.id, error: { code: -32601, message: `Method not found: ${request.method}` } }; } } private async handleListTools(request: any): Promise<any> { return { jsonrpc: '2.0', id: request.id, result: { tools: [ { name: 'run_nsaf_evolution', description: 'Run NSAF evolution with specified parameters', inputSchema: { type: 'object', properties: { population_size: { type: 'number', description: 'Size of the agent population', default: 20, }, generations: { type: 'number', description: 'Number of generations to evolve', default: 10, }, mutation_rate: { type: 'number', description: 'Mutation rate (0.0-1.0)', default: 0.2, }, crossover_rate: { type: 'number', description: 'Crossover rate (0.0-1.0)', default: 0.7, }, architecture_complexity: { type: 'string', description: 'Complexity of the agent architecture', enum: ['simple', 'medium', 'complex'], default: 'medium', }, }, required: [], }, }, { name: 'compare_nsaf_agents', description: 'Compare different NSAF agent architectures', inputSchema: { type: 'object', properties: { architectures: { type: 'array', description: 'List of architectures to compare', items: { type: 'string', enum: ['simple', 'medium', 'complex'], }, default: ['simple', 'medium', 'complex'], }, }, required: [], }, }, ] } }; } private async handleCallTool(request: any): Promise<any> { const { name, arguments: args } = request.params; if (!name) { return { jsonrpc: '2.0', id: request.id, error: { code: -32602, message: 'Invalid params: missing tool name' } }; } try { let result; switch (name) { case 'run_nsaf_evolution': result = await this.handleRunNSAFEvolution(args || {}); break; case 'compare_nsaf_agents': result = await this.handleCompareNSAFAgents(args || {}); break; default: return { jsonrpc: '2.0', id: request.id, error: { code: -32601, message: `Tool not found: ${name}` } }; } return { jsonrpc: '2.0', id: request.id, result }; } catch (error) { return { jsonrpc: '2.0', id: request.id, error: { code: -32603, message: error instanceof Error ? error.message : String(error) } }; } } private async handleRunNSAFEvolution(args: any): Promise<any> { try { // Set environment variables for the NSAF script process.env.NSAF_POPULATION_SIZE = args?.population_size?.toString() || '20'; process.env.NSAF_GENERATIONS = args?.generations?.toString() || '10'; process.env.NSAF_MUTATION_RATE = args?.mutation_rate?.toString() || '0.2'; process.env.NSAF_CROSSOVER_RATE = args?.crossover_rate?.toString() || '0.7'; process.env.NSAF_ARCHITECTURE_COMPLEXITY = args?.architecture_complexity || 'medium'; // Execute the main.py script const result = await executePythonScript('main.py'); return { content: [ { type: 'text', text: result, }, ], }; } catch (error) { throw new Error(`Error running NSAF evolution: ${error instanceof Error ? error.message : String(error)}`); } } private async handleCompareNSAFAgents(args: any): Promise<any> { try { // Set environment variables for the NSAF script process.env.NSAF_ARCHITECTURES = JSON.stringify(args?.architectures || ['simple', 'medium', 'complex']); // Execute a custom script to compare agents const result = await executePythonScript('run_example.py'); return { content: [ { type: 'text', text: result, }, ], }; } catch (error) { throw new Error(`Error comparing NSAF agents: ${error instanceof Error ? error.message : String(error)}`); } } } const server = new SimplifiedMCPServer(); server.run().catch(console.error);

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/ariunbolor/nsaf-mcp-server'

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