initial commit
This commit is contained in:
24
.env
Normal file
24
.env
Normal file
@@ -0,0 +1,24 @@
|
||||
# MikroTik Gemini Integration - Environment Variables
|
||||
|
||||
# Google Gemini API Key (required)
|
||||
# Dapatkan dari: https://makersuite.google.com/app/apikey
|
||||
GEMINI_API_KEY=AIzaSyC9RXt7VHVIlvxU_OuI7xONzwIuu56iS-g
|
||||
|
||||
# MikroTik Connection (optional, for data updates)
|
||||
MIKROTIK_HOST=192.168.7.1
|
||||
MIKROTIK_PORT=80
|
||||
MIKROTIK_USER=admin11
|
||||
MIKROTIK_PASSWORD=Dua75316__
|
||||
|
||||
# API Server Configuration
|
||||
API_HOST=0.0.0.0
|
||||
API_PORT=8010
|
||||
API_DEBUG=true
|
||||
API_KEY=mkmcp_secret_key_2026
|
||||
|
||||
# Data File Path
|
||||
DATA_FILE=data/mikrotik_mcp_data.json
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=INFO
|
||||
LOG_FILE=logs/app.log
|
||||
23
.env.example
Normal file
23
.env.example
Normal file
@@ -0,0 +1,23 @@
|
||||
# MikroTik Gemini Integration - Environment Variables
|
||||
|
||||
# Google Gemini API Key (required)
|
||||
# Dapatkan dari: https://makersuite.google.com/app/apikey
|
||||
GEMINI_API_KEY=your_gemini_api_key_here
|
||||
|
||||
# MikroTik Connection (optional, for data updates)
|
||||
MIKROTIK_HOST=192.168.1.1
|
||||
MIKROTIK_PORT=8728
|
||||
MIKROTIK_USER=admin
|
||||
MIKROTIK_PASSWORD=password
|
||||
|
||||
# API Server Configuration
|
||||
API_HOST=0.0.0.0
|
||||
API_PORT=8000
|
||||
API_DEBUG=true
|
||||
|
||||
# Data File Path
|
||||
DATA_FILE=../mikrotik_mcp_data.json
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=INFO
|
||||
LOG_FILE=logs/app.log
|
||||
164
README.md
Normal file
164
README.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# 🚀 Integrasi MikroTik MCP dengan Gemini AI
|
||||
|
||||
## 📋 **Daftar Isi**
|
||||
1. [Overview](#overview)
|
||||
2. [Prerequisites](#prerequisites)
|
||||
3. [Struktur File](#struktur-file)
|
||||
4. [Instalasi Cepat](#instalasi-cepat)
|
||||
5. [Penggunaan](#penggunaan)
|
||||
6. [Deployment](#deployment)
|
||||
7. [Contoh Penggunaan](#contoh-penggunaan)
|
||||
8. [Troubleshooting](#troubleshooting)
|
||||
|
||||
## 🔍 **Overview**
|
||||
|
||||
Integrasi ini memungkinkan Anda bertanya tentang perangkat MikroTik menggunakan **Google Gemini AI** dengan konteks data real-time dari perangkat.
|
||||
|
||||
**Fitur Utama:**
|
||||
- ✅ Query natural language tentang MikroTik
|
||||
- ✅ Context-aware responses
|
||||
- ✅ Real-time monitoring
|
||||
- ✅ Web API interface
|
||||
- ✅ Docker deployment
|
||||
- ✅ Optimized token usage
|
||||
|
||||
## 📦 **Prerequisites**
|
||||
|
||||
### **1. Google Cloud Account**
|
||||
- API Key Gemini dari [Google AI Studio](https://makersuite.google.com/app/apikey)
|
||||
|
||||
### **2. Python 3.11+**
|
||||
```bash
|
||||
python --version
|
||||
```
|
||||
|
||||
### **3. MikroTik Data**
|
||||
File: `mikrotik_mcp_data.json` (sudah ada di project)
|
||||
|
||||
## 📁 **Struktur File**
|
||||
|
||||
```
|
||||
gemini_integration/
|
||||
├── README.md # File ini
|
||||
├── gemini_mikrotik_integration.py # Script utama
|
||||
├── api_server.py # FastAPI server
|
||||
├── realtime_monitor.py # Monitoring real-time
|
||||
├── context_optimizer.py # Optimasi context
|
||||
├── update_data.py # Script update data MikroTik
|
||||
├── requirements.txt # Dependencies
|
||||
├── docker-compose.yml # Docker deployment
|
||||
├── config.yaml # Konfigurasi
|
||||
├── example_prompts.md # Contoh prompt
|
||||
├── .env.example # Template environment
|
||||
└── logs/ # Log directory (auto-created)
|
||||
```
|
||||
```
|
||||
|
||||
## ⚡ **Instalasi Cepat**
|
||||
|
||||
### **Step 1: Setup Environment**
|
||||
```bash
|
||||
cd /a0/usr/projects/project_1/gemini_integration
|
||||
|
||||
# Copy environment template
|
||||
cp .env.example .env
|
||||
|
||||
# Edit .env dengan API key Anda
|
||||
nano .env
|
||||
```
|
||||
|
||||
### **Step 2: Install Dependencies**
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### **Step 3: Test Integration**
|
||||
```bash
|
||||
python gemini_mikrotik_integration.py
|
||||
```
|
||||
|
||||
## 🎯 **Penggunaan**
|
||||
|
||||
### **1. Interactive Chat**
|
||||
```bash
|
||||
python gemini_mikrotik_integration.py
|
||||
```
|
||||
|
||||
### **2. Web API**
|
||||
```bash
|
||||
python api_server.py
|
||||
# Akses: http://localhost:8000/docs
|
||||
```
|
||||
|
||||
### **3. Real-time Monitoring**
|
||||
```bash
|
||||
python realtime_monitor.py
|
||||
```
|
||||
|
||||
## 🐳 **Deployment dengan Docker**
|
||||
|
||||
### **Build dan Run**
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### **Check Status**
|
||||
```bash
|
||||
docker-compose ps
|
||||
curl http://localhost:8000/health
|
||||
```
|
||||
|
||||
## 💡 **Contoh Penggunaan**
|
||||
|
||||
### **Via Python Script**
|
||||
```python
|
||||
from gemini_mikrotik_integration import MikroTikGeminiAssistant
|
||||
|
||||
assistant = MikroTikGeminiAssistant()
|
||||
answer = assistant.ask_question("Berapa CPU usage router?")
|
||||
print(answer)
|
||||
```
|
||||
|
||||
### **Via API**
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/ask \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"question": "Ada berapa interface yang running?"}'
|
||||
```
|
||||
|
||||
## 🔧 **Troubleshooting**
|
||||
|
||||
### **Error: API Key Invalid**
|
||||
```bash
|
||||
# Periksa .env file
|
||||
cat .env | grep GEMINI_API_KEY
|
||||
```
|
||||
|
||||
### **Error: MikroTik Data Not Found**
|
||||
```bash
|
||||
# Pastikan file data ada
|
||||
ls -la ../mikrotik_mcp_data.json
|
||||
```
|
||||
|
||||
### **Error: Port Already in Use**
|
||||
```bash
|
||||
# Ganti port di api_server.py atau kill process
|
||||
lsof -i :8000
|
||||
kill -9 <PID>
|
||||
```
|
||||
|
||||
## 📞 **Support**
|
||||
|
||||
- **Issues**: Check error logs
|
||||
- **Questions**: Lihat example_prompts.md
|
||||
- **Updates**: Pantau perubahan API Gemini
|
||||
|
||||
## 📄 **License**
|
||||
|
||||
MIT License - Bebas digunakan untuk keperluan apapun.
|
||||
|
||||
---
|
||||
|
||||
**Dibuat oleh:** Agent Zero AI Assistant
|
||||
**Tanggal:** 2026-01-20
|
||||
**Versi:** 1.0.0
|
||||
162
README.md.backup
Normal file
162
README.md.backup
Normal file
@@ -0,0 +1,162 @@
|
||||
# 🚀 Integrasi MikroTik MCP dengan Gemini AI
|
||||
|
||||
## 📋 **Daftar Isi**
|
||||
1. [Overview](#overview)
|
||||
2. [Prerequisites](#prerequisites)
|
||||
3. [Struktur File](#struktur-file)
|
||||
4. [Instalasi Cepat](#instalasi-cepat)
|
||||
5. [Penggunaan](#penggunaan)
|
||||
6. [Deployment](#deployment)
|
||||
7. [Contoh Penggunaan](#contoh-penggunaan)
|
||||
8. [Troubleshooting](#troubleshooting)
|
||||
|
||||
## 🔍 **Overview**
|
||||
|
||||
Integrasi ini memungkinkan Anda bertanya tentang perangkat MikroTik menggunakan **Google Gemini AI** dengan konteks data real-time dari perangkat.
|
||||
|
||||
**Fitur Utama:**
|
||||
- ✅ Query natural language tentang MikroTik
|
||||
- ✅ Context-aware responses
|
||||
- ✅ Real-time monitoring
|
||||
- ✅ Web API interface
|
||||
- ✅ Docker deployment
|
||||
- ✅ Optimized token usage
|
||||
|
||||
## 📦 **Prerequisites**
|
||||
|
||||
### **1. Google Cloud Account**
|
||||
- API Key Gemini dari [Google AI Studio](https://makersuite.google.com/app/apikey)
|
||||
|
||||
### **2. Python 3.11+**
|
||||
```bash
|
||||
python --version
|
||||
```
|
||||
|
||||
### **3. MikroTik Data**
|
||||
File: `mikrotik_mcp_data.json` (sudah ada di project)
|
||||
|
||||
## 📁 **Struktur File**
|
||||
|
||||
```
|
||||
gemini_integration/
|
||||
├── README.md # File ini
|
||||
├── gemini_mikrotik_integration.py # Script utama
|
||||
├── api_server.py # FastAPI server
|
||||
├── realtime_monitor.py # Monitoring real-time
|
||||
├── context_optimizer.py # Optimasi context
|
||||
├── requirements.txt # Dependencies
|
||||
├── docker-compose.yml # Docker deployment
|
||||
├── nginx.conf # Nginx config
|
||||
├── example_prompts.md # Contoh prompt
|
||||
├── .env.example # Template environment
|
||||
└── config.yaml # Konfigurasi
|
||||
```
|
||||
|
||||
## ⚡ **Instalasi Cepat**
|
||||
|
||||
### **Step 1: Setup Environment**
|
||||
```bash
|
||||
cd /a0/usr/projects/project_1/gemini_integration
|
||||
|
||||
# Copy environment template
|
||||
cp .env.example .env
|
||||
|
||||
# Edit .env dengan API key Anda
|
||||
nano .env
|
||||
```
|
||||
|
||||
### **Step 2: Install Dependencies**
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### **Step 3: Test Integration**
|
||||
```bash
|
||||
python gemini_mikrotik_integration.py
|
||||
```
|
||||
|
||||
## 🎯 **Penggunaan**
|
||||
|
||||
### **1. Interactive Chat**
|
||||
```bash
|
||||
python gemini_mikrotik_integration.py
|
||||
```
|
||||
|
||||
### **2. Web API**
|
||||
```bash
|
||||
python api_server.py
|
||||
# Akses: http://localhost:8000/docs
|
||||
```
|
||||
|
||||
### **3. Real-time Monitoring**
|
||||
```bash
|
||||
python realtime_monitor.py
|
||||
```
|
||||
|
||||
## 🐳 **Deployment dengan Docker**
|
||||
|
||||
### **Build dan Run**
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### **Check Status**
|
||||
```bash
|
||||
docker-compose ps
|
||||
curl http://localhost:8000/health
|
||||
```
|
||||
|
||||
## 💡 **Contoh Penggunaan**
|
||||
|
||||
### **Via Python Script**
|
||||
```python
|
||||
from gemini_mikrotik_integration import MikroTikGeminiAssistant
|
||||
|
||||
assistant = MikroTikGeminiAssistant()
|
||||
answer = assistant.ask_question("Berapa CPU usage router?")
|
||||
print(answer)
|
||||
```
|
||||
|
||||
### **Via API**
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/ask \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"question": "Ada berapa interface yang running?"}'
|
||||
```
|
||||
|
||||
## 🔧 **Troubleshooting**
|
||||
|
||||
### **Error: API Key Invalid**
|
||||
```bash
|
||||
# Periksa .env file
|
||||
cat .env | grep GEMINI_API_KEY
|
||||
```
|
||||
|
||||
### **Error: MikroTik Data Not Found**
|
||||
```bash
|
||||
# Pastikan file data ada
|
||||
ls -la ../mikrotik_mcp_data.json
|
||||
```
|
||||
|
||||
### **Error: Port Already in Use**
|
||||
```bash
|
||||
# Ganti port di api_server.py atau kill process
|
||||
lsof -i :8000
|
||||
kill -9 <PID>
|
||||
```
|
||||
|
||||
## 📞 **Support**
|
||||
|
||||
- **Issues**: Check error logs
|
||||
- **Questions**: Lihat example_prompts.md
|
||||
- **Updates**: Pantau perubahan API Gemini
|
||||
|
||||
## 📄 **License**
|
||||
|
||||
MIT License - Bebas digunakan untuk keperluan apapun.
|
||||
|
||||
---
|
||||
|
||||
**Dibuat oleh:** Agent Zero AI Assistant
|
||||
**Tanggal:** 2026-01-20
|
||||
**Versi:** 1.0.0
|
||||
BIN
__pycache__/context_optimizer.cpython-313.pyc
Normal file
BIN
__pycache__/context_optimizer.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/gemini_mikrotik_integration.cpython-313.pyc
Normal file
BIN
__pycache__/gemini_mikrotik_integration.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/update_data.cpython-313.pyc
Normal file
BIN
__pycache__/update_data.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/__pycache__/context_optimizer.cpython-313.pyc
Normal file
BIN
app/__pycache__/context_optimizer.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/__pycache__/gemini_mikrotik_integration.cpython-313.pyc
Normal file
BIN
app/__pycache__/gemini_mikrotik_integration.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/__pycache__/update_data.cpython-313.pyc
Normal file
BIN
app/__pycache__/update_data.cpython-313.pyc
Normal file
Binary file not shown.
153
app/api_server.py
Normal file
153
app/api_server.py
Normal file
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
FastAPI Server untuk MikroTik Gemini Integration
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI, HTTPException, Security, status, Depends
|
||||
from fastapi.security import APIKeyHeader
|
||||
from pydantic import BaseModel
|
||||
from datetime import datetime
|
||||
import uvicorn
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Import our assistant
|
||||
from gemini_mikrotik_integration import MikroTikGeminiAssistant
|
||||
|
||||
# Load environment
|
||||
load_dotenv()
|
||||
|
||||
# Security
|
||||
API_KEY = os.getenv("API_KEY", "mkmcp_secret_key_2026")
|
||||
API_KEY_NAME = "X-API-Key"
|
||||
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)
|
||||
|
||||
async def get_api_key(api_key: str = Security(api_key_header)):
|
||||
if api_key == API_KEY:
|
||||
return api_key
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="API Key tidak valid atau tidak ditemukan",
|
||||
)
|
||||
|
||||
# Initialize FastAPI
|
||||
app = FastAPI(
|
||||
title="MikroTik Gemini API",
|
||||
description="API untuk query MikroTik dengan Gemini AI",
|
||||
version="1.0.0",
|
||||
docs_url="/docs",
|
||||
redoc_url="/redoc",
|
||||
dependencies=[Depends(get_api_key)]
|
||||
)
|
||||
|
||||
# Initialize assistant
|
||||
assistant = None
|
||||
try:
|
||||
assistant = MikroTikGeminiAssistant()
|
||||
print("✅ MikroTik Gemini Assistant initialized")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Assistant initialization failed: {e}")
|
||||
assistant = None
|
||||
|
||||
# Request/Response models
|
||||
class QuestionRequest(BaseModel):
|
||||
question: str
|
||||
detailed: bool = False
|
||||
|
||||
class AnswerResponse(BaseModel):
|
||||
question: str
|
||||
answer: str
|
||||
timestamp: str
|
||||
success: bool
|
||||
|
||||
class HealthResponse(BaseModel):
|
||||
status: str
|
||||
service: str
|
||||
version: str
|
||||
timestamp: str
|
||||
mikrotik_device: str = "N/A"
|
||||
data_age: str = "N/A"
|
||||
|
||||
# API Endpoints
|
||||
@app.get("/")
|
||||
def root():
|
||||
return {
|
||||
"service": "MikroTik Gemini API",
|
||||
"version": "1.0.0",
|
||||
"endpoints": {
|
||||
"docs": "/docs",
|
||||
"health": "/health",
|
||||
"ask": "/ask (POST)"
|
||||
}
|
||||
}
|
||||
|
||||
@app.get("/health", response_model=HealthResponse)
|
||||
def health_check():
|
||||
"""Check API and MikroTik status"""
|
||||
status = "healthy"
|
||||
device_info = "N/A"
|
||||
data_age = "N/A"
|
||||
|
||||
if assistant:
|
||||
try:
|
||||
summary = assistant.get_summary()
|
||||
device_info = summary["device"]
|
||||
data_age = summary["timestamp"]
|
||||
except:
|
||||
status = "degraded"
|
||||
else:
|
||||
status = "degraded"
|
||||
|
||||
return HealthResponse(
|
||||
status=status,
|
||||
service="MikroTik Gemini API",
|
||||
version="1.0.0",
|
||||
timestamp=datetime.now().isoformat(),
|
||||
mikrotik_device=device_info,
|
||||
data_age=data_age
|
||||
)
|
||||
|
||||
@app.post("/ask", response_model=AnswerResponse)
|
||||
def ask_question(request: QuestionRequest):
|
||||
"""Ask Gemini about MikroTik"""
|
||||
if not assistant:
|
||||
raise HTTPException(status_code=503, detail="Assistant not available")
|
||||
|
||||
try:
|
||||
answer = assistant.ask(request.question)
|
||||
|
||||
return AnswerResponse(
|
||||
question=request.question,
|
||||
answer=answer,
|
||||
timestamp=datetime.now().isoformat(),
|
||||
success=True
|
||||
)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
|
||||
|
||||
@app.get("/summary")
|
||||
def get_summary():
|
||||
"""Get MikroTik device summary"""
|
||||
if not assistant:
|
||||
raise HTTPException(status_code=503, detail="Assistant not available")
|
||||
|
||||
try:
|
||||
return assistant.get_summary()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
|
||||
|
||||
# Run server
|
||||
if __name__ == "__main__":
|
||||
host = os.getenv("API_HOST", "0.0.0.0")
|
||||
port = int(os.getenv("API_PORT", "8000"))
|
||||
debug = os.getenv("API_DEBUG", "false").lower() == "true"
|
||||
|
||||
print(f"🚀 Starting MikroTik Gemini API on {host}:{port}")
|
||||
print(f"📚 Documentation: http://{host}:{port}/docs")
|
||||
|
||||
uvicorn.run(
|
||||
app,
|
||||
host=host,
|
||||
port=port,
|
||||
log_level="info"
|
||||
)
|
||||
256
app/context_optimizer.py
Normal file
256
app/context_optimizer.py
Normal file
@@ -0,0 +1,256 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Context Optimizer untuk MikroTik Gemini Integration
|
||||
|
||||
Optimasi data context untuk Gemini AI agar sesuai dengan token limits
|
||||
"""
|
||||
|
||||
import json
|
||||
from typing import Dict, List, Any
|
||||
|
||||
class ContextOptimizer:
|
||||
"""Optimize MikroTik data for Gemini context"""
|
||||
|
||||
def __init__(self, max_tokens: int = 8000):
|
||||
"""
|
||||
Initialize optimizer dengan max tokens
|
||||
"""
|
||||
self.max_tokens = max_tokens
|
||||
self.estimated_tokens_per_char = 0.25 # Estimasi kasar
|
||||
|
||||
def _is_true(self, value: Any) -> bool:
|
||||
"""Helper untuk cek boolean dari MikroTik (bisa bool atau string 'true')"""
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
if isinstance(value, str):
|
||||
return value.lower() == "true"
|
||||
return False
|
||||
|
||||
def estimate_tokens(self, text: str) -> int:
|
||||
"""Estimasi jumlah tokens dari text"""
|
||||
return int(len(text) * self.estimated_tokens_per_char)
|
||||
|
||||
def optimize_system_info(self, system_data: Dict) -> Dict:
|
||||
"""Optimize system information"""
|
||||
resource = system_data.get("resource", {})
|
||||
|
||||
# Ambil hanya field penting
|
||||
optimized = {
|
||||
"board_name": resource.get("board-name", "N/A"),
|
||||
"cpu_load": resource.get("cpu-load", "N/A"),
|
||||
"cpu_count": resource.get("cpu-count", "N/A"),
|
||||
"free_memory": self._format_memory(resource.get("free-memory", 0)),
|
||||
"total_memory": self._format_memory(resource.get("total-memory", 0)),
|
||||
"uptime": resource.get("uptime", "N/A"),
|
||||
"version": resource.get("version", "N/A"),
|
||||
}
|
||||
|
||||
return optimized
|
||||
|
||||
def optimize_interfaces(self, interfaces: List[Dict], max_interfaces: int = 20) -> List[Dict]:
|
||||
"""Optimize interfaces list"""
|
||||
if not interfaces:
|
||||
return []
|
||||
|
||||
# Prioritize: running interfaces, then physical, then others
|
||||
running = [i for i in interfaces if self._is_true(i.get("running"))]
|
||||
not_running = [i for i in interfaces if not self._is_true(i.get("running"))]
|
||||
|
||||
# Ambil sample dari masing-masing
|
||||
optimized = []
|
||||
|
||||
# Running interfaces (prioritas tinggi)
|
||||
for i in running[:max_interfaces//2]:
|
||||
optimized.append({
|
||||
"name": i.get("name", "N/A"),
|
||||
"type": i.get("type", "N/A"),
|
||||
"mtu": i.get("mtu", "N/A"),
|
||||
"rx": i.get("rx-byte", "N/A"),
|
||||
"tx": i.get("tx-byte", "N/A"),
|
||||
"status": "running"
|
||||
})
|
||||
|
||||
# Non-running interfaces
|
||||
for i in not_running[:max_interfaces//4]:
|
||||
optimized.append({
|
||||
"name": i.get("name", "N/A"),
|
||||
"type": i.get("type", "N/A"),
|
||||
"status": "not running",
|
||||
"disabled": i.get("disabled", "N/A")
|
||||
})
|
||||
|
||||
return optimized
|
||||
|
||||
def optimize_ppp_secrets(self, secrets: List[Dict], max_secrets: int = 10) -> List[Dict]:
|
||||
"""Optimize PPP secrets list"""
|
||||
if not secrets:
|
||||
return []
|
||||
|
||||
# Ambil hanya field penting
|
||||
optimized = []
|
||||
for secret in secrets[:max_secrets]:
|
||||
optimized.append({
|
||||
"name": secret.get("name", "N/A"),
|
||||
"service": secret.get("service", "N/A"),
|
||||
"disabled": self._is_true(secret.get("disabled")),
|
||||
"profile": secret.get("profile", "N/A")
|
||||
})
|
||||
|
||||
return optimized
|
||||
|
||||
def optimize_routes(self, routes: List[Dict], max_routes: int = 10) -> List[Dict]:
|
||||
"""Optimize routes list"""
|
||||
if not routes:
|
||||
return []
|
||||
|
||||
# Prioritize default routes dan active routes
|
||||
default_routes = [r for r in routes if r.get("dst-address", "") == "0.0.0.0/0"]
|
||||
other_routes = [r for r in routes if r.get("dst-address", "") != "0.0.0.0/0"]
|
||||
|
||||
optimized = []
|
||||
|
||||
# Default routes
|
||||
for route in default_routes[:2]:
|
||||
optimized.append({
|
||||
"dst": route.get("dst-address", "N/A"),
|
||||
"gateway": route.get("gateway", "N/A"),
|
||||
"distance": route.get("distance", "N/A"),
|
||||
"scope": route.get("scope", "N/A")
|
||||
})
|
||||
|
||||
# Other important routes
|
||||
for route in other_routes[:max_routes-2]:
|
||||
optimized.append({
|
||||
"dst": route.get("dst-address", "N/A"),
|
||||
"gateway": route.get("gateway", "N/A")
|
||||
})
|
||||
|
||||
return optimized
|
||||
|
||||
def optimize_logs(self, logs: List[Dict], max_logs: int = 40) -> List[Dict]:
|
||||
"""Optimize and filter logs (Prioritas: critical, error, warning)"""
|
||||
if not logs:
|
||||
return []
|
||||
|
||||
# Prioritas topik
|
||||
high_priority = ['critical', 'error', 'warning', 'caps']
|
||||
|
||||
important = []
|
||||
others = []
|
||||
|
||||
# Sort logs (MikroTik biasanya kasih dari terlama ke terbaru, kita mau terbaru dulu)
|
||||
sorted_logs = list(reversed(logs))
|
||||
|
||||
for log in sorted_logs:
|
||||
topics = log.get("topics", "")
|
||||
message = log.get("message", "")
|
||||
|
||||
# Cek apakah mengandung topik prioritas
|
||||
if any(p in topics for p in high_priority):
|
||||
important.append({
|
||||
"time": log.get("time", "N/A"),
|
||||
"topics": topics,
|
||||
"msg": message
|
||||
})
|
||||
else:
|
||||
others.append({
|
||||
"time": log.get("time", "N/A"),
|
||||
"topics": topics,
|
||||
"msg": message
|
||||
})
|
||||
|
||||
# Gabungkan: Important dulu, lalu others sampai limit
|
||||
optimized = important[:max_logs]
|
||||
if len(optimized) < max_logs:
|
||||
optimized.extend(others[:max_logs - len(optimized)])
|
||||
|
||||
return optimized
|
||||
|
||||
def optimize_hotspot(self, active_users: List[Dict], max_users: int = 15) -> List[Dict]:
|
||||
"""Optimize hotspot active users list"""
|
||||
if not active_users:
|
||||
return []
|
||||
|
||||
optimized = []
|
||||
for user in active_users[:max_users]:
|
||||
optimized.append({
|
||||
"user": user.get("user", "N/A"),
|
||||
"address": user.get("address", "N/A"),
|
||||
"uptime": user.get("uptime", "N/A"),
|
||||
"bytes_in": self._format_memory(user.get("bytes-in", 0)),
|
||||
"bytes_out": self._format_memory(user.get("bytes-out", 0))
|
||||
})
|
||||
return optimized
|
||||
|
||||
def create_optimized_context(self, mikrotik_data: Dict, question: str = "") -> Dict:
|
||||
"""Create optimized context untuk Gemini"""
|
||||
optimized = {
|
||||
"metadata": {
|
||||
"original_size": len(json.dumps(mikrotik_data)),
|
||||
"optimized_for": question[:50] + "..." if len(question) > 50 else question,
|
||||
"strategy": "priority_based_compression"
|
||||
},
|
||||
"summary": {
|
||||
"system": self.optimize_system_info(mikrotik_data.get("system", {})),
|
||||
"interfaces_count": len(mikrotik_data.get("interfaces", {}).get("interfaces", [])),
|
||||
"running_interfaces_count": sum(1 for i in mikrotik_data.get("interfaces", {}).get("interfaces", []) if self._is_true(i.get("running"))),
|
||||
"ppp_secrets_count": len(mikrotik_data.get("ppp", {}).get("secrets", [])),
|
||||
"routes_count": len(mikrotik_data.get("network", {}).get("routes", [])),
|
||||
},
|
||||
"details": {
|
||||
"interfaces_sample": self.optimize_interfaces(mikrotik_data.get("interfaces", {}).get("interfaces", [])),
|
||||
"ppp_secrets_sample": self.optimize_ppp_secrets(mikrotik_data.get("ppp", {}).get("secrets", [])),
|
||||
"routes_sample": self.optimize_routes(mikrotik_data.get("network", {}).get("routes", [])),
|
||||
"recent_logs": self.optimize_logs(mikrotik_data.get("logs", [])),
|
||||
"hotspot_active": self.optimize_hotspot(mikrotik_data.get("hotspot", {}).get("active", [])),
|
||||
}
|
||||
}
|
||||
|
||||
# Estimate tokens
|
||||
context_text = json.dumps(optimized)
|
||||
optimized["metadata"]["estimated_tokens"] = self.estimate_tokens(context_text)
|
||||
optimized["metadata"]["compression_ratio"] = optimized["metadata"]["original_size"] / len(context_text) if len(context_text) > 0 else 1
|
||||
|
||||
return optimized
|
||||
|
||||
def _format_memory(self, bytes_value: Any) -> str:
|
||||
"""Format memory bytes to human readable"""
|
||||
try:
|
||||
val = float(bytes_value)
|
||||
except (ValueError, TypeError):
|
||||
return "0 B"
|
||||
|
||||
if val == 0:
|
||||
return "0 B"
|
||||
|
||||
for unit in ['B', 'KB', 'MB', 'GB']:
|
||||
if val < 1024.0:
|
||||
return f"{val:.1f} {unit}"
|
||||
val /= 1024.0
|
||||
return f"{val:.1f} TB"
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
# Load sample data
|
||||
try:
|
||||
with open("../mikrotik_mcp_data.json", "r") as f:
|
||||
data = json.load(f)
|
||||
except:
|
||||
print("Error loading data")
|
||||
sys.exit(1)
|
||||
|
||||
optimizer = ContextOptimizer()
|
||||
optimized = optimizer.create_optimized_context(data, "test question")
|
||||
|
||||
print(f"Original size: {optimized['metadata']['original_size']} bytes")
|
||||
print(f"Optimized size: {len(json.dumps(optimized))} bytes")
|
||||
print(f"Compression ratio: {optimized['metadata']['compression_ratio']:.1f}x")
|
||||
print(f"Estimated tokens: {optimized['metadata']['estimated_tokens']}")
|
||||
print(f"Max tokens: {optimizer.max_tokens}")
|
||||
|
||||
if optimized["metadata"]["estimated_tokens"] > optimizer.max_tokens:
|
||||
print("⚠️ Warning: Context mungkin terlalu besar")
|
||||
else:
|
||||
print("✅ Context size OK")
|
||||
159
app/gemini_mikrotik_integration.py
Normal file
159
app/gemini_mikrotik_integration.py
Normal file
@@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Integrasi MikroTik MCP Data dengan Gemini AI - Versi Sederhana
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
from google import genai
|
||||
from dotenv import load_dotenv
|
||||
from datetime import datetime
|
||||
from context_optimizer import ContextOptimizer
|
||||
from update_data import gather_all_info, save_data
|
||||
|
||||
# Load environment
|
||||
load_dotenv()
|
||||
|
||||
class MikroTikGeminiAssistant:
|
||||
def __init__(self, data_file="data/mikrotik_mcp_data.json"):
|
||||
# Setup Gemini Client (SDK Baru)
|
||||
api_key = os.getenv("GEMINI_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError("GEMINI_API_KEY tidak ditemukan di .env")
|
||||
|
||||
self.client = genai.Client(api_key=api_key)
|
||||
self.model_id = "gemini-2.0-flash"
|
||||
|
||||
|
||||
# Load data
|
||||
self.data_file = data_file
|
||||
self.data = self._load_data()
|
||||
|
||||
# Setup Optimizer
|
||||
self.optimizer = ContextOptimizer()
|
||||
|
||||
# Inisialisasi Chat Session
|
||||
self.chat_session = None
|
||||
self._reset_chat()
|
||||
|
||||
def refresh_data(self):
|
||||
"""Ambil data terbaru langsung dari MikroTik API"""
|
||||
print("\n⏳ Sedang mengambil data terbaru dari router...")
|
||||
new_data = gather_all_info()
|
||||
if new_data:
|
||||
save_data(new_data, self.data_file)
|
||||
self.data = new_data
|
||||
self._reset_chat()
|
||||
print("✅ Data berhasil diperbarui dan sesi chat di-reset.")
|
||||
return True
|
||||
print("❌ Gagal memperbarui data.")
|
||||
return False
|
||||
|
||||
def _reset_chat(self):
|
||||
"""Reset session chat dengan konteks MikroTik terbaru yang dioptimasi"""
|
||||
optimized = self.optimizer.create_optimized_context(self.data)
|
||||
|
||||
context = f"""Anda adalah asisten ahli MikroTik. Gunakan data JSON berikut sebagai SATU-SATUNYA sumber kebenaran kondisi router saat ini.
|
||||
JANGAN membuat-buat nama interface, IP, atau status yang tidak ada di data ini.
|
||||
|
||||
DATA ROUTER (OPTIMIZED JSON):
|
||||
{json.dumps(optimized, indent=2)}
|
||||
|
||||
INSTRUKSI:
|
||||
1. Jika user bertanya tentang hal spesifik (seperti interface atau route), lihat di bagian 'details' pada JSON di atas.
|
||||
2. Jika data tidak ada, katakan jujur bahwa data tersebut tidak tersedia di snapshot saat ini.
|
||||
3. Jawab selalu dalam Bahasa Indonesia yang profesional dan format markdown.
|
||||
4. Utamakan akurasi data daripada memberikan nasihat umum.
|
||||
5. Jika user meminta data paling baru ("live" atau "sekarang"), beritahukan bahwa Anda menggunakan data terakhir yang diambil. User bisa mengetik `sync` atau `refresh` untuk melakukan sinkronisasi ulang data langsung dari router."""
|
||||
|
||||
self.chat_session = self.client.chats.create(model=self.model_id, history=[])
|
||||
# Kirim konteks awal
|
||||
self.chat_session.send_message(context)
|
||||
|
||||
def _load_data(self):
|
||||
try:
|
||||
with open(self.data_file, 'r') as f:
|
||||
return json.load(f)
|
||||
except:
|
||||
return {"error": "Data tidak ditemukan"}
|
||||
|
||||
def get_summary(self):
|
||||
"""Ringkasan data MikroTik"""
|
||||
d = self.data
|
||||
system = d.get("system", {})
|
||||
|
||||
# Handle cases where resource might be a list or missing
|
||||
resource = system.get("resource", {})
|
||||
if isinstance(resource, list):
|
||||
resource = resource[0] if len(resource) > 0 else {}
|
||||
|
||||
return {
|
||||
"device": resource.get("board-name", "N/A"),
|
||||
"cpu": resource.get("cpu-load", "N/A"),
|
||||
"memory": resource.get("free-memory", "N/A"),
|
||||
"uptime": resource.get("uptime", "N/A"),
|
||||
"version": resource.get("version", "N/A"),
|
||||
"interfaces": len(d.get("interfaces", {}).get("interfaces", [])),
|
||||
"ppp_secrets": len(d.get("ppp", {}).get("secrets", [])),
|
||||
"timestamp": d.get("metadata", {}).get("timestamp", "N/A")
|
||||
}
|
||||
|
||||
def ask(self, question):
|
||||
"""Tanya Gemini menggunakan session chat yang aktif"""
|
||||
if not self.chat_session:
|
||||
self._reset_chat()
|
||||
|
||||
try:
|
||||
response = self.chat_session.send_message(question)
|
||||
return response.text
|
||||
except Exception as e:
|
||||
return f"Error: {e}"
|
||||
|
||||
def chat(self):
|
||||
"""Mode interaktif yang mendukung history"""
|
||||
print("\n" + "="*40)
|
||||
print("🤖 MIKROTIK GEMINI INTERACTIVE CHAT")
|
||||
print("="*40)
|
||||
print("Ketik 'exit' untuk keluar")
|
||||
print("Ketik 'reset' untuk mengulang percakapan\n")
|
||||
|
||||
while True:
|
||||
q = input("👤 Anda: ").strip()
|
||||
|
||||
if not q:
|
||||
continue
|
||||
|
||||
if q.lower() in ['exit', 'quit', 'keluar']:
|
||||
print("\nSampai jumpa! 👋")
|
||||
break
|
||||
|
||||
if q.lower() in ['reset', 'refresh', 'sync', 'update']:
|
||||
self.refresh_data()
|
||||
continue
|
||||
|
||||
print("\n🤖 AI: Thinking...")
|
||||
answer = self.ask(q)
|
||||
print(f"\n{answer}\n")
|
||||
print("-" * 20)
|
||||
|
||||
# Main execution
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
if not os.getenv("GEMINI_API_KEY"):
|
||||
print("ERROR: Set GEMINI_API_KEY di .env file")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
assistant = MikroTikGeminiAssistant()
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
# Command line mode
|
||||
question = " ".join(sys.argv[1:])
|
||||
answer = assistant.ask(question)
|
||||
print(answer)
|
||||
else:
|
||||
# Interactive mode
|
||||
assistant.chat()
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
10
app/list_models.py
Normal file
10
app/list_models.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import google.generativeai as genai
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
|
||||
|
||||
for m in genai.list_models():
|
||||
if 'generateContent' in m.supported_generation_methods:
|
||||
print(m.name)
|
||||
119
app/realtime_monitor.py
Normal file
119
app/realtime_monitor.py
Normal file
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Real-time Monitoring untuk MikroTik dengan Gemini AI
|
||||
"""
|
||||
|
||||
import time
|
||||
import json
|
||||
from datetime import datetime
|
||||
from gemini_mikrotik_integration import MikroTikGeminiAssistant
|
||||
|
||||
class RealTimeMonitor:
|
||||
def __init__(self, interval=60):
|
||||
"""Initialize monitor dengan interval detik"""
|
||||
self.interval = interval
|
||||
self.assistant = MikroTikGeminiAssistant()
|
||||
self.metrics_history = []
|
||||
|
||||
def collect_metrics(self):
|
||||
"""Kumpulkan metrics dari MikroTik"""
|
||||
summary = self.assistant.get_summary()
|
||||
|
||||
metrics = {
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"cpu": summary["cpu"],
|
||||
"memory": summary["memory"],
|
||||
"interfaces": summary["interfaces"],
|
||||
"ppp_secrets": summary["ppp_secrets"],
|
||||
}
|
||||
|
||||
self.metrics_history.append(metrics)
|
||||
# Keep only last 100 readings
|
||||
if len(self.metrics_history) > 100:
|
||||
self.metrics_history = self.metrics_history[-100:]
|
||||
|
||||
return metrics
|
||||
|
||||
def check_alerts(self, metrics):
|
||||
"""Check untuk alert conditions"""
|
||||
alerts = []
|
||||
|
||||
# CPU alert
|
||||
try:
|
||||
cpu = int(metrics["cpu"].replace("%", ""))
|
||||
if cpu > 80:
|
||||
alerts.append(f"CPU tinggi: {cpu}%")
|
||||
except:
|
||||
pass
|
||||
|
||||
return alerts
|
||||
|
||||
def generate_report(self, hours=1):
|
||||
"""Generate report untuk periode tertentu"""
|
||||
# Filter metrics untuk periode terakhir
|
||||
cutoff = datetime.now().timestamp() - (hours * 3600)
|
||||
recent_metrics = [
|
||||
m for m in self.metrics_history
|
||||
if datetime.fromisoformat(m["timestamp"]).timestamp() > cutoff
|
||||
]
|
||||
|
||||
if not recent_metrics:
|
||||
return "Tidak ada data untuk periode ini"
|
||||
|
||||
# Analisis sederhana
|
||||
avg_cpu = sum(int(m["cpu"].replace("%", "")) for m in recent_metrics) / len(recent_metrics)
|
||||
|
||||
report = f"""📊 **Laporan Monitoring ({hours} jam)**
|
||||
|
||||
**Statistik:**
|
||||
- Periode: {len(recent_metrics)} readings
|
||||
- CPU Rata-rata: {avg_cpu:.1f}%
|
||||
- Interfaces: {recent_metrics[-1]['interfaces']}
|
||||
- PPP Secrets: {recent_metrics[-1]['ppp_secrets']}
|
||||
|
||||
**Status:** {'⚠️' if avg_cpu > 70 else '✅'}"""
|
||||
|
||||
return report
|
||||
|
||||
def start_monitoring(self):
|
||||
"""Start real-time monitoring loop"""
|
||||
print(f"🔍 Starting real-time monitoring (interval: {self.interval}s)")
|
||||
print("Press Ctrl+C to stop\n")
|
||||
|
||||
try:
|
||||
while True:
|
||||
metrics = self.collect_metrics()
|
||||
alerts = self.check_alerts(metrics)
|
||||
|
||||
print(f"[{metrics['timestamp'][11:19]}] ", end="")
|
||||
print(f"CPU: {metrics['cpu']} ", end="")
|
||||
print(f"Intf: {metrics['interfaces']} ", end="")
|
||||
|
||||
if alerts:
|
||||
print(f" ⚠️ Alerts: {', '.join(alerts)}")
|
||||
else:
|
||||
print(" ✅")
|
||||
|
||||
time.sleep(self.interval)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n🛑 Monitoring stopped")
|
||||
print(f"Total readings: {len(self.metrics_history)}")
|
||||
|
||||
# Generate final report
|
||||
if self.metrics_history:
|
||||
report = self.generate_report()
|
||||
print("\n" + report)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
interval = 60 # default 60 seconds
|
||||
if len(sys.argv) > 1:
|
||||
try:
|
||||
interval = int(sys.argv[1])
|
||||
except:
|
||||
pass
|
||||
|
||||
monitor = RealTimeMonitor(interval=interval)
|
||||
monitor.start_monitoring()
|
||||
20
app/test_history.py
Normal file
20
app/test_history.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from gemini_mikrotik_integration import MikroTikGeminiAssistant
|
||||
import os
|
||||
|
||||
def test():
|
||||
assistant = MikroTikGeminiAssistant()
|
||||
|
||||
print("--- Test 1: CPU Load ---")
|
||||
ans1 = assistant.ask("Berapa CPU load router saat ini?")
|
||||
print(f"A: {ans1}")
|
||||
|
||||
print("\n--- Test 2: History (Uptime) ---")
|
||||
ans2 = assistant.ask("Berapa uptimenya?")
|
||||
print(f"A: {ans2}")
|
||||
|
||||
print("\n--- Test 3: Context Connection ---")
|
||||
ans3 = assistant.ask("Apakah angka-angka tersebut masih dalam batas normal?")
|
||||
print(f"A: {ans3}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
||||
114
app/update_data.py
Normal file
114
app/update_data.py
Normal file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script untuk update data MikroTik dari REST API
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment
|
||||
load_dotenv()
|
||||
|
||||
# MikroTik credentials
|
||||
MIKROTIK_HOST = os.getenv("MIKROTIK_HOST", "192.168.1.1")
|
||||
MIKROTIK_PORT = os.getenv("MIKROTIK_PORT", "8728")
|
||||
MIKROTIK_USER = os.getenv("MIKROTIK_USER", "admin")
|
||||
MIKROTIK_PASSWORD = os.getenv("MIKROTIK_PASSWORD", "password")
|
||||
|
||||
# API endpoints
|
||||
BASE_URL = f"http://{MIKROTIK_HOST}:{MIKROTIK_PORT}/rest"
|
||||
AUTH = (MIKROTIK_USER, MIKROTIK_PASSWORD)
|
||||
|
||||
def fetch_data(endpoint):
|
||||
"""Fetch data from MikroTik REST API"""
|
||||
url = f"{BASE_URL}/{endpoint}"
|
||||
try:
|
||||
response = requests.get(url, auth=AUTH, timeout=10)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
print(f"Error fetching {endpoint}: {e}")
|
||||
return []
|
||||
|
||||
def gather_all_info():
|
||||
"""Gather all MikroTik information"""
|
||||
print("🔍 Gathering MikroTik data...")
|
||||
|
||||
data = {
|
||||
"metadata": {
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"source": "MikroTik REST API",
|
||||
"host": MIKROTIK_HOST
|
||||
},
|
||||
"system": {
|
||||
"resource": fetch_data("system/resource"),
|
||||
"identity": fetch_data("system/identity"),
|
||||
"license": fetch_data("system/license"),
|
||||
"users": fetch_data("user")
|
||||
},
|
||||
"interfaces": {
|
||||
"interfaces": fetch_data("interface")
|
||||
},
|
||||
"network": {
|
||||
"ip_addresses": fetch_data("ip/address"),
|
||||
"routes": fetch_data("ip/route")
|
||||
},
|
||||
"ppp": {
|
||||
"secrets": fetch_data("ppp/secret")
|
||||
},
|
||||
"logs": fetch_data("log"),
|
||||
"hotspot": {
|
||||
"active": fetch_data("ip/hotspot/active"),
|
||||
"users": fetch_data("ip/hotspot/user")
|
||||
}
|
||||
}
|
||||
|
||||
# Calculate statistics
|
||||
if data["interfaces"]["interfaces"]:
|
||||
total = len(data["interfaces"]["interfaces"])
|
||||
running = sum(1 for i in data["interfaces"]["interfaces"] if i.get("running") == True)
|
||||
data["interfaces"]["statistics"] = {
|
||||
"total": total,
|
||||
"running": running,
|
||||
"not_running": total - running
|
||||
}
|
||||
|
||||
if data["ppp"]["secrets"]:
|
||||
total = len(data["ppp"]["secrets"])
|
||||
enabled = sum(1 for s in data["ppp"]["secrets"] if s.get("disabled") == False)
|
||||
data["ppp"]["statistics"] = {
|
||||
"total_secrets": total,
|
||||
"enabled_secrets": enabled
|
||||
}
|
||||
|
||||
print(f"✅ Data gathered: {len(str(data))} bytes")
|
||||
return data
|
||||
|
||||
def save_data(data, filename="data/mikrotik_mcp_data.json"):
|
||||
"""Save data to JSON file"""
|
||||
try:
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||
print(f"💾 Data saved to {filename}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error saving data: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("🔄 Updating MikroTik MCP data...")
|
||||
|
||||
# Check credentials
|
||||
if not all([MIKROTIK_HOST, MIKROTIK_USER, MIKROTIK_PASSWORD]):
|
||||
print("⚠️ MikroTik credentials not set in .env file")
|
||||
print(" Using existing data file only")
|
||||
else:
|
||||
data = gather_all_info()
|
||||
if data:
|
||||
save_data(data)
|
||||
print("✅ Update completed successfully")
|
||||
else:
|
||||
print("❌ Failed to gather data")
|
||||
64
config.yaml
Normal file
64
config.yaml
Normal file
@@ -0,0 +1,64 @@
|
||||
# Konfigurasi MikroTik Gemini Integration
|
||||
|
||||
# Gemini AI Settings
|
||||
gemini:
|
||||
model: "gemini-1.5-flash-latest"
|
||||
temperature: 0.1
|
||||
max_output_tokens: 2048
|
||||
safety_settings: "BLOCK_NONE"
|
||||
|
||||
# MikroTik Settings
|
||||
mikrotik:
|
||||
data_file: "data/mikrotik_mcp_data.json"
|
||||
update_interval: 300 # seconds (5 minutes)
|
||||
|
||||
# REST API settings (for data updates)
|
||||
api:
|
||||
host: "192.168.1.1"
|
||||
port: 8728
|
||||
timeout: 10
|
||||
|
||||
# Context Optimization
|
||||
context:
|
||||
max_tokens: 8000
|
||||
max_interfaces_sample: 20
|
||||
max_ppp_secrets_sample: 10
|
||||
max_routes_sample: 10
|
||||
|
||||
# Monitoring
|
||||
monitoring:
|
||||
interval: 60 # seconds
|
||||
alert_thresholds:
|
||||
cpu: 80 # percentage
|
||||
memory: 90 # percentage
|
||||
interfaces_down: 10 # count
|
||||
|
||||
# API Server
|
||||
api_server:
|
||||
host: "0.0.0.0"
|
||||
port: 8000
|
||||
debug: false
|
||||
cors_origins:
|
||||
- "http://localhost:3000"
|
||||
- "http://localhost:8000"
|
||||
|
||||
# Logging
|
||||
logging:
|
||||
level: "INFO"
|
||||
file: "logs/app.log"
|
||||
max_size: 10485760 # 10MB
|
||||
backup_count: 5
|
||||
|
||||
# Features
|
||||
features:
|
||||
enable_realtime_monitoring: true
|
||||
enable_context_optimization: true
|
||||
enable_auto_update: false
|
||||
enable_alerts: true
|
||||
|
||||
# Security
|
||||
security:
|
||||
require_api_key: true
|
||||
allowed_ips:
|
||||
- "127.0.0.1"
|
||||
- "192.168.1.0/24"
|
||||
48215
data/mikrotik_mcp_data.json
Normal file
48215
data/mikrotik_mcp_data.json
Normal file
File diff suppressed because it is too large
Load Diff
52
docker-compose.yml
Normal file
52
docker-compose.yml
Normal file
@@ -0,0 +1,52 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
mikrotik-gemini-api:
|
||||
build: .
|
||||
container_name: mikrotik-gemini-api
|
||||
ports:
|
||||
- "8000:8000"
|
||||
environment:
|
||||
- GEMINI_API_KEY=${GEMINI_API_KEY}
|
||||
- API_HOST=0.0.0.0
|
||||
- API_PORT=8000
|
||||
volumes:
|
||||
- ../mikrotik_mcp_data.json:/app/mikrotik_mcp_data.json
|
||||
- ./logs:/app/logs
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
networks:
|
||||
- mikrotik-network
|
||||
|
||||
# Optional: Add data updater service
|
||||
data-updater:
|
||||
image: python:3.11-slim
|
||||
container_name: mikrotik-data-updater
|
||||
command: >
|
||||
sh -c "
|
||||
pip install requests &&
|
||||
python /app/update_data.py
|
||||
"
|
||||
volumes:
|
||||
- ./update_data.py:/app/update_data.py
|
||||
- ../mikrotik_mcp_data.json:/app/mikrotik_mcp_data.json
|
||||
environment:
|
||||
- MIKROTIK_HOST=${MIKROTIK_HOST}
|
||||
- MIKROTIK_PORT=${MIKROTIK_PORT}
|
||||
- MIKROTIK_USER=${MIKROTIK_USER}
|
||||
- MIKROTIK_PASSWORD=${MIKROTIK_PASSWORD}
|
||||
restart: "no" # Run once manually
|
||||
networks:
|
||||
- mikrotik-network
|
||||
|
||||
networks:
|
||||
mikrotik-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
mikrotik-data:
|
||||
130
example_prompts.md
Normal file
130
example_prompts.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# 📝 Contoh Prompt untuk MikroTik + Gemini
|
||||
|
||||
## 🎯 **Kategori: Monitoring & Status**
|
||||
|
||||
### **1. Status Sistem**
|
||||
```
|
||||
Berikan status lengkap perangkat MikroTik:
|
||||
- CPU usage saat ini
|
||||
- Memory usage
|
||||
- Interface yang running/tidak
|
||||
- PPPoE connections status
|
||||
- Rekomendasi jika ada masalah
|
||||
```
|
||||
|
||||
### **2. Health Check**
|
||||
```
|
||||
Lakukan health check perangkat:
|
||||
1. Cek error pada interfaces
|
||||
2. Cek PPPoE yang disconnected
|
||||
3. Cek memory usage
|
||||
4. Cek CPU load
|
||||
5. Berikan summary
|
||||
```
|
||||
|
||||
## 🔧 **Kategori: Troubleshooting**
|
||||
|
||||
### **3. Masalah Internet Lambat**
|
||||
```
|
||||
User mengeluh internet lambat. Analisis:
|
||||
1. Interface dengan traffic tertinggi
|
||||
2. Cek error counters
|
||||
3. Identifikasi bottleneck
|
||||
4. Berikan solusi
|
||||
```
|
||||
|
||||
### **4. Koneksi Putus-Putus**
|
||||
```
|
||||
PPPoE sering disconnect. Periksa:
|
||||
1. Log error PPPoE
|
||||
2. Signal quality
|
||||
3. MTU settings
|
||||
4. Rekomendasi fix
|
||||
```
|
||||
|
||||
## 📊 **Kategori: Analisis Jaringan**
|
||||
|
||||
### **5. Analisis Traffic**
|
||||
```
|
||||
Analisis pola traffic jaringan:
|
||||
1. Peak usage hours
|
||||
2. Top talkers
|
||||
3. Bandwidth utilization
|
||||
4. Rekomendasi optimasi
|
||||
```
|
||||
|
||||
### **6. Security Audit**
|
||||
```
|
||||
Lakukan audit keamanan:
|
||||
1. Port terbuka ke internet
|
||||
2. User accounts
|
||||
3. Firewall rules
|
||||
4. Rekomendasi hardening
|
||||
```
|
||||
|
||||
## 🛠️ **Kategori: Konfigurasi**
|
||||
|
||||
### **7. Tambah VLAN Baru**
|
||||
```
|
||||
Saya ingin menambahkan VLAN baru untuk departemen IT:
|
||||
1. VLAN apa yang sudah ada?
|
||||
2. Port available?
|
||||
3. Contoh konfigurasi
|
||||
4. Periksa konflik IP
|
||||
```
|
||||
|
||||
### **8. Setup QoS**
|
||||
```
|
||||
Setup QoS untuk prioritas VoIP:
|
||||
1. Current traffic patterns
|
||||
2. Recommended queues
|
||||
3. Configuration example
|
||||
4. Testing procedure
|
||||
```
|
||||
|
||||
## 📈 **Kategori: Reporting**
|
||||
|
||||
### **9. Daily Report**
|
||||
```
|
||||
Buat daily report:
|
||||
1. Uptime
|
||||
2. Traffic statistics
|
||||
3. Error counts
|
||||
4. Performance metrics
|
||||
5. Recommendations
|
||||
```
|
||||
|
||||
### **10. Capacity Planning**
|
||||
```
|
||||
Analisis capacity untuk ekspansi:
|
||||
1. Current utilization
|
||||
2. Growth trends
|
||||
3. Bottleneck identification
|
||||
4. Upgrade recommendations
|
||||
```
|
||||
|
||||
## 💡 **Tips Penggunaan**
|
||||
|
||||
1. **Spesifik**: Semakin spesifik pertanyaan, semakin baik jawaban
|
||||
2. **Context**: Gemini menggunakan data MikroTik sebagai context
|
||||
3. **Format**: Jawaban dalam markdown dengan tabel jika perlu
|
||||
4. **Bahasa**: Gunakan bahasa Indonesia untuk hasil terbaik
|
||||
|
||||
## 🚀 **Contoh Lengkap**
|
||||
|
||||
**Prompt:**
|
||||
```
|
||||
Berdasarkan data MikroTik, berikan analisis:
|
||||
1. Device model dan spesifikasi
|
||||
2. Current CPU dan memory usage
|
||||
3. Jumlah interface aktif
|
||||
4. Status PPPoE connections
|
||||
5. Rekomendasi maintenance
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
- Table dengan spesifikasi device
|
||||
- Chart usage (jika support)
|
||||
- List interface bermasalah
|
||||
- Action items
|
||||
```
|
||||
8
requirements.txt
Normal file
8
requirements.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
# Python dependencies for MikroTik Gemini Integration
|
||||
google-genai>=0.1.0
|
||||
python-dotenv>=1.0.0
|
||||
requests>=2.31.0
|
||||
fastapi>=0.104.0
|
||||
uvicorn>=0.24.0
|
||||
pydantic>=2.5.0
|
||||
python-multipart>=0.0.6
|
||||
Reference in New Issue
Block a user