@open-sunsama/mcp 1.0.0
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.
- package/README.md +374 -0
- package/build/index.d.ts +13 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +71 -0
- package/build/index.js.map +1 -0
- package/build/lib/api-client.d.ts +177 -0
- package/build/lib/api-client.d.ts.map +1 -0
- package/build/lib/api-client.js +126 -0
- package/build/lib/api-client.js.map +1 -0
- package/build/tools/subtasks.d.ts +11 -0
- package/build/tools/subtasks.d.ts.map +1 -0
- package/build/tools/subtasks.js +194 -0
- package/build/tools/subtasks.js.map +1 -0
- package/build/tools/tasks.d.ts +11 -0
- package/build/tools/tasks.d.ts.map +1 -0
- package/build/tools/tasks.js +426 -0
- package/build/tools/tasks.js.map +1 -0
- package/build/tools/time-blocks.d.ts +13 -0
- package/build/tools/time-blocks.d.ts.map +1 -0
- package/build/tools/time-blocks.js +456 -0
- package/build/tools/time-blocks.js.map +1 -0
- package/build/tools/user.d.ts +11 -0
- package/build/tools/user.d.ts.map +1 -0
- package/build/tools/user.js +147 -0
- package/build/tools/user.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tools for Time Block Management
|
|
3
|
+
*
|
|
4
|
+
* Time blocks represent scheduled chunks of focused work time on your calendar.
|
|
5
|
+
* They can optionally be linked to tasks to track what you're working on.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
/**
|
|
9
|
+
* Format a time block for display with human-readable information
|
|
10
|
+
*/
|
|
11
|
+
function formatTimeBlock(block) {
|
|
12
|
+
const lines = [
|
|
13
|
+
`Time Block: ${block.title}`,
|
|
14
|
+
`ID: ${block.id}`,
|
|
15
|
+
`Date: ${block.date}`,
|
|
16
|
+
`Time: ${block.startTime} - ${block.endTime} (${block.durationMins} mins)`,
|
|
17
|
+
];
|
|
18
|
+
if (block.description) {
|
|
19
|
+
lines.push(`Description: ${block.description}`);
|
|
20
|
+
}
|
|
21
|
+
if (block.taskId) {
|
|
22
|
+
lines.push(`Linked Task ID: ${block.taskId}`);
|
|
23
|
+
if (block.task) {
|
|
24
|
+
lines.push(`Linked Task: ${block.task.title}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (block.color) {
|
|
28
|
+
lines.push(`Color: ${block.color}`);
|
|
29
|
+
}
|
|
30
|
+
lines.push(`Created: ${block.createdAt}`);
|
|
31
|
+
lines.push(`Updated: ${block.updatedAt}`);
|
|
32
|
+
return lines.join("\n");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Format multiple time blocks as a schedule view
|
|
36
|
+
*/
|
|
37
|
+
function formatSchedule(blocks, date) {
|
|
38
|
+
if (blocks.length === 0) {
|
|
39
|
+
return `No time blocks scheduled for ${date}`;
|
|
40
|
+
}
|
|
41
|
+
// Sort by start time
|
|
42
|
+
const sorted = [...blocks].sort((a, b) => a.startTime.localeCompare(b.startTime));
|
|
43
|
+
const lines = [`Schedule for ${date}:`, "─".repeat(40)];
|
|
44
|
+
for (const block of sorted) {
|
|
45
|
+
const taskInfo = block.taskId
|
|
46
|
+
? ` [Task: ${block.task?.title || block.taskId}]`
|
|
47
|
+
: "";
|
|
48
|
+
lines.push(`${block.startTime} - ${block.endTime}: ${block.title}${taskInfo}`);
|
|
49
|
+
if (block.description) {
|
|
50
|
+
lines.push(` └─ ${block.description}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Calculate total scheduled time
|
|
54
|
+
const totalMins = sorted.reduce((sum, b) => sum + b.durationMins, 0);
|
|
55
|
+
const hours = Math.floor(totalMins / 60);
|
|
56
|
+
const mins = totalMins % 60;
|
|
57
|
+
lines.push("─".repeat(40));
|
|
58
|
+
lines.push(`Total: ${blocks.length} blocks, ${hours}h ${mins}m scheduled`);
|
|
59
|
+
return lines.join("\n");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Creates a success response for MCP tools
|
|
63
|
+
*/
|
|
64
|
+
function successResponse(text) {
|
|
65
|
+
return {
|
|
66
|
+
content: [{ type: "text", text }],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Creates an error response for MCP tools
|
|
71
|
+
*/
|
|
72
|
+
function errorResponse(message) {
|
|
73
|
+
return {
|
|
74
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
75
|
+
isError: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Register all time block MCP tools
|
|
80
|
+
*/
|
|
81
|
+
export function registerTimeBlockTools(server, apiClient) {
|
|
82
|
+
// List time blocks with optional filters
|
|
83
|
+
server.tool("list_time_blocks", `List time blocks from your calendar with optional filters.
|
|
84
|
+
|
|
85
|
+
Use this tool to:
|
|
86
|
+
- View all time blocks for a specific date (use 'date' parameter)
|
|
87
|
+
- View time blocks across a date range (use 'from' and 'to' parameters)
|
|
88
|
+
- Find all time blocks linked to a specific task (use 'taskId' parameter)
|
|
89
|
+
- Browse through paginated results (use 'page' and 'limit' parameters)
|
|
90
|
+
|
|
91
|
+
Time blocks represent scheduled chunks of focused work time. They can be
|
|
92
|
+
linked to tasks to track what work is being done during that time.
|
|
93
|
+
|
|
94
|
+
Returns a list of time blocks with their details including title, date,
|
|
95
|
+
start/end times, duration, description, color, and any linked task info.`, {
|
|
96
|
+
date: z
|
|
97
|
+
.string()
|
|
98
|
+
.optional()
|
|
99
|
+
.describe("Filter by specific date in YYYY-MM-DD format (e.g., '2024-01-15'). Cannot be used with from/to."),
|
|
100
|
+
from: z
|
|
101
|
+
.string()
|
|
102
|
+
.optional()
|
|
103
|
+
.describe("Start of date range in YYYY-MM-DD format. Must be used with 'to' parameter."),
|
|
104
|
+
to: z
|
|
105
|
+
.string()
|
|
106
|
+
.optional()
|
|
107
|
+
.describe("End of date range in YYYY-MM-DD format. Must be used with 'from' parameter."),
|
|
108
|
+
taskId: z
|
|
109
|
+
.string()
|
|
110
|
+
.optional()
|
|
111
|
+
.describe("Filter to only show time blocks linked to this specific task ID"),
|
|
112
|
+
page: z
|
|
113
|
+
.number()
|
|
114
|
+
.int()
|
|
115
|
+
.positive()
|
|
116
|
+
.optional()
|
|
117
|
+
.describe("Page number for pagination (default: 1)"),
|
|
118
|
+
limit: z
|
|
119
|
+
.number()
|
|
120
|
+
.int()
|
|
121
|
+
.positive()
|
|
122
|
+
.max(100)
|
|
123
|
+
.optional()
|
|
124
|
+
.describe("Number of results per page (default: 50, max: 100)"),
|
|
125
|
+
}, async (input) => {
|
|
126
|
+
try {
|
|
127
|
+
const response = await apiClient.listTimeBlocks({
|
|
128
|
+
date: input.date,
|
|
129
|
+
from: input.from,
|
|
130
|
+
to: input.to,
|
|
131
|
+
taskId: input.taskId,
|
|
132
|
+
page: input.page,
|
|
133
|
+
limit: input.limit,
|
|
134
|
+
});
|
|
135
|
+
if (!response.success) {
|
|
136
|
+
return errorResponse(response.error?.message || "Failed to list time blocks");
|
|
137
|
+
}
|
|
138
|
+
const blocks = response.data || [];
|
|
139
|
+
if (blocks.length === 0) {
|
|
140
|
+
return successResponse("No time blocks found matching your criteria.");
|
|
141
|
+
}
|
|
142
|
+
let result = blocks.map((b) => formatTimeBlock(b)).join("\n\n---\n\n");
|
|
143
|
+
if (response.meta) {
|
|
144
|
+
result += `\n\n---\nPage ${response.meta.page} of ${response.meta.totalPages} (${response.meta.total} total blocks)`;
|
|
145
|
+
}
|
|
146
|
+
return successResponse(result);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error");
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
// Get a specific time block by ID
|
|
153
|
+
server.tool("get_time_block", `Get detailed information about a specific time block by its ID.
|
|
154
|
+
|
|
155
|
+
Use this tool when you need to:
|
|
156
|
+
- View the full details of a time block
|
|
157
|
+
- Check if a time block exists
|
|
158
|
+
- See what task is linked to a time block
|
|
159
|
+
- Get the exact timing and duration of a scheduled block
|
|
160
|
+
|
|
161
|
+
Returns complete time block information including title, date, start/end times,
|
|
162
|
+
duration in minutes, description, color, and linked task details if any.`, {
|
|
163
|
+
id: z.string().describe("The unique ID of the time block to retrieve"),
|
|
164
|
+
}, async (input) => {
|
|
165
|
+
try {
|
|
166
|
+
const response = await apiClient.getTimeBlock(input.id);
|
|
167
|
+
if (!response.success) {
|
|
168
|
+
return errorResponse(response.error?.message || "Time block not found");
|
|
169
|
+
}
|
|
170
|
+
return successResponse(formatTimeBlock(response.data));
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error");
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
// Create a new time block
|
|
177
|
+
server.tool("create_time_block", `Create a new time block to schedule focused work time on your calendar.
|
|
178
|
+
|
|
179
|
+
Use this tool to:
|
|
180
|
+
- Schedule a block of time for focused work
|
|
181
|
+
- Plan your day by creating time-boxed sessions
|
|
182
|
+
- Reserve time for specific activities or tasks
|
|
183
|
+
- Create recurring work sessions (one at a time)
|
|
184
|
+
|
|
185
|
+
Time blocks help you:
|
|
186
|
+
- Protect time for deep work
|
|
187
|
+
- Visualize your day's schedule
|
|
188
|
+
- Track how you spend your time
|
|
189
|
+
- Link work sessions to specific tasks
|
|
190
|
+
|
|
191
|
+
The time block will appear on your calendar for the specified date and time.
|
|
192
|
+
You can optionally link it to an existing task to track what you'll work on.`, {
|
|
193
|
+
title: z
|
|
194
|
+
.string()
|
|
195
|
+
.min(1)
|
|
196
|
+
.max(200)
|
|
197
|
+
.describe("Title of the time block (e.g., 'Deep work session', 'Team standup', 'Code review')"),
|
|
198
|
+
date: z
|
|
199
|
+
.string()
|
|
200
|
+
.describe("Date for the time block in YYYY-MM-DD format (e.g., '2024-01-15')"),
|
|
201
|
+
startTime: z
|
|
202
|
+
.string()
|
|
203
|
+
.describe("Start time in 24-hour HH:MM format (e.g., '09:00', '14:30')"),
|
|
204
|
+
endTime: z
|
|
205
|
+
.string()
|
|
206
|
+
.describe("End time in 24-hour HH:MM format (e.g., '11:00', '16:00'). Must be after startTime."),
|
|
207
|
+
taskId: z
|
|
208
|
+
.string()
|
|
209
|
+
.optional()
|
|
210
|
+
.describe("Optional: ID of a task to link to this time block. Links the scheduled time to specific work."),
|
|
211
|
+
description: z
|
|
212
|
+
.string()
|
|
213
|
+
.max(1000)
|
|
214
|
+
.optional()
|
|
215
|
+
.describe("Optional: Additional notes or context for this time block"),
|
|
216
|
+
color: z
|
|
217
|
+
.string()
|
|
218
|
+
.optional()
|
|
219
|
+
.describe("Optional: Hex color code for visual distinction (e.g., '#3B82F6' for blue, '#10B981' for green)"),
|
|
220
|
+
}, async (input) => {
|
|
221
|
+
try {
|
|
222
|
+
// Validate time format
|
|
223
|
+
const timeRegex = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
|
224
|
+
if (!timeRegex.test(input.startTime)) {
|
|
225
|
+
return errorResponse(`Invalid start time format '${input.startTime}'. Use HH:MM 24-hour format (e.g., '09:00', '14:30')`);
|
|
226
|
+
}
|
|
227
|
+
if (!timeRegex.test(input.endTime)) {
|
|
228
|
+
return errorResponse(`Invalid end time format '${input.endTime}'. Use HH:MM 24-hour format (e.g., '11:00', '16:00')`);
|
|
229
|
+
}
|
|
230
|
+
// Validate date format
|
|
231
|
+
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
|
|
232
|
+
if (!dateRegex.test(input.date)) {
|
|
233
|
+
return errorResponse(`Invalid date format '${input.date}'. Use YYYY-MM-DD format (e.g., '2024-01-15')`);
|
|
234
|
+
}
|
|
235
|
+
// Validate end time is after start time
|
|
236
|
+
if (input.endTime <= input.startTime) {
|
|
237
|
+
return errorResponse(`End time (${input.endTime}) must be after start time (${input.startTime})`);
|
|
238
|
+
}
|
|
239
|
+
// Validate color format if provided
|
|
240
|
+
if (input.color && !/^#[0-9A-Fa-f]{6}$/.test(input.color)) {
|
|
241
|
+
return errorResponse(`Invalid color format '${input.color}'. Use 6-digit hex code (e.g., '#3B82F6')`);
|
|
242
|
+
}
|
|
243
|
+
const response = await apiClient.createTimeBlock({
|
|
244
|
+
title: input.title,
|
|
245
|
+
date: input.date,
|
|
246
|
+
startTime: input.startTime,
|
|
247
|
+
endTime: input.endTime,
|
|
248
|
+
taskId: input.taskId,
|
|
249
|
+
description: input.description,
|
|
250
|
+
color: input.color,
|
|
251
|
+
});
|
|
252
|
+
if (!response.success) {
|
|
253
|
+
return errorResponse(response.error?.message || "Failed to create time block");
|
|
254
|
+
}
|
|
255
|
+
return successResponse(`Time block created successfully!\n\n${formatTimeBlock(response.data)}`);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error");
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
// Update an existing time block
|
|
262
|
+
server.tool("update_time_block", `Update an existing time block's details.
|
|
263
|
+
|
|
264
|
+
Use this tool to:
|
|
265
|
+
- Reschedule a time block to a different time or date
|
|
266
|
+
- Change the title or description
|
|
267
|
+
- Update the color for visual organization
|
|
268
|
+
- Link or unlink a task (use link_task_to_time_block for just that)
|
|
269
|
+
|
|
270
|
+
Only provide the fields you want to change. Omitted fields will remain unchanged.
|
|
271
|
+
To clear optional fields (description, color, taskId), pass null explicitly.`, {
|
|
272
|
+
id: z.string().describe("The unique ID of the time block to update"),
|
|
273
|
+
title: z
|
|
274
|
+
.string()
|
|
275
|
+
.min(1)
|
|
276
|
+
.max(200)
|
|
277
|
+
.optional()
|
|
278
|
+
.describe("New title for the time block"),
|
|
279
|
+
date: z
|
|
280
|
+
.string()
|
|
281
|
+
.optional()
|
|
282
|
+
.describe("New date in YYYY-MM-DD format (e.g., '2024-01-15')"),
|
|
283
|
+
startTime: z
|
|
284
|
+
.string()
|
|
285
|
+
.optional()
|
|
286
|
+
.describe("New start time in HH:MM 24-hour format (e.g., '09:00')"),
|
|
287
|
+
endTime: z
|
|
288
|
+
.string()
|
|
289
|
+
.optional()
|
|
290
|
+
.describe("New end time in HH:MM 24-hour format (e.g., '11:00')"),
|
|
291
|
+
taskId: z
|
|
292
|
+
.string()
|
|
293
|
+
.nullable()
|
|
294
|
+
.optional()
|
|
295
|
+
.describe("Task ID to link, or null to unlink. Omit to keep current link."),
|
|
296
|
+
description: z
|
|
297
|
+
.string()
|
|
298
|
+
.max(1000)
|
|
299
|
+
.nullable()
|
|
300
|
+
.optional()
|
|
301
|
+
.describe("New description, or null to clear"),
|
|
302
|
+
color: z
|
|
303
|
+
.string()
|
|
304
|
+
.nullable()
|
|
305
|
+
.optional()
|
|
306
|
+
.describe("New hex color (e.g., '#3B82F6'), or null to clear"),
|
|
307
|
+
}, async (input) => {
|
|
308
|
+
try {
|
|
309
|
+
const { id, ...updates } = input;
|
|
310
|
+
// Validate time formats if provided
|
|
311
|
+
const timeRegex = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
|
312
|
+
if (updates.startTime && !timeRegex.test(updates.startTime)) {
|
|
313
|
+
return errorResponse(`Invalid start time format '${updates.startTime}'. Use HH:MM 24-hour format`);
|
|
314
|
+
}
|
|
315
|
+
if (updates.endTime && !timeRegex.test(updates.endTime)) {
|
|
316
|
+
return errorResponse(`Invalid end time format '${updates.endTime}'. Use HH:MM 24-hour format`);
|
|
317
|
+
}
|
|
318
|
+
// Validate date format if provided
|
|
319
|
+
if (updates.date && !/^\d{4}-\d{2}-\d{2}$/.test(updates.date)) {
|
|
320
|
+
return errorResponse(`Invalid date format '${updates.date}'. Use YYYY-MM-DD format`);
|
|
321
|
+
}
|
|
322
|
+
// Validate color format if provided
|
|
323
|
+
if (updates.color !== null &&
|
|
324
|
+
updates.color !== undefined &&
|
|
325
|
+
!/^#[0-9A-Fa-f]{6}$/.test(updates.color)) {
|
|
326
|
+
return errorResponse(`Invalid color format '${updates.color}'. Use 6-digit hex code (e.g., '#3B82F6')`);
|
|
327
|
+
}
|
|
328
|
+
// Build update payload, only including defined fields
|
|
329
|
+
const updateData = {};
|
|
330
|
+
if (updates.title !== undefined)
|
|
331
|
+
updateData.title = updates.title;
|
|
332
|
+
if (updates.date !== undefined)
|
|
333
|
+
updateData.date = updates.date;
|
|
334
|
+
if (updates.startTime !== undefined)
|
|
335
|
+
updateData.startTime = updates.startTime;
|
|
336
|
+
if (updates.endTime !== undefined)
|
|
337
|
+
updateData.endTime = updates.endTime;
|
|
338
|
+
if (updates.taskId !== undefined)
|
|
339
|
+
updateData.taskId = updates.taskId;
|
|
340
|
+
if (updates.description !== undefined)
|
|
341
|
+
updateData.description = updates.description;
|
|
342
|
+
if (updates.color !== undefined)
|
|
343
|
+
updateData.color = updates.color;
|
|
344
|
+
if (Object.keys(updateData).length === 0) {
|
|
345
|
+
return errorResponse("No updates provided. Please provide at least one field to update.");
|
|
346
|
+
}
|
|
347
|
+
const response = await apiClient.updateTimeBlock(id, updateData);
|
|
348
|
+
if (!response.success) {
|
|
349
|
+
return errorResponse(response.error?.message || "Failed to update time block");
|
|
350
|
+
}
|
|
351
|
+
return successResponse(`Time block updated successfully!\n\n${formatTimeBlock(response.data)}`);
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error");
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
// Delete a time block
|
|
358
|
+
server.tool("delete_time_block", `Delete a time block from your calendar.
|
|
359
|
+
|
|
360
|
+
Use this tool to:
|
|
361
|
+
- Remove a scheduled time block that's no longer needed
|
|
362
|
+
- Clear a time slot that was cancelled
|
|
363
|
+
- Delete mistakenly created time blocks
|
|
364
|
+
|
|
365
|
+
This action is permanent. The time block will be removed from your schedule.
|
|
366
|
+
Any linked task will NOT be deleted, only the link will be removed.`, {
|
|
367
|
+
id: z.string().describe("The unique ID of the time block to delete"),
|
|
368
|
+
}, async (input) => {
|
|
369
|
+
try {
|
|
370
|
+
const response = await apiClient.deleteTimeBlock(input.id);
|
|
371
|
+
if (!response.success) {
|
|
372
|
+
return errorResponse(response.error?.message || "Failed to delete time block");
|
|
373
|
+
}
|
|
374
|
+
return successResponse(`Time block deleted successfully. (ID: ${input.id})`);
|
|
375
|
+
}
|
|
376
|
+
catch (error) {
|
|
377
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error");
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
// Link or unlink a task to a time block
|
|
381
|
+
server.tool("link_task_to_time_block", `Link a task to a time block, or unlink a task from a time block.
|
|
382
|
+
|
|
383
|
+
Use this tool to:
|
|
384
|
+
- Connect a scheduled time block to a specific task you'll work on
|
|
385
|
+
- Track which task you're dedicating time to
|
|
386
|
+
- Unlink a task if the time block is for something else
|
|
387
|
+
|
|
388
|
+
When a task is linked to a time block:
|
|
389
|
+
- The calendar shows what you'll be working on
|
|
390
|
+
- You can see which tasks have dedicated time slots
|
|
391
|
+
- Time tracking becomes more meaningful
|
|
392
|
+
|
|
393
|
+
To unlink a task, pass null as the taskId.`, {
|
|
394
|
+
timeBlockId: z
|
|
395
|
+
.string()
|
|
396
|
+
.describe("The ID of the time block to link/unlink"),
|
|
397
|
+
taskId: z
|
|
398
|
+
.string()
|
|
399
|
+
.nullable()
|
|
400
|
+
.describe("The task ID to link to this time block, or null to unlink the current task"),
|
|
401
|
+
}, async (input) => {
|
|
402
|
+
try {
|
|
403
|
+
const response = await apiClient.updateTimeBlock(input.timeBlockId, {
|
|
404
|
+
taskId: input.taskId,
|
|
405
|
+
});
|
|
406
|
+
if (!response.success) {
|
|
407
|
+
return errorResponse(response.error?.message || "Failed to update time block");
|
|
408
|
+
}
|
|
409
|
+
const action = input.taskId ? "linked" : "unlinked";
|
|
410
|
+
return successResponse(`Task ${action} successfully!\n\n${formatTimeBlock(response.data)}`);
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error");
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
// Get schedule for a specific day (convenience tool)
|
|
417
|
+
server.tool("get_schedule_for_day", `Get all time blocks for a specific day, formatted as a schedule view.
|
|
418
|
+
|
|
419
|
+
This is a convenience tool that:
|
|
420
|
+
- Fetches all time blocks for the given date
|
|
421
|
+
- Sorts them chronologically
|
|
422
|
+
- Formats them as a readable daily schedule
|
|
423
|
+
- Shows total scheduled time
|
|
424
|
+
|
|
425
|
+
Use this tool to:
|
|
426
|
+
- See your schedule for today or any other day
|
|
427
|
+
- Review how your day is organized
|
|
428
|
+
- Check for gaps in your schedule
|
|
429
|
+
- Get an overview before planning
|
|
430
|
+
|
|
431
|
+
The schedule shows times, titles, and linked tasks in an easy-to-read format.`, {
|
|
432
|
+
date: z
|
|
433
|
+
.string()
|
|
434
|
+
.describe("The date to get the schedule for in YYYY-MM-DD format (e.g., '2024-01-15')"),
|
|
435
|
+
}, async (input) => {
|
|
436
|
+
try {
|
|
437
|
+
// Validate date format
|
|
438
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(input.date)) {
|
|
439
|
+
return errorResponse(`Invalid date format '${input.date}'. Use YYYY-MM-DD format (e.g., '2024-01-15')`);
|
|
440
|
+
}
|
|
441
|
+
const response = await apiClient.listTimeBlocks({
|
|
442
|
+
date: input.date,
|
|
443
|
+
limit: 100, // Get all blocks for the day
|
|
444
|
+
});
|
|
445
|
+
if (!response.success) {
|
|
446
|
+
return errorResponse(response.error?.message || "Failed to get schedule");
|
|
447
|
+
}
|
|
448
|
+
const blocks = response.data || [];
|
|
449
|
+
return successResponse(formatSchedule(blocks, input.date));
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error");
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
//# sourceMappingURL=time-blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-blocks.js","sourceRoot":"","sources":["../../src/tools/time-blocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tools for user profile management
|
|
3
|
+
* Provides tools for viewing and updating user profile information
|
|
4
|
+
*/
|
|
5
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
|
+
import type { ApiClient } from "../lib/api-client.js";
|
|
7
|
+
/**
|
|
8
|
+
* Register all user-related tools with the MCP server
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerUserTools(server: McpServer, apiClient: ApiClient): void;
|
|
11
|
+
//# sourceMappingURL=user.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/tools/user.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,sBAAsB,CAAC;AA6C7E;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,SAAS,GACnB,IAAI,CAiJN"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tools for user profile management
|
|
3
|
+
* Provides tools for viewing and updating user profile information
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
/**
|
|
7
|
+
* Format user profile for display
|
|
8
|
+
*/
|
|
9
|
+
function formatUserProfile(user) {
|
|
10
|
+
const lines = [
|
|
11
|
+
`Name: ${user.name || "(not set)"}`,
|
|
12
|
+
`Email: ${user.email}`,
|
|
13
|
+
`Timezone: ${user.timezone}`,
|
|
14
|
+
`Avatar URL: ${user.avatarUrl || "(not set)"}`,
|
|
15
|
+
`Account created: ${new Date(user.createdAt).toLocaleDateString()}`,
|
|
16
|
+
`Last updated: ${new Date(user.updatedAt).toLocaleDateString()}`,
|
|
17
|
+
];
|
|
18
|
+
if (user.preferences) {
|
|
19
|
+
lines.push("");
|
|
20
|
+
lines.push("Preferences:");
|
|
21
|
+
lines.push(` Theme mode: ${user.preferences.themeMode}`);
|
|
22
|
+
lines.push(` Color theme: ${user.preferences.colorTheme}`);
|
|
23
|
+
lines.push(` Font family: ${user.preferences.fontFamily}`);
|
|
24
|
+
}
|
|
25
|
+
return lines.join("\n");
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Creates a success response for MCP tools
|
|
29
|
+
*/
|
|
30
|
+
function successResponse(text) {
|
|
31
|
+
return {
|
|
32
|
+
content: [{ type: "text", text }],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates an error response for MCP tools
|
|
37
|
+
*/
|
|
38
|
+
function errorResponse(message) {
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Register all user-related tools with the MCP server
|
|
46
|
+
*/
|
|
47
|
+
export function registerUserTools(server, apiClient) {
|
|
48
|
+
// Get current user profile
|
|
49
|
+
server.tool("get_user_profile", "Get the current authenticated user's profile information. Returns the user's name, email, timezone, avatar URL, and preferences (theme mode, color theme, font family). This is useful for personalizing interactions or understanding the user's settings.", {}, async () => {
|
|
50
|
+
try {
|
|
51
|
+
const response = await apiClient.getMe();
|
|
52
|
+
if (!response.success) {
|
|
53
|
+
return errorResponse(response.error?.message || "Failed to fetch user profile");
|
|
54
|
+
}
|
|
55
|
+
const user = response.data;
|
|
56
|
+
const formattedProfile = formatUserProfile(user);
|
|
57
|
+
return successResponse(`User Profile:\n\n${formattedProfile}\n\nUser ID: ${user.id}`);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error");
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
// Update user profile
|
|
64
|
+
server.tool("update_user_profile", "Update the current user's profile information. You can update the user's display name, timezone, avatar URL, and preferences (theme mode, color theme, font family). At least one field must be provided. The timezone should be a valid IANA timezone identifier (e.g., 'America/New_York', 'Europe/London', 'Asia/Tokyo').", {
|
|
65
|
+
name: z
|
|
66
|
+
.string()
|
|
67
|
+
.optional()
|
|
68
|
+
.describe("The user's display name. This is shown in the UI and can be any string"),
|
|
69
|
+
timezone: z
|
|
70
|
+
.string()
|
|
71
|
+
.optional()
|
|
72
|
+
.describe("The user's timezone as an IANA timezone identifier (e.g., 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'UTC'). Used for scheduling and displaying times"),
|
|
73
|
+
avatarUrl: z
|
|
74
|
+
.string()
|
|
75
|
+
.nullable()
|
|
76
|
+
.optional()
|
|
77
|
+
.describe("URL to the user's avatar image. Set to null to remove the avatar"),
|
|
78
|
+
themeMode: z
|
|
79
|
+
.enum(["light", "dark", "system"])
|
|
80
|
+
.optional()
|
|
81
|
+
.describe("UI theme mode preference. 'light' for light theme, 'dark' for dark theme, 'system' to follow system settings"),
|
|
82
|
+
colorTheme: z
|
|
83
|
+
.string()
|
|
84
|
+
.optional()
|
|
85
|
+
.describe("Color theme/accent color for the UI (e.g., 'blue', 'green', 'purple')"),
|
|
86
|
+
fontFamily: z
|
|
87
|
+
.string()
|
|
88
|
+
.optional()
|
|
89
|
+
.describe("Font family preference for the UI (e.g., 'Inter', 'SF Pro', 'Roboto')"),
|
|
90
|
+
}, async (input) => {
|
|
91
|
+
try {
|
|
92
|
+
// Build update data
|
|
93
|
+
const updateData = {};
|
|
94
|
+
// Handle direct fields
|
|
95
|
+
if (input.name !== undefined) {
|
|
96
|
+
updateData.name = input.name;
|
|
97
|
+
}
|
|
98
|
+
if (input.timezone !== undefined) {
|
|
99
|
+
updateData.timezone = input.timezone;
|
|
100
|
+
}
|
|
101
|
+
if (input.avatarUrl !== undefined) {
|
|
102
|
+
updateData.avatarUrl = input.avatarUrl;
|
|
103
|
+
}
|
|
104
|
+
// Handle preferences
|
|
105
|
+
const preferences = {};
|
|
106
|
+
if (input.themeMode !== undefined) {
|
|
107
|
+
preferences.themeMode = input.themeMode;
|
|
108
|
+
}
|
|
109
|
+
if (input.colorTheme !== undefined) {
|
|
110
|
+
preferences.colorTheme = input.colorTheme;
|
|
111
|
+
}
|
|
112
|
+
if (input.fontFamily !== undefined) {
|
|
113
|
+
preferences.fontFamily = input.fontFamily;
|
|
114
|
+
}
|
|
115
|
+
if (Object.keys(preferences).length > 0) {
|
|
116
|
+
updateData.preferences = preferences;
|
|
117
|
+
}
|
|
118
|
+
// Check if at least one field is provided
|
|
119
|
+
if (Object.keys(updateData).length === 0) {
|
|
120
|
+
return errorResponse("At least one field must be provided to update the profile");
|
|
121
|
+
}
|
|
122
|
+
const response = await apiClient.updateMe(updateData);
|
|
123
|
+
if (!response.success) {
|
|
124
|
+
return errorResponse(response.error?.message || "Failed to update user profile");
|
|
125
|
+
}
|
|
126
|
+
const user = response.data;
|
|
127
|
+
const updatedFields = [];
|
|
128
|
+
if (input.name !== undefined)
|
|
129
|
+
updatedFields.push("name");
|
|
130
|
+
if (input.timezone !== undefined)
|
|
131
|
+
updatedFields.push("timezone");
|
|
132
|
+
if (input.avatarUrl !== undefined)
|
|
133
|
+
updatedFields.push("avatarUrl");
|
|
134
|
+
if (input.themeMode !== undefined)
|
|
135
|
+
updatedFields.push("themeMode");
|
|
136
|
+
if (input.colorTheme !== undefined)
|
|
137
|
+
updatedFields.push("colorTheme");
|
|
138
|
+
if (input.fontFamily !== undefined)
|
|
139
|
+
updatedFields.push("fontFamily");
|
|
140
|
+
return successResponse(`Successfully updated user profile (fields: ${updatedFields.join(", ")}):\n\n${formatUserProfile(user)}`);
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error");
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=user.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/tools/user.ts"],"names":[],"mappings":"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"}
|