Skip to main content
Glama

Sleeper Fantasy MCP

TransactionsTool.ts•10.9 kB
import { config, getLeagueConfig } from "../config.js"; import type { SleeperRoster } from "../types/sleeper.js"; export class TransactionsTool { name = "get_league_transactions"; description = "Get league transactions including trades, waivers, and free agent moves"; inputSchema = { type: "object", properties: { league: { type: "string", description: "League name (ROAD_TO_GLORY or DYNASTY), defaults to configured default", enum: ["ROAD_TO_GLORY", "DYNASTY"] }, week: { type: "number", description: "Week number to get transactions for (defaults to current week)", minimum: 1, maximum: 18 }, transactionType: { type: "string", description: "Filter by transaction type", enum: ["trade", "waiver", "free_agent", "all"], default: "all" }, limit: { type: "number", description: "Maximum number of transactions to return (default: 20)", minimum: 1, maximum: 100, default: 20 }, includeAllWeeks: { type: "boolean", description: "Get transactions from all weeks (default: false)", default: false } } }; async execute(args: any) { const leagueConfig = getLeagueConfig(args.league); if (!leagueConfig) { throw new Error(`League configuration not found for: ${args.league}`); } const week = args.week || this.getCurrentWeek(); const transactionType = args.transactionType || 'all'; const limit = args.limit || 20; const includeAllWeeks = args.includeAllWeeks || false; try { // Fetch required data const fetchPromises = [ fetch(`${config.api.baseUrl}/league/${leagueConfig.id}/users`), fetch(`${config.api.baseUrl}/league/${leagueConfig.id}/rosters`), fetch(`${config.api.baseUrl}/players/nfl`) ]; // Add transactions for specific week or all weeks if (includeAllWeeks) { // Fetch transactions for weeks 1-18 for (let w = 1; w <= 18; w++) { fetchPromises.push( fetch(`${config.api.baseUrl}/league/${leagueConfig.id}/transactions/${w}`) .catch(() => new Response('[]', { status: 404 })) // Handle weeks that don't exist yet ); } } else { fetchPromises.push( fetch(`${config.api.baseUrl}/league/${leagueConfig.id}/transactions/${week}`) ); } const responses = await Promise.all(fetchPromises); // Check core data responses if (!responses[0]?.ok || !responses[1]?.ok || !responses[2]?.ok) { throw new Error('Failed to fetch core league data'); } const users = await responses[0].json(); const rosters: SleeperRoster[] = await responses[1].json(); const players = await responses[2].json(); // Process transaction responses let allTransactions: any[] = []; if (includeAllWeeks) { // Process all week responses (starting from index 3) for (let i = 3; i < responses.length; i++) { if (responses[i]?.ok) { const weekTransactions = await (responses[i] as Response).json(); if (Array.isArray(weekTransactions)) { allTransactions = allTransactions.concat( weekTransactions.map(t => ({ ...t, week: i - 2 })) // Add week number ); } } } } else { // Single week response if (responses[3]?.ok) { const weekTransactions = await responses[3].json(); if (Array.isArray(weekTransactions)) { allTransactions = weekTransactions.map(t => ({ ...t, week })); } } } // Create lookup maps const userMap = new Map(users.map((user: any) => [user.user_id, user])); const rosterMap = new Map(rosters.map(roster => [roster.owner_id, roster])); // Filter and format transactions const formattedTransactions = allTransactions .filter(transaction => { if (transactionType === 'all') return true; return transaction.type === transactionType; }) .map(transaction => { const creator = userMap.get(transaction.creator); const creatorRoster = rosterMap.get(transaction.creator); // Process adds and drops const adds = Object.entries(transaction.adds || {}).map(([playerId, rosterId]) => { const player = players[playerId]; const targetRoster = rosters.find(r => r.roster_id === rosterId); const targetUser = targetRoster ? userMap.get(targetRoster.owner_id) : null; return { playerId, playerName: player ? `${player.first_name} ${player.last_name}` : 'Unknown Player', position: player?.position || 'UNK', team: player?.team || 'FA', acquiredBy: { rosterId, teamName: leagueConfig.teamName, // This would need roster metadata for team names username: (targetUser as any)?.display_name || 'Unknown' } }; }); const drops = Object.entries(transaction.drops || {}).map(([playerId, rosterId]) => { const player = players[playerId]; const sourceRoster = rosters.find(r => r.roster_id === rosterId); const sourceUser = sourceRoster ? userMap.get(sourceRoster.owner_id) : null; return { playerId, playerName: player ? `${player.first_name} ${player.last_name}` : 'Unknown Player', position: player?.position || 'UNK', team: player?.team || 'FA', droppedBy: { rosterId, teamName: leagueConfig.teamName, // This would need roster metadata for team names username: (sourceUser as any)?.display_name || 'Unknown' } }; }); // Process FAAB budget const faabSpent = Object.entries(transaction.waiver_budget || {}).map(([rosterId, amount]) => { const roster = rosters.find(r => r.roster_id === parseInt(rosterId)); const user = roster ? userMap.get(roster.owner_id) : null; return { rosterId: parseInt(rosterId), username: (user as any)?.display_name || 'Unknown', amount: Number(amount) }; }); return { transactionId: transaction.transaction_id, type: transaction.type, status: transaction.status, week: transaction.week, created: new Date(transaction.created).toISOString(), createdBy: { username: (creator as any)?.display_name || 'Unknown', rosterId: creatorRoster?.roster_id || null }, adds: adds, drops: drops, faabSpent: faabSpent, totalFaabSpent: faabSpent.reduce((sum, f) => sum + f.amount, 0), rosterIds: transaction.roster_ids || [], metadata: { isWaiverClaim: transaction.type === 'waiver', isTrade: transaction.type === 'trade', isFreeAgent: transaction.type === 'free_agent', playerCount: (transaction.adds ? Object.keys(transaction.adds).length : 0) + (transaction.drops ? Object.keys(transaction.drops).length : 0) } }; }) .sort((a, b) => new Date(b.created).getTime() - new Date(a.created).getTime()) .slice(0, limit); const result = { league: args.league || config.defaultLeague, week: includeAllWeeks ? 'All weeks' : week, transactionType: transactionType, totalTransactions: formattedTransactions.length, timeRange: { includeAllWeeks: includeAllWeeks, requestedWeek: week }, transactions: formattedTransactions, summary: { byType: this.getTransactionTypeSummary(formattedTransactions), totalFaabSpent: formattedTransactions.reduce((sum, t) => sum + t.totalFaabSpent, 0), mostActiveUsers: this.getMostActiveUsers(formattedTransactions), recentActivity: formattedTransactions.slice(0, 5).map(t => ({ type: t.type, playerNames: [...t.adds.map(a => a.playerName), ...t.drops.map(d => d.playerName)], username: t.createdBy.username, timeAgo: this.getTimeAgo(t.created) })) } }; return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { throw new Error(`Failed to get league transactions: ${error instanceof Error ? error.message : String(error)}`); } } private getCurrentWeek(): number { const now = new Date(); const seasonStart = new Date('2024-09-05'); const weeksSinceStart = Math.floor((now.getTime() - seasonStart.getTime()) / (7 * 24 * 60 * 60 * 1000)); return Math.max(1, Math.min(18, weeksSinceStart + 1)); } private getTransactionTypeSummary(transactions: any[]): Record<string, number> { return transactions.reduce((summary, transaction) => { summary[transaction.type] = (summary[transaction.type] || 0) + 1; return summary; }, {}); } private getMostActiveUsers(transactions: any[]): Array<{username: string, transactionCount: number}> { const userActivity = transactions.reduce((activity, transaction) => { const username = transaction.createdBy.username; activity[username] = (activity[username] || 0) + 1; return activity; }, {} as Record<string, number>); return Object.entries(userActivity) .map(([username, count]) => ({ username, transactionCount: Number(count) })) .sort((a, b) => b.transactionCount - a.transactionCount) .slice(0, 5); } private getTimeAgo(dateString: string): string { const now = new Date(); const past = new Date(dateString); const diffMs = now.getTime() - past.getTime(); const minutes = Math.floor(diffMs / (1000 * 60)); const hours = Math.floor(diffMs / (1000 * 60 * 60)); const days = Math.floor(diffMs / (1000 * 60 * 60 * 24)); if (minutes < 60) return `${minutes} minutes ago`; if (hours < 24) return `${hours} hours ago`; return `${days} days ago`; } }

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/justfeltlikerunning/sleeper-fantasy-mcp'

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