Mycal MCP Server
MCP (Model Context Protocol) server exposing the Malaysia Calendar API as 12 tools for Claude, ChatGPT, and other AI agents
Ask AI about Mycal MCP Server
Powered by Claude ยท Grounded in docs
I know everything about Mycal MCP Server. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
Malaysia Calendar API
Malaysia's most complete calendar API โ public holidays, school calendar, exam schedules, and MCP server for AI tools.
Data source: Official government gazette (JPM BKPP), JAKIM, KPM, MPM. Not scraped from third-party websites.
Links
- Website + demo: https://mycal-web.pages.dev
- Developer docs: https://mycal-web.pages.dev/docs
- API base URL: https://mycal-api.huijun00100101.workers.dev/v1
- GitHub: https://github.com/Junhui20/malaysia-calendar-api
Features
- 49 public holidays for 2026 from official gazette (Warta Kerajaan) โ federal + state-specific
- 16 states + 3 Federal Territories with aliases (KL, JB, Penang, etc.)
- Weekend-aware โ Kedah/Kelantan/Terengganu use Fri-Sat (Kumpulan A), all others use Sat-Sun (Kumpulan B), with Johor's historical switch tracked
- Cuti ganti (replacement holiday) auto-calculation per state weekend config
- Business day calculator โ per-state, holiday-aware
- School calendar โ terms, holidays, KPM cuti perayaan (Lampiran A/B/C)
- Exam schedules โ SPM, STPM, MUET, PT3
- iCal subscription feeds โ per-state
.icsfeeds - MCP Server for AI agents โ 12 tools for Claude, ChatGPT, and other assistants
- TypeScript SDK (
@catlabtech/mycal-sdk) with typed responses - OpenAPI 3.1 spec + interactive docs
- Trilingual โ Bahasa Melayu, English, Chinese names (ไธ่ฏญๆฏๆ)
Quick Start
# Clone and install
git clone https://github.com/Junhui20/malaysia-calendar-api.git
cd MalaysiaCalanderApi
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 Examples
Base URL: https://mycal-api.huijun00100101.workers.dev/v1
List holidays
# 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"
Check a date
# Is March 21 a holiday/weekend/working day?
curl "https://mycal-api.huijun00100101.workers.dev/v1/holidays/check?date=2026-03-21&state=KL"
Response:
{
"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"
}
]
}
}
Business days
# 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"
School calendar
# 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
# Next holiday for Penang
curl "https://mycal-api.huijun00100101.workers.dev/v1/holidays/next?state=penang"
State resolution
# Resolve alias
curl "https://mycal-api.huijun00100101.workers.dev/v1/states/resolve?q=kl"
# -> { "data": { "canonical": "kuala-lumpur", "group": "B" } }
Full API Reference
| Endpoint | Description |
|---|---|
GET /v1/holidays | List holidays (filter by year, state, type, status, month) |
GET /v1/holidays/check | Is this date a holiday/weekend/working day/school day? |
GET /v1/holidays/today | Today's holiday status |
GET /v1/holidays/next | Next upcoming holiday |
GET /v1/holidays/between | Holidays in date range |
GET /v1/business-days | Count business days between dates |
GET /v1/business-days/add | Add N business days to a date |
GET /v1/states | All 16 states + 3 FTs with weekend config |
GET /v1/states/resolve | Resolve alias (KL, penang, jb) to canonical code |
GET /v1/school/terms | School term dates + day counts |
GET /v1/school/holidays | School holidays + KPM cuti perayaan |
GET /v1/school/exams | SPM, STPM, MUET, PT3 schedule |
GET /v1/school/is-school-day | Is this a school day? |
GET /v1/feed/ical/:state | iCal subscription feed |
See the full OpenAPI 3.1 spec for request/response schemas.
SDK Usage
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 Server
Connect the Malaysia Calendar API to Claude, ChatGPT, or any MCP-compatible AI assistant.
Setup with Claude Desktop / Claude Code
Add to your MCP configuration:
{
"mcpServers": {
"malaysia-calendar": {
"command": "npx",
"args": ["@catlabtech/mycal-mcp-server"]
}
}
}
Available Tools (12)
| Tool | Description |
|---|---|
get_malaysia_holidays | Get public holidays (filter by year, state, type) |
check_malaysia_holiday | Check if a date is a holiday or working day |
next_malaysia_holiday | Find the next upcoming holiday |
malaysia_business_days | Count working days between two dates |
malaysia_long_weekends | Find long weekends (3+ days) |
list_malaysia_states | List all states with weekend config |
resolve_malaysia_state | Resolve alias (KL, JB) to canonical code |
malaysia_holiday_changes | Recent data changes |
malaysia_school_terms | School term dates and day counts |
malaysia_school_holidays | School holidays (cuti penggal, cuti perayaan) |
malaysia_exams | SPM, STPM, MUET, PT3 exam schedule |
malaysia_is_school_day | Check if a date is a school day |
State Codes
| Code | Aliases | Group | Weekend |
|---|---|---|---|
johor | jhr, jb | B | Sat-Sun (was Fri-Sat 2014-2024) |
kedah | kd, kdh | A | Fri-Sat |
kelantan | kel, kb | A | Fri-Sat |
terengganu | trg, kt | A | Fri-Sat |
perak | prk, ipoh | B | Sat-Sun |
pulau-pinang | penang, pg | B | Sat-Sun |
selangor | sel, sgr | B | Sat-Sun |
negeri-sembilan | ns, n9 | B | Sat-Sun |
melaka | mlk, malacca | B | Sat-Sun |
pahang | phg, kuantan | B | Sat-Sun |
perlis | pls, kangar | B | Sat-Sun |
sabah | sbh, kk | B | Sat-Sun |
sarawak | swk, kuching | B | Sat-Sun |
kuala-lumpur | kl | B | Sat-Sun |
wp-putrajaya | putrajaya, pjy | B | Sat-Sun |
wp-labuan | labuan, lbn | B | Sat-Sun |
State aliases are case-insensitive. Use GET /v1/states/resolve?q=kl to resolve any alias to the canonical code.
Project Structure
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 # 16 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 (12 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
โโโ parsers/ # Year-specific PDF layout adapters
โโโ openapi.yaml # OpenAPI 3.1 spec (spec-first)
โโโ pnpm-workspace.yaml
โโโ turbo.json
Data Sources
All data is sourced from official Malaysian government publications:
| Source | Data | URL |
|---|---|---|
| JPM BKPP | Federal Gazette / Warta Kerajaan (public holidays) | kabinet.gov.my |
| JAKIM | Takwim Hijri-Miladi (Islamic calendar) | e-solat.gov.my |
| KPM | Kalendar Akademik / school calendar (Lampiran A/B/C) | moe.gov.my |
| MPM | STPM & MUET exam schedules | mpm.edu.my |
| State Portals | State-specific holidays (16 states) | *.gov.my |
Holiday data includes gazette references (e.g., P.U.(B) 305/2025) for traceability.
Deploy
Two parts deploy independently:
API โ Cloudflare Workers
pnpm --filter @catlabtech/mycal-core build
cd packages/api && npx wrangler deploy
Website โ 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
First-time Pages setup:
- Create a Pages project named
mycal-webin the Cloudflare dashboard. - Either connect the GitHub repo for automatic builds, or rely on the GitHub Actions workflow (
.github/workflows/deploy.yml) to push viawrangler pages deploy. - Required GitHub secrets:
CLOUDFLARE_API_TOKEN,CLOUDFLARE_ACCOUNT_ID.
CI/CD
GitHub Actions handles:
- PR gate โ Zod schema validation + cross-source checks on every PR
- Deploy โ On merge to
main: build and deploy API to Workers + Web to Pages in parallel - Daily scrape โ Government portal monitoring for updates
- Rukyah monitor โ Islamic date confirmation tracking
Contributing
See CONTRIBUTING.md for how to:
- Report a missing holiday or cuti peristiwa
- Fix data errors
- Add new features
License
MIT
