@sonill/nepali-dates 1.0.4 → 1.0.6

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,948 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // src/bin/mcp-server.ts
5
+ var import_server = require("@modelcontextprotocol/sdk/server/index.js");
6
+ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
7
+ var import_types3 = require("@modelcontextprotocol/sdk/types.js");
8
+
9
+ // src/types/index.ts
10
+ var NEPALI_MONTH_NAMES_EN = {
11
+ 1: "Baisakh",
12
+ 2: "Jestha",
13
+ 3: "Ashar",
14
+ 4: "Shrawan",
15
+ 5: "Bhadra",
16
+ 6: "Ashwin",
17
+ 7: "Kartik",
18
+ 8: "Mangsir",
19
+ 9: "Poush",
20
+ 10: "Magh",
21
+ 11: "Falgun",
22
+ 12: "Chaitra"
23
+ };
24
+ var NEPALI_MONTH_NAMES_NE = {
25
+ 1: "\u092C\u0948\u0936\u093E\u0916",
26
+ 2: "\u091C\u0947\u0920",
27
+ 3: "\u0905\u0938\u093E\u0930",
28
+ 4: "\u0936\u094D\u0930\u093E\u0935\u0923",
29
+ 5: "\u092D\u093E\u0926\u094D\u0930",
30
+ 6: "\u0906\u0936\u094D\u0935\u093F\u0928",
31
+ 7: "\u0915\u093E\u0930\u094D\u0924\u093F\u0915",
32
+ 8: "\u092E\u0902\u0938\u093F\u0930",
33
+ 9: "\u092A\u094C\u0937",
34
+ 10: "\u092E\u093E\u0918",
35
+ 11: "\u092B\u093E\u0932\u094D\u0917\u0941\u0928",
36
+ 12: "\u091A\u0948\u0924\u094D\u0930"
37
+ };
38
+
39
+ // data/calendar-data.json
40
+ var calendar_data_default = {
41
+ $schema: "http://json-schema.org/draft-07/schema#",
42
+ description: "Nepali Calendar Data (Bikram Sambat). Each year maps to an array of 12 numbers representing the days in each month. Months: [Baisakh, Jestha, Ashar, Shrawan, Bhadra, Ashwin, Kartik, Mangsir, Poush, Magh, Falgun, Chaitra]. Data Sources: Nepal Panchanga Nirnayak Samiti, verified against historical records. Data Range: BS 2000 - 2100 (AD 1943 - 2043)",
43
+ "2000": [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
44
+ "2001": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
45
+ "2002": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
46
+ "2003": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
47
+ "2004": [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
48
+ "2005": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
49
+ "2006": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
50
+ "2007": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
51
+ "2008": [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31],
52
+ "2009": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
53
+ "2010": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
54
+ "2011": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
55
+ "2012": [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30],
56
+ "2013": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
57
+ "2014": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
58
+ "2015": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
59
+ "2016": [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30],
60
+ "2017": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
61
+ "2018": [31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30],
62
+ "2019": [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
63
+ "2020": [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30],
64
+ "2021": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
65
+ "2022": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30],
66
+ "2023": [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
67
+ "2024": [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30],
68
+ "2025": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
69
+ "2026": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
70
+ "2027": [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
71
+ "2028": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
72
+ "2029": [31, 31, 32, 31, 32, 30, 30, 29, 30, 29, 30, 30],
73
+ "2030": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
74
+ "2031": [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
75
+ "2032": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
76
+ "2033": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
77
+ "2034": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
78
+ "2035": [30, 32, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31],
79
+ "2036": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
80
+ "2037": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
81
+ "2038": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
82
+ "2039": [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30],
83
+ "2040": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
84
+ "2041": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
85
+ "2042": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
86
+ "2043": [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30],
87
+ "2044": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
88
+ "2045": [31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30],
89
+ "2046": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
90
+ "2047": [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30],
91
+ "2048": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
92
+ "2049": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30],
93
+ "2050": [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
94
+ "2051": [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30],
95
+ "2052": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
96
+ "2053": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30],
97
+ "2054": [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
98
+ "2055": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
99
+ "2056": [31, 31, 32, 31, 32, 30, 30, 29, 30, 29, 30, 30],
100
+ "2057": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
101
+ "2058": [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
102
+ "2059": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
103
+ "2060": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
104
+ "2061": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
105
+ "2062": [30, 32, 31, 32, 31, 31, 29, 30, 29, 30, 29, 31],
106
+ "2063": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
107
+ "2064": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
108
+ "2065": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
109
+ "2066": [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31],
110
+ "2067": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
111
+ "2068": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
112
+ "2069": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
113
+ "2070": [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30],
114
+ "2071": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
115
+ "2072": [31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30],
116
+ "2073": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31],
117
+ "2074": [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30],
118
+ "2075": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
119
+ "2076": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30],
120
+ "2077": [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
121
+ "2078": [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30],
122
+ "2079": [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30],
123
+ "2080": [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30],
124
+ "2081": [31, 31, 32, 32, 31, 30, 30, 30, 29, 30, 30, 30],
125
+ "2082": [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30],
126
+ "2083": [31, 31, 32, 31, 31, 30, 30, 30, 29, 30, 30, 30],
127
+ "2084": [31, 31, 32, 31, 31, 30, 30, 30, 29, 30, 30, 30],
128
+ "2085": [31, 32, 31, 32, 30, 31, 30, 30, 29, 30, 30, 30],
129
+ "2086": [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30],
130
+ "2087": [31, 31, 32, 31, 31, 31, 30, 30, 29, 30, 30, 30],
131
+ "2088": [30, 31, 32, 32, 30, 31, 30, 30, 29, 30, 30, 30],
132
+ "2089": [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30],
133
+ "2090": [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30],
134
+ "2091": [31, 31, 32, 31, 31, 31, 30, 30, 29, 30, 30, 30],
135
+ "2092": [30, 31, 32, 32, 31, 30, 30, 30, 29, 30, 30, 30],
136
+ "2093": [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30],
137
+ "2094": [31, 31, 32, 31, 31, 30, 30, 30, 29, 30, 30, 30],
138
+ "2095": [31, 31, 32, 31, 31, 31, 30, 29, 30, 30, 30, 30],
139
+ "2096": [30, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30],
140
+ "2097": [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30],
141
+ "2098": [31, 31, 32, 31, 31, 31, 29, 30, 29, 30, 30, 31],
142
+ "2099": [31, 31, 32, 31, 31, 31, 30, 29, 29, 30, 30, 30],
143
+ "2100": [31, 32, 31, 32, 30, 31, 30, 29, 30, 29, 30, 30]
144
+ };
145
+
146
+ // src/data/calendar-data.ts
147
+ var NEPALI_CALENDAR_DATA = Object.fromEntries(
148
+ Object.entries(calendar_data_default).filter(([key]) => !key.startsWith("$") && key !== "description").map(([key, value]) => [Number(key), value])
149
+ );
150
+ var MIN_YEAR = Math.min(...Object.keys(NEPALI_CALENDAR_DATA).map(Number));
151
+ var MAX_YEAR = Math.max(...Object.keys(NEPALI_CALENDAR_DATA).map(Number));
152
+
153
+ // data/reference-dates.json
154
+ var reference_dates_default = {
155
+ $schema: "http://json-schema.org/draft-07/schema#",
156
+ description: "Reference date pairs for validation and testing. These are verified BS-AD date pairs used to validate conversion accuracy. Each pair represents a known accurate conversion point. Sources: Official Nepal government publications, historical records and verified events, cross-referenced with multiple calendar systems.",
157
+ referenceDates: [
158
+ {
159
+ bs: { year: 2001, month: 1, day: 1 },
160
+ ad: { year: 1944, month: 4, day: 13 }
161
+ },
162
+ {
163
+ bs: { year: 2010, month: 1, day: 1 },
164
+ ad: { year: 1953, month: 4, day: 13 }
165
+ },
166
+ {
167
+ bs: { year: 2015, month: 1, day: 1 },
168
+ ad: { year: 1958, month: 4, day: 13 }
169
+ },
170
+ {
171
+ bs: { year: 2025, month: 1, day: 1 },
172
+ ad: { year: 1968, month: 4, day: 13 }
173
+ },
174
+ {
175
+ bs: { year: 2035, month: 1, day: 1 },
176
+ ad: { year: 1978, month: 4, day: 14 }
177
+ },
178
+ {
179
+ bs: { year: 2045, month: 1, day: 1 },
180
+ ad: { year: 1988, month: 4, day: 13 }
181
+ },
182
+ {
183
+ bs: { year: 2055, month: 1, day: 1 },
184
+ ad: { year: 1998, month: 4, day: 14 }
185
+ },
186
+ {
187
+ bs: { year: 2065, month: 1, day: 1 },
188
+ ad: { year: 2008, month: 4, day: 13 }
189
+ },
190
+ {
191
+ bs: { year: 2075, month: 1, day: 1 },
192
+ ad: { year: 2018, month: 4, day: 14 }
193
+ },
194
+ {
195
+ bs: { year: 2082, month: 1, day: 1 },
196
+ ad: { year: 2025, month: 4, day: 14 }
197
+ },
198
+ {
199
+ bs: { year: 2083, month: 1, day: 1 },
200
+ ad: { year: 2026, month: 4, day: 14 }
201
+ }
202
+ ]
203
+ };
204
+
205
+ // src/data/reference-dates.ts
206
+ var BASE_BS_DATE = { year: 2e3, month: 1, day: 1 };
207
+ var BASE_AD_DATE = { year: 1943, month: 4, day: 14 };
208
+ var REFERENCE_DATES = reference_dates_default.referenceDates.map(
209
+ ({ bs, ad }) => ({ bs, ad })
210
+ );
211
+
212
+ // src/utils/validators.ts
213
+ function hasDataForYear(year) {
214
+ return year in NEPALI_CALENDAR_DATA;
215
+ }
216
+ function isValidBsDate(year, month, day) {
217
+ if (year < MIN_YEAR || year > MAX_YEAR) {
218
+ return false;
219
+ }
220
+ if (!hasDataForYear(year)) {
221
+ return false;
222
+ }
223
+ if (month < 1 || month > 12) {
224
+ return false;
225
+ }
226
+ const daysInMonth = NEPALI_CALENDAR_DATA[year][month - 1];
227
+ if (day < 1 || day > daysInMonth) {
228
+ return false;
229
+ }
230
+ return true;
231
+ }
232
+ function isValidAdDate(year, month, day) {
233
+ if (year < 1 || year > 9999) {
234
+ return false;
235
+ }
236
+ if (month < 1 || month > 12) {
237
+ return false;
238
+ }
239
+ const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
240
+ if (month === 2 && isLeapYear(year)) {
241
+ daysInMonth[1] = 29;
242
+ }
243
+ if (day < 1 || day > daysInMonth[month - 1]) {
244
+ return false;
245
+ }
246
+ return true;
247
+ }
248
+ function isLeapYear(year) {
249
+ return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
250
+ }
251
+ function getDaysInAdMonth(year, month) {
252
+ const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
253
+ if (month === 2 && isLeapYear(year)) {
254
+ return 29;
255
+ }
256
+ return daysInMonth[month - 1];
257
+ }
258
+
259
+ // src/converters/bs-to-ad.ts
260
+ function bsToAd(year, month, day, options) {
261
+ if (!isValidBsDate(year, month, day)) {
262
+ throw new Error(`Invalid BS date: ${year}-${month}-${day}`);
263
+ }
264
+ let totalDays = 0;
265
+ for (let y = BASE_BS_DATE.year; y < year; y++) {
266
+ if (y in NEPALI_CALENDAR_DATA) {
267
+ totalDays += NEPALI_CALENDAR_DATA[y].reduce((sum, days) => sum + days, 0);
268
+ }
269
+ }
270
+ for (let m = 0; m < month - 1; m++) {
271
+ totalDays += NEPALI_CALENDAR_DATA[year][m];
272
+ }
273
+ totalDays += day - 1;
274
+ const adDate = addDaysToAdDate(
275
+ BASE_AD_DATE.year,
276
+ BASE_AD_DATE.month,
277
+ BASE_AD_DATE.day,
278
+ totalDays
279
+ );
280
+ return formatDate(adDate, options);
281
+ }
282
+ function addDaysToAdDate(year, month, day, daysToAdd) {
283
+ let y = year;
284
+ let m = month;
285
+ let d = day;
286
+ for (let i = 0; i < daysToAdd; i++) {
287
+ d++;
288
+ const daysInCurrentMonth = getDaysInAdMonth(y, m);
289
+ if (d > daysInCurrentMonth) {
290
+ d = 1;
291
+ m++;
292
+ if (m > 12) {
293
+ m = 1;
294
+ y++;
295
+ }
296
+ }
297
+ }
298
+ return { year: y, month: m, day: d };
299
+ }
300
+ function formatDate(date, options) {
301
+ const format = options?.format || "object";
302
+ switch (format) {
303
+ case "object":
304
+ return date;
305
+ case "iso":
306
+ return `${date.year}-${String(date.month).padStart(2, "0")}-${String(date.day).padStart(2, "0")}`;
307
+ case "string": {
308
+ const pattern = options?.pattern || "YYYY-MM-DD";
309
+ return pattern.replace("YYYY", String(date.year)).replace("MM", String(date.month).padStart(2, "0")).replace("DD", String(date.day).padStart(2, "0"));
310
+ }
311
+ case "array":
312
+ return [date.year, date.month, date.day];
313
+ default:
314
+ return date;
315
+ }
316
+ }
317
+
318
+ // src/converters/ad-to-bs.ts
319
+ function adToBs(year, month, day, options) {
320
+ if (!isValidAdDate(year, month, day)) {
321
+ throw new Error(`Invalid AD date: ${year}-${month}-${day}`);
322
+ }
323
+ const totalDaysFromBase = calculateDaysBetweenAdDates(
324
+ BASE_AD_DATE.year,
325
+ BASE_AD_DATE.month,
326
+ BASE_AD_DATE.day,
327
+ year,
328
+ month,
329
+ day
330
+ );
331
+ if (totalDaysFromBase < 0) {
332
+ throw new Error(`Date is before the minimum supported date (${BASE_AD_DATE.year}-${BASE_AD_DATE.month}-${BASE_AD_DATE.day})`);
333
+ }
334
+ const bsDate = addDaysToBsDate(
335
+ BASE_BS_DATE.year,
336
+ BASE_BS_DATE.month,
337
+ BASE_BS_DATE.day,
338
+ totalDaysFromBase
339
+ );
340
+ return formatDate2(bsDate, options);
341
+ }
342
+ function calculateDaysBetweenAdDates(fromYear, fromMonth, fromDay, toYear, toMonth, toDay) {
343
+ let days = 0;
344
+ if (toYear < fromYear || toYear === fromYear && toMonth < fromMonth || toYear === fromYear && toMonth === fromMonth && toDay < fromDay) {
345
+ return -1;
346
+ }
347
+ let y = fromYear;
348
+ let m = fromMonth;
349
+ let d = fromDay;
350
+ while (y !== toYear || m !== toMonth || d !== toDay) {
351
+ d++;
352
+ const daysInMonth = getDaysInAdMonth(y, m);
353
+ if (d > daysInMonth) {
354
+ d = 1;
355
+ m++;
356
+ if (m > 12) {
357
+ m = 1;
358
+ y++;
359
+ }
360
+ }
361
+ days++;
362
+ }
363
+ return days;
364
+ }
365
+ function addDaysToBsDate(year, month, day, daysToAdd) {
366
+ let y = year;
367
+ let m = month;
368
+ let d = day;
369
+ for (let i = 0; i < daysToAdd; i++) {
370
+ d++;
371
+ const daysInCurrentMonth = NEPALI_CALENDAR_DATA[y][m - 1];
372
+ if (d > daysInCurrentMonth) {
373
+ d = 1;
374
+ m++;
375
+ if (m > 12) {
376
+ m = 1;
377
+ y++;
378
+ }
379
+ if (y > MAX_YEAR) {
380
+ throw new Error(`Date exceeds maximum supported year (BS ${MAX_YEAR})`);
381
+ }
382
+ if (!(y in NEPALI_CALENDAR_DATA)) {
383
+ throw new Error(`No calendar data available for BS year ${y}`);
384
+ }
385
+ }
386
+ }
387
+ return { year: y, month: m, day: d };
388
+ }
389
+ function formatDate2(date, options) {
390
+ const format = options?.format || "object";
391
+ switch (format) {
392
+ case "object":
393
+ return date;
394
+ case "iso":
395
+ return `${date.year}-${String(date.month).padStart(2, "0")}-${String(date.day).padStart(2, "0")}`;
396
+ case "string": {
397
+ const pattern = options?.pattern || "YYYY-MM-DD";
398
+ return pattern.replace("YYYY", String(date.year)).replace("MM", String(date.month).padStart(2, "0")).replace("DD", String(date.day).padStart(2, "0"));
399
+ }
400
+ case "array":
401
+ return [date.year, date.month, date.day];
402
+ default:
403
+ return date;
404
+ }
405
+ }
406
+
407
+ // src/utils/date-helpers.ts
408
+ function getTotalDaysInMonth(year, month) {
409
+ if (!hasDataForYear(year)) {
410
+ throw new Error(`No data available for year ${year}`);
411
+ }
412
+ if (month < 1 || month > 12) {
413
+ throw new Error(`Invalid month: ${month}. Month must be between 1 and 12.`);
414
+ }
415
+ return NEPALI_CALENDAR_DATA[year][month - 1];
416
+ }
417
+ function getNextMonth(year, month) {
418
+ if (month < 1 || month > 12) {
419
+ throw new Error(`Invalid month: ${month}. Month must be between 1 and 12.`);
420
+ }
421
+ if (month === 12) {
422
+ const nextYear = year + 1;
423
+ if (!hasDataForYear(nextYear)) {
424
+ throw new Error(`No data available for year ${nextYear}`);
425
+ }
426
+ return { year: nextYear, month: 1 };
427
+ }
428
+ return { year, month: month + 1 };
429
+ }
430
+ function getPrevMonth(year, month) {
431
+ if (month < 1 || month > 12) {
432
+ throw new Error(`Invalid month: ${month}. Month must be between 1 and 12.`);
433
+ }
434
+ if (month === 1) {
435
+ const prevYear = year - 1;
436
+ if (!hasDataForYear(prevYear)) {
437
+ throw new Error(`No data available for year ${prevYear}`);
438
+ }
439
+ return { year: prevYear, month: 12 };
440
+ }
441
+ return { year, month: month - 1 };
442
+ }
443
+ function getCalendarData(year) {
444
+ if (!hasDataForYear(year)) {
445
+ throw new Error(`No data available for year ${year}`);
446
+ }
447
+ return [...NEPALI_CALENDAR_DATA[year]];
448
+ }
449
+
450
+ // src/utils/formatters.ts
451
+ function getNepaliMonthName(month, locale = "en") {
452
+ if (month < 1 || month > 12) {
453
+ throw new Error(`Invalid month: ${month}. Month must be between 1 and 12.`);
454
+ }
455
+ if (locale === "ne") {
456
+ return NEPALI_MONTH_NAMES_NE[month];
457
+ }
458
+ return NEPALI_MONTH_NAMES_EN[month];
459
+ }
460
+
461
+ // src/bin/mcp-server.ts
462
+ var TOOLS = [
463
+ {
464
+ name: "convert_bs_to_ad",
465
+ description: "Convert a Nepali (Bikram Sambat/BS) date to English (Anno Domini/AD) date. Supports dates from BS 2000-2100.",
466
+ inputSchema: {
467
+ type: "object",
468
+ properties: {
469
+ year: {
470
+ type: "number",
471
+ description: "BS year (2000-2100)",
472
+ minimum: 2e3,
473
+ maximum: 2100
474
+ },
475
+ month: {
476
+ type: "number",
477
+ description: "BS month (1-12, where 1=Baisakh, 2=Jestha, etc.)",
478
+ minimum: 1,
479
+ maximum: 12
480
+ },
481
+ day: {
482
+ type: "number",
483
+ description: "BS day (1-32, depending on month)",
484
+ minimum: 1,
485
+ maximum: 32
486
+ },
487
+ format: {
488
+ type: "string",
489
+ description: 'Output format: "object" (default), "iso" (YYYY-MM-DD), or "string"',
490
+ enum: ["object", "iso", "string"]
491
+ }
492
+ },
493
+ required: ["year", "month", "day"]
494
+ }
495
+ },
496
+ {
497
+ name: "convert_ad_to_bs",
498
+ description: "Convert an English (Anno Domini/AD) date to Nepali (Bikram Sambat/BS) date. Supports dates from AD 1943-2043.",
499
+ inputSchema: {
500
+ type: "object",
501
+ properties: {
502
+ year: {
503
+ type: "number",
504
+ description: "AD year (1943-2043)",
505
+ minimum: 1943,
506
+ maximum: 2043
507
+ },
508
+ month: {
509
+ type: "number",
510
+ description: "AD month (1-12, where 1=January, 2=February, etc.)",
511
+ minimum: 1,
512
+ maximum: 12
513
+ },
514
+ day: {
515
+ type: "number",
516
+ description: "AD day (1-31, depending on month)",
517
+ minimum: 1,
518
+ maximum: 31
519
+ },
520
+ format: {
521
+ type: "string",
522
+ description: 'Output format: "object" (default), "iso" (YYYY-MM-DD), or "string"',
523
+ enum: ["object", "iso", "string"]
524
+ }
525
+ },
526
+ required: ["year", "month", "day"]
527
+ }
528
+ },
529
+ {
530
+ name: "get_month_calendar",
531
+ description: "Get complete calendar information for a specific Nepali month. Returns the number of days in the month, month name, and a grid structure suitable for rendering a calendar.",
532
+ inputSchema: {
533
+ type: "object",
534
+ properties: {
535
+ year: {
536
+ type: "number",
537
+ description: "BS year (2000-2100)",
538
+ minimum: 2e3,
539
+ maximum: 2100
540
+ },
541
+ month: {
542
+ type: "number",
543
+ description: "BS month (1-12)",
544
+ minimum: 1,
545
+ maximum: 12
546
+ },
547
+ locale: {
548
+ type: "string",
549
+ description: 'Locale for month name: "en" (English) or "ne" (Nepali)',
550
+ enum: ["en", "ne"],
551
+ default: "en"
552
+ }
553
+ },
554
+ required: ["year", "month"]
555
+ }
556
+ },
557
+ {
558
+ name: "validate_bs_date",
559
+ description: "Validate if a Nepali (BS) date is valid. Checks if the year has data available and if the day is within the valid range for that month.",
560
+ inputSchema: {
561
+ type: "object",
562
+ properties: {
563
+ year: {
564
+ type: "number",
565
+ description: "BS year to validate"
566
+ },
567
+ month: {
568
+ type: "number",
569
+ description: "BS month (1-12)",
570
+ minimum: 1,
571
+ maximum: 12
572
+ },
573
+ day: {
574
+ type: "number",
575
+ description: "BS day to validate",
576
+ minimum: 1
577
+ }
578
+ },
579
+ required: ["year", "month", "day"]
580
+ }
581
+ },
582
+ {
583
+ name: "validate_ad_date",
584
+ description: "Validate if an English (AD) date is valid.",
585
+ inputSchema: {
586
+ type: "object",
587
+ properties: {
588
+ year: {
589
+ type: "number",
590
+ description: "AD year to validate"
591
+ },
592
+ month: {
593
+ type: "number",
594
+ description: "AD month (1-12)",
595
+ minimum: 1,
596
+ maximum: 12
597
+ },
598
+ day: {
599
+ type: "number",
600
+ description: "AD day to validate",
601
+ minimum: 1
602
+ }
603
+ },
604
+ required: ["year", "month", "day"]
605
+ }
606
+ },
607
+ {
608
+ name: "get_nepali_month_name",
609
+ description: "Get the name of a Nepali month in English or Nepali script.",
610
+ inputSchema: {
611
+ type: "object",
612
+ properties: {
613
+ month: {
614
+ type: "number",
615
+ description: "Month number (1-12, where 1=Baisakh/\u092C\u0948\u0936\u093E\u0916)",
616
+ minimum: 1,
617
+ maximum: 12
618
+ },
619
+ locale: {
620
+ type: "string",
621
+ description: 'Locale: "en" for English (Baisakh) or "ne" for Nepali (\u092C\u0948\u0936\u093E\u0916)',
622
+ enum: ["en", "ne"],
623
+ default: "en"
624
+ }
625
+ },
626
+ required: ["month"]
627
+ }
628
+ },
629
+ {
630
+ name: "navigate_month",
631
+ description: "Navigate to the next or previous month from a given Nepali date. Useful for building calendar navigation.",
632
+ inputSchema: {
633
+ type: "object",
634
+ properties: {
635
+ year: {
636
+ type: "number",
637
+ description: "Current BS year",
638
+ minimum: 2e3,
639
+ maximum: 2100
640
+ },
641
+ month: {
642
+ type: "number",
643
+ description: "Current BS month (1-12)",
644
+ minimum: 1,
645
+ maximum: 12
646
+ },
647
+ direction: {
648
+ type: "string",
649
+ description: 'Navigation direction: "next" or "prev"',
650
+ enum: ["next", "prev"]
651
+ }
652
+ },
653
+ required: ["year", "month", "direction"]
654
+ }
655
+ },
656
+ {
657
+ name: "get_year_calendar",
658
+ description: "Get calendar data for an entire Nepali year. Returns an array of 12 numbers representing days in each month.",
659
+ inputSchema: {
660
+ type: "object",
661
+ properties: {
662
+ year: {
663
+ type: "number",
664
+ description: "BS year (2000-2100)",
665
+ minimum: 2e3,
666
+ maximum: 2100
667
+ }
668
+ },
669
+ required: ["year"]
670
+ }
671
+ },
672
+ {
673
+ name: "get_current_nepali_date",
674
+ description: "Get the current date in Nepali (BS) calendar by converting today's date.",
675
+ inputSchema: {
676
+ type: "object",
677
+ properties: {
678
+ format: {
679
+ type: "string",
680
+ description: 'Output format: "object" (default), "iso", or "string"',
681
+ enum: ["object", "iso", "string"]
682
+ }
683
+ }
684
+ }
685
+ }
686
+ ];
687
+ var server = new import_server.Server(
688
+ {
689
+ name: "nepali-dates-mcp",
690
+ version: "1.0.0"
691
+ },
692
+ {
693
+ capabilities: {
694
+ tools: {}
695
+ }
696
+ }
697
+ );
698
+ server.setRequestHandler(import_types3.ListToolsRequestSchema, async () => {
699
+ return {
700
+ tools: TOOLS
701
+ };
702
+ });
703
+ server.setRequestHandler(import_types3.CallToolRequestSchema, async (request) => {
704
+ const { name, arguments: args } = request.params;
705
+ try {
706
+ switch (name) {
707
+ case "convert_bs_to_ad": {
708
+ const { year, month, day, format = "object" } = args;
709
+ const result = bsToAd(year, month, day, { format });
710
+ return {
711
+ content: [
712
+ {
713
+ type: "text",
714
+ text: JSON.stringify({
715
+ success: true,
716
+ input: { year, month, day, calendar: "BS" },
717
+ output: result,
718
+ calendar: "AD"
719
+ }, null, 2)
720
+ }
721
+ ]
722
+ };
723
+ }
724
+ case "convert_ad_to_bs": {
725
+ const { year, month, day, format = "object" } = args;
726
+ const result = adToBs(year, month, day, { format });
727
+ return {
728
+ content: [
729
+ {
730
+ type: "text",
731
+ text: JSON.stringify({
732
+ success: true,
733
+ input: { year, month, day, calendar: "AD" },
734
+ output: result,
735
+ calendar: "BS"
736
+ }, null, 2)
737
+ }
738
+ ]
739
+ };
740
+ }
741
+ case "get_month_calendar": {
742
+ const { year, month, locale = "en" } = args;
743
+ const totalDays = getTotalDaysInMonth(year, month);
744
+ const monthName = getNepaliMonthName(month, locale);
745
+ const firstDayAd = bsToAd(year, month, 1, { format: "object" });
746
+ const firstDayDate = new Date(
747
+ firstDayAd.year,
748
+ firstDayAd.month - 1,
749
+ firstDayAd.day
750
+ );
751
+ const startingWeekday = firstDayDate.getDay();
752
+ const weeks = [];
753
+ let currentWeek = new Array(7).fill(null);
754
+ for (let i = 0; i < startingWeekday; i++) {
755
+ currentWeek[i] = null;
756
+ }
757
+ for (let day = 1; day <= totalDays; day++) {
758
+ const dayIndex = (startingWeekday + day - 1) % 7;
759
+ currentWeek[dayIndex] = day;
760
+ if (dayIndex === 6 || day === totalDays) {
761
+ weeks.push([...currentWeek]);
762
+ currentWeek = new Array(7).fill(null);
763
+ }
764
+ }
765
+ return {
766
+ content: [
767
+ {
768
+ type: "text",
769
+ text: JSON.stringify({
770
+ success: true,
771
+ year,
772
+ month,
773
+ monthName,
774
+ locale,
775
+ totalDays,
776
+ startingWeekday,
777
+ weeks,
778
+ weekdayLabels: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
779
+ }, null, 2)
780
+ }
781
+ ]
782
+ };
783
+ }
784
+ case "validate_bs_date": {
785
+ const { year, month, day } = args;
786
+ const isValid = isValidBsDate(year, month, day);
787
+ let reason = "";
788
+ if (!isValid) {
789
+ if (month < 1 || month > 12) {
790
+ reason = "Month must be between 1 and 12";
791
+ } else {
792
+ try {
793
+ const maxDays = getTotalDaysInMonth(year, month);
794
+ if (day < 1 || day > maxDays) {
795
+ reason = `Day must be between 1 and ${maxDays} for this month`;
796
+ }
797
+ } catch (e) {
798
+ reason = "Year is outside available data range (2000-2100)";
799
+ }
800
+ }
801
+ }
802
+ return {
803
+ content: [
804
+ {
805
+ type: "text",
806
+ text: JSON.stringify({
807
+ success: true,
808
+ valid: isValid,
809
+ date: { year, month, day },
810
+ calendar: "BS",
811
+ reason: reason || "Valid date"
812
+ }, null, 2)
813
+ }
814
+ ]
815
+ };
816
+ }
817
+ case "validate_ad_date": {
818
+ const { year, month, day } = args;
819
+ const isValid = isValidAdDate(year, month, day);
820
+ return {
821
+ content: [
822
+ {
823
+ type: "text",
824
+ text: JSON.stringify({
825
+ success: true,
826
+ valid: isValid,
827
+ date: { year, month, day },
828
+ calendar: "AD"
829
+ }, null, 2)
830
+ }
831
+ ]
832
+ };
833
+ }
834
+ case "get_nepali_month_name": {
835
+ const { month, locale = "en" } = args;
836
+ const monthName = getNepaliMonthName(month, locale);
837
+ return {
838
+ content: [
839
+ {
840
+ type: "text",
841
+ text: JSON.stringify({
842
+ success: true,
843
+ month,
844
+ monthName,
845
+ locale,
846
+ allMonths: locale === "en" ? NEPALI_MONTH_NAMES_EN : NEPALI_MONTH_NAMES_NE
847
+ }, null, 2)
848
+ }
849
+ ]
850
+ };
851
+ }
852
+ case "navigate_month": {
853
+ const { year, month, direction } = args;
854
+ const result = direction === "next" ? getNextMonth(year, month) : getPrevMonth(year, month);
855
+ return {
856
+ content: [
857
+ {
858
+ type: "text",
859
+ text: JSON.stringify({
860
+ success: true,
861
+ from: { year, month },
862
+ to: result,
863
+ direction
864
+ }, null, 2)
865
+ }
866
+ ]
867
+ };
868
+ }
869
+ case "get_year_calendar": {
870
+ const { year } = args;
871
+ const yearData = getCalendarData(year);
872
+ const totalDays = yearData.reduce((sum, days) => sum + days, 0);
873
+ return {
874
+ content: [
875
+ {
876
+ type: "text",
877
+ text: JSON.stringify({
878
+ success: true,
879
+ year,
880
+ months: yearData,
881
+ totalDays,
882
+ monthNames: NEPALI_MONTH_NAMES_EN
883
+ }, null, 2)
884
+ }
885
+ ]
886
+ };
887
+ }
888
+ case "get_current_nepali_date": {
889
+ const { format = "object" } = args;
890
+ const now = /* @__PURE__ */ new Date();
891
+ const result = adToBs(
892
+ now.getFullYear(),
893
+ now.getMonth() + 1,
894
+ now.getDate(),
895
+ { format }
896
+ );
897
+ return {
898
+ content: [
899
+ {
900
+ type: "text",
901
+ text: JSON.stringify({
902
+ success: true,
903
+ currentDate: result,
904
+ calendar: "BS",
905
+ format
906
+ }, null, 2)
907
+ }
908
+ ]
909
+ };
910
+ }
911
+ default:
912
+ return {
913
+ content: [
914
+ {
915
+ type: "text",
916
+ text: JSON.stringify({
917
+ success: false,
918
+ error: `Unknown tool: ${name}`
919
+ })
920
+ }
921
+ ],
922
+ isError: true
923
+ };
924
+ }
925
+ } catch (error) {
926
+ return {
927
+ content: [
928
+ {
929
+ type: "text",
930
+ text: JSON.stringify({
931
+ success: false,
932
+ error: error instanceof Error ? error.message : "Unknown error"
933
+ })
934
+ }
935
+ ],
936
+ isError: true
937
+ };
938
+ }
939
+ });
940
+ async function main() {
941
+ const transport = new import_stdio.StdioServerTransport();
942
+ await server.connect(transport);
943
+ console.error("Nepali Dates MCP Server running on stdio");
944
+ }
945
+ main().catch((error) => {
946
+ console.error("Server error:", error);
947
+ process.exit(1);
948
+ });