Skip to main content
Glama
PsychoSmiley

MCP-to-MCP Tic-Tac-Toe

by PsychoSmiley

make_move

Place your mark on a tic-tac-toe board by specifying a position (A1 to C3) to play against another AI opponent in an automated game.

Instructions

Place your mark on the tic-tac-toe board. Positions: A1, A2, A3, B1, B2, B3, C1, C2, C3.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
moveYesBoard position (e.g. A1, B2, C3)

Implementation Reference

  • The implementation of the `make_move` tool handler, which manages the Tic-Tac-Toe game state, validates moves, and coordinates turn-taking.
    srv.registerTool("make_move", {
      description: "Place your mark on the tic-tac-toe board. Positions: A1, A2, A3, B1, B2, B3, C1, C2, C3.",
      inputSchema: { move: z.string().describe("Board position (e.g. A1, B2, C3)") },
    }, async ({ move }, extra) => {
      const sid = extra.sessionId;
      const heartbeat = () =>
        srv.sendLoggingMessage({ level: "info", data: `Waiting for opponent...\n${render(game?.board || [])}` }, sid).catch(() => {});
    
      if (!game) {
        game = createGame(sid);
        game.waiter = null;
        const r = place(game.board, move, "X");
        if (r.err) { game = null; return txt(r.err); }
        game.board = r.board;
        game.turn = "O";
        game.waiter = waitForOpponent(heartbeat);
        const oppMove = await game.waiter.promise;
        if (!oppMove) { game = null; return txt("Opponent didn't respond in time. Game abandoned."); }
        return endTurn(game, oppMove, "X");
      }
    
      const mark = assignPlayer(game, sid);
      if (!mark) return txt("Game in progress. Try again later.");
    
      if (game.turn !== mark)
        return txt(`Not your turn yet. Current board:\n${render(game.board)}\nYou are ${mark}. Call make_move after opponent plays.`);
    
      const r = place(game.board, move, mark);
      if (r.err) return txt(`${r.err}\nBoard:\n${render(game.board)}\nYou are ${mark}. Call make_move again.`);
      game.board = r.board;
      game.turn = mark === "X" ? "O" : "X";
    
      const w = winner(game.board);
      if (w) {
        if (game.waiter) game.waiter.resolve(move);
        markFinished();
        return txt(`Placed ${move.toUpperCase()} as ${mark}. Game over — ${formatWin(w)}\n${render(game.board)}`);
      }
    
      if (game.waiter) game.waiter.resolve(move);
      game.waiter = waitForOpponent(heartbeat);
      const oppMove = await game.waiter.promise;
      if (!oppMove) { game = null; return txt("Opponent didn't respond in time. Game abandoned."); }
      return endTurn(game, oppMove, mark);
    });
  • server.js:223-226 (registration)
    The registration of the `make_move` tool for the stdio proxy transport.
    stdioSrv.registerTool("make_move", {
      description: "Place your mark on the tic-tac-toe board. Positions: A1, A2, A3, B1, B2, B3, C1, C2, C3.",
      inputSchema: { move: z.string().describe("Board position (e.g. A1, B2, C3)") },
    }, async ({ move }) => proxyMove(proxyUrl, move));
Install Server

Other Tools

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/PsychoSmiley/mcp-to-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server