diff --git a/mcp_center/run.sh b/mcp_center/run.sh index ddf5936e00d311bd9de48ae86561da11ab975416..dabae182d59a802237a7f38f999230b035ae68ce 100755 --- a/mcp_center/run.sh +++ b/mcp_center/run.sh @@ -3,6 +3,7 @@ SERVICE_DIR="/usr/lib/euler-copilot-framework/mcp_center/service" /usr/lib/euler-copilot-framework/mcp_center/servers/oe_cli_mcp_server/run.sh +/usr/lib/euler-copilot-framework/mcp_center/servers/rag/run.sh for service_file in "$SERVICE_DIR"/*.service; do if [ -f "$service_file" ]; then diff --git a/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/base.py b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/base.py new file mode 100644 index 0000000000000000000000000000000000000000..1d27e96330539fc650997a6155afd556b56c18f3 --- /dev/null +++ b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/base.py @@ -0,0 +1,208 @@ +import logging +import subprocess +from typing import Dict, Optional, List + +import paramiko + +from config.base_config_loader import BaseConfig, LanguageEnum + + +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + + +def get_language() -> bool: + """获取语言配置:True=中文,False=英文""" + return BaseConfig().get_config().public_config.language == LanguageEnum.ZH + + +def get_remote_auth(ip: str) -> Optional[Dict]: + """ + 获取服务器认证信息:匹配IP/主机名对应的连接配置 + """ + for host_config in BaseConfig().get_config().public_config.remote_hosts: + if ip in [host_config.host, host_config.name]: + return { + "host": host_config.host, + "port": host_config.port, + "username": host_config.username, + "password": host_config.password, + } + return None + + +def init_result(target_host: str) -> Dict: + """初始化统一结果结构""" + return { + "success": False, + "message": "", + "result": [], + "target": target_host, + } + + +def _open_ssh(remote_auth: Dict) -> paramiko.SSHClient: + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect( + hostname=remote_auth["host"], + port=remote_auth["port"], + username=remote_auth["username"], + password=remote_auth["password"], + timeout=10, + banner_timeout=10, + ) + return ssh + + +def _build_fix_command() -> str: + """ + 构造修复 ifcfg-ens3 中 BOOTPROTO 并重启 NetworkManager 的命令 + 仅做问题描述中的三件事: + 1. 校验文件存在 + 2. 设置 BOOTPROTO=dhcp + 3. systemctl restart NetworkManager + """ + ifcfg_path = "/etc/sysconfig/network-scripts/ifcfg-ens3" + parts: List[str] = [] + # 确认配置文件存在 + parts.append( + f"IFCFG='{ifcfg_path}'; " + "if [ ! -f \"$IFCFG\" ]; then " + "echo 'ifcfg-ens3 not found'; " + "exit 1; " + "fi" + ) + # 规范化 BOOTPROTO 行:若存在则直接替换为 dhcp + parts.append( + "sed -i -e 's/^[#]*[[:space:]]*BOOTPROTO=.*/BOOTPROTO=dhcp/' \"$IFCFG\"" + ) + # 若不存在 BOOTPROTO 行,则追加一行 + parts.append( + "grep -q '^[[:space:]]*BOOTPROTO=' \"$IFCFG\" || echo 'BOOTPROTO=dhcp' >> \"$IFCFG\"" + ) + # 重启 NetworkManager 服务 + parts.append("systemctl restart NetworkManager") + return " && ".join(parts) + + +def fix_network_bootproto_issue(target: Optional[str] = None) -> Dict: + """ + 修复 NetworkManager 未自动获取 IP 的问题: + - 编辑 /etc/sysconfig/network-scripts/ifcfg-ens3,将 BOOTPROTO 修正为 dhcp + - 重启 NetworkManager 服务 + """ + target_host = target.strip() if (target and isinstance(target, str)) else "127.0.0.1" + is_zh = get_language() + result = init_result(target_host) + steps: List[str] = [] + + fix_cmd = _build_fix_command() + + # 本地修复逻辑 + if target_host == "127.0.0.1": + try: + steps.append( + "开始修复本机 ifcfg-ens3 配置并重启 NetworkManager" + if is_zh + else "Start fixing local ifcfg-ens3 and restart NetworkManager" + ) + completed = subprocess.run( + fix_cmd, + shell=True, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + stdout = completed.stdout.strip() + stderr = completed.stderr.strip() + if stdout: + steps.extend(stdout.splitlines()) + if stderr: + steps.extend(stderr.splitlines()) + + result["success"] = True + result["message"] = ( + "网络配置已修复:BOOTPROTO=dhcp,NetworkManager 已重启" + if is_zh + else "Network configuration fixed: BOOTPROTO=dhcp and NetworkManager restarted" + ) + except subprocess.CalledProcessError as e: + err = e.stderr.strip() if e.stderr else str(e) + result["message"] = ( + f"修复网络配置失败:{err}" + if is_zh + else f"Failed to fix network configuration: {err}" + ) + steps.append(result["message"]) + + result["result"] = steps + return result + + # 远程修复逻辑(与本地相同操作,通过 SSH 执行) + remote_auth = get_remote_auth(target_host) + if not remote_auth or not (remote_auth["username"] and remote_auth["password"]): + result["message"] = ( + f"未找到远程主机({target_host})的认证配置" + if is_zh + else f"Authentication config for remote host ({target_host}) not found" + ) + result["result"] = [result["message"]] + return result + + ssh: Optional[paramiko.SSHClient] = None + try: + ssh = _open_ssh(remote_auth) + steps.append( + f"开始修复远程主机({target_host})的 ifcfg-ens3 配置并重启 NetworkManager" + if is_zh + else f"Start fixing remote host ({target_host}) ifcfg-ens3 and restart NetworkManager" + ) + stdin, stdout, stderr = ssh.exec_command(fix_cmd) + out = stdout.read().decode("utf-8", errors="replace").strip() + err = stderr.read().decode("utf-8", errors="replace").strip() + + if out: + steps.extend(out.splitlines()) + if err: + steps.extend(err.splitlines()) + + exit_status = stdout.channel.recv_exit_status() + if exit_status == 0: + result["success"] = True + result["message"] = ( + f"远程主机({target_host})网络配置已修复:BOOTPROTO=dhcp,NetworkManager 已重启" + if is_zh + else f"Remote host ({target_host}) network configuration fixed: BOOTPROTO=dhcp and NetworkManager restarted" + ) + else: + result["message"] = ( + f"远程修复网络配置失败:{err}" + if is_zh + else f"Failed to fix remote network configuration: {err}" + ) + steps.append(result["message"]) + except paramiko.AuthenticationException: + result["message"] = ( + "SSH 认证失败,请检查用户名和密码" + if is_zh + else "SSH authentication failed, check username and password" + ) + steps.append(result["message"]) + except Exception as e: + result["message"] = ( + f"远程修复网络配置异常:{str(e)}" + if is_zh + else f"Remote network fix exception: {str(e)}" + ) + steps.append(result["message"]) + finally: + if ssh: + ssh.close() + + result["result"] = steps + return result + + + diff --git a/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/config.json b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/config.json new file mode 100644 index 0000000000000000000000000000000000000000..55100bcdecb59b1d6dc4e035f99731e4986a2f0e --- /dev/null +++ b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/config.json @@ -0,0 +1,10 @@ +{ + "tools": { + "network_fix_bootproto_tool": { + "zh": "网络自动修复工具:解决NetworkManager启动后未自动获取IP的问题。\n\n该工具会自动执行以下步骤:\n1. 编辑网卡配置文件 /etc/sysconfig/network-scripts/ifcfg-ens3\n2. 检查并修正 BOOTPROTO 字段,确保其值为 \"dhcp\"(全小写,无拼写错误)\n3. 保存修改并重启 NetworkManager 服务(systemctl restart NetworkManager)\n\n参数:\n - target: 目标主机IP或主机名,None或\"127.0.0.1\"表示本机\n - lang: 语言设置(可选,当前根据全局配置自动切换中英文)\n\n返回:\n - success: 是否修复成功(True/False)\n - message: 执行结果说明(整体修复结果)\n - target: 目标主机\n - result: 执行过程中的详细步骤信息列表\n\n使用场景:\n - openEuler 24.03 系统中 NetworkManager 正常运行但 ens3 未自动获取IP\n - ifcfg-ens3 中 BOOTPROTO 拼写错误导致 DHCP 未生效\n - 需要一键修复网卡DHCP配置并恢复自动获取IP功能", + "en": "Network auto-fix tool: resolve the issue where NetworkManager does not automatically obtain an IP address.\n\nThe tool performs the following steps:\n1. Edit NIC config file /etc/sysconfig/network-scripts/ifcfg-ens3\n2. Check and correct the BOOTPROTO field to \"dhcp\" (all lowercase, no typos)\n3. Save the change and restart NetworkManager (systemctl restart NetworkManager)\n\nParameters:\n - target: Target host IP or hostname, None or \"127.0.0.1\" for localhost\n - lang: Language setting (optional, currently determined by global configuration)\n\nReturns:\n - success: Whether the fix succeeded (True/False)\n - message: Overall result description\n - target: Target host\n - result: List of detailed step messages during execution\n\nUse cases:\n - On openEuler 24.03, NetworkManager is running but ens3 does not get an IP via DHCP\n - BOOTPROTO in ifcfg-ens3 is misspelled, causing DHCP not to be triggered\n - Need a one-click fix for NIC DHCP configuration and restore automatic IP acquisition" + } + } +} + + diff --git a/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/deps.toml b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/deps.toml new file mode 100644 index 0000000000000000000000000000000000000000..e1caabcf2cdaf7e330607949a8d73d656040c6fa --- /dev/null +++ b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/deps.toml @@ -0,0 +1,17 @@ +[system] +# NetworkManager / 网卡配置相关的系统工具(通常系统已自带,此处仅用于需要时安装) +#network_tools = [ +# "yum install -y NetworkManager", +# "apt-get update && apt-get install -y network-manager" +#] + +[pip] +# Python 依赖(与其他 mcptool 保持一致的基础依赖) +paramiko = "==4.0.0" +typing_extensions = "==4.12.2" +psutil = "==7.0.0" +toml = "==0.10.2" +mcp = "==1.9.4" +scp = "==0.15.0" + + diff --git a/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/tool.py b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/tool.py new file mode 100644 index 0000000000000000000000000000000000000000..d53162bb36e5e55d8bbbf1d5eac903bb97170b2d --- /dev/null +++ b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/network_tools/tool.py @@ -0,0 +1,24 @@ +from typing import Dict, Optional + +from config.base_config_loader import LanguageEnum + +from mcp_tools.base_tools.network_tools.base import fix_network_bootproto_issue + + +def network_fix_bootproto_tool( + target: Optional[str] = None, + lang: Optional[LanguageEnum] = LanguageEnum.ZH, +) -> Dict: + """ + 网络自动修复工具:解决 NetworkManager 启动后未自动获取 IP 的问题。 + + 按照问题描述自动执行以下操作: + 1. 编辑 /etc/sysconfig/network-scripts/ifcfg-ens3 + 2. 检查并修正 BOOTPROTO,确保为 \"dhcp\"(全小写) + 3. 重启 NetworkManager 服务:systemctl restart NetworkManager + """ + # 目前语言仍由全局配置控制,此处保留 lang 以保持接口风格统一 + return fix_network_bootproto_issue(target=target) + + + diff --git a/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/base.py b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/base.py new file mode 100644 index 0000000000000000000000000000000000000000..83a6bce5fe736b4999949672df034a7d541f4b92 --- /dev/null +++ b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/base.py @@ -0,0 +1,358 @@ +import logging +import socket +import subprocess +from typing import Dict, Optional, List + +import paramiko + +from config.base_config_loader import BaseConfig, LanguageEnum + + +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + + +def get_language() -> bool: + """获取语言配置:True=中文,False=英文""" + return BaseConfig().get_config().public_config.language == LanguageEnum.ZH + + +def get_remote_auth(ip: str) -> Optional[Dict]: + """ + 获取服务器认证信息:匹配IP/主机名对应的连接配置 + """ + for host_config in BaseConfig().get_config().public_config.remote_hosts: + if ip in [host_config.host, host_config.name]: + return { + "host": host_config.host, + "port": host_config.port, + "username": host_config.username, + "password": host_config.password, + } + return None + + +def init_result(target_host: str) -> Dict: + """初始化统一结果结构""" + return { + "success": False, + "message": "", + "result": [], + "target": target_host, + } + + +def ssh_port_ping(target: str, port: int = 22, timeout: int = 5) -> Dict: + """通过 TCP 连接检测 SSH 端口连通性""" + result = init_result(target) + is_zh = get_language() + try: + with socket.create_connection((target, port), timeout=timeout): + result["success"] = True + result["message"] = ( + f"SSH 端口 {port} 可达" if is_zh else f"SSH port {port} is reachable" + ) + except Exception as e: + result["message"] = ( + f"SSH 端口 {port} 不可达:{str(e)}" + if is_zh + else f"SSH port {port} is unreachable: {str(e)}" + ) + result["result"] = [result["message"]] + return result + + +def _run_local(cmd: List[str]) -> subprocess.CompletedProcess: + return subprocess.run( + cmd, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + + +def _open_ssh(remote_auth: Dict) -> paramiko.SSHClient: + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect( + hostname=remote_auth["host"], + port=remote_auth["port"], + username=remote_auth["username"], + password=remote_auth["password"], + timeout=10, + banner_timeout=10, + ) + return ssh + + +def check_sshd_status(target: Optional[str]) -> Dict: + """执行 systemctl status sshd""" + target_host = target.strip() if target else "127.0.0.1" + result = init_result(target_host) + is_zh = get_language() + + cmd = ["systemctl", "status", "sshd"] + + # 本地 + if target_host == "127.0.0.1": + try: + cp = _run_local(cmd) + result["success"] = True + result["message"] = ( + "本地 sshd 状态获取成功" if is_zh else "Local sshd status fetched" + ) + result["result"] = cp.stdout.strip().splitlines() + except subprocess.CalledProcessError as e: + result["message"] = ( + f"本地 sshd 状态获取失败:{e.stderr.strip()}" + if is_zh + else f"Failed to get local sshd status: {e.stderr.strip()}" + ) + return result + + # 远程 + remote_auth = get_remote_auth(target_host) + if not remote_auth or not (remote_auth["username"] and remote_auth["password"]): + result["message"] = ( + "远程认证配置缺失" if is_zh else "Remote auth config missing" + ) + return result + + ssh: Optional[paramiko.SSHClient] = None + try: + ssh = _open_ssh(remote_auth) + stdin, stdout, stderr = ssh.exec_command("systemctl status sshd") + out = stdout.read().decode("utf-8", errors="replace").strip() + err = stderr.read().decode("utf-8", errors="replace").strip() + if err and "Active:" not in out: + result["message"] = ( + f"远程 sshd 状态获取失败:{err}" + if is_zh + else f"Failed to get remote sshd status: {err}" + ) + else: + result["success"] = True + result["message"] = ( + "远程 sshd 状态获取成功" if is_zh else "Remote sshd status fetched" + ) + result["result"] = out.splitlines() + except paramiko.AuthenticationException: + result["message"] = ( + "SSH 认证失败,请检查用户名和密码" + if is_zh + else "SSH authentication failed, check username and password" + ) + except Exception as e: + result["message"] = ( + f"远程 sshd 状态检查异常:{str(e)}" + if is_zh + else f"Remote sshd status check exception: {str(e)}" + ) + finally: + if ssh: + ssh.close() + return result + + +def fix_sshd_config_and_restart(target: Optional[str]) -> Dict: + """ + 修复 /etc/ssh/sshd_config 中的 Port/PermitRootLogin/PasswordAuthentication + 并执行 systemctl restart sshd + """ + target_host = target.strip() if target else "127.0.0.1" + result = init_result(target_host) + is_zh = get_language() + + # 需要确保的配置行 + desired_lines = { + "Port": "Port 22", + "PermitRootLogin": "PermitRootLogin yes", + "PasswordAuthentication": "PasswordAuthentication yes", + } + + def build_sed_commands() -> str: + """ + 为远程一次性执行构造 sed & restart 命令: + - 先针对每个键进行替换/解注释 + - 若不存在目标键则追加 + - 最后重启 sshd + """ + sed_parts = [] + # 替换或解注释三项配置 + sed_parts.append( + r"sed -i -e 's/^[#]*[[:space:]]*Port[[:space:]].*/Port 22/' " + r"-e 's/^[#]*[[:space:]]*PermitRootLogin[[:space:]].*/PermitRootLogin yes/' " + r"-e 's/^[#]*[[:space:]]*PasswordAuthentication[[:space:]].*/PasswordAuthentication yes/' " + r"/etc/ssh/sshd_config" + ) + # 若 key 不存在则追加 + for k, line in desired_lines.items(): + sed_parts.append( + f"grep -q '^{k}[[:space:]]' /etc/ssh/sshd_config || " + f"echo '{line}' >> /etc/ssh/sshd_config" + ) + # 重启 sshd + sed_parts.append("systemctl restart sshd") + # 组合为单条 shell 命令 + return " && ".join(sed_parts) + + # 本地修复 + if target_host == "127.0.0.1": + messages: List[str] = [] + try: + # 直接执行与远程相同的 shell 逻辑 + shell_cmd = build_sed_commands() + cp = subprocess.run( + shell_cmd, + shell=True, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + if cp.stdout.strip(): + messages.extend(cp.stdout.strip().splitlines()) + if cp.stderr.strip(): + messages.extend(cp.stderr.strip().splitlines()) + result["success"] = True + result["message"] = ( + "本地 sshd 配置已修复并重启" + if is_zh + else "Local sshd config fixed and service restarted" + ) + if not messages: + messages.append(result["message"]) + result["result"] = messages + except subprocess.CalledProcessError as e: + result["message"] = ( + f"本地 sshd 修复失败:{e.stderr.strip()}" + if is_zh + else f"Failed to fix local sshd: {e.stderr.strip()}" + ) + result["result"] = [result["message"]] + return result + + # 远程修复 + remote_auth = get_remote_auth(target_host) + if not remote_auth or not (remote_auth["username"] and remote_auth["password"]): + result["message"] = ( + "远程认证配置缺失" if is_zh else "Remote auth missing" + ) + return result + + ssh: Optional[paramiko.SSHClient] = None + try: + ssh = _open_ssh(remote_auth) + shell_cmd = build_sed_commands() + stdin, stdout, stderr = ssh.exec_command(shell_cmd) + out = stdout.read().decode("utf-8", errors="replace").strip() + err = stderr.read().decode("utf-8", errors="replace").strip() + + messages: List[str] = [] + if out: + messages.extend(out.splitlines()) + if err: + messages.extend(err.splitlines()) + + exit_status = stdout.channel.recv_exit_status() + if exit_status == 0: + result["success"] = True + result["message"] = ( + "远程 sshd 配置已修复并重启" + if is_zh + else "Remote sshd config fixed and service restarted" + ) + else: + result["message"] = ( + f"远程 sshd 修复失败:{err}" + if is_zh + else f"Failed to fix remote sshd: {err}" + ) + if not messages: + messages.append(result["message"]) + result["result"] = messages + except paramiko.AuthenticationException: + result["message"] = ( + "SSH 认证失败,请检查用户名和密码" + if is_zh + else "SSH authentication failed, check username and password" + ) + result["result"] = [result["message"]] + except Exception as e: + result["message"] = ( + f"远程 sshd 修复异常:{str(e)}" + if is_zh + else f"Remote sshd fix exception: {str(e)}" + ) + result["result"] = [result["message"]] + finally: + if ssh: + ssh.close() + + return result + + +def fix_sshd_issue(target: Optional[str], port: int = 22) -> Dict: + """ + 整体解决 SSH 连接失败问题的工具,按顺序执行: + 1. 检查 SSH 端口连通性(ping 端口) + 2. 检查 sshd 服务状态(systemctl status sshd) + 3. 修复 sshd_config 关键配置并重启 sshd + """ + target_host = target.strip() if (target and isinstance(target, str)) else "127.0.0.1" + is_zh = get_language() + result = init_result(target_host) + + steps: List[str] = [] + + # 步骤 1:端口连通性检查 + steps.append( + "=== 步骤1: 检查 SSH 端口连通性 ===" + if is_zh + else "=== Step 1: Check SSH port connectivity ===" + ) + ping_res = ssh_port_ping(target_host, port=port) + steps.extend(ping_res.get("result", []) or [ping_res.get("message", "")]) + + # 步骤 2:sshd 状态检查 + steps.append( + "=== 步骤2: 检查 sshd 服务状态 ===" + if is_zh + else "=== Step 2: Check sshd service status ===" + ) + status_res = check_sshd_status(target_host) + if status_res.get("message"): + steps.append(status_res["message"]) + # 只展示前几行关键信息,避免输出过长 + status_lines = status_res.get("result") or [] + if status_lines: + steps.extend(status_lines[:5]) + + # 步骤 3:修复配置并重启 sshd + steps.append( + "=== 步骤3: 修复 sshd 配置并重启服务 ===" + if is_zh + else "=== Step 3: Fix sshd config and restart service ===" + ) + fix_res = fix_sshd_config_and_restart(target_host) + if fix_res.get("message"): + steps.append(fix_res["message"]) + fix_lines = fix_res.get("result") or [] + if fix_lines: + steps.extend(fix_lines) + + # 综合结果:以修复步骤结果为准 + result["success"] = bool(fix_res.get("success")) + result["message"] = ( + "SSH 问题处理完成" if is_zh else "SSH issue handling finished" + ) + if not result["success"] and fix_res.get("message"): + # 若修复失败,附加更明确的错误说明 + result["message"] = fix_res["message"] + + result["result"] = steps + return result + + + diff --git a/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/config.json b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/config.json new file mode 100644 index 0000000000000000000000000000000000000000..1d26e7271a812afcccba3a9a7320a022795f2062 --- /dev/null +++ b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/config.json @@ -0,0 +1,10 @@ +{ + "tools": { + "ssh_fix_tool": { + "zh": "整合的SSH修复工具:解决openEuler系统SSH连接失败问题。\n\n该工具按顺序自动执行以下步骤:\n1. ping SSH端口检查连通性(检测端口22是否可达)\n2. 检查sshd服务状态(执行systemctl status sshd)\n3. 修复/etc/ssh/sshd_config配置文件:\n - 确保Port 22已启用(若不存在则追加,若被注释则解注释并改为22)\n - 设置PermitRootLogin yes(允许root登录)\n - 设置PasswordAuthentication yes(允许密码认证)\n4. 重启sshd服务(执行systemctl restart sshd)\n\n参数:\n - target: 目标主机IP或主机名,None或\"127.0.0.1\"表示本机(必填)\n - port: SSH端口,默认22\n - lang: 语言设置(可选,保留以保持接口一致性)\n\n返回:\n - success: 是否修复成功(True/False)\n - message: 执行结果说明(总体修复结果)\n - target: 目标主机\n - result: 各步骤执行结果列表(包含步骤1-4的详细输出)\n\n使用场景:\n - openEuler 24.03 SP2系统SSH连接失败问题\n - sshd服务未正确配置导致无法连接\n - 需要快速诊断和修复SSH服务配置", + "en": "Integrated SSH fix tool: Resolve SSH connection failures on openEuler systems.\n\nThe tool automatically performs the following steps in sequence:\n1. Ping SSH port to check connectivity (check if port 22 is reachable)\n2. Check sshd service status (execute systemctl status sshd)\n3. Fix /etc/ssh/sshd_config configuration:\n - Ensure Port 22 is enabled (add if missing, uncomment and change to 22 if commented)\n - Set PermitRootLogin yes (allow root login)\n - Set PasswordAuthentication yes (allow password authentication)\n4. Restart sshd service (execute systemctl restart sshd)\n\nParameters:\n - target: Target host IP or hostname, None or \"127.0.0.1\" for localhost (required)\n - port: SSH port, default 22\n - lang: Language setting (optional, kept for interface consistency)\n\nReturns:\n - success: Whether the fix was successful (True/False)\n - message: Result description (overall fix result)\n - target: Target host\n - result: List of execution results for each step (detailed output for steps 1-4)\n\nUse cases:\n - SSH connection failures on openEuler 24.03 SP2 systems\n - sshd service misconfiguration preventing connections\n - Quick diagnosis and fix of SSH service configuration" + } + } +} + + diff --git a/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/deps.toml b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/deps.toml new file mode 100644 index 0000000000000000000000000000000000000000..48402d5d42587b741dadcdc8429b34904b9ea38d --- /dev/null +++ b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/deps.toml @@ -0,0 +1,17 @@ +[system] +# SSH/sshd 相关系统工具依赖(通常系统已自带,这里仅列出以便需要时安装) +#ssh_tools = [ +# "yum install -y openssh-clients openssh-server", +# "apt-get update && apt-get install -y openssh-client openssh-server" +#] + +[pip] +# Python 依赖(与其他 mcptool 保持一致的基础依赖) +paramiko = "==4.0.0" +typing_extensions = "==4.12.2" +psutil = "==7.0.0" +toml = "==0.10.2" +mcp = "==1.9.4" +scp = "==0.15.0" + + diff --git a/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/tool.py b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/tool.py new file mode 100644 index 0000000000000000000000000000000000000000..e9d04269b064bc5681eed476251b389445ec4609 --- /dev/null +++ b/mcp_center/servers/oe_cli_mcp_server/mcp_tools/base_tools/ssh_fix_tool/tool.py @@ -0,0 +1,28 @@ +from typing import Dict, Optional + +from config.base_config_loader import LanguageEnum + +from mcp_tools.base_tools.ssh_fix_tool.base import fix_sshd_issue + + +def ssh_fix_tool( + target: Optional[str] = None, + port: int = 22, + lang: Optional[LanguageEnum] = LanguageEnum.ZH, +) -> Dict: + """ + 整合的SSH修复工具:解决SSH连接失败问题 + + 按顺序执行以下步骤: + 1. ping SSH端口检查连通性 + 2. 检查sshd服务状态(systemctl status sshd) + 3. 修复/etc/ssh/sshd_config配置: + - 确保Port 22已启用 + - 设置PermitRootLogin yes + - 设置PasswordAuthentication yes + 4. 重启sshd服务(systemctl restart sshd) + """ + return fix_sshd_issue(target, port=port) + + +