nmp-mcp-server
Version:
NMP Plus MCP Server - 36 commands via HTTP API for Cursor
215 lines (180 loc) • 7.52 kB
JavaScript
const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
// Создаем директорию для логов, если её нет
try {
if (!fs.existsSync('./logs')) {
fs.mkdirSync('./logs', { recursive: true });
}
} catch (e) {
// Игнорируем ошибки создания директории
}
// Путь к Python серверу
const pythonServerPath = path.join(__dirname, 'nmp_mcp_server_complete.py');
// Ищем подходящую команду Python
let pythonPath = 'python3';
try {
const testPython3 = spawn('python3', ['--version']);
testPython3.on('error', () => {
pythonPath = 'python';
console.error('Python3 не найден, используем python');
});
} catch (e) {
pythonPath = 'python';
console.error('Python3 не найден, используем python');
}
console.error('🧠 Запуск NMP_Plus MCP Server...');
console.error(`Python: ${pythonPath}`);
console.error(`Server: ${pythonServerPath}`);
// Проверяем наличие файла Python сервера
if (!fs.existsSync(pythonServerPath)) {
console.error(`❌ ОШИБКА: Python сервер не найден: ${pythonServerPath}`);
// Создаем базовую версию Python сервера если его нет
const basicServerContent = `#!/usr/bin/env python3
"""
NMP_Plus MCP Server - базовая версия
"""
import asyncio
import json
import sys
import urllib.request
import urllib.parse
class NMPMCPServer:
def __init__(self):
self.server_host = "localhost"
self.server_port = "8001"
self.base_url = f"http://{self.server_host}:{self.server_port}"
def make_request(self, endpoint, data=None):
try:
url = f"{self.base_url}/{endpoint}"
# Debug логи убраны для MCP
if data:
json_data = json.dumps(data).encode('utf-8')
req = urllib.request.Request(
url,
data=json_data,
headers={'Content-Type': 'application/json'}
)
else:
req = urllib.request.Request(url)
with urllib.request.urlopen(req, timeout=10) as response:
return json.loads(response.read().decode('utf-8'))
except Exception as e:
# Debug логи убраны для MCP
return {"error": f"Server connection failed: {str(e)}"}
async def handle_request(self, request):
method = request.get('method')
params = request.get('params', {})
if method == 'initialize':
return {
"protocolVersion": "2024-11-05",
"capabilities": { "tools": {} },
"serverInfo": {
"name": "nmp-plus-mcp",
"version": "1.0.0"
}
}
elif method == 'tools/list':
return {
"tools": [
{ "name": "mcp_nmp_memory_save", "description": "🧠 Сохранить информацию в память NMP" },
{ "name": "mcp_nmp_memory_search", "description": "🔍 Поиск в памяти NMP" },
{ "name": "mcp_nmp_memory_stats", "description": "📊 Статистика системы NMP" }
]
}
elif method == 'tools/call':
name = params.get('name', '')
args = params.get('arguments', {})
# Преобразуем имя инструмента в эндпоинт API
clean_name = name.replace("mcp_nmp_", "")
parts = clean_name.split('_')
endpoint = f"api/{'/'.join(parts)}"
result = self.make_request(endpoint, args)
return {
"content": [{
"type": "text",
"text": json.dumps(result, ensure_ascii=False, indent=2)
}]
}
return {"error": f"Unknown method: {method}"}
async def run(self):
# Убрано логирование для чистого MCP вывода
while True:
try:
line = await asyncio.get_event_loop().run_in_executor(None, sys.stdin.readline)
if not line:
break
request = json.loads(line)
response = await self.handle_request(request)
print(json.dumps({
"jsonrpc": "2.0",
"id": request.get('id'),
"result": response
}))
sys.stdout.flush()
except Exception as e:
print(json.dumps({
"jsonrpc": "2.0",
"id": None,
"error": {"code": -1, "message": str(e)}
}))
sys.stdout.flush()
async def main():
server = NMPMCPServer()
await server.run()
if __name__ == "__main__":
asyncio.run(main())
`;
try {
fs.writeFileSync(pythonServerPath, basicServerContent);
console.error(`✅ Создан базовый Python сервер: ${pythonServerPath}`);
} catch (e) {
console.error(`❌ Не удалось создать Python сервер: ${e.message}`);
process.exit(1);
}
}
// Запускаем Python сервер
const pythonProcess = spawn(pythonPath, [pythonServerPath], {
stdio: ['pipe', 'pipe', 'pipe'],
env: {
...process.env,
PYTHONIOENCODING: 'utf-8'
}
});
// Настраиваем логи
const logStream = fs.createWriteStream('./logs/mcp_server.log', { flags: 'a' });
const timestamp = () => new Date().toISOString();
// Перенаправляем stdout и stderr Python процесса на stdin и stderr текущего процесса
pythonProcess.stdout.pipe(process.stdout);
pythonProcess.stderr.on('data', (data) => {
const message = data.toString();
process.stderr.write(message);
logStream.write(`[${timestamp()}] ${message}`);
});
// Перенаправляем stdin текущего процесса на stdin Python процесса
process.stdin.pipe(pythonProcess.stdin);
// Обработка сигналов
process.on('SIGINT', () => {
console.error('\n🛑 Остановка NMP сервера...');
logStream.write(`[${timestamp()}] Остановка сервера по SIGINT\n`);
pythonProcess.kill('SIGINT');
process.exit(0);
});
process.on('SIGTERM', () => {
logStream.write(`[${timestamp()}] Остановка сервера по SIGTERM\n`);
pythonProcess.kill('SIGTERM');
process.exit(0);
});
pythonProcess.on('close', (code) => {
console.error(`🧠 NMP сервер завершен с кодом ${code}`);
logStream.write(`[${timestamp()}] Сервер завершен с кодом ${code}\n`);
logStream.end();
process.exit(code);
});
pythonProcess.on('error', (err) => {
console.error('❌ Ошибка запуска NMP сервера:', err);
logStream.write(`[${timestamp()}] Ошибка запуска: ${err.message}\n`);
logStream.end();
process.exit(1);
});