@openephemeris/mcp-server 3.13.8 → 3.13.9
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/dist/tools/apps/bodygraph-app.js +78 -11
- package/dist/ui/bi-wheel.html +1771 -1704
- package/dist/ui/bodygraph.html +1360 -1335
- package/dist/ui/chart-wheel.html +304 -315
- package/package.json +1 -1
|
@@ -65,6 +65,54 @@ function ensureTimezone(dt) {
|
|
|
65
65
|
return dt;
|
|
66
66
|
return dt + "Z";
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Convert a local datetime string (no offset) to a UTC ISO 8601 string.
|
|
70
|
+
* Uses the IANA timezone to compute the correct UTC offset.
|
|
71
|
+
* Falls back to appending 'Z' (treating input as UTC) when no timezone is given
|
|
72
|
+
* or when the Intl API cannot resolve the zone.
|
|
73
|
+
*
|
|
74
|
+
* @param dt - "YYYY-MM-DDTHH:MM:SS" (no offset)
|
|
75
|
+
* @param tz - IANA timezone name, e.g. "America/New_York"
|
|
76
|
+
*/
|
|
77
|
+
function localToUtcIso(dt, tz) {
|
|
78
|
+
// Already has an offset / Z — pass through as-is
|
|
79
|
+
if (!dt || /[Zz]$/.test(dt) || /[+-]\d{2}:\d{2}$/.test(dt))
|
|
80
|
+
return ensureTimezone(dt);
|
|
81
|
+
if (!tz)
|
|
82
|
+
return dt + "Z"; // treat as UTC
|
|
83
|
+
try {
|
|
84
|
+
// Parse the local date components
|
|
85
|
+
const [datePart, timePart = "00:00:00"] = dt.split("T");
|
|
86
|
+
const [year, month, day] = datePart.split("-").map(Number);
|
|
87
|
+
const [hour, min, sec = 0] = timePart.split(":").map(Number);
|
|
88
|
+
// Build a Date assuming the inputs are LOCAL in the given timezone.
|
|
89
|
+
// Strategy: create a UTC candidate and shift by the Intl-reported offset.
|
|
90
|
+
// We iterate twice because DST can cause the offset to change at boundary datetimes.
|
|
91
|
+
const candidateUtcMs = Date.UTC(year, month - 1, day, hour, min, sec);
|
|
92
|
+
const getOffsetMs = (utcMs) => {
|
|
93
|
+
const fmtParts = new Intl.DateTimeFormat("en-US", {
|
|
94
|
+
timeZone: tz,
|
|
95
|
+
year: "numeric", month: "2-digit", day: "2-digit",
|
|
96
|
+
hour: "2-digit", minute: "2-digit", second: "2-digit",
|
|
97
|
+
hour12: false,
|
|
98
|
+
}).formatToParts(new Date(utcMs));
|
|
99
|
+
const get = (t) => Number(fmtParts.find(p => p.type === t)?.value ?? 0);
|
|
100
|
+
const localizedUtcMs = Date.UTC(get("year"), get("month") - 1, get("day"), get("hour") % 24, get("minute"), get("second"));
|
|
101
|
+
return utcMs - localizedUtcMs; // positive = timezone behind UTC
|
|
102
|
+
};
|
|
103
|
+
// First pass: rough offset
|
|
104
|
+
const offsetMs1 = getOffsetMs(candidateUtcMs);
|
|
105
|
+
const correctedUtcMs1 = candidateUtcMs + offsetMs1;
|
|
106
|
+
// Second pass: refine around DST boundary
|
|
107
|
+
const offsetMs2 = getOffsetMs(correctedUtcMs1);
|
|
108
|
+
const finalUtcMs = candidateUtcMs + offsetMs2;
|
|
109
|
+
return new Date(finalUtcMs).toISOString();
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Intl failed (bad timezone string etc.) — fall back to naive UTC
|
|
113
|
+
return dt + "Z";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
68
116
|
const CENTER_ORDER = [
|
|
69
117
|
"Head", "Ajna", "Throat", "G", "Sacral",
|
|
70
118
|
"Heart", "Spleen", "Solar Plexus", "Root",
|
|
@@ -202,7 +250,13 @@ function buildHdModelPayload(data, birthParams) {
|
|
|
202
250
|
design_gates,
|
|
203
251
|
personality_activations,
|
|
204
252
|
design_activations,
|
|
205
|
-
_birth_params:
|
|
253
|
+
_birth_params: {
|
|
254
|
+
datetime: birthParams.datetime,
|
|
255
|
+
location: birthParams.location,
|
|
256
|
+
timezone: birthParams.timezone ?? null,
|
|
257
|
+
latitude: birthParams.latitude ?? null,
|
|
258
|
+
longitude: birthParams.longitude ?? null,
|
|
259
|
+
},
|
|
206
260
|
};
|
|
207
261
|
}
|
|
208
262
|
/**
|
|
@@ -275,15 +329,18 @@ registerTool({
|
|
|
275
329
|
},
|
|
276
330
|
handler: async (args) => {
|
|
277
331
|
const client = getActiveClient();
|
|
278
|
-
const
|
|
332
|
+
const timezone = args.timezone;
|
|
333
|
+
const datetime = localToUtcIso(String(args.datetime), timezone);
|
|
279
334
|
const location = String(args.location ?? (args.latitude != null ? `${args.latitude}, ${args.longitude}` : "Unknown")).slice(0, 120);
|
|
335
|
+
const lat = args.latitude;
|
|
336
|
+
const lon = args.longitude;
|
|
280
337
|
const body = {
|
|
281
338
|
birth_datetime_utc: datetime,
|
|
282
339
|
};
|
|
283
|
-
if (
|
|
284
|
-
body.latitude =
|
|
285
|
-
if (
|
|
286
|
-
body.longitude =
|
|
340
|
+
if (lat != null)
|
|
341
|
+
body.latitude = lat;
|
|
342
|
+
if (lon != null)
|
|
343
|
+
body.longitude = lon;
|
|
287
344
|
const chartData = await client.request("POST", "/human-design/chart", {
|
|
288
345
|
data: body,
|
|
289
346
|
});
|
|
@@ -293,6 +350,9 @@ registerTool({
|
|
|
293
350
|
const modelPayload = buildHdModelPayload(chart, {
|
|
294
351
|
datetime,
|
|
295
352
|
location: args.location ?? null,
|
|
353
|
+
timezone: timezone ?? null,
|
|
354
|
+
latitude: lat ?? null,
|
|
355
|
+
longitude: lon ?? null,
|
|
296
356
|
});
|
|
297
357
|
const summary = buildHdSummary(modelPayload, location);
|
|
298
358
|
const bundleAvailable = Boolean(getBodygraphBundle());
|
|
@@ -334,14 +394,18 @@ registerTool({
|
|
|
334
394
|
_meta: { ui: { resourceUri: BODYGRAPH_RESOURCE_URI, visibility: ["app"] } },
|
|
335
395
|
handler: async (args) => {
|
|
336
396
|
const client = getActiveClient();
|
|
337
|
-
const
|
|
397
|
+
const timezone = args.timezone;
|
|
398
|
+
// Convert local-time input → UTC using IANA timezone when provided
|
|
399
|
+
const datetime = localToUtcIso(String(args.datetime), timezone);
|
|
400
|
+
const lat = args.latitude;
|
|
401
|
+
const lon = args.longitude;
|
|
338
402
|
const body = {
|
|
339
403
|
birth_datetime_utc: datetime,
|
|
340
404
|
};
|
|
341
|
-
if (
|
|
342
|
-
body.latitude =
|
|
343
|
-
if (
|
|
344
|
-
body.longitude =
|
|
405
|
+
if (lat != null)
|
|
406
|
+
body.latitude = lat;
|
|
407
|
+
if (lon != null)
|
|
408
|
+
body.longitude = lon;
|
|
345
409
|
const chartData = await client.request("POST", "/human-design/chart", {
|
|
346
410
|
data: body,
|
|
347
411
|
});
|
|
@@ -349,6 +413,9 @@ registerTool({
|
|
|
349
413
|
const modelPayload = buildHdModelPayload(chart, {
|
|
350
414
|
datetime,
|
|
351
415
|
location: args.location ?? null,
|
|
416
|
+
timezone: timezone ?? null,
|
|
417
|
+
latitude: lat ?? null,
|
|
418
|
+
longitude: lon ?? null,
|
|
352
419
|
});
|
|
353
420
|
return {
|
|
354
421
|
content: [{ type: "text", text: JSON.stringify({ ...modelPayload, server_version: SERVER_VERSION }) }],
|