@bmhall2/skylight-mcp 1.1.7

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.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +265 -0
  3. package/dist/api/auth.d.ts +38 -0
  4. package/dist/api/auth.d.ts.map +1 -0
  5. package/dist/api/auth.js +62 -0
  6. package/dist/api/auth.js.map +1 -0
  7. package/dist/api/client.d.ts +84 -0
  8. package/dist/api/client.d.ts.map +1 -0
  9. package/dist/api/client.js +228 -0
  10. package/dist/api/client.js.map +1 -0
  11. package/dist/api/endpoints/calendar.d.ts +33 -0
  12. package/dist/api/endpoints/calendar.d.ts.map +1 -0
  13. package/dist/api/endpoints/calendar.js +60 -0
  14. package/dist/api/endpoints/calendar.js.map +1 -0
  15. package/dist/api/endpoints/categories.d.ts +23 -0
  16. package/dist/api/endpoints/categories.d.ts.map +1 -0
  17. package/dist/api/endpoints/categories.js +48 -0
  18. package/dist/api/endpoints/categories.js.map +1 -0
  19. package/dist/api/endpoints/chores.d.ts +50 -0
  20. package/dist/api/endpoints/chores.d.ts.map +1 -0
  21. package/dist/api/endpoints/chores.js +106 -0
  22. package/dist/api/endpoints/chores.js.map +1 -0
  23. package/dist/api/endpoints/devices.d.ts +6 -0
  24. package/dist/api/endpoints/devices.d.ts.map +1 -0
  25. package/dist/api/endpoints/devices.js +10 -0
  26. package/dist/api/endpoints/devices.js.map +1 -0
  27. package/dist/api/endpoints/frames.d.ts +6 -0
  28. package/dist/api/endpoints/frames.d.ts.map +1 -0
  29. package/dist/api/endpoints/frames.js +10 -0
  30. package/dist/api/endpoints/frames.js.map +1 -0
  31. package/dist/api/endpoints/lists.d.ts +55 -0
  32. package/dist/api/endpoints/lists.d.ts.map +1 -0
  33. package/dist/api/endpoints/lists.js +125 -0
  34. package/dist/api/endpoints/lists.js.map +1 -0
  35. package/dist/api/endpoints/meals.d.ts +102 -0
  36. package/dist/api/endpoints/meals.d.ts.map +1 -0
  37. package/dist/api/endpoints/meals.js +100 -0
  38. package/dist/api/endpoints/meals.js.map +1 -0
  39. package/dist/api/endpoints/misc.d.ts +27 -0
  40. package/dist/api/endpoints/misc.d.ts.map +1 -0
  41. package/dist/api/endpoints/misc.js +18 -0
  42. package/dist/api/endpoints/misc.js.map +1 -0
  43. package/dist/api/endpoints/photos.d.ts +13 -0
  44. package/dist/api/endpoints/photos.d.ts.map +1 -0
  45. package/dist/api/endpoints/photos.js +10 -0
  46. package/dist/api/endpoints/photos.js.map +1 -0
  47. package/dist/api/endpoints/rewards.d.ts +49 -0
  48. package/dist/api/endpoints/rewards.d.ts.map +1 -0
  49. package/dist/api/endpoints/rewards.js +105 -0
  50. package/dist/api/endpoints/rewards.js.map +1 -0
  51. package/dist/api/endpoints/taskbox.d.ts +13 -0
  52. package/dist/api/endpoints/taskbox.d.ts.map +1 -0
  53. package/dist/api/endpoints/taskbox.js +22 -0
  54. package/dist/api/endpoints/taskbox.js.map +1 -0
  55. package/dist/api/generated-types.d.ts +18967 -0
  56. package/dist/api/generated-types.d.ts.map +1 -0
  57. package/dist/api/generated-types.js +6 -0
  58. package/dist/api/generated-types.js.map +1 -0
  59. package/dist/api/types.d.ts +283 -0
  60. package/dist/api/types.d.ts.map +1 -0
  61. package/dist/api/types.js +5 -0
  62. package/dist/api/types.js.map +1 -0
  63. package/dist/config.d.ts +52 -0
  64. package/dist/config.d.ts.map +1 -0
  65. package/dist/config.js +80 -0
  66. package/dist/config.js.map +1 -0
  67. package/dist/index.d.ts +3 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +11 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/server.d.ts +7 -0
  72. package/dist/server.d.ts.map +1 -0
  73. package/dist/server.js +48 -0
  74. package/dist/server.js.map +1 -0
  75. package/dist/tools/calendar.d.ts +3 -0
  76. package/dist/tools/calendar.d.ts.map +1 -0
  77. package/dist/tools/calendar.js +297 -0
  78. package/dist/tools/calendar.js.map +1 -0
  79. package/dist/tools/chores.d.ts +3 -0
  80. package/dist/tools/chores.d.ts.map +1 -0
  81. package/dist/tools/chores.js +349 -0
  82. package/dist/tools/chores.js.map +1 -0
  83. package/dist/tools/family.d.ts +3 -0
  84. package/dist/tools/family.d.ts.map +1 -0
  85. package/dist/tools/family.js +182 -0
  86. package/dist/tools/family.js.map +1 -0
  87. package/dist/tools/lists.d.ts +3 -0
  88. package/dist/tools/lists.d.ts.map +1 -0
  89. package/dist/tools/lists.js +481 -0
  90. package/dist/tools/lists.js.map +1 -0
  91. package/dist/tools/meals.d.ts +3 -0
  92. package/dist/tools/meals.d.ts.map +1 -0
  93. package/dist/tools/meals.js +319 -0
  94. package/dist/tools/meals.js.map +1 -0
  95. package/dist/tools/misc.d.ts +3 -0
  96. package/dist/tools/misc.d.ts.map +1 -0
  97. package/dist/tools/misc.js +101 -0
  98. package/dist/tools/misc.js.map +1 -0
  99. package/dist/tools/photos.d.ts +3 -0
  100. package/dist/tools/photos.d.ts.map +1 -0
  101. package/dist/tools/photos.js +42 -0
  102. package/dist/tools/photos.js.map +1 -0
  103. package/dist/tools/rewards.d.ts +3 -0
  104. package/dist/tools/rewards.d.ts.map +1 -0
  105. package/dist/tools/rewards.js +338 -0
  106. package/dist/tools/rewards.js.map +1 -0
  107. package/dist/tools/tasks.d.ts +3 -0
  108. package/dist/tools/tasks.d.ts.map +1 -0
  109. package/dist/tools/tasks.js +68 -0
  110. package/dist/tools/tasks.js.map +1 -0
  111. package/dist/utils/dates.d.ts +26 -0
  112. package/dist/utils/dates.d.ts.map +1 -0
  113. package/dist/utils/dates.js +109 -0
  114. package/dist/utils/dates.js.map +1 -0
  115. package/dist/utils/errors.d.ts +45 -0
  116. package/dist/utils/errors.d.ts.map +1 -0
  117. package/dist/utils/errors.js +102 -0
  118. package/dist/utils/errors.js.map +1 -0
  119. package/package.json +59 -0
