timezest-mcp 1.0.1 → 1.0.4
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 +3 -3
- package/build/client.js +31 -13
- package/build/index.js +16 -3
- package/build/utils/filter.js +4 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,8 +28,8 @@ Add this entry to the `mcpServers` section:
|
|
|
28
28
|
{
|
|
29
29
|
"mcpServers": {
|
|
30
30
|
"timezest": {
|
|
31
|
-
"command": "
|
|
32
|
-
"args": ["-y", "timezest-mcp@latest"],
|
|
31
|
+
"command": "cmd",
|
|
32
|
+
"args": ["/c", "npx", "-y", "timezest-mcp@latest"],
|
|
33
33
|
"env": {
|
|
34
34
|
"TIMEZEST_API_KEY": "YOUR_API_KEY_HERE",
|
|
35
35
|
"TIMEZEST_DEFAULT_TZ": "America/Chicago"
|
|
@@ -43,7 +43,7 @@ Add this entry to the `mcpServers` section:
|
|
|
43
43
|
If you use the terminal-based **Claude Code**, run this single command to add the server globally:
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
claude mcp add-json timezest "{\"type\": \"stdio\", \"command\": \"
|
|
46
|
+
claude mcp add-json timezest "{\"type\": \"stdio\", \"command\": \"cmd\", \"args\": [\"/c\", \"npx\", \"-y\", \"timezest-mcp@latest\"], \"env\": {\"TIMEZEST_API_KEY\": \"YOUR_API_KEY_HERE\", \"TIMEZEST_DEFAULT_TZ\": \"America/Chicago\"}}"
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
---
|
package/build/client.js
CHANGED
|
@@ -17,15 +17,27 @@ export class TimeZestClient {
|
|
|
17
17
|
headers: { Authorization: `Bearer ${this.apiKey}` }
|
|
18
18
|
});
|
|
19
19
|
const data = response.data;
|
|
20
|
+
// Handle both flat arrays and wrapped responses (e.g., { scheduling_requests: [...] })
|
|
21
|
+
let items;
|
|
20
22
|
if (Array.isArray(data)) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
items = data;
|
|
24
|
+
}
|
|
25
|
+
else if (data && typeof data === 'object') {
|
|
26
|
+
// Find the first array value in the response object
|
|
27
|
+
const arrayValue = Object.values(data).find(v => Array.isArray(v));
|
|
28
|
+
if (arrayValue) {
|
|
29
|
+
items = arrayValue;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
throw new Error(`Unexpected API response format from ${endpoint}: ${JSON.stringify(data).slice(0, 200)}`);
|
|
33
|
+
}
|
|
24
34
|
}
|
|
25
35
|
else {
|
|
26
|
-
|
|
27
|
-
break;
|
|
36
|
+
throw new Error(`Unexpected API response format from ${endpoint}: ${typeof data}`);
|
|
28
37
|
}
|
|
38
|
+
results.push(...items);
|
|
39
|
+
if (items.length < 50)
|
|
40
|
+
break;
|
|
29
41
|
page++;
|
|
30
42
|
}
|
|
31
43
|
return results;
|
|
@@ -41,17 +53,22 @@ export class TimeZestClient {
|
|
|
41
53
|
return this.appointmentTypes;
|
|
42
54
|
}
|
|
43
55
|
catch (error) {
|
|
44
|
-
|
|
45
|
-
|
|
56
|
+
const status = error?.response?.status;
|
|
57
|
+
const msg = error?.response?.data?.message || error?.message || String(error);
|
|
58
|
+
throw new Error(`TimeZest API error fetching appointment types (HTTP ${status || 'unknown'}): ${msg}`);
|
|
46
59
|
}
|
|
47
60
|
}
|
|
48
61
|
/**
|
|
49
|
-
* Fetches
|
|
62
|
+
* Fetches scheduling requests for a configurable window by created_at.
|
|
63
|
+
* Falls back to env vars TIMEZEST_WINDOW_DAYS_BACK / TIMEZEST_WINDOW_DAYS_FORWARD,
|
|
64
|
+
* then to 14 / 30 defaults.
|
|
50
65
|
*/
|
|
51
|
-
async
|
|
66
|
+
async getSchedulingRequests(daysBack, daysForward) {
|
|
67
|
+
const back = daysBack ?? parseInt(process.env.TIMEZEST_WINDOW_DAYS_BACK || '14', 10);
|
|
68
|
+
const forward = daysForward ?? parseInt(process.env.TIMEZEST_WINDOW_DAYS_FORWARD || '30', 10);
|
|
52
69
|
const now = new Date();
|
|
53
|
-
const start = subDays(now,
|
|
54
|
-
const end = addDays(now,
|
|
70
|
+
const start = subDays(now, back);
|
|
71
|
+
const end = addDays(now, forward);
|
|
55
72
|
// API limits filters to created_at
|
|
56
73
|
const params = {
|
|
57
74
|
created_at_after: getUnixTime(start),
|
|
@@ -61,8 +78,9 @@ export class TimeZestClient {
|
|
|
61
78
|
return await this.fetchAllPages('/scheduling_requests', params);
|
|
62
79
|
}
|
|
63
80
|
catch (error) {
|
|
64
|
-
|
|
65
|
-
|
|
81
|
+
const status = error?.response?.status;
|
|
82
|
+
const msg = error?.response?.data?.message || error?.message || String(error);
|
|
83
|
+
throw new Error(`TimeZest API error fetching scheduling requests (HTTP ${status || 'unknown'}): ${msg}`);
|
|
66
84
|
}
|
|
67
85
|
}
|
|
68
86
|
}
|
package/build/index.js
CHANGED
|
@@ -116,10 +116,23 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
116
116
|
}));
|
|
117
117
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
118
118
|
const { name, arguments: args } = request.params;
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
let appointmentTypes;
|
|
120
|
+
let all;
|
|
121
121
|
const tz = args?.timezone || process.env.TIMEZEST_DEFAULT_TZ || 'America/Chicago';
|
|
122
|
-
|
|
122
|
+
try {
|
|
123
|
+
appointmentTypes = await client.getAppointmentTypes();
|
|
124
|
+
// Determine fetch window from tool-specific args
|
|
125
|
+
const daysBack = args?.days_back;
|
|
126
|
+
const daysForward = args?.days_forward;
|
|
127
|
+
const rawRequests = await client.getSchedulingRequests(daysBack, daysForward);
|
|
128
|
+
all = rawRequests.map(r => transformAppointment(r, appointmentTypes, tz));
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
return {
|
|
132
|
+
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
133
|
+
isError: true
|
|
134
|
+
};
|
|
135
|
+
}
|
|
123
136
|
switch (name) {
|
|
124
137
|
case "get_todays_appointments": {
|
|
125
138
|
const today = new Date();
|
package/build/utils/filter.js
CHANGED
|
@@ -12,9 +12,11 @@ export function filterByDateRange(appointments, startDate, endDate) {
|
|
|
12
12
|
const start = parseISO(startDate);
|
|
13
13
|
const end = parseISO(endDate);
|
|
14
14
|
return appointments.filter(a => {
|
|
15
|
-
|
|
15
|
+
// Use start_time for scheduled appointments, fall back to created_at for pending
|
|
16
|
+
const dateStr = a.start_time || a.created_at;
|
|
17
|
+
if (!dateStr)
|
|
16
18
|
return false;
|
|
17
|
-
const date = parseISO(
|
|
19
|
+
const date = parseISO(dateStr);
|
|
18
20
|
return isWithinInterval(date, { start, end });
|
|
19
21
|
});
|
|
20
22
|
}
|
package/package.json
CHANGED