@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
JavaScript
#!/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);
});