| | import { z } from "zod"; |
| | import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; |
| | import { safeToolHandler } from "./base"; |
| | import * as service from "../../codeforces/service"; |
| |
|
| | |
| | |
| | |
| | export function register(mcp: McpServer): void { |
| | |
| | mcp.tool( |
| | "codeforces_get_rating", |
| | "Fetches a Codeforces user's current rating, rank, max rating, contribution score, and avatar URL.", |
| | { username: z.string().describe("The Codeforces handle (username)") }, |
| | safeToolHandler(({ username }) => service.getUserRating(username)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_contest_history", |
| | "Fetches the complete contest participation history for a Codeforces user, including rating changes after each contest.", |
| | { username: z.string().describe("The Codeforces handle (username)") }, |
| | safeToolHandler(({ username }) => service.getContestHistory(username)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_user_status", |
| | "Fetches recent submissions for a Codeforces user with verdict, problem info, and submission details.", |
| | { |
| | username: z.string().describe("The Codeforces handle (username)"), |
| | from: z.number().optional().default(1).describe("1-based index of the first submission to return (default: 1)"), |
| | count: z.number().optional().default(10).describe("Number of submissions to return (default: 10)") |
| | }, |
| | safeToolHandler(({ username, from, count }) => service.getUserStatus(username, from, count)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_user_blogs", |
| | "Fetches all blog entries authored by a Codeforces user, including titles, ratings, and creation times.", |
| | { username: z.string().describe("The Codeforces handle (username)") }, |
| | safeToolHandler(({ username }) => service.getUserBlogs(username)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_solved_problems", |
| | "Fetches all problems solved by a Codeforces user, including problem ratings, tags, and direct links.", |
| | { username: z.string().describe("The Codeforces handle (username)") }, |
| | safeToolHandler(({ username }) => service.getSolvedProblems(username)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_contests", |
| | "Fetches the list of all Codeforces contests (past and upcoming), optionally including gym contests.", |
| | { gym: z.boolean().optional().default(false).describe("If true, include gym contests (default: false)") }, |
| | safeToolHandler(({ gym }) => service.getContests(gym)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_recent_actions", |
| | "Fetches recent actions on Codeforces such as new blog entries and comments.", |
| | { maxCount: z.number().optional().default(20).describe("Maximum number of actions to return (default: 20, max: 100)") }, |
| | safeToolHandler(({ maxCount }) => service.getRecentActions(maxCount)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_problems", |
| | "Fetches all problems from the Codeforces problemset, optionally filtered by tags.", |
| | { tags: z.string().optional().describe("Semicolon-separated tags to filter problems (e.g., 'dp;greedy')") }, |
| | safeToolHandler(({ tags }) => service.getProblems(tags)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_contest_standings", |
| | "Fetches the standings/leaderboard for a specific Codeforces contest with participant rankings and scores.", |
| | { |
| | contestId: z.number().describe("The numeric ID of the contest"), |
| | from: z.number().optional().describe("1-based index of the first standing row"), |
| | count: z.number().optional().describe("Number of standings rows to return"), |
| | handles: z.string().optional().describe("Semicolon-separated handles to filter the standings"), |
| | room: z.number().optional().describe("Room number to filter standings"), |
| | showUnofficial: z.boolean().optional().describe("Include unofficial participants") |
| | }, |
| | safeToolHandler(({ contestId, from, count, handles, room, showUnofficial }) => |
| | service.getContestStandings(contestId, from, count, handles, room, showUnofficial) |
| | ) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_contest_rating_changes", |
| | "Fetches the rating changes for all participants in a specific Codeforces contest.", |
| | { contestId: z.number().describe("The numeric ID of the contest") }, |
| | safeToolHandler(({ contestId }) => service.getContestRatingChanges(contestId)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_contest_hacks", |
| | "Fetches all successful and unsuccessful hacks that occurred during a Codeforces contest.", |
| | { contestId: z.number().describe("The numeric ID of the contest") }, |
| | safeToolHandler(({ contestId }) => service.getContestHacks(contestId)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_contest_status", |
| | "Fetches submissions made in a specific Codeforces contest, optionally filtered by a handle.", |
| | { |
| | contestId: z.number().describe("The numeric ID of the contest"), |
| | handle: z.string().optional().describe("Optional handle to filter submissions"), |
| | from: z.number().optional().describe("1-based index of the first submission"), |
| | count: z.number().optional().describe("Number of submissions to return") |
| | }, |
| | safeToolHandler(({ contestId, handle, from, count }) => |
| | service.getContestStatus(contestId, handle, from, count) |
| | ) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_problemset_recent_status", |
| | "Fetches the most recent submissions across the entire Codeforces problemset.", |
| | { count: z.number().describe("Number of recent submissions to return (max: 1000)") }, |
| | safeToolHandler(({ count }) => service.getProblemsetRecentStatus(count)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_blog_entry", |
| | "Fetches the full content of a specific Codeforces blog entry by its ID.", |
| | { blogEntryId: z.number().describe("The numeric ID of the blog entry") }, |
| | safeToolHandler(({ blogEntryId }) => service.getBlogEntry(blogEntryId)) |
| | ); |
| |
|
| | |
| | mcp.tool( |
| | "codeforces_get_blog_comments", |
| | "Fetches all comments on a specific Codeforces blog entry.", |
| | { blogEntryId: z.number().describe("The numeric ID of the blog entry") }, |
| | safeToolHandler(({ blogEntryId }) => service.getBlogComments(blogEntryId)) |
| | ); |
| | } |
| |
|