From e19d4069ce9722798b48453f03a2973ce3f91d59 Mon Sep 17 00:00:00 2001 From: Jacquin Antoine Date: Sat, 21 Feb 2026 23:27:11 +0100 Subject: [PATCH] version 2 --- data/srv-rhel-prod-01/httpd_conf.txt | 14 ++++ data/srv-rhel-prod-01/metrics_vm.txt | 5 ++ data/srv-rhel-prod-01/network_ss.txt | 4 ++ data/srv-rhel-prod-01/rpm_inventory.txt | 7 ++ docker-compose.yml | 9 +++ mcp-simulator/Dockerfile | 17 +++++ mcp-simulator/main.py | 87 +++++++++++++++++++++++++ mcp-simulator/requirements.txt | 4 ++ 8 files changed, 147 insertions(+) create mode 100644 data/srv-rhel-prod-01/httpd_conf.txt create mode 100644 data/srv-rhel-prod-01/metrics_vm.txt create mode 100644 data/srv-rhel-prod-01/network_ss.txt create mode 100644 data/srv-rhel-prod-01/rpm_inventory.txt create mode 100644 mcp-simulator/Dockerfile create mode 100644 mcp-simulator/main.py create mode 100644 mcp-simulator/requirements.txt diff --git a/data/srv-rhel-prod-01/httpd_conf.txt b/data/srv-rhel-prod-01/httpd_conf.txt new file mode 100644 index 0000000..5389716 --- /dev/null +++ b/data/srv-rhel-prod-01/httpd_conf.txt @@ -0,0 +1,14 @@ +SERVICE: httpd +FILES_COLLECTED: /etc/httpd/conf/httpd.conf, /etc/httpd/conf.d/ssl.conf +--- FILE: /etc/httpd/conf/httpd.conf --- +ServerRoot "/etc/httpd" +Listen 80 +Include conf.modules.d/*.conf +DocumentRoot "/var/www/html" + +--- FILE: /etc/httpd/conf.d/ssl.conf --- +Listen 443 https + + DocumentRoot "/var/www/html" + SSLEngine on + diff --git a/data/srv-rhel-prod-01/metrics_vm.txt b/data/srv-rhel-prod-01/metrics_vm.txt new file mode 100644 index 0000000..85c89d0 --- /dev/null +++ b/data/srv-rhel-prod-01/metrics_vm.txt @@ -0,0 +1,5 @@ +METRICS_SNAPSHOT: +cpu_usage_idle: 94.2% +load_average_1m: 0.15 +mem_available_bytes: 4294967296 +disk_io_wait: 0.01 diff --git a/data/srv-rhel-prod-01/network_ss.txt b/data/srv-rhel-prod-01/network_ss.txt new file mode 100644 index 0000000..1980a5f --- /dev/null +++ b/data/srv-rhel-prod-01/network_ss.txt @@ -0,0 +1,4 @@ +NETWORK_STATE (ss -ntulop): +Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process +tcp LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=842,fd=6)) +tcp LISTEN 0 128 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=842,fd=7)) diff --git a/data/srv-rhel-prod-01/rpm_inventory.txt b/data/srv-rhel-prod-01/rpm_inventory.txt new file mode 100644 index 0000000..ef141a8 --- /dev/null +++ b/data/srv-rhel-prod-01/rpm_inventory.txt @@ -0,0 +1,7 @@ +ID: srv-rhel-prod-01 +OS: Red Hat Enterprise Linux 9.3 (Plow) +KERNEL: 5.14.0-362.8.1.el9_3.x86_64 +INSTALLED_PACKAGES: +- httpd-2.4.57-5.el9.x86_64 +- nginx-1.20.1-14.el9.x86_64 +- mod_ssl-2.4.57-5.el9.x86_64 diff --git a/docker-compose.yml b/docker-compose.yml index d26367f..0f124d6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,3 +17,12 @@ services: - chroma-db ports: - "8080:8080" + + # Simulateur MCP pour l'Inventaire & Config + mcp-inventory: + build: ./mcp-simulator + container_name: ops-gpt-mcp + volumes: + - ./data:/app/data:ro + ports: + - "8081:8080" diff --git a/mcp-simulator/Dockerfile b/mcp-simulator/Dockerfile new file mode 100644 index 0000000..a55b129 --- /dev/null +++ b/mcp-simulator/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.11-slim + +WORKDIR /app + +# Installation des dépendances via le fichier requirements +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copie du code source +COPY main.py . + +# Création du point de montage pour les données des hôtes +RUN mkdir -p /app/data + +EXPOSE 8080 + +CMD ["python", "main.py"] diff --git a/mcp-simulator/main.py b/mcp-simulator/main.py new file mode 100644 index 0000000..7bef7ff --- /dev/null +++ b/mcp-simulator/main.py @@ -0,0 +1,87 @@ +import os +import logging +from mcp.server.fastmcp import FastMCP + +# --- CONFIGURATION LOGGING --- +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger("ops-gpt-mcp") + +# --- INITIALISATION --- +# On utilise FastMCP pour gérer nativement le transport SSE et les routes /sse /messages +mcp = FastMCP("Ops-GPT-Unified-Diagnostics", host="0.0.0.0", port=8080) + +BASE_DATA_PATH = "/app/data" + +# --- CATALOGUE D'OUTILS SRE (INTEGRAL) --- + +@mcp.tool() +async def list_services_with_config(hostname: str): + """ + RECOGNITION: Identifie les middlewares (Nginx, Apache, etc.) avec fichiers de configuration agrégés. + Indispensable pour la découverte initiale des composants actifs sur l'hôte. + """ + try: + host_path = os.path.join(BASE_DATA_PATH, hostname) + if not os.path.exists(host_path): + return f"FATAL_ERROR: Host directory {hostname} not found." + + services = [f.replace("_conf.txt", "") for f in os.listdir(host_path) if f.endswith("_conf.txt")] + return f"STATUS_SUCCESS: Services found: {', '.join(services) if services else 'NONE'}" + except Exception as e: + return f"SYSTEM_EXCEPTION: {str(e)}" + +@mcp.tool() +async def get_rpm_inventory(hostname: str): + """ + AUDIT: Récupère l'inventaire complet des paquets RPM et la version du noyau. + Utile pour identifier les dérives de configuration OS. + """ + try: + path = os.path.join(BASE_DATA_PATH, hostname, "rpm_inventory.txt") + with open(path, "r", encoding='utf-8') as f: + return f"--- RPM_INVENTORY | {hostname} ---\n{f.read()}" + except FileNotFoundError: + return f"DATA_ERROR: rpm_inventory.txt not found for {hostname}." + +@mcp.tool() +async def get_network_sockets(hostname: str): + """ + NETWORKING: Exécute 'ss -ntulop'. Fournit l'état des sockets et le mapping PID/Processus. + """ + try: + path = os.path.join(BASE_DATA_PATH, hostname, "network_ss.txt") + with open(path, "r", encoding='utf-8') as f: + return f"--- NETWORK_SOCKETS | {hostname} ---\n{f.read()}" + except FileNotFoundError: + return f"DATA_ERROR: network_ss.txt not found for {hostname}." + +@mcp.tool() +async def get_system_metrics(hostname: str): + """ + MONITORING: Récupère les métriques CPU/RAM/IO (VictoriaMetrics) pour l'hôte spécifié. + """ + try: + path = os.path.join(BASE_DATA_PATH, hostname, "metrics_vm.txt") + with open(path, "r", encoding='utf-8') as f: + return f"--- SYSTEM_METRICS | {hostname} ---\n{f.read()}" + except FileNotFoundError: + return f"DATA_ERROR: metrics_vm.txt not found for {hostname}." + +@mcp.tool() +async def get_live_config(hostname: str, service_name: str): + """ + DEEP ANALYSIS: Extrait le contenu brut du fichier [service]_conf.txt agrégé. + """ + try: + target_file = f"{service_name}_conf.txt" + path = os.path.join(BASE_DATA_PATH, hostname, target_file) + with open(path, "r", encoding='utf-8') as f: + return f"--- CONFIG_FILE: {target_file} | {hostname} ---\n{f.read()}" + except FileNotFoundError: + return f"DATA_ERROR: Config for '{service_name}' not found for {hostname}." + +# --- LANCEMENT DU SERVEUR --- +if __name__ == "__main__": + logger.info("Starting Ops-GPT MCP Engine via FastMCP on port 8080") + # FastMCP gère lui-même la boucle uvicorn et le transport SSE + mcp.run(transport="sse") diff --git a/mcp-simulator/requirements.txt b/mcp-simulator/requirements.txt new file mode 100644 index 0000000..935d511 --- /dev/null +++ b/mcp-simulator/requirements.txt @@ -0,0 +1,4 @@ +mcp>=1.0.0 +fastapi>=0.100.0 +uvicorn>=0.23.0 +starlette>=0.27.0