竞赛日历管理服务

一个自动化管理编程竞赛日历的服务,支持从多个平台获取竞赛信息并同步到Google日历。

  • by grilled-swampert
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 grilled-swampert/mcp-coding-test-reminder

使用说明

竞赛日历MCP服务器-重构结构

项目结构

contest-calendar-mcp/
├── config.py              # Configuration settings and constants
├── utils.py               # Utility functions for time conversion
├── database.py            # Database management and queries
├── fetchers.py            # API fetchers for contest platforms
├── calendar_manager.py    # Google Calendar integration
├── tools.py               # MCP tool implementations
├── server.py              # Main MCP server entry point
├── requirements.txt       # Python dependencies
└── README.md              # Documentation

~/.contest_calendar/       # Data directory (auto-created)
├── contests.db            # SQLite database
├── token.pickle           # Google OAuth token
└── credentials.json       # Google OAuth credentials (user provided)

安装说明

1.安装依赖项

pip install fastmcp aiohttp google-auth-oauthlib google-api-python-client

或运行:

pip install -r requirements.txt

2.谷歌日历设置

  1. 首选 谷歌云控制台
  2. 创建新项目或选择现有项目
  3. 启用Google日历API
  4. 创建OAuth 2.0凭据(桌面应用程序)
  5. 下载凭据并另存为 ~/.contest_calendar/credentials.json

3.运行服务器

python server.py

首次运行时,它将打开一个浏览器进行谷歌身份验证。

调试指南

测试单个组件

测试数据库:

from database import ContestDatabase

db = ContestDatabase()
contests = db.get_upcoming_contests()
print(contests)

测试取件器:

import asyncio
from fetchers import ContestFetcher

async def test():
    contests = await ContestFetcher.fetch_codeforces()
    print(contests)

asyncio.run(test())

测试日历:

from calendar_manager import GoogleCalendarManager

cal = GoogleCalendarManager()
cal.authenticate()
events = cal.list_events()
print(events)

测试工具:

from datetime import datetime, timezone
from utils import to_ist, format_ist_time

now = datetime.now(timezone.utc)
print(format_ist_time(now))

添加新平台

要添加新的竞赛平台(例如AtCoder):

  1. 在 config.py:添加API URL常量
  2. 在 fetchers.py:添加 fetch_atcoder() 方法
  3. 在 fetchers.py:更新 fetch_all() 包括新的提取器

例子:

# In config.py
ATCODER_API_URL = "https://atcoder.jp/contests/..."

# In fetchers.py
@staticmethod
async def fetch_atcoder():
    # Implementation here
    pass

@staticmethod
async def fetch_all():
    results = await asyncio.gather(
        ContestFetcher.fetch_codeforces(),
        ContestFetcher.fetch_leetcode(),
        ContestFetcher.fetch_codechef(),
        ContestFetcher.fetch_atcoder(),  # Add here
        return_exceptions=True
    )
    # Rest of the code...

在生产中运行

对于生产部署:

# Run with process manager
pm2 start server.py --interpreter python3 --name contest-calendar