holiplan
holiplan is a stateless MCP server that calculates and checks a family's holiday plan against school/public holidays and leave allowance, while the assistant handles judgement.
Fetch school holiday windows, effective dates, closures, and public holidays by country/region/year, including local, half-day, and observed flags.
Calculate the leave days a trip needs, accounting for weekends, holidays, half days, part-time patterns, and local-holiday settings.
Find bridge days that buy the most time off, ranked by value and school-holiday coverage.
Compare planned versus available leave, including carryover expiry.
Add or update trips, then re-check the ledger for overlaps, budget breaches, bad dates, and trips outside school holidays.
List booking and cancel-by deadlines, summarize the whole plan, and export it as an .ics calendar file.
Use a user-held JSON ledger as the source of truth, plus schema resources, a starter ledger, and setup/planning prompts; the server stores nothing and never books anything.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@holiplan Here's my ledger. What do the 2027 school holidays look like, and what can I afford?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
holiplan
An MCP server for planning a family's year around school holidays and a limited leave allowance.
Assistants are good at suggesting destinations and bad at remembering that Whit Monday is a public holiday, that five carried-over days expire in June, and that you already said no drive over three and a half hours. This server does the parts that should be calculated; the assistant does the parts that need judgement.
Holiday data comes from OpenHolidays (CC BY 4.0), which covers public and school holidays for a growing list of countries, with no API key.
Status
Pre-release (0.6). Stateless: your ledger is a JSON file you keep, and the server stores nothing. See PRIVACY.md for exactly what goes where, and docs/examples.md for what a conversation looks like.
Related MCP server: Apple Calendar MCP Server
Use it in Claude Desktop
Install uv, then add holiplan to
claude_desktop_config.json and restart Claude:
{
"mcpServers": {
"holiplan": {
"command": "uvx",
"args": ["holiplan"]
}
}
}uvx fetches holiplan from PyPI and runs it; there is nothing else to install. Without uv,
pip install holiplan and use "command": "holiplan" with no args.
Start with the Set up my family profile prompt, which builds a ledger with you one
question at a time, or copy examples/ledger.example.json to my-ledger.json and edit it.
Tell Claude where the file is, and save the updated ledger whenever Claude hands it back.
A conversation then looks like:
Here's my ledger. What do the 2027 school holidays look like, and what can I afford?
Add two weeks on the Danish coast from 17 July.
What needs booking next?
docs/examples.md has these conversations in full, with real figures.
Tools
Tool | Purpose |
| School holidays (official and effective dates), single-day closures, and public holidays marked local, half-day and observed |
| Leave days a given trip needs, with the holidays inside it listed |
| The leave days that buy the most time off, and whether the kids are off too |
| Planned versus available leave, including carryover expiry |
| Add or update a trip, then re-check the ledger |
| Overlaps, budget breaches, bad dates, trips outside school holidays |
| Booking deadlines and cancel-by dates, soonest first |
| The whole plan at a glance, for a brief to your partner |
| The plan as a calendar file |
Resources: JSON schemas for the ledger, profile and trip (holiplan://schema/...), and a blank
starter ledger (holiplan://ledger/starter).
Prompts: Set up my family profile, Plan my year, Plan this holiday window, What needs doing next?, Make a brief for my partner.
Design notes
The ledger is the source of truth. Tools take it in and hand it back, so the plan doesn't drift between conversations.
Intent decides leave. A week with intent
homeorcampoccupies a school holiday window without costing leave. Override withtakes_leave.Carryover is spent first, but only by trips ending before the expiry date, so "these days expire in June" shows up as a warning while you can still act on it.
A trip over New Year costs each year only its own days.
Local holidays follow your home town. Some holidays cover only part of a region, like Augsburg's Peace Festival in Bavaria. With the profile's
homeset to a town, only that town's local holidays count as days off; without a home they all do. Setlocal_holidaysto"include"or"exclude"to override.ignore_holidays("MM-DD") covers what the data can't tell apart, such as Assumption Day ("08-15"), which is only a holiday in Catholic-majority Bavarian towns.School windows include the free days around them. The official Monday-to-Friday dates are stretched over adjacent weekends and public holidays before trips are checked against them. School holidays of two school days or fewer, like All Souls' Day in Austria, are listed separately as closures.
One school type's holidays. Where a region's dates differ by school type (general and vocational schools in Mecklenburg-Vorpommern, primary and secondary in Zürich), the profile's
school_grouppicks one; without it, the general schools'.get_holiday_windowslists the region's groups.A drafted year to start from.
holiplan.service.draft_yearplaces one trip in each school holiday, summer first with two weeks, where each costs the least leave, and never over budget. Every drafted trip is an idea to keep, move or delete.Half-day holidays cost half a day. Zürich's Sechseläuten afternoon is a half day off, not a full one.
Regions accept ISO codes. OpenHolidays uses its own codes where they differ (Vienna is
AT-WI, notAT-9); either works, and an unknown region is an error rather than a quietly incomplete year.Ledgers are versioned. Older ledgers are migrated when read, a newer one is refused, and a malformed one gets an error naming the trip and field at fault.
When OpenHolidays is down, the server serves the last copy it fetched, or says plainly that it can't check dates right now. It never guesses.
No real names. Children are identified by alias and interests only.
The server never books anything. It knows what needs booking and by when; you book it and record the result.
Roadmap
Drive-time filtering (OpenRouteService or self-hosted OSRM)
Remote deployment over Streamable HTTP
Publish to the MCP registry
School holidays that differ by municipality (Appenzell Innerrhoden, Graubünden), chosen by the profile's
home
Development
git clone https://github.com/adekola/holiplan.git
cd holiplan
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
python -m unittest discover -s tests # offlineTo run your working copy in Claude Desktop, point command at the venv's Python
(.venv/bin/python, or .venv\Scripts\python.exe on Windows) with
"args": ["-m", "holiplan.server"].
Licence
MIT, see LICENSE. Holiday data: OpenHolidays, CC BY 4.0.
Available Tools
9 toolscalculate_leave_costB
Leave days needed to be away from start to end (inclusive).
Accounts for weekends, public holidays inside the trip, and any half days, part-time pattern or local-holiday settings in the ledger's profile.
Inputs: end (required), start (required), country (required), ledger, +1 more. Returns: object
check_ledgerA
Validate the whole ledger: overlaps, budget breaches, bad dates, and trips that fall outside the school holidays.
Run this before telling the user a plan works.
Inputs: ledger (required). Returns: object
export_icsB
The ledger as an .ics calendar file the user can import.
Returns file contents -- tell the user to save it and import it.
Inputs: ledger (required), include_deadlines. Returns: result
find_bridge_daysC
The leave days that buy the most time off, best value first.
Each option says which days to take off, the stretch that buys, days off
per leave day, the public holidays that make it a bridge, and school:
"holiday" when the children are off school for all of it, "partly", or
"term". Pass the ledger so the parent's work pattern, half days and
local holidays count. Options can overlap -- they are alternatives.
Inputs: year (required), country (required), limit, ledger, +2 more. Returns: object
get_holiday_windowsA
School holiday windows and public holidays for a region and year.
Use this to frame the year before discussing destinations. region is a
subdivision code such as "DE-BY" (Bavaria) or "AT-WI" (Vienna; the ISO code
"AT-9" works too). Pass the profile's home (the family's town) when known.
Each school window has its official dates and its effective dates, stretched
over the weekends and public holidays that touch it -- the days the family
can actually be away. Holidays of two school days or fewer are listed
separately as school_closures. Public holidays marked local apply to only
part of the region; observed says whether the home keeps them, and is null
when there is no home to check -- then ask the family.
Inputs: year (required), country (required), home, region. Returns: object
get_year_budgetB
Leave planned versus available for a year, including carryover expiry.
Answers "can we afford all of this?" -- call it after every change.
Inputs: year (required), ledger (required). Returns: object
list_deadlinesB
Dated actions the plan implies: booking deadlines and cancel-by dates.
Use it to answer "what needs doing next?".
Inputs: ledger (required), today. Returns: result
summarise_planB
The whole plan at a glance, for a brief to a partner or a quick recap.
Returns the family, leave per year, every trip with its leave cost and
booking state, each school window with the plans in it, open_windows
still to decide, issues, and overdue and upcoming deadlines. Turn it into
prose; don't recalculate any figure in it.
Inputs: ledger (required), today. Returns: object
upsert_tripB
Add or update one trip in the ledger, then re-check the whole ledger.
Returns the updated ledger plus any issues. Hand the ledger back to the user so they can save it.
Inputs: trip (required), ledger (required). Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 9 tools
Most tools have clearly distinct purposes: holiday lookup, leave-cost calculation, bridge-day discovery, budgeting, trip upsert, validation, deadlines, summarisation, and export. Some overlap exists among get_year_budget, check_ledger, and summarise_plan, since all can surface budget or ledger issues, but their primary intents are different enough that an agent should usually choose correctly.
All tool names use snake_case with a consistent verb_noun or verb_object pattern: get_holiday_windows, calculate_leave_cost, find_bridge_days, upsert_trip, check_ledger, list_deadlines, summarise_plan, export_ics. The only minor variation is export_ics being noun-oriented rather than verb_noun, but it still fits the convention and is unambiguous.
Nine tools is well-scoped for a holiday/leave planning server. Each tool covers a distinct part of the workflow, and there is no obvious bloat or missing core capability that would require several extra tools.
The surface covers the main lifecycle: holiday windows, leave cost, bridge days, budget, trip upsert, validation, deadlines, summary, and calendar export. The main gap is the absence of an explicit delete_trip or remove operation, though upsert_trip may allow updates and agents can likely work around this for most planning tasks.
Related MCP Connectors
Family calendar MCP server: read the family's week and propose changes a parent approves.
MCP server for public_holidays_mcp
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server for business-day arithmetic with country-aware holiday calendars. It offers tools to check, calculate, and list business days and holidays for over 60 countries.9MIT
- AlicenseNot gradedqualityDmaintenanceA comprehensive MCP server that provides AI assistants with natural language access to Apple Calendar, enabling reading, searching, creating, and managing calendar events.3MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for personal finance management. Enables natural language expense logging, budgeting, recurring charge detection, and statement import with deterministic local calculations.-
- FlicenseNot gradedqualityCmaintenanceAn MCP server for agent-bookable holiday lets, enabling AI assistants to check availability, get signed quotes, and request bookings with mandatory owner approval.-