plaier-mcp-server
Version:
MCP Server for Plaier Football API - Advanced football analytics and predictions
338 lines • 17 kB
JavaScript
import { validateInput, PlayerSearchSchema, PlayerDetailsSchema, PlayerRankingSchema, TeamPlayersSchema, TournamentPlayersSchema, } from '../utils/validation.js';
import { formatPlayerInfo, formatPlayerRanking, formatError, formatDataSummary } from '../utils/formatting.js';
export function createPlayerTools(client) {
return [
{
name: "search_players",
description: "Search for football players by name using fuzzy search. Supports nicknames and can be narrowed by team.",
inputSchema: {
type: "object",
properties: {
player_name: {
type: "string",
description: "Player name to search for (minimum 3 characters). Supports nicknames and partial matches."
},
team_name: {
type: "string",
description: "Optional team name to narrow the search results"
},
show_details: {
type: "boolean",
description: "If true, returns full player details. If false, returns only player ID.",
default: false
}
},
required: ["player_name"]
}
},
{
name: "get_player_details",
description: "Get detailed information about a specific player including stats, team, position, and market value.",
inputSchema: {
type: "object",
properties: {
player_id: {
type: "number",
description: "The unique ID of the player"
}
},
required: ["player_id"]
}
},
{
name: "rank_players",
description: "Get a ranked list of players with advanced filtering options. Can filter by tournament, team, age, nationality, position, and sort by different criteria.",
inputSchema: {
type: "object",
properties: {
tournament_ids: {
type: "array",
items: { type: "number" },
description: "Filter by specific tournament IDs"
},
team_ids: {
type: "array",
items: { type: "number" },
description: "Filter by specific team IDs"
},
age: {
type: "number",
description: "Filter by exact age (cannot use with min_age/max_age)"
},
min_age: {
type: "number",
description: "Minimum age filter"
},
max_age: {
type: "number",
description: "Maximum age filter"
},
nationality_ids: {
type: "array",
items: { type: "number" },
description: "Filter by nationality IDs"
},
position_ids: {
type: "array",
items: { type: "number" },
description: "Filter by specific position IDs"
},
position_group_ids: {
type: "array",
items: { type: "number" },
description: "Filter by position group IDs (e.g., defenders, midfielders)"
},
in_national_team: {
type: "boolean",
description: "Filter by national team status"
},
sort_by: {
type: "string",
enum: ["score", "fair-market-value", "value-for-money"],
description: "Sort criteria: score (default), fair-market-value, or value-for-money",
default: "score"
},
limit: {
type: "number",
description: "Maximum number of players to return (1-1000, default 50)",
default: 50
}
}
}
},
{
name: "get_team_players",
description: "Get all players from a specific team with their details.",
inputSchema: {
type: "object",
properties: {
team_id: {
type: "number",
description: "The unique ID of the team"
}
},
required: ["team_id"]
}
},
{
name: "get_tournament_players",
description: "Get all players from a specific tournament.",
inputSchema: {
type: "object",
properties: {
tournament_id: {
type: "number",
description: "The unique ID of the tournament"
},
limit: {
type: "number",
description: "Maximum number of players to show in summary (default 20)",
default: 20
}
},
required: ["tournament_id"]
}
},
];
}
export async function handlePlayerTool(toolName, args, client) {
try {
switch (toolName) {
case "search_players": {
const params = validateInput(PlayerSearchSchema, args);
try {
// Build search parameters
const searchParams = {
player_name: params.player_name,
show_details: params.show_details || false
};
if (params.team_name)
searchParams.team_name = params.team_name;
const result = await client.searchPlayer(searchParams);
if (params.show_details) {
const player = result;
return `Found player:\n\n${formatPlayerInfo(player)}`;
}
else {
const playerId = result;
return `Found player ID: ${playerId}\n\nUse get_player_details with this ID to get full player information.`;
}
}
catch (error) {
return formatError(`No player found matching "${params.player_name}". The search requires at least 3 characters and uses fuzzy matching.`);
}
}
case "get_player_details": {
const params = validateInput(PlayerDetailsSchema, args);
try {
const result = await client.getPlayers({ player_id: params.player_id });
if (!result) {
return formatError(`No player found with ID ${params.player_id}`);
}
const player = result;
return formatPlayerInfo(player);
}
catch (error) {
return formatError(`Error retrieving player details for ID ${params.player_id}: ${error}`);
}
}
case "rank_players": {
const params = validateInput(PlayerRankingSchema, args);
try {
// Create clean params object without undefined values
const rankingParams = {};
if (params.tournament_ids)
rankingParams.tournament_ids = params.tournament_ids;
if (params.team_ids)
rankingParams.team_ids = params.team_ids;
if (params.age !== undefined)
rankingParams.age = params.age;
if (params.min_age !== undefined)
rankingParams.min_age = params.min_age;
if (params.max_age !== undefined)
rankingParams.max_age = params.max_age;
if (params.nationality_ids)
rankingParams.nationality_ids = params.nationality_ids;
if (params.position_ids)
rankingParams.position_ids = params.position_ids;
if (params.position_group_ids)
rankingParams.position_group_ids = params.position_group_ids;
if (params.in_national_team !== undefined)
rankingParams.in_national_team = params.in_national_team;
if (params.sort_by)
rankingParams.sort_by = params.sort_by;
const players = await client.getPlayerRanking(rankingParams);
if (players.length === 0) {
return formatError('No players found matching the specified criteria.');
}
const displayLimit = Math.min(params.limit || 50, 20); // Show max 20 in chat
let result = formatPlayerRanking(players, displayLimit);
// Add filter summary
const filters = [];
if (params.tournament_ids)
filters.push(`tournaments: ${params.tournament_ids.length}`);
if (params.team_ids)
filters.push(`teams: ${params.team_ids.length}`);
if (params.age)
filters.push(`age: ${params.age}`);
if (params.min_age || params.max_age) {
const ageRange = `${params.min_age || 'any'}-${params.max_age || 'any'}`;
filters.push(`age range: ${ageRange}`);
}
if (params.nationality_ids)
filters.push(`nationalities: ${params.nationality_ids.length}`);
if (params.position_ids)
filters.push(`positions: ${params.position_ids.length}`);
if (params.position_group_ids)
filters.push(`position groups: ${params.position_group_ids.length}`);
if (params.in_national_team !== undefined) {
filters.push(`national team: ${params.in_national_team ? 'yes' : 'no'}`);
}
if (filters.length > 0) {
result += `\n**Filters applied:** ${filters.join(', ')}\n`;
}
result += `**Sorted by:** ${params.sort_by || 'score'}\n`;
result += formatDataSummary('Players', displayLimit, players.length);
return result;
}
catch (error) {
return formatError(`Error retrieving player rankings: ${error}`);
}
}
case "get_team_players": {
const params = validateInput(TeamPlayersSchema, args);
try {
const result = await client.getPlayers({ team_id: params.team_id });
const players = Array.isArray(result) ? result : [result];
if (players.length === 0) {
return formatError(`No players found for team ID ${params.team_id}`);
}
// Get team name for better display
let teamName = `Team ID ${params.team_id}`;
if (players.length > 0 && players[0].team_name) {
teamName = players[0].team_name;
}
// Sort players by score (highest first)
const sortedPlayers = players.sort((a, b) => b.score - a.score);
let resultText = `**Players in ${teamName} (${players.length} total):**\n\n`;
// Show top 15 players with basic info
const displayLimit = Math.min(sortedPlayers.length, 15);
sortedPlayers.slice(0, displayLimit).forEach((player, index) => {
resultText += `${index + 1}. **${player.player_name}** (${player.age})\n`;
resultText += ` - Position: ${player.position} | Score: ${player.score} | Value: €${player.fair_market_value}M\n\n`;
});
if (players.length > displayLimit) {
resultText += `... and ${players.length - displayLimit} more players.\n\n`;
}
// Group by position for summary
const byPosition = players.reduce((acc, player) => {
if (!acc[player.position_group]) {
acc[player.position_group] = 0;
}
acc[player.position_group]++;
return acc;
}, {});
resultText += `**Position Distribution:**\n`;
Object.entries(byPosition).forEach(([position, count]) => {
resultText += `- ${position}: ${count} players\n`;
});
resultText += `\n💡 **Tip:** Use get_player_details with a player ID for complete information.`;
return resultText;
}
catch (error) {
return formatError(`Error retrieving players for team ID ${params.team_id}: ${error}`);
}
}
case "get_tournament_players": {
const params = validateInput(TournamentPlayersSchema, args);
try {
const result = await client.getPlayers({ tournament_id: params.tournament_id });
const players = Array.isArray(result) ? result : [result];
if (players.length === 0) {
return formatError(`No players found for tournament ID ${params.tournament_id}`);
}
// Get tournament name for better display
let tournamentName = `Tournament ID ${params.tournament_id}`;
if (players.length > 0 && players[0].tournament_name) {
tournamentName = players[0].tournament_name;
}
// Sort players by score (highest first)
const sortedPlayers = players.sort((a, b) => b.score - a.score);
const displayLimit = args.limit || 20;
const topPlayers = sortedPlayers.slice(0, displayLimit);
let resultText = `**Top ${displayLimit} Players in ${tournamentName} (${players.length} total):**\n\n`;
topPlayers.forEach((player, index) => {
resultText += `${index + 1}. **${player.player_name}** (${player.team_name})\n`;
resultText += ` - Position: ${player.position} | Age: ${player.age} | Score: ${player.score}\n`;
resultText += ` - Nationality: ${player.nationality} | Value: €${player.fair_market_value}M\n\n`;
});
// Group by position for summary
const byPosition = players.reduce((acc, player) => {
if (!acc[player.position_group]) {
acc[player.position_group] = 0;
}
acc[player.position_group]++;
return acc;
}, {});
resultText += `**Position Distribution:**\n`;
Object.entries(byPosition).forEach(([position, count]) => {
resultText += `- ${position}: ${count} players\n`;
});
if (players.length > displayLimit) {
resultText += `\n💡 **Tip:** Use rank_players with tournament_id filter for more advanced filtering and sorting.`;
}
return resultText;
}
catch (error) {
return formatError(`Error retrieving players for tournament ID ${params.tournament_id}: ${error}`);
}
}
default:
throw new Error(`Unknown player tool: ${toolName}`);
}
}
catch (error) {
return formatError(`Tool execution failed: ${error}`);
}
}
//# sourceMappingURL=player-tools.js.map