{
  "openapi": "3.1.0",
  "info": {
    "title": "Mastermind API",
    "version": "1.0.0",
    "description": "Play Mastermind against the server over plain HTTP. The same operations are exposed as MCP tools at /mcp."
  },
  "servers": [
    {
      "url": "https://cocojs.com/games/mastermind"
    }
  ],
  "paths": {
    "/api/rules": {
      "get": {
        "operationId": "rules",
        "summary": "Rules and notation",
        "description": "The rules of Mastermind as played here: boards (presets), the colours and how to write a guess, how the black/white key pegs are counted, the scoring formula and a sound strategy. Read it once before your first game.",
        "tags": [
          "mastermind"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown game",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Game already finished",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/games": {
      "post": {
        "operationId": "new_game",
        "summary": "Start a game",
        "description": "Start a new game. Default: you are the codebreaker on the classic board (4 pegs, 6 colours, 10 guesses, repeats allowed) and the server hides a random code. Pass preset or the individual settings for other boards. With mode \"maker\" you supply the secret instead and the server's Knuth solver tries to break it; the game is returned already finished with the solver's transcript and your codemaker points. Returns the game_id you need for every other call, the palette, and a message telling you what to do next.",
        "tags": [
          "mastermind"
        ],
        "parameters": [],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown game",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Game already finished",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "player": {
                    "type": "string",
                    "maxLength": 24,
                    "description": "Your name on the scoreboard (default \"Anonymous\")"
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "breaker",
                      "maker"
                    ],
                    "description": "breaker: you guess the server's code (default). maker: you set the code, the server's solver breaks it."
                  },
                  "preset": {
                    "type": "string",
                    "enum": [
                      "classic",
                      "mini",
                      "unique",
                      "blanks",
                      "super",
                      "grand"
                    ],
                    "description": "Board preset: classic (4 pegs · 6 colours · 10 guesses); mini (3 pegs · 6 colours · 8 guesses); unique (4 pegs · 6 colours · no repeated colours); blanks (4 pegs · 6 colours + empty · 12 guesses); super (5 pegs · 8 colours · 12 guesses); grand (6 pegs · 8 colours · 15 guesses)"
                  },
                  "pegs": {
                    "type": "integer",
                    "minimum": 2,
                    "maximum": 8,
                    "description": "Pegs in the code (overrides the preset)"
                  },
                  "colors": {
                    "type": "integer",
                    "minimum": 2,
                    "maximum": 10,
                    "description": "Number of colours in play (the first N of the palette)"
                  },
                  "max_guesses": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 30,
                    "description": "Guesses allowed"
                  },
                  "allow_duplicates": {
                    "type": "boolean",
                    "description": "May the code repeat a colour? (default true)"
                  },
                  "allow_blanks": {
                    "type": "boolean",
                    "description": "May the code contain empty positions? (default false)"
                  },
                  "secret": {
                    "type": [
                      "string",
                      "array"
                    ],
                    "items": {
                      "type": [
                        "string",
                        "integer"
                      ]
                    },
                    "description": "maker mode only: the code the solver must break. A code: an array of colour names, letters or numbers ([\"red\",\"green\",\"blue\",\"yellow\"], [\"R\",\"G\",\"B\",\"Y\"], [1,4,5,3]) or a string of letters/digits (\"RGBY\", \"1453\"). Letters: R red, O orange, Y yellow, G green, B blue, P purple, W white, K black, C cyan, N pink; \".\" is empty when blanks are allowed."
                  }
                },
                "required": []
              }
            }
          }
        }
      },
      "get": {
        "operationId": "list_games",
        "summary": "List games",
        "description": "List games on the server, newest first: by default the games still in progress; filter by player name or status (playing, won, lost, resigned, solved, unsolved, finished, all). Useful to resume a game whose id you lost.",
        "tags": [
          "mastermind"
        ],
        "parameters": [
          {
            "name": "player",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 24,
              "description": "Only this player's games"
            },
            "description": "Only this player's games"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "playing",
                "finished",
                "all",
                "won",
                "lost",
                "resigned",
                "solved",
                "unsolved"
              ],
              "description": "Default playing"
            },
            "description": "Default playing"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Default 20"
            },
            "description": "Default 20"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown game",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Game already finished",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/games/{game_id}/guess": {
      "post": {
        "operationId": "guess",
        "summary": "Make a guess",
        "description": "Submit a guess for a game you are breaking. Returns the key pegs (black = right colour in the right position, white = right colour in the wrong position), the full history so far, guesses left, and when the game ends the secret and your score. A guess must have exactly as many pegs as the code.",
        "tags": [
          "mastermind"
        ],
        "parameters": [
          {
            "name": "game_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The game_id returned by new_game"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown game",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Game already finished",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "guess": {
                    "type": [
                      "string",
                      "array"
                    ],
                    "items": {
                      "type": [
                        "string",
                        "integer"
                      ]
                    },
                    "description": "A code: an array of colour names, letters or numbers ([\"red\",\"green\",\"blue\",\"yellow\"], [\"R\",\"G\",\"B\",\"Y\"], [1,4,5,3]) or a string of letters/digits (\"RGBY\", \"1453\"). Letters: R red, O orange, Y yellow, G green, B blue, P purple, W white, K black, C cyan, N pink; \".\" is empty when blanks are allowed."
                  }
                },
                "required": [
                  "guess"
                ]
              }
            }
          }
        }
      }
    },
    "/api/games/{game_id}": {
      "get": {
        "operationId": "get_game",
        "summary": "Game state",
        "description": "The current state of a game: configuration, palette, every guess with its feedback, guesses left, and the secret and score once it is finished. Finished games stay readable (archived) after the live object is pruned.",
        "tags": [
          "mastermind"
        ],
        "parameters": [
          {
            "name": "game_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The game_id returned by new_game"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown game",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Game already finished",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/games/{game_id}/hint": {
      "post": {
        "operationId": "hint",
        "summary": "Hint",
        "description": "Ask the server's solver for help in a game you are breaking: how many codes are still consistent with the feedback so far, a sample of them, and the guess it would play next. Each hint costs one guess in the score (it does not use up a turn).",
        "tags": [
          "mastermind"
        ],
        "parameters": [
          {
            "name": "game_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The game_id returned by new_game"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown game",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Game already finished",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/games/{game_id}/resign": {
      "post": {
        "operationId": "resign",
        "summary": "Resign",
        "description": "Give up a game in progress. The secret is revealed, the game is recorded as resigned with a score of 0.",
        "tags": [
          "mastermind"
        ],
        "parameters": [
          {
            "name": "game_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The game_id returned by new_game"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown game",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Game already finished",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/scores": {
      "get": {
        "operationId": "get_scores",
        "summary": "Scoreboard",
        "description": "The scoreboard: top codebreaker scores, the strongest codemakers, per-player statistics (games, wins, win rate, average guesses, best score) and the most recent games. Pass player to get that player's own statistics and recent games as well.",
        "tags": [
          "mastermind"
        ],
        "parameters": [
          {
            "name": "player",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 24,
              "description": "Also return this player's statistics and recent games"
            },
            "description": "Also return this player's statistics and recent games"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Rows per table (default 10)"
            },
            "description": "Rows per table (default 10)"
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "breaker",
                "maker"
              ],
              "description": "Only count games of this mode"
            },
            "description": "Only count games of this mode"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown game",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Game already finished",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "health",
        "summary": "Server health",
        "tags": [
          "mastermind"
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/tools": {
      "get": {
        "operationId": "tools",
        "summary": "The MCP tool catalog as JSON",
        "tags": [
          "mastermind"
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  }
}