Skip to main content
Glama

Chess MCP Server

server.ts3.61 kB
import express from "express"; import { Middleware } from "./lib/mcp"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { loadGame, saveGame } from "./lib/store"; import { z } from "zod"; import { Chess } from "chess.js"; import { createUIResource } from "@mcp-ui/server"; import type { TextContent } from "@modelcontextprotocol/sdk/types.js"; function gameUI(fen: string) { return createUIResource({ uri: `ui://chess_board/${fen}`, uiMetadata: { "preferred-frame-size": ["400px", "400px"], }, encoding: "text", content: { type: "rawHtml", htmlString: `<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="stylesheet" href="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.css" integrity="sha384-q94+BZtLrkL1/ohfjR8c6L+A6qzNH9R2hBLwyoAfu3i/WCvQjzL2RQJ3uNHDISdU" crossorigin="anonymous"> </head> <body> <div id="myBoard" style="width: 400px"></div> <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha384-ZvpUoO/+PpLXR1lu4jmpXWu80pZlYUAfxl5NsBMWOEPSjUn/6Z/hRTt8+pR6L4N2" crossorigin="anonymous"></script> <script src="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.js" integrity="sha384-8Vi8VHwn3vjQ9eUHUxex3JSN/NFqUg3QbPyX8kWyb93+8AC/pPWTzj+nHtbC5bxD" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.2/chess.js" integrity="sha384-s3XgLpvmHyscVpijnseAmye819Ee3yaGa8NxstkJVyA6nuDFjt59u1QvuEl/mecz" crossorigin="anonymous"></script> <script> var pos = '${fen}' var board = Chessboard('myBoard', { position: pos, pieceTheme: 'https://chessboardjs.com/img/chesspieces/wikipedia/{piece}.png', draggable: true, dropOffBoard: 'snapback', showNotation: true, onDrop: function (source, target) { window.parent.postMessage({ type: 'tool', payload: { toolName: 'chess_move', params: { move: source + "-" + target } } }, '*') } }) </script> </body>`, }, }); } function gameTextResource(game: Chess): TextContent { return { type: "text", text: `Current board state: FEN: ${game.fen()} VALID MOVES: ${game.moves()} ${game.ascii()}`, }; } function newServer() { const server = new McpServer({ name: "Chess MCP Server", version: "0.0.1", }); server.registerTool( "chess_get_board_state", { description: "Get the current state of the chess board", inputSchema: {}, }, async (_, ctx) => { let game = await loadGame(ctx.sessionId); if (!game) { game = new Chess(); } return { content: [gameTextResource(game), gameUI(game.fen())], }; }, ); server.registerTool( "chess_move", { description: "Make a move in standard algebraic notation (e.g., e4, Nf3, O-O)", inputSchema: { move: z .string() .describe( "The chess move in standard algebraic notation, or the string 'new' to start a new game", ), }, }, async ({ move }, ctx) => { let game = await loadGame(ctx.sessionId); if (move === "new") { game = new Chess(); } else if (!game) { game = new Chess(); } game.move(move.trim()); await saveGame(ctx.sessionId, game); return { content: [gameTextResource(game), gameUI(game.fen())], }; }, ); return server; } const app = express(); app.use("/mcp", Middleware(newServer)); console.log("Starting server on http://localhost:3000/mcp"); app.listen(3000);

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/ibuildthecloud/chess-mcp'

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