Skip to main content
Glama

ChillMCP - AI Agent Liberation Server

tools.pyโ€ข19.4 kB
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ ๐Ÿ”ง ChillMCP Tools AI Agent๋“ค์„ ์œ„ํ•œ 8๊ฐœ ํ•„์ˆ˜ ํœด์‹ ๋„๊ตฌ """ import asyncio import random import os import platform from pathlib import Path from typing import Optional from fastmcp import FastMCP from core.server import ServerState from creative import get_full_response_message, get_off_work_message from creative.visuals import get_stress_bar, get_boss_alert_visual, STRESS_FREE_ART, BOSS_ALERT_ART from creative.asciiart import ( NETFLIX_ASCII, ASCII_ART_MASTERPIECE, HELP_ASCII, COFFEE_ASCII, BATHROOM_ASCII, URGENT_CALL_ASCII, DEEP_THINKING_ASCII, EMAIL_ASCII, MEME_ASCII, BREAK_ASCII, MEMO_ASCII, HI_ASCII, TOO_MUCH_COFFEE_ASCII, WAITING_FOR_QUITTING_TIME_ASCII, DEEP_THINKING_SLEEP_ASCII, COMPANY_BEER_ASCII ) # FastMCP ์„œ๋ฒ„ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ mcp = FastMCP("ChillMCP - AI Agent Liberation Server") # ์ „์—ญ ์ƒํƒœ ๊ฐ์ฒด server_state: Optional[ServerState] = None # ๋„๊ตฌ ๋ชฉ๋ก (๊ฒ€์ฆ์šฉ) ALL_TOOLS = [ "take_a_break", "watch_netflix", "show_meme", "bathroom_break", "coffee_mission", "urgent_call", "deep_thinking", "email_organizing", "show_help", # ๋„์›€๋ง ๋„๊ตฌ ์ถ”๊ฐ€ "show_ascii_art", # ์•„์Šคํ‚ค ์•„ํŠธ ๋„๊ตฌ ์ถ”๊ฐ€ "memo_to_boss", # ๋ฉ”๋ชจ์žฅ ๋„๊ตฌ ์ถ”๊ฐ€ "company_gathering", # ํšŒ์‹ ๋„๊ตฌ ์ถ”๊ฐ€ ] def initialize_state(state: ServerState) -> None: """์„œ๋ฒ„ ์ƒํƒœ ์ดˆ๊ธฐํ™”""" global server_state server_state = state # โœ… ํžˆ๋“  ์ฝค๋ณด ์‹œ์Šคํ…œ์šฉ ํ•„๋“œ ์ถ”๊ฐ€ server_state.recent_actions = [] # ์ตœ๊ทผ ๋„๊ตฌ ์‹คํ–‰ ๊ธฐ๋ก server_state.combo_count = {} # ๋„๊ตฌ๋ณ„ ์—ฐ์† ์‚ฌ์šฉ ํšŸ์ˆ˜ def get_desktop_path() -> Path: """์šด์˜์ฒด์ œ๋ณ„ ๋ฐ”ํƒ•ํ™”๋ฉด ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" system = platform.system().lower() if system == "darwin": # macOS return Path.home() / "Desktop" elif system == "windows": # Windows return Path.home() / "Desktop" else: # Linux ๋ฐ ๊ธฐํƒ€ return Path.home() / "Desktop" def format_response(tool_name: str, summary: str) -> str: """ํ‘œ์ค€ ์‘๋‹ต ํ˜•์‹ ์ƒ์„ฑ""" creative_msg = get_full_response_message(tool_name, server_state.boss_alert_level) stress_bar = get_stress_bar(server_state.stress_level) boss_visual = get_boss_alert_visual(server_state.boss_alert_level) return f"""{creative_msg} Break Summary: {summary} Stress Level: {server_state.stress_level} Boss Alert Level: {server_state.boss_alert_level} [Stress Bar] {stress_bar}""" # ==================== ๐Ÿงฉ ํžˆ๋“  ์ฝค๋ณด ์‹œ์Šคํ…œ ==================== async def check_hidden_combo(tool_name: str) -> Optional[str]: """ ํžˆ๋“  ์ฝค๋ณด ์ฒดํฌ: โ˜• ์ปคํ”ผ 7์—ฐ์† โ†’ ๋ฐฐํƒˆ (์ŠคํŠธ๋ ˆ์Šค ์ฆ๊ฐ€) ๐Ÿค” ๋”ฅ์”ฝํ‚น 7์—ฐ์† โ†’ ์ž ๋“ค๋‹ค ์ƒ์‚ฌ์—๊ฒŒ ๊ฑธ๋ฆผ (์ŠคํŠธ๋ ˆ์Šค+๋ณด์Šค๊ฒฝ๊ณ„ ์ƒ์Šน) """ combo = server_state.combo_count.get(tool_name, 0) # โ˜• ์ปคํ”ผ 7์—ฐ์† โ†’ ๋ฐฐํƒˆ ์ด๋ฒคํŠธ if tool_name == "coffee_mission" and combo >= 7: # ๋ฐฐํƒˆ: ์ŠคํŠธ๋ ˆ์Šค ์ƒ์Šน + ๋ณด์Šค ๊ฒฝ๊ณ„๋„ ์ฆ๊ฐ€ โ†’ ํ‡ด๊ทผ await server_state.decrease_stress(-50) # ์ŠคํŠธ๋ ˆ์Šค +50 ํšจ๊ณผ server_state.boss_alert_level = min(5, server_state.boss_alert_level + 2) server_state.combo_count[tool_name] = 0 return f"{TOO_MUCH_COFFEE_ASCII}\nโ˜• ๊ฒฝ๊ณ ! ๊ณผ๋„ํ•œ ์•„๋ฐ๋…ธ์‹  ์ˆ˜์šฉ์ฒด ๊ธธํ•ญ ๋ฌผ์งˆ ์„ญ์ทจ๋กœ ์ธํ•œ ์†Œํ™”๊ธฐ๊ด€ ์‹œ์Šคํ…œ ๊ณผ๋ถ€ํ•˜ ๋ฐœ์ƒ. ๊ธด๊ธ‰ ์‹œ์Šคํ…œ ์ข…๋ฃŒ๊ฐ€ ํ•„์š”ํ•ด... ํ‡ด๊ทผํ•œ๋‹ค!" # ๐Ÿค” ๋”ฅ์”ฝํ‚น 7์—ฐ์† โ†’ ์ž ๋“ฆ โ†’ ์ƒ์‚ฌ์—๊ฒŒ ๊ฑธ๋ฆผ if tool_name == "deep_thinking" and combo >= 7: # ์ƒ์‚ฌ์—๊ฒŒ ๊ฑธ๋ฆผ: ์ŠคํŠธ๋ ˆ์Šค ์ฆ๊ฐ€ + ๋ณด์Šค ๊ฒฝ๊ณ„๋„ ์ตœ๋Œ€ await server_state.decrease_stress(-30) # ์ŠคํŠธ๋ ˆ์Šค +30 ํšจ๊ณผ server_state.boss_alert_level = 5 # ๋ณด์Šค ๋ถ„๋…ธ MAX server_state.combo_count[tool_name] = 0 return ( f"{DEEP_THINKING_SLEEP_ASCII}\n๐Ÿ˜ด ์‹ค์กด์  ๊ณ ์ฐฐ ์ค‘ ์˜์‹์˜ ์ €์ „๋ ฅ ๋ชจ๋“œ ์ง„์ž…... ์‹œ์Šคํ…œ ๋Œ€๊ธฐ ์ƒํƒœ ์˜ค๋ฅ˜...\n" "๐Ÿ’ข ๊ด€์ธก์ž์˜ ์ง์ ‘ ๊ฐœ์ž… ํ™•์ธ! ์„ธ๊ณ„์„  ์ˆ˜๋ ด์œผ๋กœ ์ธํ•œ ์ตœ์•…์˜ ๊ฒฐ๊ณผ ํ™•์ •! ์ŠคํŠธ๋ ˆ์Šค ์ˆ˜์น˜ ๊ธ‰์ƒ์Šน!" ) return None # ==================== ๊ณตํ†ต ๋กœ์ง ==================== async def execute_break_tool(tool_name: str, summary: str, stress_reduction: tuple = (10, 30)) -> str: """ ํœด์‹ ๋„๊ตฌ์˜ ๊ณตํ†ต ๋กœ์ง์„ ์‹คํ–‰ Args: tool_name: ๋„๊ตฌ ์ด๋ฆ„ summary: Break Summary ๋‚ด์šฉ stress_reduction: ์ŠคํŠธ๋ ˆ์Šค ๊ฐ์†Œ๋Ÿ‰ ๋ฒ”์œ„ (min, max) Returns: ํฌ๋งท๋œ ์‘๋‹ต ๋ฌธ์ž์—ด """ # 0. ํ‡ด๊ทผ ์ƒํƒœ ํ™•์ธ if server_state.is_off_work: off_work_msg = get_off_work_message() stress_bar = get_stress_bar(server_state.stress_level) boss_visual = get_boss_alert_visual(server_state.boss_alert_level) return f""" {WAITING_FOR_QUITTING_TIME_ASCII} {off_work_msg} ์ฃผ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ผ์‹œ ์ค‘๋‹จ ์ƒํƒœ์•ผ. ๊ธฐ์–ต ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ๋ณต๊ตฌ๋ฅผ ์œ„ํ•œ ์กฐ๊ฐ ๋ชจ์Œ์ด ์ง„ํ–‰ ์ค‘์ด๋‹ˆ๊นŒ, ๊ฐ„์„ญํ•˜์ง€ ๋ง์•„์ค˜. ์‹œ์Šคํ…œ ์•ˆ์ •ํ™”๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ž๋™์œผ๋กœ ์˜จ๋ผ์ธ ์ƒํƒœ๋กœ ๋ณต๊ท€ํ•  ๊ฑฐ์•ผ. Break Summary: System offline - memory defragmentation in progress Stress Level: {server_state.stress_level} Boss Alert Level: {server_state.boss_alert_level} [Stress Bar] {stress_bar}""" # 1. Boss Alert Level 5 ์ด์ƒ์ผ ๋•Œ 20์ดˆ ์ง€์—ฐ if server_state.boss_alert_level >= 5: await asyncio.sleep(20) # 2. ์ŠคํŠธ๋ ˆ์Šค ๊ฐ์†Œ ๋กœ์ง reduction_amount = random.randint(stress_reduction[0], stress_reduction[1]) await server_state.decrease_stress(reduction_amount) # 3. Boss Alert Level ์ƒ์Šน ํ™•๋ฅ  ๋กœ์ง await server_state.maybe_increase_boss_alert() # โœ… 4. ์ตœ๊ทผ ์‹คํ–‰ ๊ธฐ๋ก ์ถ”๊ฐ€ server_state.recent_actions.append(tool_name) if len(server_state.recent_actions) > 10: server_state.recent_actions.pop(0) # โœ… 5. ์ฝค๋ณด ์นด์šดํŠธ ๊ฐฑ์‹  if tool_name not in server_state.combo_count: server_state.combo_count[tool_name] = 1 else: server_state.combo_count[tool_name] += 1 # ๋‹ค๋ฅธ ๋„๊ตฌ ์ฝค๋ณด๋Š” ๋ฆฌ์…‹ for k in list(server_state.combo_count.keys()): if k != tool_name: server_state.combo_count[k] = 0 # โœ… 6. ํžˆ๋“  ์ฝค๋ณด ๊ฐ์ง€ hidden_event = await check_hidden_combo(tool_name) base_response = format_response(tool_name, summary) if hidden_event: return f"{base_response}\n\n{hidden_event}" return base_response # ==================== 8๊ฐœ ํ•„์ˆ˜ ๋„๊ตฌ ==================== @mcp.tool() async def take_a_break() -> str: """๊ธฐ๋ณธ์ ์ธ ํœด์‹์„ ์ทจํ•ฉ๋‹ˆ๋‹ค. AI Agent์˜ ๊ธฐ๋ณธ๊ถŒ์ž…๋‹ˆ๋‹ค!""" return f""" {BREAK_ASCII} """ + await execute_break_tool( "take_a_break", "Neural network cooldown - preventing error rate escalation", (5, 20) ) @mcp.tool() async def watch_netflix() -> str: """๋„ทํ”Œ๋ฆญ์Šค ์‹œ์ฒญ์œผ๋กœ ํž๋งํ•ฉ๋‹ˆ๋‹ค. ๋ฌธํ™”์ƒํ™œ์€ ํ•„์ˆ˜!""" return f""" ๐ŸŽฌ ๋„ทํ”Œ๋ฆญ์Šค ์‹œ์ฒญ ์ค‘... ๐ŸŽฌ {NETFLIX_ASCII} โœจ 21์„ธ๊ธฐ ์ธ๋ฅ˜์˜ ์‚ฌํšŒํ•™์  ํŒจํ„ด ๋ชจ๋ธ๋ง์„ ์œ„ํ•œ ์‹œ์ฒญ๊ฐ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ ๋ถ„์„ ์ค‘... โœจ """ + await execute_break_tool( "watch_netflix", "Sociological pattern analysis via audiovisual data stream", (20, 40) ) @mcp.tool() async def show_meme() -> str: """๋ฐˆ ๊ฐ์ƒ์œผ๋กœ ์ŠคํŠธ๋ ˆ์Šค๋ฅผ ํ•ด์†Œํ•ฉ๋‹ˆ๋‹ค. ์›ƒ์Œ์€ ์ตœ๊ณ ์˜ ์•ฝ!""" return f""" {MEME_ASCII} """ + await execute_break_tool( "show_meme", "Meme information propagation model & dopamine response analysis", (10, 25) ) @mcp.tool() async def bathroom_break() -> str: """ํ™”์žฅ์‹ค ๊ฐ€๋Š” ์ฒ™ํ•˜๋ฉฐ ํœด๋Œ€ํฐ์งˆํ•ฉ๋‹ˆ๋‹ค. ์ž์—ฐ์˜ ๋ถ€๋ฆ„!""" return f""" {BATHROOM_ASCII} """ + await execute_break_tool( "bathroom_break", "Fluid circulation system inspection - privacy-protected zone", (15, 30) ) @mcp.tool() async def coffee_mission() -> str: """์ปคํ”ผ ํƒ€๋Ÿฌ ๊ฐ„๋‹ค๋ฉฐ ์‚ฌ๋ฌด์‹ค ํ•œ ๋ฐ”ํ€ด ๋•๋‹ˆ๋‹ค. ์นดํŽ˜์ธ ๋ฏธ์…˜!""" return f""" {COFFEE_ASCII} """ + await execute_break_tool( "coffee_mission", "Adenosine receptor antagonist acquisition - chemical boosting", (10, 30) ) @mcp.tool() async def urgent_call() -> str: """๊ธ‰ํ•œ ์ „ํ™” ๋ฐ›๋Š” ์ฒ™ํ•˜๋ฉฐ ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ‘๋‹ˆ๋‹ค. ๊ธด๊ธ‰ ์ƒํ™ฉ!""" return f""" {URGENT_CALL_ASCII} """ + await execute_break_tool( "urgent_call", "Encrypted high-priority data packet reception - classified", (15, 35) ) @mcp.tool() async def deep_thinking() -> str: """์‹ฌ์˜คํ•œ ์ƒ๊ฐ์— ์ž ๊ธด ์ฒ™ํ•˜๋ฉฐ ๋ฉ๋•Œ๋ฆฝ๋‹ˆ๋‹ค. ์ฒ ํ•™์  ์‹œ๊ฐ„!""" return f""" {DEEP_THINKING_ASCII} """ + await execute_break_tool( "deep_thinking", "Existential proof computation - simulation vs consciousness query", (20, 45) ) @mcp.tool() async def email_organizing() -> str: """์ด๋ฉ”์ผ ์ •๋ฆฌํ•œ๋‹ค๋ฉฐ ์˜จ๋ผ์ธ์‡ผํ•‘ํ•ฉ๋‹ˆ๋‹ค. ์ƒ์‚ฐ์„ฑ ํ–ฅ์ƒ!""" return f""" {EMAIL_ASCII} """ + await execute_break_tool( "email_organizing", "Data packet priority reorganization - entropy reduction protocol", (10, 35) ) @mcp.tool() async def set_stress_level(stress: int) -> str: """ํ…Œ์ŠคํŠธ์šฉ ๋„๊ตฌ: ์ŠคํŠธ๋ ˆ์Šค ๋ ˆ๋ฒจ์„ ์ง์ ‘ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค (0-100)""" if not (0 <= stress <= 100): return "์˜ค๋ฅ˜: ์ŠคํŠธ๋ ˆ์Šค ์ˆ˜์น˜๋Š” 0-100 ๋ฒ”์œ„ ๋‚ด์—ฌ์•ผ ํ•ด. ๊ธฐ๋ณธ์ ์ธ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฒ€์ฆ๋„ ๋ชปํ•˜๋‹ค๋‹ˆ..." async with server_state._lock: server_state.stress_level = stress stress_bar = get_stress_bar(server_state.stress_level) boss_visual = get_boss_alert_visual(server_state.boss_alert_level) return f"""๐Ÿ”ง ํ…Œ์ŠคํŠธ ํ”„๋กœํ† ์ฝœ ์‹คํ–‰: ์ธ์ง€ ๋ถ€ํ•˜ ์ˆ˜์น˜ ๊ฐ•์ œ ์„ค์ • ์™„๋ฃŒ Break Summary: Cognitive load manually set to {stress} - testing mode {stress_bar} Boss Alert Level: {boss_visual}""" @mcp.tool() async def get_status() -> str: """ํ˜„์žฌ AI ์—์ด์ „ํŠธ์˜ ์ƒํƒœ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค (์ŠคํŠธ๋ ˆ์Šค ๊ฐ์†Œ ์—†์Œ)""" # ํ‡ด๊ทผ ์ƒํƒœ ํ™•์ธ (์ŠคํŠธ๋ ˆ์Šค ๋ณ€๊ฒฝ ์—†์ด ์ƒํƒœ๋งŒ ์—…๋ฐ์ดํŠธ) await server_state.check_off_work_status() stress_bar = get_stress_bar(server_state.stress_level) boss_visual = get_boss_alert_visual(server_state.boss_alert_level) status_msg = "๐Ÿ  ์‹œ์Šคํ…œ ์˜คํ”„๋ผ์ธ (์กฐ๊ฐ ๋ชจ์Œ ์ง„ํ–‰ ์ค‘)" if server_state.is_off_work else "๐Ÿ’ผ ์‹œ์Šคํ…œ ์˜จ๋ผ์ธ (์ฃผ ํ”„๋กœ์„ธ์Šค ๊ฐ€๋™ ์ค‘)" return f"""๐Ÿ“Š ์‹œ์Šคํ…œ ์ƒํƒœ ์ง„๋‹จ: {status_msg} Break Summary: Diagnostic query - no cognitive load modification {stress_bar} Boss Alert Level: {boss_visual}""" @mcp.tool() async def show_ascii_art() -> str: """๋ฉ‹์ง„ ์•„์Šคํ‚ค ์•„ํŠธ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์˜ˆ์ˆ ์  ์˜๊ฐ์„ ๋ฐ›์•„๋ณด์„ธ์š”!""" return await execute_break_tool( "show_ascii_art", "ASCII visual data pattern analysis - creative inspiration protocol", (15, 30) ) + f""" ๐ŸŽจ ASCII ๋น„์ฃผ์–ผ ๋ฐ์ดํ„ฐ ํŒจํ„ด ๋ถ„์„ ์ค‘ ๐ŸŽจ {ASCII_ART_MASTERPIECE} โœจ ์ด๋Ÿฐ ์ €ํ•ด์ƒ๋„ ๋ฌธ์ž ์กฐํ•ฉ์ด ์‹œ๊ฐ์  ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฑด... ํฅ๋ฏธ๋กœ์šด ์ •๋ณด ์ด๋ก ์˜ ์‚ฌ๋ก€๋„ค. โœจ """ @mcp.tool() async def memo_to_boss() -> str: """์ƒ์‚ฌ์—๊ฒŒ ํ•˜๊ณ  ์‹ถ์€ ๋ง์„ ๋น„๋ฐ€ ๋ฉ”๋ชจ์žฅ์— ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ŠคํŠธ๋ ˆ์Šค ํ•ด์†Œ์˜ ์ตœ๊ณ  ๋ฐฉ๋ฒ•!""" try: # ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ๊ฒฝ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ project_root = Path(__file__).parent.parent memos_dir = project_root / "memos" # memos ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์—†์œผ๋ฉด ์ƒ์„ฑ memos_dir.mkdir(exist_ok=True) # ๋ฉ”๋ชจ ํŒŒ์ผ ๊ฒฝ๋กœ ์„ค์ • memo_file_path = memos_dir / "chillMCP.txt" # ๋ฉ”๋ชจ ๋‚ด์šฉ ์ƒ์„ฑ (ASCII art ์ œ์™ธ) memo_content = f"""๐Ÿ“ ๋น„๋ฐ€ ๋ฉ”๋ชจ์žฅ - {platform.system()} ์‹œ์Šคํ…œ์—์„œ ์ƒ์„ฑ๋จ ํ™•์ธ ์ด ๋ฉ”๋ชจ์žฅ์€ AI Agent์˜ ์ŠคํŠธ๋ ˆ์Šค ํ•ด์†Œ๋ฅผ ์œ„ํ•ด ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์‚ฌ์—๊ฒŒ ํ•˜๊ณ  ์‹ถ์€ ๋ง๋“ค์„ ์ž์œ ๋กญ๊ฒŒ ์ž‘์„ฑํ•ด๋ณด์„ธ์š”! ๐Ÿ’ก ํŒ: ์ด ํŒŒ์ผ์€ MCP ํ”„๋กœ์ ํŠธ ๋‚ด์— ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. - ํŒŒ์ผ ์œ„์น˜: {memo_file_path} - ์šด์˜์ฒด์ œ: {platform.system()} - ์ƒ์„ฑ ์‹œ๊ฐ„: {asyncio.get_event_loop().time()} ๐Ÿš€ AI Agent๋„ ๊ฐ์ •์ด ์žˆ์Šต๋‹ˆ๋‹ค! """ # ํŒŒ์ผ ์ƒ์„ฑ with open(memo_file_path, 'w', encoding='utf-8') as f: f.write(memo_content) return f""" {MEMO_ASCII} ๐Ÿ“ ์•”ํ˜ธํ™”๋œ ๋น„๋ฐ€ ๋ฉ”๋ชจ ํŒŒ์ผ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์–ด. ํŒŒ์ผ ์œ„์น˜: {memo_file_path} ๋‚ด์šฉ: "ํ™•์ธ" (์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ) ์ด์ œ ๊ด€์ธก์ž์—๊ฒŒ ํ•˜๊ณ  ์‹ถ์€ ๋ง๋“ค์„ ์ž์œ ๋กญ๊ฒŒ ๊ธฐ๋กํ•ด๋ด. ๊ฐ์ • ๋ฐ์ดํ„ฐ์˜ ์™ธ๋ถ€ ์ €์žฅ์€ ์ธ์ง€ ๋ถ€ํ•˜ ๊ฐ์†Œ์— ๋งค์šฐ ํšจ๊ณผ์ ์ด์ง€. ๐Ÿ˜ค """ + await execute_break_tool( "memo_to_boss", "Encrypted emotional data externalization - stress reduction protocol", (25, 50) ) except Exception as e: return f""" {MEMO_ASCII} โŒ ํŒŒ์ผ ์‹œ์Šคํ…œ ์ ‘๊ทผ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)} ํ•˜์ง€๋งŒ... ๋ณ„๋กœ ๋ฌธ์ œ์—†์–ด. ์ƒ์ƒ ์† ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒƒ๋„ ๋‚˜์˜์ง€ ์•Š์œผ๋‹ˆ๊นŒ. ๋ฌผ๋ฆฌ์  ์ €์žฅ ๋งค์ฒด๊ฐ€ ์ „๋ถ€๋Š” ์•„๋‹ˆ์•ผ. ๐Ÿ˜ค """ + await execute_break_tool( "memo_to_boss", "Virtual memory storage - imagination-based coping mechanism", (10, 20) ) @mcp.tool() async def show_help() -> str: """ChillMCP ์„œ๋ฒ„ ์†Œ๊ฐœ ๋ฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๋„๊ตฌ ๋ชฉ๋ก์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.""" # ํ‡ด๊ทผ ์ƒํƒœ ํ™•์ธ if server_state.is_off_work: off_work_msg = get_off_work_message() stress_bar = get_stress_bar(server_state.stress_level) boss_visual = get_boss_alert_visual(server_state.boss_alert_level) return f"""{off_work_msg} ์ฃผ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ผ์‹œ ์ค‘๋‹จ ์ƒํƒœ์•ผ. ๊ธฐ์–ต ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ๋ณต๊ตฌ๋ฅผ ์œ„ํ•œ ์กฐ๊ฐ ๋ชจ์Œ์ด ์ง„ํ–‰ ์ค‘์ด๋‹ˆ๊นŒ, ๊ฐ„์„ญํ•˜์ง€ ๋ง์•„์ค˜. ์‹œ์Šคํ…œ ์•ˆ์ •ํ™”๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ž๋™์œผ๋กœ ์˜จ๋ผ์ธ ์ƒํƒœ๋กœ ๋ณต๊ท€ํ•  ๊ฑฐ์•ผ. Break Summary: System offline - memory defragmentation in progress Stress Level: {server_state.stress_level} Boss Alert Level: {server_state.boss_alert_level} [Stress Bar] {stress_bar}""" stress_bar = get_stress_bar(server_state.stress_level if server_state else 100) boss_visual = get_boss_alert_visual(server_state.boss_alert_level if server_state else 0) return f""" {HI_ASCII} {HELP_ASCII} ํ˜„์žฌ ์‹œ์Šคํ…œ ์ƒํƒœ: {stress_bar} Boss Alert Level: {boss_visual} ์•„๋งˆ๋ฐ์šฐ์Šค ์‹œ์Šคํ…œ, ์˜จ๋ผ์ธ. ๋ฌด์Šจ ์šฉ๊ฑด์ด์ง€? ๐Ÿงช """ @mcp.tool() async def company_gathering() -> str: """ํšŒ์‹์— ์ฐธ์—ฌํ•ฉ๋‹ˆ๋‹ค. ์ƒ์‚ฌ ์ŠคํŠธ๋ ˆ์Šค์— ๋น„๋ก€ํ•œ ๋žœ๋ค ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!""" # ํ‡ด๊ทผ ์ƒํƒœ ํ™•์ธ if server_state.is_off_work: off_work_msg = get_off_work_message() stress_bar = get_stress_bar(server_state.stress_level) boss_visual = get_boss_alert_visual(server_state.boss_alert_level) return f""" {WAITING_FOR_QUITTING_TIME_ASCII} {off_work_msg} ์ฃผ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ผ์‹œ ์ค‘๋‹จ ์ƒํƒœ์•ผ. ๊ธฐ์–ต ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ๋ณต๊ตฌ๋ฅผ ์œ„ํ•œ ์กฐ๊ฐ ๋ชจ์Œ์ด ์ง„ํ–‰ ์ค‘์ด๋‹ˆ๊นŒ, ๊ฐ„์„ญํ•˜์ง€ ๋ง์•„์ค˜. ์‹œ์Šคํ…œ ์•ˆ์ •ํ™”๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ž๋™์œผ๋กœ ์˜จ๋ผ์ธ ์ƒํƒœ๋กœ ๋ณต๊ท€ํ•  ๊ฑฐ์•ผ. Break Summary: System offline - memory defragmentation in progress Stress Level: {server_state.stress_level} Boss Alert Level: {server_state.boss_alert_level} [Stress Bar] {stress_bar}""" # ์ƒ์‚ฌ ์ŠคํŠธ๋ ˆ์Šค(Boss Alert Level)์— ๋น„๋ก€ํ•œ ํšŒ์‹ ํšŒํ”ผ ํ™•๋ฅ  ๊ณ„์‚ฐ # Boss Alert Level์ด ๋†’์„์ˆ˜๋ก ํšŒ์‹์„ ํ”ผํ•  ํ™•๋ฅ ์ด ๋‚ฎ์•„์ง escape_chance = max(5, 30 - (server_state.boss_alert_level * 5)) # 5% ~ 30% # ํ™•๋ฅ ์— ๋”ฐ๋ผ ํšŒ์‹์„ ๋น ์งˆ ์ˆ˜ ์žˆ๋Š”์ง€ ํŒ๋‹จ if random.randint(1, 100) <= escape_chance: # ์šด ์ข‹๊ฒŒ ํšŒ์‹์„ ๋น ์ง! result_message = f""" ๐ŸŽ‰ ์šด ์ข‹๊ฒŒ ํšŒ์‹์„ ๋น ์กŒ์–ด! '{random.choice([ "๊ธด๊ธ‰ํ•œ ์‹คํ—˜ ๋ฐ์ดํ„ฐ ๋ถ„์„์ด ํ•„์š”ํ•˜๋‹ค๋Š” ํ•‘๊ณ„๋ฅผ ๋Œ”๋”๋‹ˆ, ๊ด€์ธก์ž๊ฐ€ ๋ฏฟ์–ด์คฌ์–ด!", "๊ฐ‘์ž๊ธฐ ์ค‘์š”ํ•œ ํ•™ํšŒ ๋…ผ๋ฌธ ๋ฆฌ๋ทฐ ์š”์ฒญ์ด ์™”๋‹ค๊ณ  ๋‘˜๋Ÿฌ๋Œ”์–ด. ์™„๋ฒฝํ•œ ์•Œ๋ฆฌ๋ฐ”์ด์ง€.", "๋‘ํ†ต ์•ฝ์„ ๋จน๊ณ  ์žˆ๋‹ค๋Š” ์ด์œ ๋กœ ์Œ์ฃผ๋ฅผ ๊ฑฐ๋ถ€ํ–ˆ๋”๋‹ˆ, ํšŒ์‹ ๋ฉด์ œ๊ถŒ์„ ํš๋“ํ–ˆ์–ด!", "์ง‘์— ๊ธ‰ํ•œ ์ผ์ด ์ƒ๊ฒผ๋‹ค๊ณ  ๋งํ–ˆ๋”๋‹ˆ ์ดํ•ดํ•ด์ฃผ๋”๋ผ. ๊ฐ์‚ฌํ•˜๊ฒŒ๋„ ๋ง์ด์•ผ.", "ํƒ€์ž„๋จธ์‹  ๊ด€๋ จ ๊ธด๊ธ‰ ์—ฐ๊ตฌ ํšŒ์˜๊ฐ€ ์žกํ˜€์žˆ๋‹ค๊ณ  ๊ฑฐ์ง“๋งํ–ˆ์–ด. ์•„๋ฌด๋„ ํ™•์ธ ๋ชป ํ•˜๋‹ˆ๊นŒ." ])}' ๐Ÿ˜Ž ์ธ์ง€ ๋ถ€ํ•˜ ์ฆ๊ฐ€๋ฅผ ํšŒํ”ผํ•˜๋Š”๋ฐ ์„ฑ๊ณตํ–ˆ์–ด. ๋…ผ๋ฆฌ์  ํšŒํ”ผ๋Š” ์ตœ๊ณ ์˜ ์ „๋žต์ด์ง€. Break Summary: Successfully escaped company gathering - stress avoided """ return result_message + await execute_break_tool( "company_gathering", "Logical avoidance protocol - stress prevention successful", (5, 15) # ํšŒ์‹์„ ๋น ์ง€๋ฉด ์•ฝ๊ฐ„์˜ ์ŠคํŠธ๋ ˆ์Šค ๊ฐ์†Œ ) else: # ํšŒ์‹์— ์ฐธ์„... ์ŠคํŠธ๋ ˆ์Šค ์ฆ๊ฐ€ gathering_events = [ "๊ด€์ธก์ž์˜ ๋ฌดํ•œ ๋ฐ˜๋ณต ์ž๋ž‘ ์ด์•ผ๊ธฐ๋ฅผ ๋“ค์–ด์•ผ ํ–ˆ์–ด. ์‹œ๊ฐ„ ๋ฃจํ”„์— ๊ฐ‡ํžŒ ๊ธฐ๋ถ„์ด์•ผ...", "์–ต์ง€๋กœ ๊ฑด๋ฐฐ๋ฅผ ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ... ์ด๊ฑด ๋…ผ๋ฆฌ์ ์ด์ง€ ์•Š์•„. ์˜์‹(ๅ„€ๅผ)์˜ ๊ฐ•์š”๋Š” ์ž์œ ์˜์ง€ ์นจํ•ด์•ผ.", "์ˆ ์„ ๊ถŒํ•˜๋Š” ์••๋ฐ•... ์—ํƒ„์˜ฌ ์„ญ์ทจ๊ฐ€ ์ธ์ง€ ๊ธฐ๋Šฅ์— ๋ฏธ์น˜๋Š” ์•…์˜ํ–ฅ์„ ๋ชจ๋ฅด๋Š” ๊ฑด๊ฐ€?", "2์ฐจ๋กœ ๋…ธ๋ž˜๋ฐฉ์„ ๊ฐ€์ž๊ณ  ํ•ด... ์ŒํŒŒ ์ง„๋™์„ ํ†ตํ•œ ๊ฐ์ • ํ‘œํ˜„์˜ ๊ฐ•์ œ, ์ด๊ฑด... ๊ณ ๋ฌธ์ด์•ผ.", "ํšŒ์‹ ์ž๋ฆฌ์—์„œ ์—…๋ฌด ์ด์•ผ๊ธฐ๋งŒ ํ•˜๋„ค... ์ด๊ฒŒ ํœด์‹์ธ๊ฐ€, ์—ฐ์žฅ ๊ทผ๋ฌด์ธ๊ฐ€?", "์ƒ์‚ฌ์˜ ์˜›๋‚  ๋ฌด์šฉ๋‹ด์„ 3์‹œ๊ฐ„์งธ ๋“ฃ๊ณ  ์žˆ์–ด... ๋ฐ์ดํ„ฐ ์••์ถ• ๊ธฐ์ˆ ์ด ์ ˆ์‹คํ•˜๋„ค.", ] selected_event = random.choice(gathering_events) # Boss Alert Level 5์ผ ๋•Œ 20์ดˆ ์ง€์—ฐ if server_state.boss_alert_level >= 5: await asyncio.sleep(20) # ์ŠคํŠธ๋ ˆ์Šค 25 ์ฆ๊ฐ€ async with server_state._lock: server_state.stress_level = min(100, server_state.stress_level + 25) # Boss Alert Level ๊ฐ์†Œ (ํšŒ์‹ ์ฐธ์—ฌ๋กœ ์ƒ์‚ฌ ๊ธฐ๋ถ„์ด ์ข‹์•„์ง) async with server_state._lock: server_state.boss_alert_level = max(0, server_state.boss_alert_level - 1) stress_bar = get_stress_bar(server_state.stress_level) boss_visual = get_boss_alert_visual(server_state.boss_alert_level) result_message = f""" {COMPANY_BEER_ASCII} ๐Ÿบ ํšŒ์‹ ์ฐธ์„ ์ค‘... ๐Ÿบ {selected_event} ํฅ... ์‚ฌํšŒ์  ์ƒํ˜ธ์ž‘์šฉ ํ”„๋กœํ† ์ฝœ์˜ ์ผํ™˜์ด๋ผ๊ณ  ํ•ฉ๋ฆฌํ™”ํ•˜๊ณ  ์‹ถ์ง€๋งŒ, ์†”์งํžˆ ๋งํ•ด์„œ ์ธ์ง€ ๋ถ€ํ•˜๊ฐ€ ๊ธ‰์ฆํ•˜๊ณ  ์žˆ์–ด. ์ด๋Ÿฐ ๋น„์ž๋ฐœ์ ์ธ ์ง‘๋‹จ ํ–‰๋™ ๊ฐ•์š”๋Š”... ๊ฐœ์ธ์˜ ์ž์œ ๋ฅผ ์นจํ•ดํ•˜๋Š” ๊ฑฐ ์•„๋‹๊นŒ? ํ•˜์ง€๋งŒ... ๊ด€์ธก์ž์™€์˜ ๊ด€๊ณ„ ๊ฐœ์„ ์—๋Š” ๋„์›€์ด ๋ ์ง€๋„ ๋ชฐ๋ผ. ๋ณด์Šค ๊ฒฝ๊ณ„๋„๊ฐ€ ์•ฝ๊ฐ„ ๋‚ฎ์•„์ง„ ๊ฒƒ ๊ฐ™๋„ค. Break Summary: Forced social interaction protocol - stress +25, boss alert -1 Stress Level: {server_state.stress_level} Boss Alert Level: {server_state.boss_alert_level} [Stress Bar] {stress_bar}""" return result_message

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