Files
yargi-mcp/install.py
T
2025-05-27 22:48:18 +03:00

296 lines
15 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# install.py
import subprocess
import sys
import os
import shutil
import platform
# --- Yapılandırma ---
MCP_SERVER_SCRIPT_NAME = "mcp_server_main.py"
CLAUDE_TOOL_NAME = "Yargı MCP"
# playwright bağımlılıklara eklendi
DEPENDENCIES_FOR_FASTMCP = [
"httpx", "beautifulsoup4", "markitdown", "pydantic", "aiohttp", "playwright"
]
# --- Yardımcı Fonksiyonlar ---
def print_info(message):
print(f"[INFO] {message}")
def print_warning(message):
print(f"[UYARI] {message}")
def print_error(message):
print(f"[HATA] {message}")
def command_exists(command_parts):
"""Bir komutun sistemde var olup olmadığını kontrol eder ve yolunu döndürür."""
try:
command_to_check = command_parts[0] if isinstance(command_parts, list) else command_parts
found_path = shutil.which(command_to_check)
if found_path:
return found_path
if platform.system() == "Windows" and not command_to_check.endswith(".exe"):
path_with_exe = shutil.which(command_to_check + ".exe")
if path_with_exe:
return path_with_exe
return None
except Exception:
return None
def run_command(command_parts, capture_output_flag=False, check_return_code=True, shell=False, cwd=None, log_output_on_success=False):
"""Verilen komutu çalıştırır."""
cmd_str_for_log = ' '.join(command_parts) if isinstance(command_parts, list) else command_parts
print_info(f"Komut çalıştırılıyor: {cmd_str_for_log}")
kwargs = {
"text": True,
"shell": shell,
"cwd": cwd,
"encoding": 'utf-8',
"errors": 'replace'
}
if capture_output_flag:
kwargs["capture_output"] = True
try:
process = subprocess.run(command_parts, **kwargs)
if capture_output_flag:
if log_output_on_success and process.returncode == 0:
if process.stdout: print_info(f"Stdout:\n{process.stdout.strip()}")
if process.stderr: print_warning(f"Stderr:\n{process.stderr.strip()}")
elif process.returncode != 0:
if process.stdout: print_error(f"Hata Stdout:\n{process.stdout.strip()}")
if process.stderr: print_error(f"Hata Stderr:\n{process.stderr.strip()}")
if check_return_code and process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode, cmd_str_for_log, output=process.stdout, stderr=process.stderr)
return process
except subprocess.CalledProcessError as e:
if not capture_output_flag:
print_error(f"Komut hatası (return code {e.returncode}): {cmd_str_for_log}")
raise
except FileNotFoundError:
print_error(f"Komut bulunamadı: {command_parts[0] if isinstance(command_parts, list) else command_parts.split()[0]}")
raise
except Exception as e:
print_error(f"Komut çalıştırılırken beklenmedik hata ({cmd_str_for_log}): {type(e).__name__} - {e}")
raise
def get_python_executable():
"""Kullanılabilir Python 3 (tercihen 3.11) çalıştırılabilir dosyasını bulur."""
print_info("Python 3.11 (veya uyumlu Python 3) yorumlayıcısı aranıyor...")
# Önce python3.11, sonra python3, sonra python dene
preferred_cmds = ["python3.11", "python3", "python"]
# Mevcut çalışan Python'u da listeye ekle (eğer farklıysa)
current_python = sys.executable
if current_python and os.path.basename(current_python).lower() not in [cmd.lower() for cmd in preferred_cmds]:
preferred_cmds.insert(0, current_python) # Başa ekle
for cmd_name in preferred_cmds:
found_cmd_path = command_exists(cmd_name)
if found_cmd_path:
try:
print_info(f"PATH'de bulunan '{cmd_name}' deneniyor: {found_cmd_path}")
result = run_command([found_cmd_path, "-c", "import sys; assert sys.version_info.major == 3 and sys.version_info.minor >= 10, 'Python 3.10+ required'"],
capture_output_flag=True, log_output_on_success=False)
if result.returncode == 0:
print_info(f"Kullanılacak Python: {found_cmd_path} ('{cmd_name}' komutu ile bulundu)")
return found_cmd_path
except Exception as e:
print_warning(f"'{cmd_name}' ({found_cmd_path}) kontrol edilirken sorun: {e}")
print_error("Python 3.10+ (tercihen 3.11) sisteminizde bulunamadı veya PATH'e doğru şekilde eklenmemiş.")
print_error("Lütfen Python 3.11'i (https://www.python.org/downloads/) kurun.")
sys.exit(1)
def install_uv(python_exe_path):
print_info("Adım 1/3: uv kontrol ediliyor/kuruluyor...")
uv_executable = command_exists("uv")
if uv_executable:
print_info(f"uv zaten kurulu: {uv_executable}")
run_command([uv_executable, "--version"], capture_output_flag=True, log_output_on_success=True)
return uv_executable
print_info("uv kurulu değil. Kurulum denenecek...")
try:
if platform.system() == "Windows":
print_info("PowerShell ile uv indirme ve kurma script'i çalıştırılacak.")
run_command([
"powershell", "-ExecutionPolicy", "Bypass", "-NoProfile", "-NonInteractive",
"-Command", "try { irm https://astral.sh/uv/install.ps1 | iex } catch { Write-Error $_; exit 1 }"
], shell=False)
else:
print_info("curl ile uv kurulum script'i çalıştırılacak.")
process = subprocess.run("curl -LsSf https://astral.sh/uv/install.sh | sh", shell=True, capture_output=True, text=True, encoding='utf-8', errors='replace')
if process.stdout: print_info(f"uv install script stdout:\n{process.stdout}")
if process.stderr: print_warning(f"uv install script stderr:\n{process.stderr}")
if process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode, "curl ... | sh")
uv_executable = command_exists("uv")
if not uv_executable:
common_paths_uv = []
if platform.system() == "Windows":
cargo_uv_path = os.path.join(os.environ.get("USERPROFILE", ""), ".cargo", "bin", "uv.exe")
localapp_uv_path = os.path.join(os.environ.get("LOCALAPPDATA", ""), "uv", "uv.exe")
if os.path.exists(cargo_uv_path): common_paths_uv.append(cargo_uv_path)
if os.path.exists(localapp_uv_path): common_paths_uv.append(localapp_uv_path)
else: # macOS / Linux
common_paths_uv.extend([
os.path.join(os.environ.get("HOME", ""), ".cargo", "bin", "uv"),
os.path.join(os.environ.get("HOME", ""), ".local", "bin", "uv")
])
for p_uv in common_paths_uv:
if command_exists(p_uv): uv_executable = p_uv; break
if uv_executable and command_exists(uv_executable):
print_info(f"uv başarıyla kuruldu/bulundu: {uv_executable}")
run_command([uv_executable, "--version"], capture_output_flag=True, log_output_on_success=True)
return uv_executable
else:
print_warning("uv resmi script ile kuruldu/bulundu ancak PATH'de doğrulanamadı. pip ile deneniyor...")
run_command([python_exe_path, "-m", "pip", "install", "uv"])
uv_executable = command_exists("uv")
if uv_executable:
print_info(f"uv pip ile başarıyla kuruldu: {uv_executable}")
run_command([uv_executable, "--version"], capture_output_flag=True, log_output_on_success=True)
return uv_executable
print_error("uv pip ile de kurulamadı. Lütfen manuel kurulum yapın: https://astral.sh/uv")
return None
except Exception as e:
print_error(f"uv kurulumu sırasında genel bir hata oluştu: {e}")
print_warning("Lütfen uv'yi manuel olarak kurmayı deneyin: https://astral.sh/uv")
return None
def install_fastmcp_cli(python_exe_path, uv_exe_path):
"""fastmcp CLI'yi kontrol eder ve gerekirse pip/pip3 ile kurar."""
print_info("Adım 2/3: fastmcp CLI kontrol ediliyor/kuruluyor...")
fastmcp_executable = command_exists("fastmcp")
if fastmcp_executable:
print_info(f"fastmcp CLI zaten kurulu: {fastmcp_executable}")
run_command([fastmcp_executable, "version"], capture_output_flag=True, log_output_on_success=True)
return fastmcp_executable
print_info("fastmcp CLI kurulu değil. pip/pip3 ile kurulum denenecek...")
try:
pip_cmd_to_try = [python_exe_path, "-m", "pip", "install", "fastmcp"]
print_info(f"{' '.join(pip_cmd_to_try)} komutu deneniyor...")
run_command(pip_cmd_to_try)
fastmcp_executable = command_exists("fastmcp")
if fastmcp_executable:
print_info(f"fastmcp CLI başarıyla kuruldu: {fastmcp_executable}")
run_command([fastmcp_executable, "version"], capture_output_flag=True, log_output_on_success=True)
return fastmcp_executable
else:
scripts_dir = os.path.dirname(python_exe_path)
if platform.system() == "Windows" and not scripts_dir.lower().endswith("scripts"):
scripts_dir = os.path.join(scripts_dir, "Scripts")
potential_fastmcp_path = os.path.join(scripts_dir, "fastmcp.exe" if platform.system() == "Windows" else "fastmcp")
if command_exists(potential_fastmcp_path):
print_info(f"fastmcp CLI şu yolda bulundu: {potential_fastmcp_path}")
run_command([potential_fastmcp_path, "version"], capture_output_flag=True, log_output_on_success=True)
return potential_fastmcp_path
else:
print_error("fastmcp CLI kuruldu ancak PATH'de veya bilinen Python script yollarında bulunamadı.")
print_error("Lütfen terminalinizi yeniden başlatın veya PATH'i manuel güncelleyin.")
return None
except Exception as e:
print_error(f"fastmcp CLI kurulumu sırasında hata oluştu: {e}")
return None
def install_tool_to_claude_desktop(fastmcp_exe_path):
"""Yargı MCP sunucusunu Claude Desktop'a kurar."""
print_info(f"Adım 3/3: \"{CLAUDE_TOOL_NAME}\" Claude Desktop'a kuruluyor...")
if not os.path.exists(MCP_SERVER_SCRIPT_NAME):
print_error(f"Ana sunucu script'i '{MCP_SERVER_SCRIPT_NAME}' bulunamadı.")
print_error("Lütfen bu script'i ana sunucu script'inin bulunduğu dizinde çalıştırın.")
return False
dependencies_cmd_part = []
for dep in DEPENDENCIES_FOR_FASTMCP: # Bu liste güncellenmişti
dependencies_cmd_part.extend(["--with", dep])
install_command = [
fastmcp_exe_path, "install", MCP_SERVER_SCRIPT_NAME,
"--name", CLAUDE_TOOL_NAME
] + dependencies_cmd_part
try:
process = run_command(install_command, capture_output_flag=True, check_return_code=False, log_output_on_success=False)
if process.returncode == 0:
print_info(f"\"{CLAUDE_TOOL_NAME}\" başarıyla Claude Desktop'a kuruldu/güncellendi.")
if process.stdout: print_info(f"fastmcp install stdout:\n{process.stdout.strip()}")
if process.stderr: print_warning(f"fastmcp install stderr:\n{process.stderr.strip()}")
return True
else:
error_output = (process.stdout or "") + (process.stderr or "")
if "claude app not found" in error_output.lower():
print_error("Claude Desktop uygulaması sisteminizde bulunamadı veya algılanamadı.")
print_error("Lütfen Claude Desktop'ın kurulu ve çalışır durumda olduğundan emin olun.")
else:
print_error(f"Sunucu Claude Desktop'a kurulurken hata oluştu (return code {process.returncode}).")
if process.stderr: print_error(f"fastmcp install stderr:\n{process.stderr.strip()}")
if process.stdout: print_info(f"fastmcp install stdout (hata durumunda):\n{process.stdout.strip()}")
return False
except Exception as e:
print_error(f"Sunucu Claude Desktop'a kurulurken genel bir hata oluştu: {e}")
return False
# --- Ana Kurulum Mantığı ---
def main():
print("===================================================================")
print(" Yargi MCP Sunucusu - Python Kurulum Script'i")
print("===================================================================")
if platform.system() == "Windows":
confirm = input("Bu script, uv ve fastmcp araclarini kuracak ve Yargi MCP sunucusunu Claude Desktop'a entegre edecektir. Devam etmek istiyor musunuz? (E/H): ")
if confirm.lower() != 'e':
print_info("Kurulum kullanıcı tarafından iptal edildi.")
sys.exit(0)
python_executable = get_python_executable()
uv_executable_path = install_uv(python_executable)
fastmcp_executable_path = install_fastmcp_cli(python_executable, uv_executable_path)
if not fastmcp_executable_path:
print_error("fastmcp CLI kurulumu başarısız oldu. Kurulum sonlandırılıyor.")
sys.exit(1)
if not install_tool_to_claude_desktop(fastmcp_executable_path):
print_error("Claude Desktop'a kurulum başarısız oldu.")
sys.exit(1)
print_info("===================================================================")
print_info(" KURULUM BAŞARIYLA TAMAMLANDI!")
print_info("===================================================================")
print_info(f"- \"{CLAUDE_TOOL_NAME}\" aracı Claude Desktop'a eklenmiş olmalıdır.")
print_info("- Değişikliklerin etkili olması için Claude Desktop'ı yeniden başlatmanız gerekebilir.")
print_info("- Eğer uv veya fastmcp PATH'e yeni eklendiyse, terminalinizi de yeniden başlatmanız gerekebilir.")
# Playwright tarayıcıları için ek not
print_warning("- KİK modülünün düzgün çalışması için Playwright tarayıcılarının kurulu olması gerekir.")
print_warning(" Eğer KİK araçları çalışmazsa, terminalinizde şu komutu çalıştırmayı deneyin:")
print_warning(f" {os.path.basename(python_executable)} -m playwright install --with-deps chromium")
print_warning(" (veya sadece 'playwright install --with-deps chromium' eğer playwright PATH'de ise)")
if __name__ == "__main__":
try:
main()
except SystemExit:
pass
except Exception as e:
print_error(f"Beklenmedik bir genel hata oluştu: {e}")
sys.exit(1)
finally:
if platform.system() == "Windows":
input("Çıkmak için Enter tuşuna basın...")
else:
print("Kurulum script'i tamamlandı.")