feat(infra): MCP 인프라 서버 통합 — 7개 도구 + core/ 분리

mcp-infra-server를 gpu-services/infra/로 통합.
core/ 순수 로직은 Agent/NanoClaude에서도 직접 import 가능.
도구: docker_status, docker_logs, service_health, disk_usage,
tailscale_status, ollama_models, mlx_models.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-04-13 13:11:54 +09:00
parent 6b36063010
commit b1f9e87d6a
14 changed files with 996 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
"""Host configuration and tool-host validation.
All host IPs are Tailscale IPs (except nas-company which also works via Tailscale).
"""
from __future__ import annotations
import os
from dataclasses import dataclass, field
from dotenv import load_dotenv
load_dotenv()
@dataclass(frozen=True)
class HostConfig:
ip: str
user: str
auth: str # "key" | "password"
docker_path: str = "docker"
needs_sudo: bool = False
password: str | None = None # only for auth="password"
HOSTS: dict[str, HostConfig] = {
"gpu": HostConfig(
ip="100.111.160.84",
user="hyungi",
auth="key",
),
"macmini": HostConfig(
ip="100.76.254.116",
user="hyungi",
auth="key",
),
"nas-company": HostConfig(
ip="100.71.132.52",
user="hyungi",
auth="password",
docker_path="/usr/local/bin/docker",
needs_sudo=True,
password=os.getenv("NAS_COMPANY_PASSWORD"),
),
}
# Per-tool allowed hosts — invalid host → immediate error
TOOL_HOST_MAP: dict[str, list[str]] = {
"docker_status": ["gpu", "nas-company"],
"docker_logs": ["gpu", "nas-company"],
"disk_usage": ["gpu", "macmini", "nas-company"],
"ollama_models": ["gpu", "macmini"],
"mlx_models": ["macmini"],
}
# SSH timeouts
SSH_TIMEOUT = 5 # connection timeout (seconds)
CMD_TIMEOUT = 10 # command execution timeout (seconds)
MAX_RETRIES = 1 # retry once on failure
def validate_host(tool: str, host: str) -> HostConfig:
"""Validate host is allowed for tool and return config. Raises ValueError if invalid."""
allowed = TOOL_HOST_MAP.get(tool)
if allowed and host not in allowed:
raise ValueError(
f"'{host}'{tool}에서 지원하지 않습니다. 허용: {', '.join(allowed)}"
)
config = HOSTS.get(host)
if not config:
raise ValueError(
f"알 수 없는 호스트: '{host}'. 허용: {', '.join(HOSTS.keys())}"
)
return config