File size: 10,818 Bytes
3d23b0f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
import { z } from "zod";
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { safeToolHandler } from "./base";
import * as userService from "../../leetcode/services/user";
import * as contestService from "../../leetcode/services/contest";
import * as problemService from "../../leetcode/services/problem";
import * as discussionService from "../../leetcode/services/discussion";

export function register(mcp: McpServer): void {
    // ==================== USER TOOLS ====================

    // Get user contest rating
    mcp.tool(
        "leetcode_get_rating",
        "Fetches the LeetCode contest rating for a user, including their global ranking, attended contests count, and rating percentile.",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => userService.getUserRating(username))
    );

    // Get user profile
    mcp.tool(
        "leetcode_get_profile",
        "Fetches the complete LeetCode profile for a user, including basic info, company, school, skills, and social links.",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => userService.getUserProfile(username))
    );

    // Get user details
    mcp.tool(
        "leetcode_get_details",
        "Fetches detailed user information from LeetCode including profile data, submission stats, and problem solving summary.",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => userService.getUserDetails(username))
    );

    // Get user badges
    mcp.tool(
        "leetcode_get_badges",
        "Fetches all badges earned by a LeetCode user, including annual badges and special achievements.",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => userService.getUserBadges(username))
    );

    // Get user solved problems
    mcp.tool(
        "leetcode_get_solved",
        "Fetches the solved problems count for a LeetCode user, broken down by difficulty (Easy, Medium, Hard).",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => userService.getUserSolved(username))
    );

    // Get user contest ranking
    mcp.tool(
        "leetcode_get_contest_ranking",
        "Fetches detailed contest ranking information for a LeetCode user, including rating, ranking, and top percentage.",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => userService.getUserContest(username))
    );

    // Get user contest history
    mcp.tool(
        "leetcode_get_contest_history",
        "Fetches the complete contest participation history for a LeetCode user, including each contest's ranking and rating changes.",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => userService.getUserContestHistory(username))
    );

    // Get user submissions
    mcp.tool(
        "leetcode_get_submissions",
        "Fetches recent submissions for a LeetCode user, including problem title, status, language, and timestamp.",
        {
            username: z.string().describe("The LeetCode username to look up"),
            limit: z.number().optional().default(20).describe("Maximum number of submissions to return (default: 20)")
        },
        safeToolHandler(({ username, limit }) => userService.getUserSubmission(username, limit))
    );

    // Get user accepted submissions
    mcp.tool(
        "leetcode_get_ac_submissions",
        "Fetches recent accepted (AC) submissions for a LeetCode user, filtered to only show successful solutions.",
        {
            username: z.string().describe("The LeetCode username to look up"),
            limit: z.number().optional().default(20).describe("Maximum number of AC submissions to return (default: 20)")
        },
        safeToolHandler(({ username, limit }) => userService.getUserAcSubmission(username, limit))
    );

    // Get user calendar/activity
    mcp.tool(
        "leetcode_get_calendar",
        "Fetches the submission calendar/heatmap data for a LeetCode user for a specific year, showing daily activity.",
        {
            username: z.string().describe("The LeetCode username to look up"),
            year: z.number().describe("The year to fetch calendar data for (e.g., 2024)")
        },
        safeToolHandler(({ username, year }) => userService.getUserCalendar(username, year))
    );

    // Get user skill stats
    mcp.tool(
        "leetcode_get_skill_stats",
        "Fetches the skill/tag statistics for a LeetCode user, showing proficiency in different problem categories like DP, Graph, etc.",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => userService.getUserSkill(username))
    );

    // Get user language stats
    mcp.tool(
        "leetcode_get_languages",
        "Fetches the programming language statistics for a LeetCode user, showing problems solved per language.",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => userService.getUserLanguage(username))
    );

    // Get user progress
    mcp.tool(
        "leetcode_get_progress",
        "Fetches the overall problem-solving progress for a LeetCode user across all categories.",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => userService.getUserProgress(username))
    );

    // ==================== CONTEST TOOLS ====================

    // Get contest ranking info
    mcp.tool(
        "leetcode_get_contest_ranking_info",
        "Fetches detailed contest ranking information including rating, global rank, and percentile for a user.",
        { username: z.string().describe("The LeetCode username to look up") },
        safeToolHandler(({ username }) => contestService.getContestRankingInfo(username))
    );

    // Get contest histogram
    mcp.tool(
        "leetcode_get_contest_histogram",
        "Fetches the contest rating distribution histogram showing how many users are at each rating level.",
        {},
        safeToolHandler(() => contestService.getContestHistogram())
    );

    // Get all contests
    mcp.tool(
        "leetcode_get_all_contests",
        "Fetches a list of all LeetCode contests including past weekly and biweekly contests with their details.",
        {},
        safeToolHandler(() => contestService.getAllContests())
    );

    // Get upcoming contests
    mcp.tool(
        "leetcode_get_upcoming_contests",
        "Fetches a list of upcoming LeetCode contests that haven't started yet.",
        {},
        safeToolHandler(() => contestService.getUpcomingContests())
    );

    // ==================== PROBLEM TOOLS ====================

    // Get daily problem
    mcp.tool(
        "leetcode_get_daily_problem",
        "Fetches today's LeetCode Daily Challenge problem with its details, difficulty, and constraints.",
        {
            raw: z.boolean().optional().default(false).describe("Return raw API response if true (default: false)")
        },
        safeToolHandler(({ raw }) => problemService.getDailyProblem(raw))
    );

    // Get specific problem by slug
    mcp.tool(
        "leetcode_get_problem",
        "Fetches detailed information about a specific LeetCode problem by its title slug (e.g., 'two-sum').",
        {
            titleSlug: z.string().describe("The URL slug of the problem (e.g., 'two-sum', 'add-two-numbers')"),
            raw: z.boolean().optional().default(false).describe("Return raw API response if true (default: false)")
        },
        safeToolHandler(({ titleSlug, raw }) => problemService.getSelectProblem(titleSlug, raw))
    );

    // Get problems list
    mcp.tool(
        "leetcode_get_problems",
        "Fetches a filtered list of LeetCode problems with pagination, difficulty filter, and category support.",
        {
            limit: z.number().optional().default(20).describe("Number of problems to return"),
            skip: z.number().optional().default(0).describe("Number of problems to skip (for pagination)"),
            categorySlug: z.string().optional().describe("Category slug to filter by (e.g., 'algorithms', 'database')"),
            filters: z.object({
                difficulty: z.string().optional().describe("Difficulty filter: 'EASY', 'MEDIUM', or 'HARD'"),
                tags: z.array(z.string()).optional().describe("Array of tag slugs to filter by")
            }).optional().describe("Optional filters object")
        },
        safeToolHandler((params) => problemService.getProblems(params))
    );

    // Get official solution
    mcp.tool(
        "leetcode_get_official_solution",
        "Fetches the official LeetCode solution/editorial for a specific problem.",
        {
            titleSlug: z.string().describe("The URL slug of the problem (e.g., 'two-sum')")
        },
        safeToolHandler(({ titleSlug }) => problemService.getOfficialSolution(titleSlug))
    );

    // ==================== DISCUSSION TOOLS ====================

    // Get trending discussions
    mcp.tool(
        "leetcode_get_trending_discussions",
        "Fetches the top trending discussions from LeetCode's discussion forum.",
        {
            first: z.number().optional().default(10).describe("Number of trending discussions to return (default: 10)")
        },
        safeToolHandler(({ first }) => discussionService.getTrendingDiscuss(first))
    );

    // Get specific discussion topic
    mcp.tool(
        "leetcode_get_discussion_topic",
        "Fetches a specific discussion topic by its ID, including the full content and metadata.",
        {
            topicId: z.number().describe("The numeric ID of the discussion topic")
        },
        safeToolHandler(({ topicId }) => discussionService.getDiscussTopic(topicId))
    );

    // Get discussion comments
    mcp.tool(
        "leetcode_get_discussion_comments",
        "Fetches comments/replies on a specific LeetCode discussion topic.",
        {
            topicId: z.number().describe("The numeric ID of the discussion topic"),
            orderBy: z.string().optional().default("hot").describe("Order by: 'hot', 'newest', or 'oldest'"),
            pageNo: z.number().optional().default(1).describe("Page number for pagination"),
            numPerPage: z.number().optional().default(10).describe("Number of comments per page")
        },
        safeToolHandler((params) => discussionService.getDiscussComments(params))
    );
}