Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Mycal

БесплатноНе проверен

Malaysia public holidays, school terms, business days & a leave optimizer (13 tools).

GitHubEmbed

Описание

Malaysia public holidays, school terms, business days & a leave optimizer (13 tools).

README

Malaysia's most complete calendar API — public holidays, school calendar, exam schedules, and MCP server for AI tools.

npm: mycal-core npm: mycal-sdk npm: mycal-mcp-server License: MIT Deploys on Cloudflare

Data source: Official government gazette (JPM BKPP), JAKIM, KPM, MPM. Not scraped from third-party websites.

Links

Packages

Published to npm under the @catlabtech scope:

Package Purpose Install
@catlabtech/mycal-core Shared types, Zod schemas, and calendar/business-day logic npm install @catlabtech/mycal-core
@catlabtech/mycal-sdk TypeScript client SDK for the REST API npm install @catlabtech/mycal-sdk
@catlabtech/mycal-mcp-server MCP server exposing 13 calendar tools for AI agents npm install @catlabtech/mycal-mcp-server

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 .ics feeds
  • MCP Server for AI agents — 13 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 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 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/holidays/leave-optimizer Suggest annual-leave days to spend for the longest consecutive break
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
GET /v1/feed/csv/:state CSV/spreadsheet export of holidays
GET /v1/data/* Raw, cacheable open-data snapshots — manifest, states, holidays/:year, all (no API key required)
GET /v1/prayer-times/:zone JAKIM prayer times for a zone (MYT-formatted); GET /v1/prayer-times/zones lists the zone directory
POST /v1/keys Issue an API key (admin-gated for now; GET /v1/keys/whoami checks the caller's tier)

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 (13)

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)
malaysia_leave_optimizer Find the most efficient leave days to take to maximise consecutive days off
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 (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

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:

  1. Create a Pages project named mycal-web in the Cloudflare dashboard.
  2. Either connect the GitHub repo for automatic builds, or rely on the GitHub Actions workflow (.github/workflows/deploy.yml) to push via wrangler pages deploy.
  3. Required GitHub secrets: CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID.

CI/CD

GitHub Actions handles:

  1. PR gate — Zod schema validation + cross-source checks on every PR
  2. Deploy — On merge to main: build and deploy API to Workers + Web to Pages in parallel
  3. Daily scrape — Government portal monitoring for updates
  4. 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

from github.com/Junhui20/malaysia-calendar-api

Установить Mycal в Claude Desktop, Claude Code, Cursor

Рекомендуется · одна команда, все IDE
unyly install mycal

Ставит в Claude Desktop, Claude Code, Cursor и VS Code — сам разбирается с npx, uvx и сборкой из исходников.

Впервые? Поставь CLI: curl -fsSL https://unyly.org/install | sh

Или настроить вручную

Выполни в терминале:

claude mcp add mycal -- npx -y @catlabtech/mycal-mcp-server

FAQ

Mycal MCP бесплатный?

Да, Mycal MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Mycal?

Нет, Mycal работает без API-ключей и переменных окружения.

Mycal — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Mycal в Claude Desktop, Claude Code или Cursor?

Открой Mycal на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Mycal with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development