Skip to main content
Glama

NHL MCP Server

by argotdev
nhl-api.ts7.19 kB
/** * NHL API Client * * Interfaces with the official NHL APIs: * - api-web.nhle.com (primary data source) * - api.nhle.com/stats/rest (statistics) */ import fetch from 'node-fetch'; const NHL_API_BASE = 'https://api-web.nhle.com/v1'; const NHL_STATS_API_BASE = 'https://api.nhle.com/stats/rest/en'; export interface GameScore { id: number; season: number; gameType: number; gameDate: string; venue: string; homeTeam: { id: number; abbrev: string; name: string; score: number; }; awayTeam: { id: number; abbrev: string; name: string; score: number; }; gameState: string; period: number; periodDescriptor?: { number: number; periodType: string; }; } export interface TeamStandings { teamAbbrev: { default: string; }; teamName: { default: string; }; teamLogo: string; wins: number; losses: number; otLosses: number; points: number; gamesPlayed: number; goalFor: number; goalAgainst: number; goalDifferential: number; regulationWins: number; winPctg: number; conferenceAbbrev: string; divisionAbbrev: string; placeName?: { default: string; }; } export interface PlayerStats { id: number; firstName: { default: string; }; lastName: { default: string; }; sweaterNumber: number; headshot: string; teamAbbrev: string; teamName: { default: string; }; teamLogo: string; position: string; value: number; // The stat value (points, goals, assists, etc.) } export interface GoalieStats { id: number; firstName: { default: string; }; lastName: { default: string; }; sweaterNumber: number; headshot: string; teamAbbrev: string; teamName: { default: string; }; teamLogo: string; position: string; value: number; // The stat value (savePctg, wins, etc.) } export class NHLAPIClient { private async fetchJSON(url: string): Promise<any> { const response = await fetch(url); if (!response.ok) { throw new Error(`NHL API error: ${response.status} ${response.statusText}`); } return response.json(); } /** * Get today's NHL games with scores and status */ async getTodaysScores(date?: string): Promise<GameScore[]> { const dateStr = date || new Date().toISOString().split('T')[0]; const data = await this.fetchJSON(`${NHL_API_BASE}/score/${dateStr}`); return data.games || []; } /** * Get detailed game data including play-by-play */ async getGameDetails(gameId: number): Promise<any> { return this.fetchJSON(`${NHL_API_BASE}/gamecenter/${gameId}/play-by-play`); } /** * Get game boxscore with detailed stats */ async getGameBoxscore(gameId: number): Promise<any> { return this.fetchJSON(`${NHL_API_BASE}/gamecenter/${gameId}/boxscore`); } /** * Get current standings (optionally by date) */ async getStandings(date?: string): Promise<{ standings: TeamStandings[] }> { const dateStr = date || new Date().toISOString().split('T')[0]; return this.fetchJSON(`${NHL_API_BASE}/standings/${dateStr}`); } /** * Get standings by season */ async getStandingsBySeason(season: string): Promise<{ standings: TeamStandings[] }> { return this.fetchJSON(`${NHL_API_BASE}/standings/${season}`); } /** * Get team schedule */ async getTeamSchedule(teamAbbrev: string, season?: string): Promise<any> { const seasonStr = season || this.getCurrentSeason(); return this.fetchJSON(`${NHL_API_BASE}/club-schedule-season/${teamAbbrev}/${seasonStr}`); } /** * Get schedule for a specific week */ async getSchedule(date?: string): Promise<any> { const dateStr = date || new Date().toISOString().split('T')[0]; return this.fetchJSON(`${NHL_API_BASE}/schedule/${dateStr}`); } /** * Get player stats for current season */ async getPlayerStats(playerId: number, season?: string): Promise<any> { const seasonStr = season || this.getCurrentSeason(); return this.fetchJSON(`${NHL_API_BASE}/player/${playerId}/landing`); } /** * Get top skaters by category */ async getTopSkaters(category: string = 'points', limit: number = 20, season?: string): Promise<PlayerStats[]> { const seasonStr = season || this.getCurrentSeason(); if (!season) { // Use current stats leaders endpoint const data = await this.fetchJSON( `${NHL_API_BASE}/skater-stats-leaders/current?categories=${category}&limit=${limit}` ); return data[category] || []; } else { // Use seasonal stats leaders endpoint const data = await this.fetchJSON( `${NHL_API_BASE}/skater-stats-leaders/${seasonStr}/2?categories=${category}&limit=${limit}` ); return data[category] || []; } } /** * Get top goalies */ async getTopGoalies(limit: number = 20, season?: string): Promise<GoalieStats[]> { const seasonStr = season || this.getCurrentSeason(); const category = 'savePctg'; // Default to save percentage if (!season) { // Use current stats leaders endpoint const data = await this.fetchJSON( `${NHL_API_BASE}/goalie-stats-leaders/current?categories=${category}&limit=${limit}` ); return data[category] || []; } else { // Use seasonal stats leaders endpoint const data = await this.fetchJSON( `${NHL_API_BASE}/goalie-stats-leaders/${seasonStr}/2?categories=${category}&limit=${limit}` ); return data[category] || []; } } /** * Get playoff bracket (when available) */ async getPlayoffBracket(season?: string): Promise<any> { const year = season || new Date().getFullYear().toString(); return this.fetchJSON(`${NHL_API_BASE}/playoff-bracket/${year}`); } /** * Get playoff series */ async getPlayoffSeries(season?: string): Promise<any> { const seasonStr = season || this.getCurrentSeason(); return this.fetchJSON(`${NHL_API_BASE}/playoff-series/${seasonStr}/playoff`); } /** * Get team roster and stats */ async getTeamStats(teamAbbrev: string, season?: string): Promise<any> { const seasonStr = season || this.getCurrentSeason(); return this.fetchJSON(`${NHL_API_BASE}/club-stats/${teamAbbrev}/${seasonStr}/2`); } /** * Get team roster */ async getTeamRoster(teamAbbrev: string, season?: string): Promise<any> { const seasonStr = season || this.getCurrentSeason(); return this.fetchJSON(`${NHL_API_BASE}/roster/${teamAbbrev}/${seasonStr}`); } /** * Helper: Get current NHL season ID (e.g., 20242025) */ private getCurrentSeason(): string { const now = new Date(); const year = now.getFullYear(); const month = now.getMonth() + 1; // 0-indexed // NHL season typically starts in October if (month >= 10) { return `${year}${year + 1}`; } else { return `${year - 1}${year}`; } } /** * Parse season string to readable format */ formatSeason(season: string): string { if (season.length === 8) { const startYear = season.substring(0, 4); const endYear = season.substring(4, 8); return `${startYear}-${endYear}`; } return season; } }

Latest Blog Posts

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/argotdev/nhl-mcp-ts'

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