|
|
""" |
|
|
MCP tools for Unpredictable Lord game. |
|
|
|
|
|
This module contains all MCP tool functions that are exposed |
|
|
to external LLM clients via the Gradio MCP server. |
|
|
""" |
|
|
|
|
|
import logging |
|
|
import uuid |
|
|
|
|
|
from unpredictable_lord.game_state import ( |
|
|
ADVICE_DESCRIPTIONS, |
|
|
PERSONALITY_DESCRIPTIONS, |
|
|
create_session, |
|
|
execute_turn_logic, |
|
|
get_available_advice, |
|
|
get_session, |
|
|
) |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
|
def init_game(personality: str = "cautious") -> dict: |
|
|
""" |
|
|
Initialize a new game session and return the session information. |
|
|
|
|
|
This MCP tool creates a new game session with the specified lord personality. |
|
|
Use the returned session_id for all subsequent game operations. |
|
|
|
|
|
Args: |
|
|
personality: The lord's personality type. |
|
|
Options: "cautious" (risk-averse), "idealist" (emotional idealist), |
|
|
"populist" (popularity-focused). Defaults to "cautious". |
|
|
|
|
|
Returns: |
|
|
dict: Session information including session_id and initial game state. |
|
|
""" |
|
|
session_id = str(uuid.uuid4()) |
|
|
|
|
|
|
|
|
if personality not in PERSONALITY_DESCRIPTIONS: |
|
|
personality = "cautious" |
|
|
|
|
|
|
|
|
state = create_session(session_id, personality) |
|
|
|
|
|
logger.info( |
|
|
f"New game session created: {session_id} with personality: {personality}" |
|
|
) |
|
|
|
|
|
return { |
|
|
"session_id": session_id, |
|
|
"message": f"New game started! You are now the advisor to a {personality} lord.", |
|
|
"personality_description": PERSONALITY_DESCRIPTIONS[personality], |
|
|
"available_advice": ADVICE_DESCRIPTIONS, |
|
|
"game_state": state.to_dict(), |
|
|
} |
|
|
|
|
|
|
|
|
def get_game_state(session_id: str) -> dict: |
|
|
""" |
|
|
Get the current game state for a session. |
|
|
|
|
|
This MCP tool retrieves the current state of a game session, |
|
|
including all parameters, turn number, and game status. |
|
|
|
|
|
Args: |
|
|
session_id: The session ID returned from init_game. |
|
|
|
|
|
Returns: |
|
|
dict: Current game state or error message if session not found. |
|
|
""" |
|
|
state = get_session(session_id) |
|
|
|
|
|
if state is None: |
|
|
return { |
|
|
"error": "Session not found", |
|
|
"message": f"No game session found with ID: {session_id}. Please call init_game first.", |
|
|
} |
|
|
|
|
|
return { |
|
|
"session_id": session_id, |
|
|
"game_state": state.to_dict(), |
|
|
"status_summary": state.get_status_summary(), |
|
|
} |
|
|
|
|
|
|
|
|
def list_available_advice() -> dict: |
|
|
""" |
|
|
Get all available advice options that can be given to the lord. |
|
|
|
|
|
This MCP tool returns a list of all possible advice types that can be |
|
|
used with execute_turn(). The Lord AI should interpret the user's |
|
|
free-form suggestion and map it to one of these options. |
|
|
|
|
|
Returns: |
|
|
dict: Dictionary containing all available advice options with |
|
|
their names, descriptions, and expected effects. |
|
|
""" |
|
|
return { |
|
|
"advice_options": get_available_advice(), |
|
|
"usage": "Interpret the user's advice and select the most appropriate option from the list above.", |
|
|
} |
|
|
|
|
|
|
|
|
def execute_turn(session_id: str, advice: str) -> dict: |
|
|
""" |
|
|
Execute a turn with the given advice. |
|
|
|
|
|
This MCP tool is called by the Lord AI after interpreting the user's suggestion. |
|
|
The lord will decide whether to follow the advice based on personality and trust. |
|
|
|
|
|
Args: |
|
|
session_id: The session ID returned from init_game. |
|
|
advice: The advice type to execute. Must be one of: |
|
|
- "increase_tax": Raise taxes (Treasury β, Satisfaction β) |
|
|
- "decrease_tax": Lower taxes (Treasury β, Satisfaction β) |
|
|
- "expand_territory": Military expansion (Territory β, Treasury β, risky) |
|
|
- "improve_diplomacy": Diplomatic efforts (Royal Trust β, Treasury β) |
|
|
- "public_festival": Hold festival (Satisfaction β, Treasury β) |
|
|
- "build_infrastructure": Build infrastructure (Population β, Treasury β) |
|
|
- "do_nothing": Maintain current state |
|
|
|
|
|
Returns: |
|
|
dict: Result containing: |
|
|
- adopted: Whether the lord followed the advice |
|
|
- action_taken: The actual action the lord took |
|
|
- parameter_changes: Changes to game parameters |
|
|
- game_over: Whether the game has ended |
|
|
- new_state: Updated game state |
|
|
""" |
|
|
state = get_session(session_id) |
|
|
|
|
|
if state is None: |
|
|
return { |
|
|
"error": "Session not found", |
|
|
"message": f"No game session found with ID: {session_id}. Please call init_game first.", |
|
|
} |
|
|
|
|
|
result = execute_turn_logic(state, advice) |
|
|
|
|
|
logger.info( |
|
|
f"Turn executed for session {session_id}: advice={advice}, " |
|
|
f"adopted={result.get('adopted')}, action={result.get('action_taken')}" |
|
|
) |
|
|
|
|
|
return result |
|
|
|