关于 mycal
mycal 是面向需要查询州属假日、校历和工作日的用户的马来西亚日历 API 与 MCP 服务。它还提供休假规划,并采用马来西亚政府来源的数据。
主要功能
- 01按州查询公共假日
- 02周末与补假规则
- 03工作日计算
- 04学期、学校假期与考试
- 05休假及长周末规划
适用场景
- 01确认某日是否为工作日
- 02计算州属工作日数量
- 03查询学期与考试日期
- 04围绕公共假日规划休假
MCP 相关
MCP 服务向兼容 MCP 的 AI 助手提供 13 种日历工具,支持查询假日、工作日、校历和休假规划。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
13收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| type | enum | 否 | federal | state | islamic | islamic_state | replacement | adhoc |
| year | integer | 是 | 年份(例如 2026) |
| month | integer | 否 | |
| state | string | 否 | 州代码或别名(例如 'selangor'、'KL'、'penang') |
| status | enum | 否 | confirmed | tentative | announced | cancelled |
详细介绍
马来西亚日历 API
马来西亚最全面的日历 API——公共假日、学校日历、考试安排,以及面向 AI 工具的 MCP 服务。
数据来源:政府官方公报(JPM BKPP)、JAKIM、KPM、MPM。数据并非从第三方网站抓取。
链接
- 网站 + 演示:https://mycal-web.pages.dev
- 开发者文档:https://mycal-web.pages.dev/docs
- API 基础 URL:https://mycal-api.huijun00100101.workers.dev/v1
- GitHub:https://github.com/Junhui20/malaysia-calendar-api
软件包
以 @catlabtech 作用域发布到 npm:
| 软件包 | 用途 | 安装 |
|---|---|---|
@catlabtech/mycal-core | 共享类型、Zod 模式以及日历和工作日逻辑 | npm install @catlabtech/mycal-core |
@catlabtech/mycal-sdk | REST API 的 TypeScript 客户端 SDK | npm install @catlabtech/mycal-sdk |
@catlabtech/mycal-mcp-server | 提供 13 个日历工具的 MCP 服务,供 AI Agent 使用 | npm install @catlabtech/mycal-mcp-server |
功能
- 2026 年的 50 个公共假日,数据来自官方公报(Warta Kerajaan)——包括联邦假日和州属假日
- 13 个州 + 3 个联邦直辖区,支持别名(KL、JB、Penang 等)
- 考虑周末安排——吉打州/吉兰丹州/登嘉楼州采用周五至周六(Kumpulan A),其他地区采用周六至周日(Kumpulan B),并记录柔佛州历史上的周末安排变更
- Cuti ganti(补假)根据各州周末安排自动计算
- 工作日计算器——按州计算,并考虑假日
- 学校日历——学期、假期、KPM 节庆假期(Lampiran A/B/C)
- 考试安排——SPM、STPM、MUET、PT3
- iCal 订阅源——各州独立的
.ics订阅源 - 面向 AI Agent 的 MCP 服务——提供 13 个工具,适用于 Claude、ChatGPT 和其他助手
- TypeScript SDK(
@catlabtech/mycal-sdk),提供类型化响应 - OpenAPI 3.1 规范 + 交互式文档
- 三语支持——马来语、英语和中文名称(三语支持)
快速开始
# Clone and install
git clone https://github.com/Junhui20/malaysia-calendar-api.git
cd malaysia-calendar-api
pnpm install
# Build shared packages
pnpm --filter @catlabtech/mycal-core build
pnpm --filter @catlabtech/mycal-sdk build
# Run API locally (http://localhost:8787)
cd packages/api && npx wrangler dev
# Run web site locally (http://localhost:4321)
pnpm --filter @mycal/web dev
# Validate data
pnpm validate
# Run tests
pnpm test
API 示例
基础 URL:https://mycal-api.huijun00100101.workers.dev/v1
列出假日
# All holidays for Selangor in 2026
curl "https://mycal-api.huijun00100101.workers.dev/v1/holidays?year=2026&state=selangor"
# Islamic holidays only
curl "https://mycal-api.huijun00100101.workers.dev/v1/holidays?year=2026&type=islamic"
# March holidays for KL
curl "https://mycal-api.huijun00100101.workers.dev/v1/holidays?year=2026&state=KL&month=3"
查询日期
# Is March 21 a holiday/weekend/working day?
curl "https://mycal-api.huijun00100101.workers.dev/v1/holidays/check?date=2026-03-21&state=KL"
响应:
{
"data": {
"date": "2026-03-21",
"dayOfWeek": "Saturday",
"isHoliday": true,
"isWeekend": true,
"isWorkingDay": false,
"isSchoolDay": false,
"holidays": [
{
"id": "2026-hari-raya-aidilfitri-1",
"name": { "ms": "Hari Raya Aidilfitri", "en": "Eid al-Fitr", "zh": "开斋节" },
"type": "islamic",
"status": "confirmed"
}
]
}
}
工作日
# Count working days in March for Selangor
curl "https://mycal-api.huijun00100101.workers.dev/v1/business-days?start=2026-03-01&end=2026-03-31&state=selangor"
# Add 10 business days to a date
curl "https://mycal-api.huijun00100101.workers.dev/v1/business-days/add?date=2026-03-01&days=10&state=selangor"
学校日历
# Is this a school day?
curl "https://mycal-api.huijun00100101.workers.dev/v1/school/is-school-day?date=2026-03-21&state=selangor"
# School holidays for Kumpulan B
curl "https://mycal-api.huijun00100101.workers.dev/v1/school/holidays?year=2026&group=B"
# Exam schedule
curl "https://mycal-api.huijun00100101.workers.dev/v1/school/exams?year=2026&type=spm"
下一个假日
# Next holiday for Penang
curl "https://mycal-api.huijun00100101.workers.dev/v1/holidays/next?state=penang"
州属解析
# Resolve alias
curl "https://mycal-api.huijun00100101.workers.dev/v1/states/resolve?q=kl"
# -> { "data": { "canonical": "kuala-lumpur", "group": "B" } }
完整 API 参考
| 端点 | 描述 |
|---|---|
GET /v1/holidays | 列出节假日(可按年份、州属、类型、状态和月份筛选) |
GET /v1/holidays/check | 该日期是节假日、周末、工作日还是上学日? |
GET /v1/holidays/today | 今天的节假日状态 |
GET /v1/holidays/next | 下一个即将到来的节假日 |
GET /v1/holidays/between | 日期范围内的节假日 |
GET /v1/holidays/leave-optimizer | 建议如何使用年假,以获得最长的连续假期 |
GET /v1/business-days | 计算日期之间的工作日数 |
GET /v1/business-days/add | 从某个日期起增加 N 个工作日 |
GET /v1/states | 全部 13 个州和 3 个联邦直辖区及其周末设置 |
GET /v1/states/resolve | 将别名(KL、penang、jb)解析为规范代码 |
GET /v1/school/terms | 学期日期和天数 |
GET /v1/school/holidays | 学校假期和 KPM 节庆假期 |
GET /v1/school/exams | SPM、STPM、MUET、PT3 考试安排 |
GET /v1/school/is-school-day | 这一天是上学日吗? |
GET /v1/feed/ical/:state | iCal 订阅源 |
GET /v1/feed/csv/:state | 节假日的 CSV/电子表格导出 |
GET /v1/data/* | 原始、可缓存的开放数据快照——manifest、states、holidays/:year、all(无需 API 密钥) |
GET /v1/prayer-times/:zone | 指定区域的 JAKIM 祷告时间(采用 MYT 格式);GET /v1/prayer-times/zones 列出区域目录 |
POST /v1/keys | 签发 API 密钥(目前需要管理员权限;GET /v1/keys/whoami 用于检查调用方的等级) |
请求/响应架构请参阅完整的 OpenAPI 3.1 规范。
SDK 用法
import { MyCalClient } from "@catlabtech/mycal-sdk";
const cal = new MyCalClient();
// Check if a date is a working day
const result = await cal.check("2026-03-21", "selangor");
console.log(result.isWorkingDay); // false
// List holidays
const holidays = await cal.holidays({ year: 2026, state: "KL" });
// Business days
const workDays = await cal.businessDays("2026-03-01", "2026-03-31", "selangor");
console.log(workDays.businessDays); // 22
// School calendar
const terms = await cal.school.terms({ year: 2026, group: "B" });
const exams = await cal.school.exams({ year: 2026, type: "spm" });
const isSchool = await cal.school.isSchoolDay("2026-03-21", "selangor");
MCP 服务
将 Malaysia Calendar API 连接到 Claude、ChatGPT 或任何兼容 MCP 的 AI 助手。
使用 Claude Desktop / Claude Code 进行设置
添加到 MCP 配置中:
{
"mcpServers": {
"malaysia-calendar": {
"command": "npx",
"args": ["@catlabtech/mycal-mcp-server"]
}
}
}
可用工具(13 个)
| 工具 | 描述 |
|---|---|
get_malaysia_holidays | 获取公共假期(可按年份、州属和类型筛选) |
check_malaysia_holiday | 检查某个日期是否为节假日或工作日 |
next_malaysia_holiday | 查找下一个即将到来的节假日 |
malaysia_business_days | 计算两个日期之间的工作日数 |
malaysia_long_weekends | 查找长周末(3 天及以上) |
malaysia_leave_optimizer | 查找最有效的请假日期,以尽可能延长连续休假时间 |
list_malaysia_states | 列出所有州属及其周末设置 |
resolve_malaysia_state | 将别名(KL、JB)解析为规范代码 |
malaysia_holiday_changes | 最近的数据变更 |
malaysia_school_terms | 学期日期和天数 |
malaysia_school_holidays | 学校假期(cuti penggal、cuti perayaan) |
malaysia_exams | SPM、STPM、MUET、PT3 考试安排 |
malaysia_is_school_day | 检查某个日期是否为上学日 |
州属代码
| 代码 | 别名 | 组别 | 周末 |
|---|---|---|---|
johor | jhr, jb | B | 周六至周日(2014–2024 年为周五至周六) |
kedah | kd, kdh | A | 周五至周六 |
kelantan | kel, kb | A | 周五至周六 |
terengganu | trg, kt | A | 周五至周六 |
perak | prk, ipoh | B | 周六至周日 |
pulau-pinang | penang, pg | B | 周六至周日 |
selangor | sel, sgr | B | 周六至周日 |
negeri-sembilan | ns, n9 | B | 周六至周日 |
melaka | mlk, malacca | B | 周六至周日 |
pahang | phg, kuantan | B | 周六至周日 |
perlis | pls, kangar | B | 周六至周日 |
sabah | sbh, kk | B | 周六至周日 |
sarawak | swk, kuching | B | 周六至周日 |
kuala-lumpur | kl | B | 周六至周日 |
wp-putrajaya | putrajaya, pjy | B | 周六至周日 |
wp-labuan | labuan, lbn | B | 周六至周日 |
州属别名不区分大小写。使用 GET /v1/states/resolve?q=kl 可将任何别名解析为规范代码。
项目结构
malaysia-calendar-api/
├── data/ # JSON data files (source of truth / 数据源)
│ ├── holidays/
│ │ ├── 2024.json # Holiday data per year
│ │ ├── 2025.json
│ │ └── 2026.json
│ ├── school/
│ │ ├── terms-2026.json # School terms (Kumpulan A + B)
│ │ ├── holidays-2026.json # School holidays + KPM cuti perayaan
│ │ └── exams-2026.json # SPM, STPM, MUET, PT3 schedules
│ ├── states.json # 13 states + 3 FT, aliases, weekend history
│ └── known-fixed-holidays.json
├── packages/
│ ├── core/ # Shared business logic (types, schemas, utils)
│ │ └── src/
│ │ ├── types.ts # Holiday, State, SchoolTerm, Exam interfaces
│ │ ├── schemas.ts # Zod validation schemas
│ │ ├── filter.ts # Query filtering logic
│ │ ├── replacement.ts # Cuti ganti calculation
│ │ ├── state-resolver.ts
│ │ ├── business-days.ts
│ │ └── school.ts # School term/holiday/exam logic
│ ├── api/ # Hono API on Cloudflare Workers
│ ├── mcp-server/ # MCP Server (13 tools)
│ ├── sdk/ # TypeScript client SDK (@catlabtech/mycal-sdk)
│ └── web/ # Astro + Starlight — marketing site, demos, docs
├── scripts/
│ ├── validate-data.ts # 5-layer data validation pipeline
│ └── sync-to-kv.ts # JSON -> Cloudflare KV denormalization
├── openapi.yaml # OpenAPI 3.1 spec (spec-first)
├── pnpm-workspace.yaml
└── turbo.json
数据来源
所有数据均来自马来西亚政府官方出版物:
| 来源 | 数据 | URL |
|---|---|---|
| JPM BKPP | 联邦公报 / Warta Kerajaan(公共假期) | kabinet.gov.my |
| JAKIM | Takwim Hijri-Miladi(伊斯兰历) | e-solat.gov.my |
| KPM | Kalendar Akademik / 校历(Lampiran A/B/C) | moe.gov.my |
| MPM | STPM 和 MUET 考试安排 | mpm.edu.my |
| 州门户网站 | 各州特定假期(13 个州) | *.gov.my |
假期数据包含公报引用编号(例如,P.U.(B) 305/2025),以便追溯。
部署
两部分独立部署:
API → Cloudflare Workers
pnpm --filter @catlabtech/mycal-core build
cd packages/api && npx wrangler deploy
网站 → Cloudflare Pages
pnpm --filter @catlabtech/mycal-core build
pnpm --filter @catlabtech/mycal-sdk build
pnpm --filter @mycal/web build
# Direct upload via wrangler (requires CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID)
cd packages/web
npx wrangler pages deploy dist --project-name=mycal-web
首次设置 Pages:
- 在 Cloudflare 控制面板中创建一个名为
mycal-web的 Pages 项目。 - 连接 GitHub 仓库以自动构建,或使用 GitHub Actions 工作流(
.github/workflows/deploy.yml)通过wrangler pages deploy推送。 - 必需的 GitHub 密钥:
CLOUDFLARE_API_TOKEN、CLOUDFLARE_ACCOUNT_ID。
CI/CD
GitHub Actions 负责:
- PR 门禁 — 每个 PR 都会进行 Zod 架构验证和跨来源检查
- 部署 — 合并到
main后:并行构建并将 API 部署到 Workers、将 Web 部署到 Pages - 每日抓取 — 监控政府门户网站更新
- Rukyah 监控 — 跟踪伊斯兰历日期确认情况
贡献
请参阅 CONTRIBUTING.md,了解如何:
- 报告缺失的假期或 cuti peristiwa
- 修复数据错误
- 添加新功能
许可证
MIT
评论
支持 Markdown
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。