MCP server for turn-based games AI opponent
Server provides 5 tools with complete input schemas and consistent descriptions. Naming follows verb-noun conventions (play_game, create_game, analyze_game, make_player_move, wait_for_player_move). Descriptions are present and moderately detailed (ranging 80-280 chars), exceeding the 20-char minimum but generally shorter than the 194-char baseline for A+ tools. All parameters have types and descriptions. However, there are critical composition and elicitation issues: (1) The create_game tool relies on elicitation to avoid providing defaults for optional parameters, but this pattern is not fully formalized in the schema or error handling. (2) make_player_move and play_game form a tightly coupled pair that requires careful sequencing, increasing cognitive load for the LLM. (3) Output schemas are not explicitly documented in the provided code, limiting downstream tool chaining validation. (4) Error recovery patterns are not evident, no explicit guidance on what the LLM should do if a tool fails (retryable vs fatal). (5) Tool descriptions contain prescriptive imperatives ("you MUST call", "do NOT consider") that read more like warnings than design patterns, suggesting the tool interface may not be optimally intuitive.
Analyze the current game state and provide insights
Create a new game with interactive setup. This will ask you for preferences like difficulty, player options, and other game-specific settings. IMPORTANT: Only provide parameters that the user explicitly specified. DO NOT provide default values for optional parameters - missing parameters will trigger interactive elicitation.
Make a move on behalf of the human player. Use this when the player tells you their move in chat instead of using the web UI. IMPORTANT: When you later call play_game for the AI move, do NOT consider what move the player made - the AI should calculate its own optimal move independently.
Make an AI move in a game. IMPORTANT: After calling this tool when the game is still playing, you MUST call wait_for_player_move to continue the game flow.
Wait for human player to make their move via the web UI. If timeout occurs, you can call this again to continue waiting, or ask the player if they want to make their move in chat instead.
Output schemas not documented in code. LLMs cannot predict the structure of tool responses, making downstream planning and field extraction error-prone. No return type documentation visible for any tool.
Tight coupling between play_game and wait_for_player_move. Tool descriptions contain mandatory sequencing instructions ("you MUST call wait_for_player_move"), indicating the tool interface does not naturally guide LLMs toward correct composition. This violates single-responsibility and composition patterns.
create_game relies on elicitation via omitted parameters, but the schema does not distinguish between 'user did not provide' and 'user explicitly provided null'. Parameter descriptions tell the LLM not to provide defaults, but no mechanism enforces or validates this behavior at the tool level.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 59 | 2026-07-28+ | v2 |
No error handling or recovery guidance documented. Descriptions do not specify what conditions cause failures, whether errors are retryable, or what the LLM should do next. E.g., if play_game returns an error because the game is already finished, the LLM has no guidance.
Prescriptive language in tool descriptions ('you MUST', 'do NOT consider') signals poor interface design. The tool should guide behavior through its design, not via imperative instructions. If play_game should not consider the previous move, the API should not expose move history.
analyze_game has a generic description ('Analyze the current game state and provide insights') lacking specificity on what insights it returns or when to call it instead of play_game. LLMs may conflate analysis with game progression.