ferien-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ id-token: write # required for PyPI trusted publishing (OIDC)
12
+ contents: read
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: pip install build
19
+ - run: python -m build
20
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,95 @@
1
+ name: Publish to MCP Registry
2
+
3
+ # Official MCP Registry (registry.modelcontextprotocol.io) via GitHub OIDC.
4
+ # No secret, no interactive login: the runner's OIDC token proves ownership
5
+ # of the io.github.mohammad-abbasi-sh/* namespace.
6
+ # Refs: https://github.com/modelcontextprotocol/registry
7
+
8
+ on:
9
+ push:
10
+ tags: ["v*"]
11
+ workflow_dispatch:
12
+
13
+ jobs:
14
+ publish:
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ id-token: write # required for OIDC -> MCP Registry
18
+ contents: read
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Sync server.json version to tag
23
+ # Only sync when running on a version tag (v*). On workflow_dispatch
24
+ # (ref = refs/heads/main) keep the version committed in server.json.
25
+ run: |
26
+ VER=""
27
+ if [[ "$GITHUB_REF" == refs/tags/* ]]; then
28
+ TAG="${GITHUB_REF#refs/tags/}"
29
+ VER="${TAG#v}"
30
+ fi
31
+ if [ -n "$VER" ]; then
32
+ python3 - "$VER" << 'EOF'
33
+ import json, sys
34
+ ver = sys.argv[1]
35
+ d = json.load(open('server.json'))
36
+ d['version'] = ver
37
+ for pkg in d.get('packages', []):
38
+ pkg['version'] = ver
39
+ json.dump(d, open('server.json', 'w'), indent=2, ensure_ascii=False)
40
+ print('server.json version ->', ver)
41
+ EOF
42
+ else
43
+ echo "No version tag ($GITHUB_REF); keeping server.json version as-is"
44
+ fi
45
+
46
+ - name: Wait for PyPI
47
+ # The registry validates that the PyPI package + version exists,
48
+ # but the PyPI publish workflow runs in parallel with this one.
49
+ # Poll until the version appears instead of racing it: a 400 here
50
+ # used to fail silently under continue-on-error and left 40/43
51
+ # servers unlisted in the registry (2026-11-11).
52
+ run: |
53
+ python3 - << 'EOF'
54
+ import json, sys, time, urllib.request, urllib.error
55
+ d = json.load(open('server.json'))
56
+ pkg = d['packages'][0]
57
+ name = pkg.get('identifier') or pkg.get('name')
58
+ ver = pkg['version']
59
+ if not name:
60
+ print('ERROR: no package identifier/name in server.json')
61
+ sys.exit(1)
62
+ url = f'https://pypi.org/pypi/{name}/json'
63
+ for attempt in range(1, 21):
64
+ try:
65
+ with urllib.request.urlopen(url, timeout=30) as r:
66
+ data = json.load(r)
67
+ if ver in data.get('releases', {}):
68
+ print(f'PyPI {name}=={ver} is live (attempt {attempt})')
69
+ sys.exit(0)
70
+ except urllib.error.HTTPError as e:
71
+ print(f'attempt {attempt}: PyPI returned {e.code}')
72
+ except Exception as e:
73
+ print(f'attempt {attempt}: {e}')
74
+ print(f'attempt {attempt}: {name}=={ver} not on PyPI yet, waiting 30s...')
75
+ time.sleep(30)
76
+ print(f'ERROR: {name}=={ver} did not appear on PyPI after 10 minutes')
77
+ sys.exit(1)
78
+ EOF
79
+
80
+ - name: Install mcp-publisher
81
+ run: |
82
+ curl -sL "https://github.com/modelcontextprotocol/registry/releases/download/v1.8.7/mcp-publisher_linux_amd64.tar.gz" -o /tmp/mcp-publisher.tar.gz
83
+ tar -xzf /tmp/mcp-publisher.tar.gz -C /tmp
84
+ sudo mv /tmp/mcp-publisher /usr/local/bin/mcp-publisher
85
+ mcp-publisher --version
86
+
87
+ - name: Validate server.json
88
+ run: mcp-publisher validate server.json
89
+
90
+ - name: Publish to MCP Registry (OIDC)
91
+ # Failures must fail the run visibly: a silent publish failure
92
+ # once left 40/43 servers unlisted in the registry (2026-11-11).
93
+ run: |
94
+ mcp-publisher login github-oidc
95
+ mcp-publisher publish server.json
@@ -0,0 +1,21 @@
1
+ name: Daily live smoke
2
+
3
+ # One fixed probe per day: catches fingerprint rot / bot-wall changes
4
+ # before users hit them. Fails visibly on 403/timeout.
5
+ on:
6
+ schedule:
7
+ - cron: "0 6 * * *"
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ smoke:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - name: Install
19
+ run: pip install -e .
20
+ - name: Smoke probe
21
+ run: python tests/smoke_live.py
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohammad Abbasi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.5
2
+ Name: ferien-mcp
3
+ Version: 0.1.0
4
+ Summary: Unofficial read-only MCP server for German school holidays (Schulferien) — holidays by year & state, is-it-a-holiday, next holiday & date ranges
5
+ Author: Mohammad Abbasi
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: httpx>=0.27
10
+ Requires-Dist: mcp<2
11
+ Description-Content-Type: text/markdown
12
+
13
+ # ferien-mcp 🏖️
14
+
15
+ mcp-name: io.github.mohammad-abbasi-sh/ferien-mcp
16
+
17
+ Unofficial **read-only** MCP server for **German school holidays** (Schulferien) via the [ferien-api.de API](https://ferien-api.de) (bundesAPI project): holidays per year and federal state, is-it-a-holiday checks, the next holiday from a date, and holidays in a date range. No key, no login.
18
+
19
+ > Built by Mohammad Abbasi as part of the "Germany MCP factory". Not affiliated with ferien-api.de / the bundesAPI project.
20
+
21
+ ## For AI agents
22
+
23
+ Add to your MCP client config (stdio):
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "ferien": {
29
+ "command": "uvx",
30
+ "args": ["ferien-mcp==0.1.0"]
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ Or run locally: `python -m ferien_mcp.server` (needs `mcp<2`, `httpx`).
37
+
38
+ ## Tools
39
+
40
+ | Tool | Description |
41
+ |------|-------------|
42
+ | `ferien_list_holidays` | School holidays of one year in one federal state (optional month filter) |
43
+ | `ferien_is_holiday` | Is a date (YYYY-MM-DD) inside the school holidays in one state? |
44
+ | `ferien_next_holiday` | The next school holiday on or after a date (returns the ongoing one if inside a holiday; looks into the next year) |
45
+ | `ferien_holidays_between` | School holidays overlapping a date range (max ~2 years) |
46
+ | `ferien_list_states` | All 16 German federal states |
47
+ | `ferien_health` | Reachability check (ok / blocked / error) — one polite request |
48
+
49
+ Example output (`ferien_is_holiday` / 2026-08-10, BY):
50
+
51
+ ```json
52
+ {"date": "2026-08-10", "weekday": "Monday", "weekday_de": "Montag",
53
+ "state": "BY", "state_name": "Bayern", "is_holiday": true,
54
+ "holidays": ["sommerferien bayern 2026"],
55
+ "details": [{"name": "sommerferien bayern 2026", "kind": "sommerferien",
56
+ "slug": "sommerferien bayern 2026-2026-BY", "state": "BY",
57
+ "year": 2026, "start": "2026-08-03", "end": "2026-09-15",
58
+ "duration_days": 44, "start_weekday": "Monday",
59
+ "start_weekday_de": "Montag", "end_weekday": "Tuesday",
60
+ "end_weekday_de": "Dienstag"}]}
61
+ ```
62
+
63
+ Notes:
64
+ - State codes are the 2-letter codes: BW, BY, BE, BB, HB, HH, HE, MV, NI, NW, RP, SL, SN, ST, SH, TH. There is **no nationwide list** — school holidays are per-state, so every query needs one state. Use `ferien_list_states` for the full list.
65
+ - Holiday names are German ("sommerferien bayern 2026"); each row also carries a `kind` (winterferien, frühjahrsferien, osterferien, pfingstferien, sommerferien, herbstferien, weihnachtsferien, beweglicher ferientag) and the duration in days.
66
+ - **Coverage varies by state and year**: the API returns an empty list for a state/year it has no data for — e.g. Berlin 2026 was empty on 2026-11-14 while Berlin 2025 has 7 entries. Verify important dates against the official source.
67
+ - Cross-year holidays (e.g. Weihnachtsferien running into January) are included by `ferien_holidays_between` when they overlap the range.
68
+ - Years 2000–2100 are accepted.
69
+ - The API rate-limits aggressively per IP (its docs: "heavily abused, aggressive rate limiting is in place"). If a call reports HTTP 429, wait a few minutes and retry — on 2026-11-14 the limit cleared after ~10 minutes.
70
+
71
+ Built by [Mohammad Abbasi](https://github.com/mohammad-abbasi-sh) — [Almanibama](https://almanibama.ir) · [mabbasi.ir](https://mabbasi.ir)
@@ -0,0 +1,59 @@
1
+ # ferien-mcp 🏖️
2
+
3
+ mcp-name: io.github.mohammad-abbasi-sh/ferien-mcp
4
+
5
+ Inoffizieller **Nur-Lesen**-MCP-Server für **deutsche Schulferien** über die [ferien-api.de API](https://ferien-api.de) (bundesAPI-Projekt): Ferien pro Jahr und Bundesland, Ist-es-ein-Ferientag-Prüfung, die nächsten Ferien ab einem Datum und Ferien in einem Zeitraum. Kein Schlüssel, keine Anmeldung nötig.
6
+
7
+ > Gebaut von Mohammad Abbasi im Rahmen der „Germany MCP factory". Keine Verbindung zu ferien-api.de / dem bundesAPI-Projekt.
8
+
9
+ ## Für KI-Agenten
10
+
11
+ In die MCP-Client-Konfiguration eintragen (stdio):
12
+
13
+ ```json
14
+ {
15
+ "mcpServers": {
16
+ "ferien": {
17
+ "command": "uvx",
18
+ "args": ["ferien-mcp==0.1.0"]
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ Oder lokal starten: `python -m ferien_mcp.server` (benötigt `mcp<2`, `httpx`).
25
+
26
+ ## Tools
27
+
28
+ | Tool | Beschreibung |
29
+ |------|--------------|
30
+ | `ferien_list_holidays` | Schulferien eines Jahres in einem Bundesland (optional nach Monat gefiltert) |
31
+ | `ferien_is_holiday` | Liegt ein Datum (YYYY-MM-DD) in den Schulferien eines Bundeslandes? |
32
+ | `ferien_next_holiday` | Die nächsten Schulferien ab einem Datum (gibt die laufenden Ferien zurück, wenn das Datum in den Ferien liegt; blickt auch ins nächste Jahr) |
33
+ | `ferien_holidays_between` | Schulferien, die einen Zeitraum überschneiden (max. ca. 2 Jahre) |
34
+ | `ferien_list_states` | Alle 16 Bundesländer |
35
+ | `ferien_health` | Erreichbarkeitsprüfung (ok / blocked / error) — eine höfliche Anfrage |
36
+
37
+ Beispielausgabe (`ferien_is_holiday` / 2026-08-10, BY):
38
+
39
+ ```json
40
+ {"date": "2026-08-10", "weekday": "Monday", "weekday_de": "Montag",
41
+ "state": "BY", "state_name": "Bayern", "is_holiday": true,
42
+ "holidays": ["sommerferien bayern 2026"],
43
+ "details": [{"name": "sommerferien bayern 2026", "kind": "sommerferien",
44
+ "slug": "sommerferien bayern 2026-2026-BY", "state": "BY",
45
+ "year": 2026, "start": "2026-08-03", "end": "2026-09-15",
46
+ "duration_days": 44, "start_weekday": "Monday",
47
+ "start_weekday_de": "Montag", "end_weekday": "Tuesday",
48
+ "end_weekday_de": "Dienstag"}]}
49
+ ```
50
+
51
+ Hinweise:
52
+ - Bundesland-Codes sind die 2-Buchstaben-Codes: BW, BY, BE, BB, HB, HH, HE, MV, NI, NW, RP, SL, SN, ST, SH, TH. Es gibt **keine bundesweite Liste** — Schulferien sind Ländersache, jede Abfrage braucht ein Bundesland. `ferien_list_states` liefert die vollständige Liste.
53
+ - Feriennamen sind deutsch („sommerferien bayern 2026"); jede Zeile trägt zusätzlich eine `kind` (winterferien, frühjahrsferien, osterferien, pfingstferien, sommerferien, herbstferien, weihnachtsferien, beweglicher ferientag) und die Dauer in Tagen.
54
+ - **Die Abdeckung variiert je nach Bundesland und Jahr**: Die API liefert eine leere Liste für ein Bundesland/Jahr, zu dem sie keine Daten hat — z. B. war Berlin 2026 am 2026-11-14 leer, während Berlin 2025 sieben Einträge hat. Wichtige Termine bitte an der offiziellen Quelle prüfen.
55
+ - Jahresübergreifende Ferien (z. B. Weihnachtsferien bis in den Januar) werden von `ferien_holidays_between` einbezogen, wenn sie den Zeitraum überschneiden.
56
+ - Jahre 2000–2100 werden akzeptiert.
57
+ - Die API setzt aggressive Ratenbegrenzungen pro IP (laut Doku: „heavily abused, aggressive rate limiting is in place"). Meldet ein Aufruf HTTP 429, ein paar Minuten warten und erneut versuchen — am 2026-11-14 war die Sperre nach ca. 10 Minuten wieder aufgehoben.
58
+
59
+ Built by [Mohammad Abbasi](https://github.com/mohammad-abbasi-sh) — [Almanibama](https://almanibama.ir) · [mabbasi.ir](https://mabbasi.ir)
@@ -0,0 +1,59 @@
1
+ # ferien-mcp 🏖️
2
+
3
+ mcp-name: io.github.mohammad-abbasi-sh/ferien-mcp
4
+
5
+ سرور MCP غیررسمی و **فقط‌خواندنی** برای **تعطیلات مدارس آلمان** (Schulferien) از طریق [API سایت ferien-api.de](https://ferien-api.de) (پروژهٔ bundesAPI): تعطیلات هر سال در هر ایالت فدرال، بررسی اینکه یک تاریخ در تعطیلات مدارس است یا نه، نزدیک‌ترین تعطیلات از یک تاریخ، و تعطیلات در یک بازهٔ زمانی. بدون کلید و بدون ورود.
6
+
7
+ > ساختهٔ محمد عباسی در چارچوب «کارخانهٔ MCP آلمان». وابسته به ferien-api.de / پروژهٔ bundesAPI نیست.
8
+
9
+ ## برای ایجنت‌های هوش مصنوعی
10
+
11
+ به پیکربندی MCP Client اضافه کنید (stdio):
12
+
13
+ ```json
14
+ {
15
+ "mcpServers": {
16
+ "ferien": {
17
+ "command": "uvx",
18
+ "args": ["ferien-mcp==0.1.0"]
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ یا به‌صورت محلی اجرا کنید: `python -m ferien_mcp.server` (نیازمند `mcp<2` و `httpx`).
25
+
26
+ ## ابزارها
27
+
28
+ | ابزار | توضیح |
29
+ |------|-------|
30
+ | `ferien_list_holidays` | تعطیلات مدارس یک سال در یک ایالت فدرال (با فیلتر اختیاری ماه) |
31
+ | `ferien_is_holiday` | آیا یک تاریخ (YYYY-MM-DD) در تعطیلات مدارس یک ایالت است؟ |
32
+ | `ferien_next_holiday` | نزدیک‌ترین تعطیلات مدارس از یک تاریخ به بعد (اگر تاریخ در تعطیلات باشد، همان تعطیلات جاری را برمی‌گرداند؛ به سال بعد هم نگاه می‌کند) |
33
+ | `ferien_holidays_between` | تعطیلات مدارسی که با یک بازهٔ زمانی هم‌پوشانی دارند (حداکثر حدود ۲ سال) |
34
+ | `ferien_list_states` | هر ۱۶ ایالت فدرال |
35
+ | `ferien_health` | بررسی دسترسی به API (ok / blocked / error) — یک درخواست مؤدبانه |
36
+
37
+ نمونهٔ خروجی (`ferien_is_holiday` / ۲۰۲۶-۰۸-۱۰، BY):
38
+
39
+ ```json
40
+ {"date": "2026-08-10", "weekday": "Monday", "weekday_de": "Montag",
41
+ "state": "BY", "state_name": "Bayern", "is_holiday": true,
42
+ "holidays": ["sommerferien bayern 2026"],
43
+ "details": [{"name": "sommerferien bayern 2026", "kind": "sommerferien",
44
+ "slug": "sommerferien bayern 2026-2026-BY", "state": "BY",
45
+ "year": 2026, "start": "2026-08-03", "end": "2026-09-15",
46
+ "duration_days": 44, "start_weekday": "Monday",
47
+ "start_weekday_de": "Montag", "end_weekday": "Tuesday",
48
+ "end_weekday_de": "Dienstag"}]}
49
+ ```
50
+
51
+ نکته‌ها:
52
+ - کد ایالت‌ها دو حرفی است: BW، BY، BE، BB، HB، HH، HE، MV، NI، NW، RP، SL، SN، ST، SH، TH. **فهرست سراسری وجود ندارد** — تعطیلات مدارس به ایالت بستگی دارد، پس هر درخواست به یک ایالت نیاز دارد. فهرست کامل را از `ferien_list_states` بگیرید.
53
+ - نام تعطیلات آلمانی است («sommerferien bayern 2026»)؛ هر ردیف یک `kind` هم دارد (winterferien، frühjahrsferien، osterferien، pfingstferien، sommerferien، herbstferien، weihnachtsferien، beweglicher ferientag) و مدت آن به روز.
54
+ - **پوشش داده‌ها بسته به ایالت و سال فرق می‌کند**: API برای ایالت/سالی که داده ندارد فهرست خالی برمی‌گرداند — مثلاً برلین ۲۰۲۶ در ۲۰۲۶-۱۱-۱۴ خالی بود، در حالی که برلین ۲۰۲۵ هفت ورودی دارد. تاریخ‌های مهم را با منبع رسمی بررسی کنید.
55
+ - تعطیلاتِ میان‌سالی (مثلاً Weihnachtsferien که تا ژانویه ادامه دارد) در `ferien_holidays_between` لحاظ می‌شوند اگر با بازه هم‌پوشانی داشته باشند.
56
+ - سال‌های ۲۰۰۰ تا ۲۱۰۰ پذیرفته می‌شوند.
57
+ - این API برای هر IP محدودیت نرخ سخت‌گیرانه دارد (به گفتهٔ مستنداتش: «heavily abused, aggressive rate limiting is in place»). اگر پاسخی با HTTP 429 گرفتید، چند دقیقه صبر کنید و دوباره تلاش کنید — در ۲۰۲۶-۱۱-۱۴ محدودیت بعد از حدود ۱۰ دقیقه برطرف شد.
58
+
59
+ Built by [Mohammad Abbasi](https://github.com/mohammad-abbasi-sh) — [Almanibama](https://almanibama.ir) · [mabbasi.ir](https://mabbasi.ir)
@@ -0,0 +1,59 @@
1
+ # ferien-mcp 🏖️
2
+
3
+ mcp-name: io.github.mohammad-abbasi-sh/ferien-mcp
4
+
5
+ Unofficial **read-only** MCP server for **German school holidays** (Schulferien) via the [ferien-api.de API](https://ferien-api.de) (bundesAPI project): holidays per year and federal state, is-it-a-holiday checks, the next holiday from a date, and holidays in a date range. No key, no login.
6
+
7
+ > Built by Mohammad Abbasi as part of the "Germany MCP factory". Not affiliated with ferien-api.de / the bundesAPI project.
8
+
9
+ ## For AI agents
10
+
11
+ Add to your MCP client config (stdio):
12
+
13
+ ```json
14
+ {
15
+ "mcpServers": {
16
+ "ferien": {
17
+ "command": "uvx",
18
+ "args": ["ferien-mcp==0.1.0"]
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ Or run locally: `python -m ferien_mcp.server` (needs `mcp<2`, `httpx`).
25
+
26
+ ## Tools
27
+
28
+ | Tool | Description |
29
+ |------|-------------|
30
+ | `ferien_list_holidays` | School holidays of one year in one federal state (optional month filter) |
31
+ | `ferien_is_holiday` | Is a date (YYYY-MM-DD) inside the school holidays in one state? |
32
+ | `ferien_next_holiday` | The next school holiday on or after a date (returns the ongoing one if inside a holiday; looks into the next year) |
33
+ | `ferien_holidays_between` | School holidays overlapping a date range (max ~2 years) |
34
+ | `ferien_list_states` | All 16 German federal states |
35
+ | `ferien_health` | Reachability check (ok / blocked / error) — one polite request |
36
+
37
+ Example output (`ferien_is_holiday` / 2026-08-10, BY):
38
+
39
+ ```json
40
+ {"date": "2026-08-10", "weekday": "Monday", "weekday_de": "Montag",
41
+ "state": "BY", "state_name": "Bayern", "is_holiday": true,
42
+ "holidays": ["sommerferien bayern 2026"],
43
+ "details": [{"name": "sommerferien bayern 2026", "kind": "sommerferien",
44
+ "slug": "sommerferien bayern 2026-2026-BY", "state": "BY",
45
+ "year": 2026, "start": "2026-08-03", "end": "2026-09-15",
46
+ "duration_days": 44, "start_weekday": "Monday",
47
+ "start_weekday_de": "Montag", "end_weekday": "Tuesday",
48
+ "end_weekday_de": "Dienstag"}]}
49
+ ```
50
+
51
+ Notes:
52
+ - State codes are the 2-letter codes: BW, BY, BE, BB, HB, HH, HE, MV, NI, NW, RP, SL, SN, ST, SH, TH. There is **no nationwide list** — school holidays are per-state, so every query needs one state. Use `ferien_list_states` for the full list.
53
+ - Holiday names are German ("sommerferien bayern 2026"); each row also carries a `kind` (winterferien, frühjahrsferien, osterferien, pfingstferien, sommerferien, herbstferien, weihnachtsferien, beweglicher ferientag) and the duration in days.
54
+ - **Coverage varies by state and year**: the API returns an empty list for a state/year it has no data for — e.g. Berlin 2026 was empty on 2026-11-14 while Berlin 2025 has 7 entries. Verify important dates against the official source.
55
+ - Cross-year holidays (e.g. Weihnachtsferien running into January) are included by `ferien_holidays_between` when they overlap the range.
56
+ - Years 2000–2100 are accepted.
57
+ - The API rate-limits aggressively per IP (its docs: "heavily abused, aggressive rate limiting is in place"). If a call reports HTTP 429, wait a few minutes and retry — on 2026-11-14 the limit cleared after ~10 minutes.
58
+
59
+ Built by [Mohammad Abbasi](https://github.com/mohammad-abbasi-sh) — [Almanibama](https://almanibama.ir) · [mabbasi.ir](https://mabbasi.ir)
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "ferien-mcp"
7
+ version = "0.1.0"
8
+ description = "Unofficial read-only MCP server for German school holidays (Schulferien) — holidays by year & state, is-it-a-holiday, next holiday & date ranges"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.10"
12
+ dependencies = [
13
+ "mcp<2",
14
+ "httpx>=0.27",
15
+ ]
16
+ authors = [{ name = "Mohammad Abbasi" }]
17
+
18
+ [project.scripts]
19
+ ferien-mcp = "ferien_mcp.server:main"
20
+
21
+ [tool.hatch.build.targets.wheel]
22
+ packages = ["src/ferien_mcp"]
@@ -0,0 +1 @@
1
+ {"$schema":"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json","description":"Unofficial read-only MCP server for German school holidays — by year & state, next holiday.","name":"io.github.mohammad-abbasi-sh/ferien-mcp","packages":[{"identifier":"ferien-mcp","registryBaseUrl":"https://pypi.org","registryType":"pypi","transport":{"type":"stdio"},"version":"0.1.0"}],"repository":{"source":"github","url":"https://github.com/mohammad-abbasi-sh/ferien-mcp"},"title":"Ferien — German school holidays by year & federal state","version":"0.1.0","websiteUrl":"https://github.com/mohammad-abbasi-sh/ferien-mcp"}
@@ -0,0 +1,2 @@
1
+ """ferien_mcp package — unofficial read-only MCP access to German school
2
+ holidays (Schulferien) via ferien-api.de."""