UNPKG

@bdmarvin/mcp-server-sleeper

Version:

A Model Context Protocol (MCP) server providing access to the Sleeper Fantasy Football API.

244 lines (243 loc) 12.6 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; // @ts-ignore import { zodToJsonSchema } from 'zod-to-json-schema'; import { z } from 'zod'; import { SleeperService } from './sleeper-api.js'; // Import Sleeper API schemas import { GetUserSchema, GetUserLeaguesSchema, GetLeagueSchema, GetLeagueRostersSchema, GetLeagueUsersSchema, GetLeagueMatchupsSchema, GetLeagueWinnersBracketSchema, GetLeagueLosersBracketSchema, GetLeagueTransactionsSchema, GetLeagueTradedPicksSchema, GetNFLStateSchema, GetAllPlayersSchema, GetTrendingPlayersSchema, GetUserDraftsSchema, GetLeagueDraftsSchema, GetDraftSchema, GetDraftPicksSchema, GetDraftTradedPicksSchema, } from './schemas.js'; const server = new Server({ name: 'sleeper-mcp-server', version: '0.1.5', // Updated version }, { capabilities: { resources: {}, tools: {}, prompts: {}, }, }); // Instantiate the service const sleeperService = new SleeperService(); console.error('Sleeper Server: Setting up ListToolsRequest handler'); server.setRequestHandler(ListToolsRequestSchema, async () => { console.error('Sleeper Server: ListToolsRequest handler called'); return { tools: [ { name: 'get_user', description: 'Fetches a user object by username or user ID.', inputSchema: zodToJsonSchema(GetUserSchema), }, { name: 'get_user_leagues', description: 'Retrieves all leagues for a given user, sport, and season.', inputSchema: zodToJsonSchema(GetUserLeaguesSchema), }, { name: 'get_league', description: 'Retrieves details for a specific league.', inputSchema: zodToJsonSchema(GetLeagueSchema), }, { name: 'get_league_rosters', description: 'Retrieves all rosters in a league.', inputSchema: zodToJsonSchema(GetLeagueRostersSchema), }, { name: 'get_league_users', description: 'Retrieves all users in a league.', inputSchema: zodToJsonSchema(GetLeagueUsersSchema), }, { name: 'get_league_matchups', description: 'Retrieves all matchups in a league for a given week.', inputSchema: zodToJsonSchema(GetLeagueMatchupsSchema), }, { name: 'get_league_winners_bracket', description: 'Retrieves the winners playoff bracket for a league.', inputSchema: zodToJsonSchema(GetLeagueWinnersBracketSchema), }, { name: 'get_league_losers_bracket', description: 'Retrieves the losers playoff bracket for a league.', inputSchema: zodToJsonSchema(GetLeagueLosersBracketSchema), }, { name: 'get_league_transactions', description: 'Retrieves all free agent transactions, waivers, and trades for a league in a given week.', inputSchema: zodToJsonSchema(GetLeagueTransactionsSchema), }, { name: 'get_league_traded_picks', description: 'Retrieves all traded picks in a league, including future picks.', inputSchema: zodToJsonSchema(GetLeagueTradedPicksSchema), }, { name: 'get_nfl_state', description: 'Returns information about the current state for NFL.', inputSchema: zodToJsonSchema(GetNFLStateSchema), }, { name: 'get_all_players', description: 'Fetches all players from a bundled local file. Supports dynamic filtering by any player attribute and selecting specific fields.', inputSchema: zodToJsonSchema(GetAllPlayersSchema), }, { name: 'get_trending_players', description: 'Gets a list of trending players based on add/drop activity.', inputSchema: zodToJsonSchema(GetTrendingPlayersSchema), }, { name: 'get_user_drafts', description: 'Retrieves all drafts by a user for a given sport and season.', inputSchema: zodToJsonSchema(GetUserDraftsSchema), }, { name: 'get_league_drafts', description: 'Retrieves all drafts for a league.', inputSchema: zodToJsonSchema(GetLeagueDraftsSchema), }, { name: 'get_draft', description: 'Retrieves a specific draft.', inputSchema: zodToJsonSchema(GetDraftSchema), }, { name: 'get_draft_picks', description: 'Retrieves all picks in a draft.', inputSchema: zodToJsonSchema(GetDraftPicksSchema), }, { name: 'get_draft_traded_picks', description: 'Retrieves all traded picks in a draft.', inputSchema: zodToJsonSchema(GetDraftTradedPicksSchema), }, ], }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const parsedArgs = request.params.arguments; console.error(`Sleeper Server: Received call for tool: ${request.params.name}`); switch (request.params.name) { case 'get_user': { const { identifier } = GetUserSchema.parse(parsedArgs); const data = await sleeperService.getUser(identifier); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_user_leagues': { const { userId, sport, season } = GetUserLeaguesSchema.parse(parsedArgs); const data = await sleeperService.getUserLeagues(userId, sport, season); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_league': { const { leagueId } = GetLeagueSchema.parse(parsedArgs); const data = await sleeperService.getLeague(leagueId); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_league_rosters': { const { leagueId } = GetLeagueRostersSchema.parse(parsedArgs); const data = await sleeperService.getLeagueRosters(leagueId); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_league_users': { const { leagueId } = GetLeagueUsersSchema.parse(parsedArgs); const data = await sleeperService.getLeagueUsers(leagueId); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_league_matchups': { const { leagueId, week } = GetLeagueMatchupsSchema.parse(parsedArgs); const data = await sleeperService.getLeagueMatchups(leagueId, week); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_league_winners_bracket': { const { leagueId } = GetLeagueWinnersBracketSchema.parse(parsedArgs); const data = await sleeperService.getLeagueWinnersBracket(leagueId); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_league_losers_bracket': { const { leagueId } = GetLeagueLosersBracketSchema.parse(parsedArgs); const data = await sleeperService.getLeagueLosersBracket(leagueId); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_league_transactions': { const { leagueId, round } = GetLeagueTransactionsSchema.parse(parsedArgs); const data = await sleeperService.getLeagueTransactions(leagueId, round); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_league_traded_picks': { const { leagueId } = GetLeagueTradedPicksSchema.parse(parsedArgs); const data = await sleeperService.getLeagueTradedPicks(leagueId); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_nfl_state': { const data = await sleeperService.getNFLState(); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_all_players': { const { filters, fields } = GetAllPlayersSchema.parse(parsedArgs); const data = await sleeperService.getAllPlayers(filters, fields); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_trending_players': { const { sport, type, lookbackHours, limit } = GetTrendingPlayersSchema.parse(parsedArgs); const data = await sleeperService.getTrendingPlayers(sport, type, lookbackHours, limit); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_user_drafts': { const { userId, sport, season } = GetUserDraftsSchema.parse(parsedArgs); const data = await sleeperService.getUserDrafts(userId, sport, season); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_league_drafts': { const { leagueId } = GetLeagueDraftsSchema.parse(parsedArgs); const data = await sleeperService.getLeagueDrafts(leagueId); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_draft': { const { draftId } = GetDraftSchema.parse(parsedArgs); const data = await sleeperService.getDraft(draftId); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_draft_picks': { const { draftId } = GetDraftPicksSchema.parse(parsedArgs); const data = await sleeperService.getDraftPicks(draftId); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } case 'get_draft_traded_picks': { const { draftId } = GetDraftTradedPicksSchema.parse(parsedArgs); const data = await sleeperService.getDraftTradedPicks(draftId); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } default: throw new Error(`Unknown tool: ${request.params.name}`); } } catch (error) { console.error(`Error in CallToolRequest handler for tool '${request.params.name}':`, error); if (error instanceof z.ZodError) { const messages = error.errors.map((e) => `${e.path.join('.') || 'argument'}: ${e.message}`); throw new Error(`Invalid arguments for tool '${request.params.name}': ${messages.join('; ')}`); } if (error instanceof Error) { console.error('Sleeper Server: Caught Error:', error.message); throw error; } console.error('Sleeper Server: Caught unexpected error:', String(error)); throw new Error(`An unexpected error occurred in tool '${request.params.name}': ${String(error)}`); } }); console.error('Sleeper Server: Creating StdioServerTransport'); async function runServer() { const transport = new StdioServerTransport(); console.error('Sleeper Server: Connecting server to transport'); await server.connect(transport); console.error('Sleeper Fantasy Football MCP Server (v0.1.5) running on stdio'); // Updated version in log } runServer().catch((error) => { console.error('Sleeper Server: Fatal error running Sleeper MCP Server:', error); process.exit(1); });