{"openapi":"3.1.0","info":{"title":"Fleet Battle API","version":"0.1.0","description":"A real, stateless, playable grid-based naval fleet-hunting game: fleet placement validation, firing, hit/miss/sunk/win detection, and a random-then-hunt AI opponent or two-human-player state. Every tool call takes the full game state and returns the new state; nothing is stored server-side.\n\nEvery operation is read-only or compute-only. The same tools are available over MCP (streamable HTTP) at https://battleshipgame.connectorbay.com/mcp.","contact":{"name":"Unify Dynamics LLC","email":"hr@unifydynamics.com","url":"https://connectorbay.com/battleshipgame/docs"},"termsOfService":"https://connectorbay.com/battleshipgame/terms"},"servers":[{"url":"https://battleshipgame.connectorbay.com"}],"externalDocs":{"url":"https://connectorbay.com/battleshipgame/docs"},"security":[{},{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Optional. A Pro API key raises rate limits; no credentials are required."}},"schemas":{"Error":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object"}}}}},"paths":{"/v1/tools/new_game":{"post":{"operationId":"new_game","summary":"Starts a fresh game in the placement phase and returns its initial state. In single_player","description":"Starts a fresh game in the placement phase and returns its initial state. In single_player\n    mode the AI (p2) places its own fleet immediately. Use for \"let's play a naval battle game\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"mode":{"default":"single_player","description":"'single_player' (vs AI, default) or 'two_player' (you manage both sides).","title":"Mode","type":"string"}},"title":"new_gameArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/place_fleet":{"post":{"operationId":"place_fleet","summary":"Validates and places one player's full fleet (in-bounds, no overlaps, exact fleet","description":"Validates and places one player's full fleet (in-bounds, no overlaps, exact fleet\n    composition). Auto-advances to the battle phase once every required fleet is placed. Use for\n    \"place my ships at these positions\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"state":{"additionalProperties":true,"description":"The current game state, exactly as returned by new_game/place_fleet/auto_place_fleet/fire. Contains BOTH players' ship positions — never show a player the other side's un-hit ships; always use render(viewer=...).","title":"State","type":"object"},"player":{"description":"'p1' or 'p2'.","title":"Player","type":"string"},"ships":{"description":"Exactly 5 ships, one of each: Carrier (5), Cruiser (4), Submarine (3), Frigate (3), Destroyer (2). Each: {'name': str, 'row': int (0-9), 'col': int (0-9), 'orientation': 'horizontal'|'vertical'}.","examples":[[{"col":0,"name":"Carrier","orientation":"horizontal","row":0},{"col":0,"name":"Cruiser","orientation":"horizontal","row":2},{"col":0,"name":"Submarine","orientation":"horizontal","row":4},{"col":0,"name":"Frigate","orientation":"horizontal","row":6},{"col":0,"name":"Destroyer","orientation":"horizontal","row":8}]],"items":{"additionalProperties":true,"type":"object"},"title":"Ships","type":"array"}},"required":["state","player","ships"],"title":"place_fleetArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/auto_place_fleet":{"post":{"operationId":"auto_place_fleet","summary":"Randomly places a full, valid, non-overlapping fleet for `player` — a quick-start","description":"Randomly places a full, valid, non-overlapping fleet for `player` — a quick-start\n    alternative to place_fleet. Only reveal the returned `ships` to the player whose fleet it is.\n    Use for \"place my fleet randomly\", \"just set up my ships\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"state":{"additionalProperties":true,"description":"The current game state, exactly as returned by new_game/place_fleet/auto_place_fleet/fire. Contains BOTH players' ship positions — never show a player the other side's un-hit ships; always use render(viewer=...).","title":"State","type":"object"},"player":{"description":"'p1' or 'p2'.","title":"Player","type":"string"}},"required":["state","player"],"title":"auto_place_fleetArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/fire":{"post":{"operationId":"fire","summary":"Fires one shot. Returns the new state plus result (hit/miss/invalid_move), sunk_ship (name,","description":"Fires one shot. Returns the new state plus result (hit/miss/invalid_move), sunk_ship (name,\n    if this shot sank one), and overall status (in_progress/win/invalid_move). Use for \"fire at\n    B4\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"state":{"additionalProperties":true,"description":"The current game state, exactly as returned by new_game/place_fleet/auto_place_fleet/fire. Contains BOTH players' ship positions — never show a player the other side's un-hit ships; always use render(viewer=...).","title":"State","type":"object"},"shooter":{"description":"'p1' or 'p2' — whoever is firing.","title":"Shooter","type":"string"},"target":{"description":"'p1' or 'p2' — whoever is being fired at (must differ from shooter).","title":"Target","type":"string"},"coord":{"description":"Coordinate letter+number, e.g. 'B4'.","examples":["B4","J10"],"title":"Coord","type":"string"}},"required":["state","shooter","target","coord"],"title":"fireArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/ai_move":{"post":{"operationId":"ai_move","summary":"Chooses the AI's (p2's) next firing coordinate against p1's board using a real","description":"Chooses the AI's (p2's) next firing coordinate against p1's board using a real\n    random-then-hunt algorithm — checkerboard-parity random search until a hit, then hunting the\n    hit's neighbors until that ship sinks. Does NOT apply the shot — call fire(state, shooter=\"p2\",\n    target=\"p1\", coord=<returned coord>) to actually fire it. Use for \"what's the AI's move\",\n    \"make the computer fire\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"state":{"additionalProperties":true,"description":"The current game state, exactly as returned by new_game/place_fleet/auto_place_fleet/fire. Contains BOTH players' ship positions — never show a player the other side's un-hit ships; always use render(viewer=...).","title":"State","type":"object"}},"required":["state"],"title":"ai_moveArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_valid_moves":{"post":{"operationId":"get_valid_moves","summary":"Lists coordinates on `target`'s board that haven't been fired on yet; empty outside the","description":"Lists coordinates on `target`'s board that haven't been fired on yet; empty outside the\n    battle phase. Use for \"what cells haven't I tried on their board\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"state":{"additionalProperties":true,"description":"The current game state, exactly as returned by new_game/place_fleet/auto_place_fleet/fire. Contains BOTH players' ship positions — never show a player the other side's un-hit ships; always use render(viewer=...).","title":"State","type":"object"},"target":{"description":"'p1' or 'p2' — whose board to check untried cells on.","title":"Target","type":"string"}},"required":["state","target"],"title":"get_valid_movesArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/render":{"post":{"operationId":"render","summary":"The player-safe view for `viewer`: their own fleet board (ships visible) and a fog-of-war","description":"The player-safe view for `viewer`: their own fleet board (ships visible) and a fog-of-war\n    view of the opponent's waters (hits/misses only, no un-hit ships). ALWAYS use this instead of\n    showing the raw state to a player. Use for \"show me the board\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"state":{"additionalProperties":true,"description":"The current game state, exactly as returned by new_game/place_fleet/auto_place_fleet/fire. Contains BOTH players' ship positions — never show a player the other side's un-hit ships; always use render(viewer=...).","title":"State","type":"object"},"viewer":{"description":"'p1' or 'p2' — whose player-safe view to render.","title":"Viewer","type":"string"}},"required":["state","viewer"],"title":"renderArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/fleet_status":{"post":{"operationId":"fleet_status","summary":"A quick summary of one player's fleet: each ship's name, length, hit count, sunk flag, and","description":"A quick summary of one player's fleet: each ship's name, length, hit count, sunk flag, and\n    how many ships remain afloat. Use for \"how many of my ships are left\", \"is their carrier\n    sunk\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"state":{"additionalProperties":true,"description":"The current game state, exactly as returned by new_game/place_fleet/auto_place_fleet/fire. Contains BOTH players' ship positions — never show a player the other side's un-hit ships; always use render(viewer=...).","title":"State","type":"object"},"player":{"description":"'p1' or 'p2'.","title":"Player","type":"string"}},"required":["state","player"],"title":"fleet_statusArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}}}}