UNPKG

chess-mcp

Version:

Chess MCP server with position evaluation, move validation, and masters database

114 lines 4.55 kB
import { ErrorCode } from '@modelcontextprotocol/sdk/types.js'; export const toolSpec = { name: 'lookup_masters_position', description: 'Look up a chess position in the Lichess masters database', inputSchema: { type: 'object', properties: { fen: { type: 'string', description: 'Chess position in FEN notation', }, play: { type: 'string', description: 'Moves played in UCI format (e.g., "e2e4 e7e5")', }, since: { type: 'number', description: 'Filter games by minimum date (year)', minimum: 1952, maximum: 2024, }, until: { type: 'number', description: 'Filter games by maximum date (year)', minimum: 1952, maximum: 2024, }, moves: { type: 'number', description: 'Number of most common moves to return', minimum: 1, maximum: 12, }, topGames: { type: 'number', description: 'Number of top games to return', minimum: 0, maximum: 4, }, }, required: ['fen'], }, }; export class MastersLookupHandler { async handle(request) { const { fen, play, since, until, moves = 5, topGames = 2 } = request.params.arguments; try { // Build query parameters const params = new URLSearchParams({ fen, moves: moves.toString(), topGames: topGames.toString(), }); if (play) params.append('play', play); if (since) params.append('since', since.toString()); if (until) params.append('until', until.toString()); // Make request to Lichess API const response = await fetch(`https://explorer.lichess.ovh/masters?${params}`); if (!response.ok) { throw new Error(`Lichess API error: ${response.statusText}`); } const data = await response.json(); // Format the response const totalGames = data.white + data.draws + data.black; const content = []; // Add summary content.push({ type: 'text', text: `Position found in ${totalGames} master games:\n` + `White wins: ${data.white} (${((data.white / totalGames) * 100).toFixed(1)}%)\n` + `Draws: ${data.draws} (${((data.draws / totalGames) * 100).toFixed(1)}%)\n` + `Black wins: ${data.black} (${((data.black / totalGames) * 100).toFixed(1)}%)` }); // Add most common moves if (data.moves.length > 0) { const movesText = data.moves.map(move => { const total = move.white + move.draws + move.black; const winRate = ((move.white + move.draws * 0.5) / total * 100).toFixed(1); return `${move.san} (${total} games, ${winRate}% score, avg rating ${move.averageRating})`; }).join('\n'); content.push({ type: 'text', text: `\nMost common moves:\n${movesText}` }); } // Add recent master games if (data.topGames.length > 0) { const gamesText = data.topGames.map(game => { const result = game.winner === 'white' ? '1-0' : (game.winner === 'black' ? '0-1' : '½-½'); return `${game.white.name} (${game.white.rating}) vs ${game.black.name} (${game.black.rating}), ${game.year} - ${result}`; }).join('\n'); content.push({ type: 'text', text: `\nRecent master games:\n${gamesText}` }); } return { content }; } catch (error) { return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true, errorCode: ErrorCode.InvalidRequest }; } } } //# sourceMappingURL=masters-lookup.handler.js.map