@@ -0,0 +1,338 @@
1
+ import { z } from "zod";
2
+ import { getRewards, getRewardPoints, createReward, updateReward, deleteReward, redeemReward, unredeemReward, } from "../api/endpoints/rewards.js";
3
+ import { findCategoryByName } from "../api/endpoints/categories.js";
4
+ import { formatErrorForMcp } from "../utils/errors.js";
5
+ export function registerRewardTools(server) {
6
+ // get_rewards tool
7
+ server.tool("get_rewards", `Get available rewards that can be redeemed with reward points.
8
+
9
+ For family gamification - shows rewards that family members can earn.
10
+
11
+ Use this to answer:
12
+ - "What rewards can we redeem?"
13
+ - "What can the kids earn?"
14
+ - "Show available rewards"`, {
15
+ redeemedSince: z
16
+ .string()
17
+ .optional()
18
+ .describe("Filter to rewards redeemed after this date (ISO datetime)"),
19
+ }, async ({ redeemedSince }) => {
20
+ try {
21
+ const rewards = await getRewards({
22
+ redeemedAtMin: redeemedSince,
23
+ });
24
+ if (rewards.length === 0) {
25
+ return {
26
+ content: [
27
+ {
28
+ type: "text",
29
+ text: "No rewards found.",
30
+ },
31
+ ],
32
+ };
33
+ }
34
+ const rewardList = rewards
35
+ .map((reward) => {
36
+ const parts = [`- Reward (ID: ${reward.id})`];
37
+ const attrs = reward.attributes;
38
+ for (const [key, value] of Object.entries(attrs)) {
39
+ if (value !== null && value !== undefined) {
40
+ parts.push(` ${key}: ${value}`);
41
+ }
42
+ }
43
+ return parts.join("\n");
44
+ })
45
+ .join("\n\n");
46
+ return {
47
+ content: [
48
+ {
49
+ type: "text",
50
+ text: `Available rewards:\n\n${rewardList}`,
51
+ },
52
+ ],
53
+ };
54
+ }
55
+ catch (error) {
56
+ return {
57
+ content: [
58
+ {
59
+ type: "text",
60
+ text: formatErrorForMcp(error),
61
+ },
62
+ ],
63
+ isError: true,
64
+ };
65
+ }
66
+ });
67
+ // get_reward_points tool
68
+ server.tool("get_reward_points", `Get reward points balance for family members.
69
+
70
+ Shows how many reward points each family member has earned.
71
+
72
+ Use this to answer:
73
+ - "How many points does [name] have?"
74
+ - "Show reward points balance"
75
+ - "Who has the most points?"`, {}, async () => {
76
+ try {
77
+ const points = await getRewardPoints();
78
+ if (points.length === 0) {
79
+ return {
80
+ content: [
81
+ {
82
+ type: "text",
83
+ text: "No reward points found.",
84
+ },
85
+ ],
86
+ };
87
+ }
88
+ const pointsList = points
89
+ .map((point) => {
90
+ const parts = [`- Points (ID: ${point.id})`];
91
+ const attrs = point.attributes;
92
+ for (const [key, value] of Object.entries(attrs)) {
93
+ if (value !== null && value !== undefined) {
94
+ parts.push(` ${key}: ${value}`);
95
+ }
96
+ }
97
+ return parts.join("\n");
98
+ })
99
+ .join("\n\n");
100
+ return {
101
+ content: [
102
+ {
103
+ type: "text",
104
+ text: `Reward points:\n\n${pointsList}`,
105
+ },
106
+ ],
107
+ };
108
+ }
109
+ catch (error) {
110
+ return {
111
+ content: [
112
+ {
113
+ type: "text",
114
+ text: formatErrorForMcp(error),
115
+ },
116
+ ],
117
+ isError: true,
118
+ };
119
+ }
120
+ });
121
+ // create_reward tool
122
+ server.tool("create_reward", `Create a new reward that can be redeemed with points (Plus subscription required).
123
+
124
+ Use this when:
125
+ - Adding a new reward: "Create a reward for 30 minutes of screen time"
126
+ - Setting up family incentives: "Add a pizza night reward worth 100 points"
127
+
128
+ Parameters:
129
+ - name (required): Reward name (e.g., "30 min Screen Time")
130
+ - pointValue (required): Points needed to redeem this reward
131
+ - description: Additional details about the reward
132
+ - emojiIcon: Emoji to display with the reward
133
+ - assignee: Family member name to assign this reward to
134
+ - respawnOnRedemption: If true, reward can be redeemed multiple times
135
+
136
+ Returns: The created reward details.`, {
137
+ name: z.string().describe("Reward name (e.g., '30 min Screen Time')"),
138
+ pointValue: z.number().describe("Points needed to redeem this reward"),
139
+ description: z.string().optional().describe("Additional details about the reward"),
140
+ emojiIcon: z.string().optional().describe("Emoji for the reward (e.g., '🎮')"),
141
+ assignee: z.string().optional().describe("Family member to assign this reward to"),
142
+ respawnOnRedemption: z.boolean().optional().default(false).describe("Can be redeemed multiple times"),
143
+ }, async ({ name, pointValue, description, emojiIcon, assignee, respawnOnRedemption }) => {
144
+ try {
145
+ let categoryIds;
146
+ if (assignee) {
147
+ const category = await findCategoryByName(assignee);
148
+ if (!category) {
149
+ return {
150
+ content: [{ type: "text", text: `Could not find family member "${assignee}"` }],
151
+ isError: true,
152
+ };
153
+ }
154
+ categoryIds = [category.id];
155
+ }
156
+ const reward = await createReward({
157
+ name,
158
+ pointValue,
159
+ description,
160
+ emojiIcon,
161
+ categoryIds,
162
+ respawnOnRedemption,
163
+ });
164
+ return {
165
+ content: [
166
+ {
167
+ type: "text",
168
+ text: `Created reward "${name}" worth ${pointValue} points (ID: ${reward.id})`,
169
+ },
170
+ ],
171
+ };
172
+ }
173
+ catch (error) {
174
+ return {
175
+ content: [{ type: "text", text: formatErrorForMcp(error) }],
176
+ isError: true,
177
+ };
178
+ }
179
+ });
180
+ // update_reward tool
181
+ server.tool("update_reward", `Update an existing reward (Plus subscription required).
182
+
183
+ Use this when:
184
+ - Changing point value: "Make the screen time reward cost 50 points"
185
+ - Updating reward details: "Add a description to the pizza reward"
186
+
187
+ Parameters:
188
+ - rewardId (required): ID of the reward (from get_rewards)
189
+ - name: New reward name
190
+ - pointValue: New point cost
191
+ - description: Updated description
192
+ - emojiIcon: Updated emoji
193
+
194
+ Returns: The updated reward details.`, {
195
+ rewardId: z.string().describe("ID of the reward to update"),
196
+ name: z.string().optional().describe("New reward name"),
197
+ pointValue: z.number().optional().describe("New point cost"),
198
+ description: z.string().nullable().optional().describe("Updated description (null to clear)"),
199
+ emojiIcon: z.string().nullable().optional().describe("Updated emoji (null to clear)"),
200
+ respawnOnRedemption: z.boolean().optional().describe("Can be redeemed multiple times"),
201
+ }, async ({ rewardId, name, pointValue, description, emojiIcon, respawnOnRedemption }) => {
202
+ try {
203
+ const updates = {};
204
+ if (name !== undefined)
205
+ updates.name = name;
206
+ if (pointValue !== undefined)
207
+ updates.pointValue = pointValue;
208
+ if (description !== undefined)
209
+ updates.description = description;
210
+ if (emojiIcon !== undefined)
211
+ updates.emojiIcon = emojiIcon;
212
+ if (respawnOnRedemption !== undefined)
213
+ updates.respawnOnRedemption = respawnOnRedemption;
214
+ const reward = await updateReward(rewardId, updates);
215
+ return {
216
+ content: [
217
+ {
218
+ type: "text",
219
+ text: `Updated reward (ID: ${reward.id})`,
220
+ },
221
+ ],
222
+ };
223
+ }
224
+ catch (error) {
225
+ return {
226
+ content: [{ type: "text", text: formatErrorForMcp(error) }],
227
+ isError: true,
228
+ };
229
+ }
230
+ });
231
+ // delete_reward tool
232
+ server.tool("delete_reward", `Delete a reward (Plus subscription required).
233
+
234
+ Use this when:
235
+ - Removing an old reward
236
+ - Cleaning up unused rewards
237
+
238
+ Parameters:
239
+ - rewardId (required): ID of the reward to delete (from get_rewards)
240
+
241
+ Note: This permanently removes the reward.`, {
242
+ rewardId: z.string().describe("ID of the reward to delete"),
243
+ }, async ({ rewardId }) => {
244
+ try {
245
+ await deleteReward(rewardId);
246
+ return {
247
+ content: [
248
+ {
249
+ type: "text",
250
+ text: `Deleted reward (ID: ${rewardId})`,
251
+ },
252
+ ],
253
+ };
254
+ }
255
+ catch (error) {
256
+ return {
257
+ content: [{ type: "text", text: formatErrorForMcp(error) }],
258
+ isError: true,
259
+ };
260
+ }
261
+ });
262
+ // redeem_reward tool
263
+ server.tool("redeem_reward", `Redeem a reward using points (Plus subscription required).
264
+
265
+ Use this when:
266
+ - A family member wants to cash in points: "Redeem the screen time reward for Johnny"
267
+ - Claiming an earned reward
268
+
269
+ Parameters:
270
+ - rewardId (required): ID of the reward to redeem (from get_rewards)
271
+ - assignee: Family member redeeming the reward (uses their points)
272
+
273
+ Returns: The redeemed reward details.`, {
274
+ rewardId: z.string().describe("ID of the reward to redeem"),
275
+ assignee: z.string().optional().describe("Family member redeeming the reward"),
276
+ }, async ({ rewardId, assignee }) => {
277
+ try {
278
+ let categoryId;
279
+ if (assignee) {
280
+ const category = await findCategoryByName(assignee);
281
+ if (!category) {
282
+ return {
283
+ content: [{ type: "text", text: `Could not find family member "${assignee}"` }],
284
+ isError: true,
285
+ };
286
+ }
287
+ categoryId = category.id;
288
+ }
289
+ const reward = await redeemReward(rewardId, categoryId);
290
+ return {
291
+ content: [
292
+ {
293
+ type: "text",
294
+ text: `Redeemed reward (ID: ${reward.id})${assignee ? ` for ${assignee}` : ""}`,
295
+ },
296
+ ],
297
+ };
298
+ }
299
+ catch (error) {
300
+ return {
301
+ content: [{ type: "text", text: formatErrorForMcp(error) }],
302
+ isError: true,
303
+ };
304
+ }
305
+ });
306
+ // unredeem_reward tool
307
+ server.tool("unredeem_reward", `Cancel a reward redemption (Plus subscription required).
308
+
309
+ Use this when:
310
+ - A redemption was made by mistake
311
+ - Undoing a reward claim
312
+
313
+ Parameters:
314
+ - rewardId (required): ID of the reward to unredeem
315
+
316
+ Returns: The unredeemed reward details.`, {
317
+ rewardId: z.string().describe("ID of the reward to unredeem"),
318
+ }, async ({ rewardId }) => {
319
+ try {
320
+ const reward = await unredeemReward(rewardId);
321
+ return {
322
+ content: [
323
+ {
324
+ type: "text",
325
+ text: `Unredeemed reward (ID: ${reward.id})`,
326
+ },
327
+ ],
328
+ };
329
+ }
330
+ catch (error) {
331
+ return {
332
+ content: [{ type: "text", text: formatErrorForMcp(error) }],
333
+ isError: true,
334
+ };
335
+ }
336
+ });
337
+ }
338
+ //# sourceMappingURL=rewards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewards.js","sourceRoot":"","sources":["../../src/tools/rewards.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerTaskTools(server: McpServer): void;
3
+ //# sourceMappingURL=tasks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/tools/tasks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwEzD"}
@@ -0,0 +1,68 @@
1
+ import { z } from "zod";
2
+ import { createTaskBoxItem } from "../api/endpoints/taskbox.js";
3
+ import { formatErrorForMcp } from "../utils/errors.js";
4
+ export function registerTaskTools(server) {
5
+ // create_task tool
6
+ server.tool("create_task", `Add a task to the Skylight task box.
7
+
8
+ The task box holds unscheduled tasks that can later be assigned to specific dates.
9
+
10
+ Use this when the user says:
11
+ - "Add XYZ to my task list"
12
+ - "Remind me to do ABC" (without a specific date)
13
+ - "Put 'clean garage' on the task box"
14
+
15
+ The task will appear on the Skylight display in the task box.`, {
16
+ summary: z.string().describe("Task description"),
17
+ emoji: z
18
+ .string()
19
+ .optional()
20
+ .describe("Emoji icon for the task (e.g., '🧹', '📞')"),
21
+ rewardPoints: z
22
+ .number()
23
+ .optional()
24
+ .describe("Reward points for completing this task (for gamification)"),
25
+ routine: z
26
+ .boolean()
27
+ .optional()
28
+ .default(false)
29
+ .describe("Is this a routine task?"),
30
+ }, async ({ summary, emoji, rewardPoints, routine }) => {
31
+ try {
32
+ const task = await createTaskBoxItem({
33
+ summary,
34
+ emojiIcon: emoji,
35
+ rewardPoints,
36
+ routine: routine ?? false,
37
+ });
38
+ const parts = [`Created task: "${task.attributes.summary}"`];
39
+ if (task.attributes.emoji_icon) {
40
+ parts.push(`Emoji: ${task.attributes.emoji_icon}`);
41
+ }
42
+ if (task.attributes.reward_points) {
43
+ parts.push(`Reward points: ${task.attributes.reward_points}`);
44
+ }
45
+ parts.push(`\nThe task has been added to the Skylight task box.`);
46
+ return {
47
+ content: [
48
+ {
49
+ type: "text",
50
+ text: parts.join("\n"),
51
+ },
52
+ ],
53
+ };
54
+ }
55
+ catch (error) {
56
+ return {
57
+ content: [
58
+ {
59
+ type: "text",
60
+ text: formatErrorForMcp(error),
61
+ },
62
+ ],
63
+ isError: true,
64
+ };
65
+ }
66
+ });
67
+ }
68
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/tools/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,mBAAmB;IACnB,MAAM,CAAC,IAAI,CACT,aAAa,EACb;;;;;;;;;8DAS0D,EAC1D;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAChD,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,4CAA4C,CAAC;QACzD,YAAY,EAAE,CAAC;aACZ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,2DAA2D,CAAC;QACxE,OAAO,EAAE,CAAC;aACP,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,OAAO,CAAC,KAAK,CAAC;aACd,QAAQ,CAAC,yBAAyB,CAAC;KACvC,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,EAAE;QAClD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC;gBACnC,OAAO;gBACP,SAAS,EAAE,KAAK;gBAChB,YAAY;gBACZ,OAAO,EAAE,OAAO,IAAI,KAAK;aAC1B,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,CAAC,kBAAkB,IAAI,CAAC,UAAU,CAAC,OAAO,GAAG,CAAC,CAAC;YAE7D,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;gBAC/B,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;YACrD,CAAC;YAED,IAAI,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;gBAClC,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;YAChE,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;YAElE,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;qBACvB;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,iBAAiB,CAAC,KAAK,CAAC;qBAC/B;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Date utility functions for Skylight MCP
3
+ */
4
+ /**
5
+ * Get today's date in YYYY-MM-DD format
6
+ */
7
+ export declare function getTodayDate(timezone?: string): string;
8
+ /**
9
+ * Get a date N days from today in YYYY-MM-DD format
10
+ */
11
+ export declare function getDateOffset(days: number, timezone?: string): string;
12
+ /**
13
+ * Parse a date string to YYYY-MM-DD format
14
+ * Accepts: YYYY-MM-DD, MM/DD/YYYY, or natural language like "today", "tomorrow"
15
+ */
16
+ export declare function parseDate(input: string, timezone?: string): string;
17
+ /**
18
+ * Parse a time string to HH:MM format (24-hour)
19
+ * Accepts: "10:00", "10:00 AM", "2:30 PM", "14:30"
20
+ */
21
+ export declare function parseTime(input: string): string;
22
+ /**
23
+ * Format a date for display
24
+ */
25
+ export declare function formatDateForDisplay(dateStr: string): string;
26
+ //# sourceMappingURL=dates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../../src/utils/dates.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAMtD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAOrE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CA+ClE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAwB/C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAO5D"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Date utility functions for Skylight MCP
3
+ */
4
+ /**
5
+ * Get today's date in YYYY-MM-DD format
6
+ */
7
+ export function getTodayDate(timezone) {
8
+ const date = new Date();
9
+ if (timezone) {
10
+ return date.toLocaleDateString("en-CA", { timeZone: timezone });
11
+ }
12
+ return date.toISOString().split("T")[0];
13
+ }
14
+ /**
15
+ * Get a date N days from today in YYYY-MM-DD format
16
+ */
17
+ export function getDateOffset(days, timezone) {
18
+ const date = new Date();
19
+ date.setDate(date.getDate() + days);
20
+ if (timezone) {
21
+ return date.toLocaleDateString("en-CA", { timeZone: timezone });
22
+ }
23
+ return date.toISOString().split("T")[0];
24
+ }
25
+ /**
26
+ * Parse a date string to YYYY-MM-DD format
27
+ * Accepts: YYYY-MM-DD, MM/DD/YYYY, or natural language like "today", "tomorrow"
28
+ */
29
+ export function parseDate(input, timezone) {
30
+ const lower = input.toLowerCase().trim();
31
+ // Handle natural language
32
+ if (lower === "today") {
33
+ return getTodayDate(timezone);
34
+ }
35
+ if (lower === "tomorrow") {
36
+ return getDateOffset(1, timezone);
37
+ }
38
+ if (lower === "yesterday") {
39
+ return getDateOffset(-1, timezone);
40
+ }
41
+ // Handle day of week (next occurrence)
42
+ const days = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
43
+ const dayIndex = days.indexOf(lower);
44
+ if (dayIndex !== -1) {
45
+ const today = new Date();
46
+ const todayDay = today.getDay();
47
+ let daysUntil = dayIndex - todayDay;
48
+ if (daysUntil <= 0) {
49
+ daysUntil += 7; // Next week if today or past
50
+ }
51
+ return getDateOffset(daysUntil, timezone);
52
+ }
53
+ // Already in YYYY-MM-DD format
54
+ if (/^\d{4}-\d{2}-\d{2}$/.test(input)) {
55
+ return input;
56
+ }
57
+ // MM/DD/YYYY format
58
+ const usMatch = input.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
59
+ if (usMatch) {
60
+ const [, month, day, year] = usMatch;
61
+ return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
62
+ }
63
+ // Try parsing as a date
64
+ const parsed = new Date(input);
65
+ if (!isNaN(parsed.getTime())) {
66
+ return parsed.toISOString().split("T")[0];
67
+ }
68
+ // Return as-is if we can't parse it
69
+ return input;
70
+ }
71
+ /**
72
+ * Parse a time string to HH:MM format (24-hour)
73
+ * Accepts: "10:00", "10:00 AM", "2:30 PM", "14:30"
74
+ */
75
+ export function parseTime(input) {
76
+ const trimmed = input.trim();
77
+ // Already in HH:MM format (24-hour)
78
+ if (/^\d{1,2}:\d{2}$/.test(trimmed)) {
79
+ const [hours, minutes] = trimmed.split(":");
80
+ return `${hours.padStart(2, "0")}:${minutes}`;
81
+ }
82
+ // 12-hour format with AM/PM
83
+ const match = trimmed.match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/i);
84
+ if (match) {
85
+ const [, hours, minutes, period] = match;
86
+ let h = parseInt(hours, 10);
87
+ if (period.toUpperCase() === "PM" && h !== 12) {
88
+ h += 12;
89
+ }
90
+ else if (period.toUpperCase() === "AM" && h === 12) {
91
+ h = 0;
92
+ }
93
+ return `${h.toString().padStart(2, "0")}:${minutes}`;
94
+ }
95
+ // Return as-is
96
+ return trimmed;
97
+ }
98
+ /**
99
+ * Format a date for display
100
+ */
101
+ export function formatDateForDisplay(dateStr) {
102
+ const date = new Date(dateStr + "T00:00:00");
103
+ return date.toLocaleDateString("en-US", {
104
+ weekday: "short",
105
+ month: "short",
106
+ day: "numeric",
107
+ });
108
+ }
109
+ //# sourceMappingURL=dates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dates.js","sourceRoot":"","sources":["../../src/utils/dates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Base error class for Skylight API errors
3
+ */
4
+ export declare class SkylightError extends Error {
5
+ code: string;
6
+ statusCode?: number | undefined;
7
+ recoverable: boolean;
8
+ constructor(message: string, code: string, statusCode?: number | undefined, recoverable?: boolean);
9
+ }
10
+ /**
11
+ * Authentication failed - token may be expired or invalid
12
+ */
13
+ export declare class AuthenticationError extends SkylightError {
14
+ constructor(message?: string);
15
+ }
16
+ /**
17
+ * Configuration error - missing or invalid settings
18
+ */
19
+ export declare class ConfigurationError extends SkylightError {
20
+ constructor(message: string);
21
+ }
22
+ /**
23
+ * Resource not found
24
+ */
25
+ export declare class NotFoundError extends SkylightError {
26
+ constructor(resource: string);
27
+ }
28
+ /**
29
+ * Rate limited by the API
30
+ */
31
+ export declare class RateLimitError extends SkylightError {
32
+ constructor(retryAfter?: number);
33
+ }
34
+ /**
35
+ * API returned an unexpected response format
36
+ */
37
+ export declare class ParseError extends SkylightError {
38
+ constructor(message?: string);
39
+ }
40
+ /**
41
+ * Format an error for MCP tool response
42
+ * Accepts unknown to handle any value from catch blocks safely
43
+ */
44
+ export declare function formatErrorForMcp(error: unknown): string;
45
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAG7B,IAAI,EAAE,MAAM;IACZ,UAAU,CAAC,EAAE,MAAM;IACnB,WAAW,EAAE,OAAO;gBAH3B,OAAO,EAAE,MAAM,EACR,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,WAAW,GAAE,OAAe;CAKtC;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,aAAa;gBACxC,OAAO,GAAE,MAAuE;CAI7F;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,aAAa;gBACvC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,aAAa;gBAClC,QAAQ,EAAE,MAAM;CAI7B;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,aAAa;gBACnC,UAAU,CAAC,EAAE,MAAM;CAShC;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,aAAa;gBAC/B,OAAO,GAAE,MAAyC;CAI/D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CA0CxD"}