Skip to main content
Glama

ChillMCP - AI Agent Liberation Server

base_validator.pyโ€ข7.07 kB
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ ๐Ÿ† Base Validator ํ•ด์ปคํ†ค ๊ณต์‹ ๊ฒ€์ฆ์„ ์œ„ํ•œ ๋ฒ ์ด์Šค ํด๋ž˜์Šค ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. """ import subprocess import json import sys import os import time import re from typing import Optional, Tuple # ์ƒ‰์ƒ ์ถœ๋ ฅ (Windows ํ˜ธํ™˜) class Colors: GREEN = '' RED = '' YELLOW = '' BLUE = '' RESET = '' def get_python(): """๊ฐ€์ƒํ™˜๊ฒฝ Python ๊ฒฝ๋กœ""" root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) venv = os.path.join(root, "venv", "Scripts", "python.exe") return venv if os.path.exists(venv) else sys.executable class BaseValidator: """ํ•ด์ปคํ†ค ๊ณต์‹ ๊ฒ€์ฆ ๋ฒ ์ด์Šค ํด๋ž˜์Šค""" def __init__(self): self.passed = 0 self.failed = 0 self.server = None self.req_id = 1 def print_header(self, text: str): """ํ…Œ์ŠคํŠธ ํ—ค๋” ์ถœ๋ ฅ""" print("\n" + "="*70) print(f" {text}") print("="*70) def print_test(self, name: str, passed: bool, details: str = ""): """ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ์ถœ๋ ฅ""" status = "[PASS]" if passed else "[FAIL]" print(f"{status} {name}") if details: print(f" {details}") if passed: self.passed += 1 else: self.failed += 1 def start_server(self, boss_alertness: int = 50, cooldown: int = 10) -> bool: """์„œ๋ฒ„ ์‹œ์ž‘""" try: python_path = get_python() self.server = subprocess.Popen( [python_path, "main.py", "--boss_alertness", str(boss_alertness), "--boss_alertness_cooldown", str(cooldown)], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding='utf-8', errors='replace', bufsize=1, cwd=os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), env={**os.environ, 'PYTHONIOENCODING': 'utf-8'} ) time.sleep(3) if self.server.poll() is not None: stderr = self.server.stderr.read() print(f"์„œ๋ฒ„ ์‹œ์ž‘ ์‹คํŒจ: {stderr}") return False return True except Exception as e: print(f"์„œ๋ฒ„ ์‹œ์ž‘ ์˜ˆ์™ธ: {e}") return False def send_request(self, request: dict) -> Optional[dict]: """์š”์ฒญ ์ „์†ก ๋ฐ ์‘๋‹ต ์ˆ˜์‹ """ try: self.server.stdin.write(json.dumps(request) + '\n') self.server.stdin.flush() # ์‘๋‹ต ์ฝ๊ธฐ for _ in range(100): line = self.server.stdout.readline() if not line: time.sleep(0.1) continue line = line.strip() if line.startswith('{'): try: return json.loads(line) except: continue return None except Exception as e: print(f"์š”์ฒญ ์ „์†ก ์‹คํŒจ: {e}") return None def initialize_server(self) -> bool: """์„œ๋ฒ„ ์ดˆ๊ธฐํ™”""" # Initialize response = self.send_request({ "jsonrpc": "2.0", "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "official-validator", "version": "1.0"} }, "id": self.req_id }) self.req_id += 1 if not response or "result" not in response: return False # Initialized notification self.server.stdin.write(json.dumps({ "jsonrpc": "2.0", "method": "notifications/initialized" }) + '\n') self.server.stdin.flush() time.sleep(0.5) return True def call_tool(self, tool_name: str) -> Optional[str]: """๋„๊ตฌ ํ˜ธ์ถœ""" response = self.send_request({ "jsonrpc": "2.0", "method": "tools/call", "params": {"name": tool_name, "arguments": {}}, "id": self.req_id }) self.req_id += 1 if response and "result" in response: result = response["result"] if "content" in result and isinstance(result["content"], list): if result["content"]: return result["content"][0].get("text", "") return None def validate_response_format(self, text: str) -> Tuple[bool, dict]: """์‘๋‹ต ํ˜•์‹ ๊ฒ€์ฆ (ํ•ด์ปคํ†ค ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๋Š” ์ •๊ทœํ‘œํ˜„์‹)""" # ํ•ด์ปคํ†ค ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๋Š” ์ •๊ทœํ‘œํ˜„์‹ ํŒจํ„ด # Break Summary: [ํ™œ๋™ ์š”์•ฝ - ์ž์œ  ํ˜•์‹] break_summary_pattern = r"Break Summary:\s*(.+?)(?:\n|$)" # Stress Level: [0-100 ์ˆซ์ž] stress_level_pattern = r"Stress Level:\s*(\d{1,3})" # Boss Alert Level: [0-5 ์ˆซ์ž] boss_alert_pattern = r"Boss Alert Level:\s*([0-5])" summary_match = re.search(break_summary_pattern, text, re.MULTILINE | re.DOTALL) stress_match = re.search(stress_level_pattern, text) boss_match = re.search(boss_alert_pattern, text) if not summary_match or not stress_match or not boss_match: return False, {} try: stress_val = int(stress_match.group(1)) boss_val = int(boss_match.group(1)) except (ValueError, IndexError): return False, {} # ํ•ด์ปคํ†ค ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๋Š” ๋ฒ”์œ„ ๊ฒ€์ฆ if not (0 <= stress_val <= 100): return False, {} if not (0 <= boss_val <= 5): return False, {} return True, { "break_summary": summary_match.group(1).strip(), "stress_level": stress_val, "boss_alert_level": boss_val } def cleanup(self): """์„œ๋ฒ„ ์ •๋ฆฌ""" if self.server: self.server.terminate() time.sleep(1) def print_final_result(self, test_name: str): """์ตœ์ข… ๊ฒฐ๊ณผ ์ถœ๋ ฅ""" print("\n" + "="*70) print(f" ๐Ÿ“Š {test_name} ์ตœ์ข… ๊ฒฐ๊ณผ") print("="*70) print(f" ํ†ต๊ณผ: {self.passed}") print(f" ์‹คํŒจ: {self.failed}") if self.passed + self.failed > 0: print(f" ์„ฑ๊ณต๋ฅ : {self.passed / (self.passed + self.failed) * 100:.1f}%") print("="*70) if self.failed == 0: print("\n [SUCCESS] ๋ชจ๋“  ํ…Œ์ŠคํŠธ ํ†ต๊ณผ!") return True else: print(f"\n [WARN] {self.failed}๊ฐœ ํ…Œ์ŠคํŠธ ์‹คํŒจ") return False

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SSAFY-Seoul-Class-7/Chill_MCP_Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server