@openephemeris/mcp-server 4.8.0 → 4.10.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/CHANGELOG.md +63 -0
- package/dist/tools/apps/bazi-app.js +14 -7
- package/dist/tools/apps/bi-wheel-app.js +5 -5
- package/dist/tools/apps/bodygraph-app.js +8 -8
- package/dist/tools/apps/chart-wheel-app.js +4 -4
- package/dist/tools/apps/location-tools.js +68 -6
- package/dist/tools/apps/moon-phase-app.js +1 -1
- package/dist/tools/apps/vedic-chart-app.js +1 -1
- package/dist/tools/auth.js +8 -0
- package/dist/tools/dev.js +15 -5
- package/dist/tools/specialized/account.js +5 -1
- package/dist/tools/specialized/acg.js +2 -2
- package/dist/tools/specialized/bazi.d.ts +38 -0
- package/dist/tools/specialized/bazi.js +126 -24
- package/dist/tools/specialized/bi_wheel.js +1 -1
- package/dist/tools/specialized/chart_wheel.js +1 -1
- package/dist/tools/specialized/comparative.js +4 -4
- package/dist/tools/specialized/eclipse.js +1 -1
- package/dist/tools/specialized/electional.js +5 -5
- package/dist/tools/specialized/ephemeris_core.js +2 -2
- package/dist/tools/specialized/ephemeris_extended.js +8 -8
- package/dist/tools/specialized/hd_bodygraph.js +1 -1
- package/dist/tools/specialized/hd_cycles.js +2 -2
- package/dist/tools/specialized/hd_group.js +2 -2
- package/dist/tools/specialized/human_design.js +1 -1
- package/dist/tools/specialized/moon.js +2 -2
- package/dist/tools/specialized/natal.js +1 -1
- package/dist/tools/specialized/progressed.js +1 -1
- package/dist/tools/specialized/relocation.js +1 -1
- package/dist/tools/specialized/returns.js +3 -3
- package/dist/tools/specialized/synastry.js +1 -1
- package/dist/tools/specialized/transits.js +1 -1
- package/dist/tools/specialized/vedic.js +1 -1
- package/dist/tools/specialized/venus_star_points.js +6 -6
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { registerTool } from "../index.js";
|
|
|
2
2
|
import { getActiveClient } from "../../backend/client.js";
|
|
3
3
|
import { OUTPUT_SCHEMA_IMAGE_AND_JSON } from "../output-schemas.js";
|
|
4
4
|
export function parseBaziArgs(args, datetimeField = "datetime") {
|
|
5
|
-
let { year, month, day, hour } = args;
|
|
5
|
+
let { year, month, day, hour, minute } = args;
|
|
6
6
|
const datetime = args[datetimeField];
|
|
7
7
|
if (datetime && (!year || !month || !day)) {
|
|
8
8
|
const parts = baziLocalComponents(datetime, args.timezone, datetimeField);
|
|
@@ -11,6 +11,8 @@ export function parseBaziArgs(args, datetimeField = "datetime") {
|
|
|
11
11
|
day = parts.day;
|
|
12
12
|
if (hour == null)
|
|
13
13
|
hour = parts.hour;
|
|
14
|
+
if (minute == null)
|
|
15
|
+
minute = parts.minute;
|
|
14
16
|
}
|
|
15
17
|
if (!year || !month || !day) {
|
|
16
18
|
throw new Error("Provide year/month/day fields, or a datetime ISO string. " +
|
|
@@ -19,8 +21,48 @@ export function parseBaziArgs(args, datetimeField = "datetime") {
|
|
|
19
21
|
const out = { year, month, day };
|
|
20
22
|
if (hour != null)
|
|
21
23
|
out.hour = hour;
|
|
24
|
+
if (minute != null)
|
|
25
|
+
out.minute = minute;
|
|
22
26
|
return out;
|
|
23
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Build the optional BaZi convention fields (year_boundary, day_boundary,
|
|
30
|
+
* true_solar_time, latitude, longitude, timezone) to spread into a request
|
|
31
|
+
* body. `timezone` is wrapped to the API's `TimezoneInput` object shape.
|
|
32
|
+
*
|
|
33
|
+
* Kept separate from `parseBaziArgs`/`BaziComponents`: these fields frame
|
|
34
|
+
* which convention resolves the pillars rather than naming the birth moment
|
|
35
|
+
* itself, and bazi_compatibility needs the same set built twice under a
|
|
36
|
+
* `chart_a_`/`chart_b_` prefix.
|
|
37
|
+
*/
|
|
38
|
+
export function buildBaziConventionFields(args) {
|
|
39
|
+
const fields = {};
|
|
40
|
+
if (args.year_boundary != null)
|
|
41
|
+
fields.year_boundary = args.year_boundary;
|
|
42
|
+
if (args.day_boundary != null)
|
|
43
|
+
fields.day_boundary = args.day_boundary;
|
|
44
|
+
if (args.true_solar_time != null)
|
|
45
|
+
fields.true_solar_time = args.true_solar_time;
|
|
46
|
+
if (args.latitude != null)
|
|
47
|
+
fields.latitude = args.latitude;
|
|
48
|
+
if (args.longitude != null)
|
|
49
|
+
fields.longitude = args.longitude;
|
|
50
|
+
if (typeof args.timezone === "string" && args.timezone.trim() !== "") {
|
|
51
|
+
fields.timezone = { iana_name: args.timezone };
|
|
52
|
+
}
|
|
53
|
+
return fields;
|
|
54
|
+
}
|
|
55
|
+
/** `buildBaziConventionFields`, reading `<prefix>_<field>` args — used by bazi_compatibility. */
|
|
56
|
+
export function buildBaziConventionFieldsPrefixed(args, prefix) {
|
|
57
|
+
return buildBaziConventionFields({
|
|
58
|
+
year_boundary: args[`${prefix}_year_boundary`],
|
|
59
|
+
day_boundary: args[`${prefix}_day_boundary`],
|
|
60
|
+
true_solar_time: args[`${prefix}_true_solar_time`],
|
|
61
|
+
latitude: args[`${prefix}_latitude`],
|
|
62
|
+
longitude: args[`${prefix}_longitude`],
|
|
63
|
+
timezone: args[`${prefix}_timezone`],
|
|
64
|
+
});
|
|
65
|
+
}
|
|
24
66
|
/**
|
|
25
67
|
* Extract the LOCAL calendar/clock components a BaZi chart is built from.
|
|
26
68
|
*
|
|
@@ -50,7 +92,7 @@ function baziLocalComponents(datetime, timezone, field) {
|
|
|
50
92
|
hour: "2-digit", minute: "2-digit",
|
|
51
93
|
}).formatToParts(new Date(value));
|
|
52
94
|
const get = (t) => Number(parts.find((p) => p.type === t)?.value);
|
|
53
|
-
return { year: get("year"), month: get("month"), day: get("day"), hour: get("hour") % 24 };
|
|
95
|
+
return { year: get("year"), month: get("month"), day: get("day"), hour: get("hour") % 24, minute: get("minute") };
|
|
54
96
|
}
|
|
55
97
|
const m = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2}))?/.exec(value);
|
|
56
98
|
if (!m) {
|
|
@@ -62,6 +104,7 @@ function baziLocalComponents(datetime, timezone, field) {
|
|
|
62
104
|
month: Number(m[2]),
|
|
63
105
|
day: Number(m[3]),
|
|
64
106
|
hour: m[4] != null ? Number(m[4]) : undefined,
|
|
107
|
+
minute: m[5] != null ? Number(m[5]) : undefined,
|
|
65
108
|
};
|
|
66
109
|
}
|
|
67
110
|
// Shared datetime input schema fragment — used across all BaZiRequest tools.
|
|
@@ -83,6 +126,10 @@ const DATETIME_PROPERTIES = {
|
|
|
83
126
|
description: "Birth hour (0–23). Optional, defaults to 12 (noon). " +
|
|
84
127
|
"Chinese shí hours are 2-hour blocks — precision within a 2-hour window is sufficient.",
|
|
85
128
|
},
|
|
129
|
+
minute: {
|
|
130
|
+
type: "integer",
|
|
131
|
+
description: "Birth minute (0–59). Optional, defaults to 0. Only matters under true_solar_time or near a boundary.",
|
|
132
|
+
},
|
|
86
133
|
datetime: {
|
|
87
134
|
type: "string",
|
|
88
135
|
description: "Alternative to year/month/day: ISO 8601 datetime read as LOCAL wall-clock time at the " +
|
|
@@ -93,11 +140,49 @@ const DATETIME_PROPERTIES = {
|
|
|
93
140
|
},
|
|
94
141
|
timezone: {
|
|
95
142
|
type: "string",
|
|
96
|
-
description: "IANA timezone name for the birth place, e.g. 'Asia/Shanghai'.
|
|
97
|
-
"`datetime`
|
|
98
|
-
"
|
|
143
|
+
description: "IANA timezone name for the birth place, e.g. 'Asia/Shanghai'. Required to convert a " +
|
|
144
|
+
"zoned `datetime` back to local clock; also passed to the API to frame the year/month " +
|
|
145
|
+
"solar-term boundary at the true birth instant instead of naive local clock.",
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
// Optional convention fields, shared across every BaZiRequest-shaped tool —
|
|
149
|
+
// see BaZiRequest in the Go API. Kept terse: core tool-surface budget is
|
|
150
|
+
// near its ceiling (test/tool-surface-budget.test.ts).
|
|
151
|
+
export const CONVENTION_PROPERTIES = {
|
|
152
|
+
year_boundary: {
|
|
153
|
+
type: "string",
|
|
154
|
+
enum: ["lichun", "cny"],
|
|
155
|
+
description: "Year-pillar cutover convention. Default lichun.",
|
|
156
|
+
},
|
|
157
|
+
day_boundary: {
|
|
158
|
+
type: "string",
|
|
159
|
+
enum: ["zi_hour", "midnight"],
|
|
160
|
+
description: "Day-pillar cutover convention. Default zi_hour.",
|
|
161
|
+
},
|
|
162
|
+
true_solar_time: {
|
|
163
|
+
type: "boolean",
|
|
164
|
+
description: "Apply true solar time correction (needs latitude+longitude).",
|
|
165
|
+
},
|
|
166
|
+
latitude: {
|
|
167
|
+
type: "number",
|
|
168
|
+
description: "Birth latitude, decimal degrees (north+).",
|
|
169
|
+
},
|
|
170
|
+
longitude: {
|
|
171
|
+
type: "number",
|
|
172
|
+
description: "Birth longitude, decimal degrees (east+).",
|
|
99
173
|
},
|
|
100
174
|
};
|
|
175
|
+
/** CONVENTION_PROPERTIES (+ minute) under a `chart_a_`/`chart_b_` prefix — used by bazi_compatibility. */
|
|
176
|
+
function chartConventionProperties(label) {
|
|
177
|
+
return {
|
|
178
|
+
[`chart_${label.toLowerCase()}_minute`]: { type: "integer", description: `Chart ${label} minute (0–59).` },
|
|
179
|
+
[`chart_${label.toLowerCase()}_year_boundary`]: { type: "string", enum: ["lichun", "cny"], description: `Chart ${label} year-pillar cutover.` },
|
|
180
|
+
[`chart_${label.toLowerCase()}_day_boundary`]: { type: "string", enum: ["zi_hour", "midnight"], description: `Chart ${label} day-pillar cutover.` },
|
|
181
|
+
[`chart_${label.toLowerCase()}_true_solar_time`]: { type: "boolean", description: `Chart ${label}: true solar time correction.` },
|
|
182
|
+
[`chart_${label.toLowerCase()}_latitude`]: { type: "number", description: `Chart ${label} latitude (decimal degrees, north+).` },
|
|
183
|
+
[`chart_${label.toLowerCase()}_longitude`]: { type: "number", description: `Chart ${label} longitude (decimal degrees, east+).` },
|
|
184
|
+
};
|
|
185
|
+
}
|
|
101
186
|
// Shared visual input schema fragment — mirrors natal.ts pattern.
|
|
102
187
|
const VISUAL_PROPERTIES = {
|
|
103
188
|
include_visual: {
|
|
@@ -153,14 +238,15 @@ registerTool({
|
|
|
153
238
|
type: "object",
|
|
154
239
|
properties: {
|
|
155
240
|
...DATETIME_PROPERTIES,
|
|
241
|
+
...CONVENTION_PROPERTIES,
|
|
156
242
|
...VISUAL_PROPERTIES,
|
|
157
243
|
},
|
|
158
244
|
additionalProperties: false,
|
|
159
245
|
},
|
|
160
246
|
outputSchema: OUTPUT_SCHEMA_IMAGE_AND_JSON,
|
|
161
|
-
annotations: { title: "BaZi Four Pillars Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
247
|
+
annotations: { title: "BaZi Four Pillars Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
162
248
|
handler: async (args) => {
|
|
163
|
-
const body = { ...parseBaziArgs(args) };
|
|
249
|
+
const body = { ...parseBaziArgs(args), ...buildBaziConventionFields(args) };
|
|
164
250
|
applyVisualConfig(body, args);
|
|
165
251
|
return await getActiveClient().request("POST", "/chinese/bazi", { data: body });
|
|
166
252
|
},
|
|
@@ -190,14 +276,15 @@ registerTool({
|
|
|
190
276
|
type: "object",
|
|
191
277
|
properties: {
|
|
192
278
|
...DATETIME_PROPERTIES,
|
|
279
|
+
...CONVENTION_PROPERTIES,
|
|
193
280
|
...VISUAL_PROPERTIES,
|
|
194
281
|
},
|
|
195
282
|
additionalProperties: false,
|
|
196
283
|
},
|
|
197
284
|
outputSchema: OUTPUT_SCHEMA_IMAGE_AND_JSON,
|
|
198
|
-
annotations: { title: "BaZi Ten Gods", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
285
|
+
annotations: { title: "BaZi Ten Gods", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
199
286
|
handler: async (args) => {
|
|
200
|
-
const body = { ...parseBaziArgs(args) };
|
|
287
|
+
const body = { ...parseBaziArgs(args), ...buildBaziConventionFields(args) };
|
|
201
288
|
applyVisualConfig(body, args);
|
|
202
289
|
return await getActiveClient().request("POST", "/chinese/bazi/ten-gods", { data: body });
|
|
203
290
|
},
|
|
@@ -225,14 +312,15 @@ registerTool({
|
|
|
225
312
|
type: "object",
|
|
226
313
|
properties: {
|
|
227
314
|
...DATETIME_PROPERTIES,
|
|
315
|
+
...CONVENTION_PROPERTIES,
|
|
228
316
|
...VISUAL_PROPERTIES,
|
|
229
317
|
},
|
|
230
318
|
additionalProperties: false,
|
|
231
319
|
},
|
|
232
320
|
outputSchema: OUTPUT_SCHEMA_IMAGE_AND_JSON,
|
|
233
|
-
annotations: { title: "BaZi Element Balance", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
321
|
+
annotations: { title: "BaZi Element Balance", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
234
322
|
handler: async (args) => {
|
|
235
|
-
const body = { ...parseBaziArgs(args) };
|
|
323
|
+
const body = { ...parseBaziArgs(args), ...buildBaziConventionFields(args) };
|
|
236
324
|
applyVisualConfig(body, args);
|
|
237
325
|
return await getActiveClient().request("POST", "/chinese/bazi/element-balance", { data: body });
|
|
238
326
|
},
|
|
@@ -261,6 +349,7 @@ registerTool({
|
|
|
261
349
|
type: "object",
|
|
262
350
|
properties: {
|
|
263
351
|
...DATETIME_PROPERTIES,
|
|
352
|
+
...CONVENTION_PROPERTIES,
|
|
264
353
|
gender: {
|
|
265
354
|
type: "string",
|
|
266
355
|
enum: ["male", "female"],
|
|
@@ -273,16 +362,21 @@ registerTool({
|
|
|
273
362
|
additionalProperties: false,
|
|
274
363
|
},
|
|
275
364
|
outputSchema: OUTPUT_SCHEMA_IMAGE_AND_JSON,
|
|
276
|
-
annotations: { title: "BaZi Luck Pillars", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
365
|
+
annotations: { title: "BaZi Luck Pillars", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
277
366
|
handler: async (args) => {
|
|
278
367
|
if (!args.gender) {
|
|
279
368
|
throw new Error("gender is required for luck pillar calculation. " +
|
|
280
369
|
"Provide 'male' or 'female' — the direction of Da Yun depends on gender and year polarity.");
|
|
281
370
|
}
|
|
282
|
-
const { year, month, day, hour } = parseBaziArgs(args);
|
|
283
|
-
const body = {
|
|
371
|
+
const { year, month, day, hour, minute } = parseBaziArgs(args);
|
|
372
|
+
const body = {
|
|
373
|
+
year, month, day, gender: args.gender,
|
|
374
|
+
...buildBaziConventionFields(args),
|
|
375
|
+
};
|
|
284
376
|
if (hour != null)
|
|
285
377
|
body.hour = hour;
|
|
378
|
+
if (minute != null)
|
|
379
|
+
body.minute = minute;
|
|
286
380
|
return await getActiveClient().request("POST", "/chinese/bazi/luck-pillars", { data: body });
|
|
287
381
|
},
|
|
288
382
|
});
|
|
@@ -316,7 +410,7 @@ registerTool({
|
|
|
316
410
|
additionalProperties: false,
|
|
317
411
|
},
|
|
318
412
|
outputSchema: OUTPUT_SCHEMA_IMAGE_AND_JSON,
|
|
319
|
-
annotations: { title: "BaZi Annual Pillar", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
413
|
+
annotations: { title: "BaZi Annual Pillar", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
320
414
|
handler: async (args) => {
|
|
321
415
|
if (!args.year) {
|
|
322
416
|
throw new Error("year is required. Provide a Gregorian year (1–9999), e.g. year=2025.");
|
|
@@ -362,9 +456,10 @@ registerTool({
|
|
|
362
456
|
},
|
|
363
457
|
chart_a_timezone: {
|
|
364
458
|
type: "string",
|
|
365
|
-
description: "IANA timezone for Chart A's birth place, e.g. 'Asia/Shanghai'.
|
|
366
|
-
"chart_a_datetime carries a 'Z' or ±HH:MM offset.",
|
|
459
|
+
description: "IANA timezone for Chart A's birth place, e.g. 'Asia/Shanghai'. Needed when " +
|
|
460
|
+
"chart_a_datetime carries a 'Z' or ±HH:MM offset; also frames Chart A's year/month boundary.",
|
|
367
461
|
},
|
|
462
|
+
...chartConventionProperties("A"),
|
|
368
463
|
// Chart B
|
|
369
464
|
chart_b_year: { type: "integer", description: "Chart B birth year." },
|
|
370
465
|
chart_b_month: { type: "integer", description: "Chart B birth month (1–12)." },
|
|
@@ -378,20 +473,22 @@ registerTool({
|
|
|
378
473
|
},
|
|
379
474
|
chart_b_timezone: {
|
|
380
475
|
type: "string",
|
|
381
|
-
description: "IANA timezone for Chart B's birth place, e.g. 'Asia/Shanghai'.
|
|
382
|
-
"chart_b_datetime carries a 'Z' or ±HH:MM offset.",
|
|
476
|
+
description: "IANA timezone for Chart B's birth place, e.g. 'Asia/Shanghai'. Needed when " +
|
|
477
|
+
"chart_b_datetime carries a 'Z' or ±HH:MM offset; also frames Chart B's year/month boundary.",
|
|
383
478
|
},
|
|
479
|
+
...chartConventionProperties("B"),
|
|
384
480
|
},
|
|
385
481
|
additionalProperties: false,
|
|
386
482
|
},
|
|
387
483
|
outputSchema: OUTPUT_SCHEMA_IMAGE_AND_JSON,
|
|
388
|
-
annotations: { title: "BaZi Compatibility", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
484
|
+
annotations: { title: "BaZi Compatibility", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
389
485
|
handler: async (args) => {
|
|
390
486
|
const chartAComponents = parseBaziArgs({
|
|
391
487
|
year: args.chart_a_year,
|
|
392
488
|
month: args.chart_a_month,
|
|
393
489
|
day: args.chart_a_day,
|
|
394
490
|
hour: args.chart_a_hour,
|
|
491
|
+
minute: args.chart_a_minute,
|
|
395
492
|
datetime: args.chart_a_datetime,
|
|
396
493
|
timezone: args.chart_a_timezone,
|
|
397
494
|
});
|
|
@@ -400,13 +497,14 @@ registerTool({
|
|
|
400
497
|
month: args.chart_b_month,
|
|
401
498
|
day: args.chart_b_day,
|
|
402
499
|
hour: args.chart_b_hour,
|
|
500
|
+
minute: args.chart_b_minute,
|
|
403
501
|
datetime: args.chart_b_datetime,
|
|
404
502
|
timezone: args.chart_b_timezone,
|
|
405
503
|
});
|
|
406
504
|
return await getActiveClient().request("POST", "/chinese/bazi/compatibility", {
|
|
407
505
|
data: {
|
|
408
|
-
chart_a: chartAComponents,
|
|
409
|
-
chart_b: chartBComponents,
|
|
506
|
+
chart_a: { ...chartAComponents, ...buildBaziConventionFieldsPrefixed(args, "chart_a") },
|
|
507
|
+
chart_b: { ...chartBComponents, ...buildBaziConventionFieldsPrefixed(args, "chart_b") },
|
|
410
508
|
},
|
|
411
509
|
});
|
|
412
510
|
},
|
|
@@ -434,6 +532,7 @@ registerTool({
|
|
|
434
532
|
type: "object",
|
|
435
533
|
properties: {
|
|
436
534
|
...DATETIME_PROPERTIES,
|
|
535
|
+
...CONVENTION_PROPERTIES,
|
|
437
536
|
theme: {
|
|
438
537
|
type: "string",
|
|
439
538
|
enum: ["light", "dark", "mono"],
|
|
@@ -447,9 +546,9 @@ registerTool({
|
|
|
447
546
|
additionalProperties: false,
|
|
448
547
|
},
|
|
449
548
|
outputSchema: OUTPUT_SCHEMA_IMAGE_AND_JSON,
|
|
450
|
-
annotations: { title: "BaZi Chart (Visual)", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
549
|
+
annotations: { title: "BaZi Chart (Visual)", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
451
550
|
handler: async (args) => {
|
|
452
|
-
const { year, month, day, hour } = parseBaziArgs(args);
|
|
551
|
+
const { year, month, day, hour, minute } = parseBaziArgs(args);
|
|
453
552
|
const body = {
|
|
454
553
|
year, month, day,
|
|
455
554
|
visual_config: {
|
|
@@ -457,9 +556,12 @@ registerTool({
|
|
|
457
556
|
theme: args.theme ?? "light",
|
|
458
557
|
size: args.size ?? 800,
|
|
459
558
|
},
|
|
559
|
+
...buildBaziConventionFields(args),
|
|
460
560
|
};
|
|
461
561
|
if (hour != null)
|
|
462
562
|
body.hour = hour;
|
|
563
|
+
if (minute != null)
|
|
564
|
+
body.minute = minute;
|
|
463
565
|
return await getActiveClient().request("POST", "/chinese/bazi/chart", { data: body });
|
|
464
566
|
},
|
|
465
567
|
});
|
|
@@ -40,7 +40,7 @@ registerTool({
|
|
|
40
40
|
additionalProperties: false,
|
|
41
41
|
},
|
|
42
42
|
outputSchema: OUTPUT_SCHEMA_IMAGE,
|
|
43
|
-
annotations: { title: "Bi-Wheel Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
43
|
+
annotations: { title: "Bi-Wheel Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
44
44
|
handler: async (args) => {
|
|
45
45
|
validateRequired(args, ["datetime_a", "latitude_a", "longitude_a", "datetime_b", "latitude_b", "longitude_b"]);
|
|
46
46
|
assertZonedDatetime("datetime_a", args.datetime_a, args.timezone_a, "timezone_a");
|
|
@@ -45,7 +45,7 @@ registerTool({
|
|
|
45
45
|
additionalProperties: false,
|
|
46
46
|
},
|
|
47
47
|
outputSchema: OUTPUT_SCHEMA_IMAGE,
|
|
48
|
-
annotations: { title: "Chart Wheel SVG", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
48
|
+
annotations: { title: "Chart Wheel SVG", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
49
49
|
handler: async (args) => {
|
|
50
50
|
validateRequired(args, ["datetime", "latitude", "longitude"]);
|
|
51
51
|
assertZonedDatetime("datetime", args.datetime, args.timezone);
|
|
@@ -51,7 +51,7 @@ registerTool({
|
|
|
51
51
|
additionalProperties: false,
|
|
52
52
|
},
|
|
53
53
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
54
|
-
annotations: { title: "Davison Relationship Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
54
|
+
annotations: { title: "Davison Relationship Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
55
55
|
handler: async (args) => {
|
|
56
56
|
validateRequired(args, [
|
|
57
57
|
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
@@ -99,7 +99,7 @@ registerTool({
|
|
|
99
99
|
additionalProperties: false,
|
|
100
100
|
},
|
|
101
101
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
102
|
-
annotations: { title: "Midpoint Composite Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
102
|
+
annotations: { title: "Midpoint Composite Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
103
103
|
handler: async (args) => {
|
|
104
104
|
validateRequired(args, [
|
|
105
105
|
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
@@ -147,7 +147,7 @@ registerTool({
|
|
|
147
147
|
additionalProperties: false,
|
|
148
148
|
},
|
|
149
149
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
150
|
-
annotations: { title: "Synastry House Overlay", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
150
|
+
annotations: { title: "Synastry House Overlay", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
151
151
|
handler: async (args) => {
|
|
152
152
|
validateRequired(args, [
|
|
153
153
|
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
@@ -193,7 +193,7 @@ registerTool({
|
|
|
193
193
|
additionalProperties: false,
|
|
194
194
|
},
|
|
195
195
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
196
|
-
annotations: { title: "Transits to Natal Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
196
|
+
annotations: { title: "Transits to Natal Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
197
197
|
handler: async (args) => {
|
|
198
198
|
validateRequired(args, ["natal_datetime", "natal_latitude", "natal_longitude"]);
|
|
199
199
|
assertPersonZoned("natal", args);
|
|
@@ -42,7 +42,7 @@ registerTool({
|
|
|
42
42
|
additionalProperties: false,
|
|
43
43
|
},
|
|
44
44
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
45
|
-
annotations: { title: "Eclipse Finder", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
45
|
+
annotations: { title: "Eclipse Finder", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
46
46
|
handler: async (args) => {
|
|
47
47
|
validateRequired(args, ["eclipse_type"]);
|
|
48
48
|
validateCoordinates(args, "latitude", "longitude");
|
|
@@ -59,7 +59,7 @@ registerTool({
|
|
|
59
59
|
additionalProperties: false,
|
|
60
60
|
},
|
|
61
61
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
62
|
-
annotations: { title: "Electional Timing Window", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
62
|
+
annotations: { title: "Electional Timing Window", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
63
63
|
handler: async (args) => {
|
|
64
64
|
validateRequired(args, ["start_date", "end_date", "latitude", "longitude"]);
|
|
65
65
|
const query = {
|
|
@@ -110,7 +110,7 @@ registerTool({
|
|
|
110
110
|
additionalProperties: false,
|
|
111
111
|
},
|
|
112
112
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
113
|
-
annotations: { title: "Moment Quality Analysis", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
113
|
+
annotations: { title: "Moment Quality Analysis", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
114
114
|
handler: async (args) => {
|
|
115
115
|
const query = {};
|
|
116
116
|
if (args.date)
|
|
@@ -164,7 +164,7 @@ registerTool({
|
|
|
164
164
|
additionalProperties: false,
|
|
165
165
|
},
|
|
166
166
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
167
|
-
annotations: { title: "Retrograde Station Tracker", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
167
|
+
annotations: { title: "Retrograde Station Tracker", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
168
168
|
handler: async (args) => {
|
|
169
169
|
const query = {};
|
|
170
170
|
// Map human-readable planet names to IDs if needed
|
|
@@ -224,7 +224,7 @@ registerTool({
|
|
|
224
224
|
additionalProperties: false,
|
|
225
225
|
},
|
|
226
226
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
227
|
-
annotations: { title: "Active Aspects Search", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
227
|
+
annotations: { title: "Active Aspects Search", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
228
228
|
handler: async (args) => {
|
|
229
229
|
const query = {};
|
|
230
230
|
if (args.date)
|
|
@@ -302,7 +302,7 @@ registerTool({
|
|
|
302
302
|
additionalProperties: false,
|
|
303
303
|
},
|
|
304
304
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
305
|
-
annotations: { title: "Angle Crossing Search", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
305
|
+
annotations: { title: "Angle Crossing Search", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
306
306
|
handler: async (args) => {
|
|
307
307
|
validateRequired(args, ["latitude", "longitude"]);
|
|
308
308
|
const query = {
|
|
@@ -40,7 +40,7 @@ registerTool({
|
|
|
40
40
|
additionalProperties: false,
|
|
41
41
|
},
|
|
42
42
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
43
|
-
annotations: { title: "Planet Position", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
43
|
+
annotations: { title: "Planet Position", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
44
44
|
handler: async (args) => {
|
|
45
45
|
validateRequired(args, ["planet_id", "datetime"]);
|
|
46
46
|
const body = {
|
|
@@ -89,7 +89,7 @@ registerTool({
|
|
|
89
89
|
additionalProperties: false,
|
|
90
90
|
},
|
|
91
91
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
92
|
-
annotations: { title: "House Cusps", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
92
|
+
annotations: { title: "House Cusps", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
93
93
|
handler: async (args) => {
|
|
94
94
|
validateRequired(args, ["datetime", "latitude", "longitude"]);
|
|
95
95
|
const body = {
|
|
@@ -56,7 +56,7 @@ registerTool({
|
|
|
56
56
|
additionalProperties: false,
|
|
57
57
|
},
|
|
58
58
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
59
|
-
annotations: { title: "Natal Batch Charts", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
59
|
+
annotations: { title: "Natal Batch Charts", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
60
60
|
handler: async (args) => {
|
|
61
61
|
validateRequired(args, ["subjects"]);
|
|
62
62
|
args.subjects.forEach((s, i) => assertZonedDatetime(`subjects[${i}].datetime`, s?.datetime, s?.timezone, `subjects[${i}].timezone`));
|
|
@@ -82,7 +82,7 @@ registerTool({
|
|
|
82
82
|
additionalProperties: false,
|
|
83
83
|
},
|
|
84
84
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
85
|
-
annotations: { title: "Essential Dignities", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
85
|
+
annotations: { title: "Essential Dignities", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
86
86
|
handler: async (args) => {
|
|
87
87
|
validateRequired(args, ["datetime"]);
|
|
88
88
|
return await getActiveClient().post("/ephemeris/dignities", {
|
|
@@ -122,7 +122,7 @@ registerTool({
|
|
|
122
122
|
additionalProperties: false,
|
|
123
123
|
},
|
|
124
124
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
125
|
-
annotations: { title: "Retrograde Status", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
125
|
+
annotations: { title: "Retrograde Status", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
126
126
|
handler: async (args) => {
|
|
127
127
|
validateRequired(args, ["datetime"]);
|
|
128
128
|
const client = getActiveClient();
|
|
@@ -173,7 +173,7 @@ registerTool({
|
|
|
173
173
|
additionalProperties: false,
|
|
174
174
|
},
|
|
175
175
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
176
|
-
annotations: { title: "Midpoints", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
176
|
+
annotations: { title: "Midpoints", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
177
177
|
handler: async (args) => {
|
|
178
178
|
validateRequired(args, ["datetime", "latitude", "longitude"]);
|
|
179
179
|
return await getActiveClient().post("/ephemeris/midpoints", {
|
|
@@ -219,7 +219,7 @@ registerTool({
|
|
|
219
219
|
additionalProperties: false,
|
|
220
220
|
},
|
|
221
221
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
222
|
-
annotations: { title: "Fixed Stars", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
222
|
+
annotations: { title: "Fixed Stars", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
223
223
|
handler: async (args) => {
|
|
224
224
|
validateRequired(args, ["datetime"]);
|
|
225
225
|
// A lone latitude would silently drop the angles from the scan, which is
|
|
@@ -262,7 +262,7 @@ registerTool({
|
|
|
262
262
|
additionalProperties: false,
|
|
263
263
|
},
|
|
264
264
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
265
|
-
annotations: { title: "Hermetic Lots", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
265
|
+
annotations: { title: "Hermetic Lots", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
266
266
|
handler: async (args) => {
|
|
267
267
|
validateRequired(args, ["datetime", "latitude", "longitude"]);
|
|
268
268
|
return await getActiveClient().post("/ephemeris/hermetic-lots", {
|
|
@@ -290,7 +290,7 @@ registerTool({
|
|
|
290
290
|
additionalProperties: false,
|
|
291
291
|
},
|
|
292
292
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
293
|
-
annotations: { title: "Angles & Points", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
293
|
+
annotations: { title: "Angles & Points", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
294
294
|
handler: async (args) => {
|
|
295
295
|
validateRequired(args, ["datetime", "latitude", "longitude"]);
|
|
296
296
|
return await getActiveClient().post("/ephemeris/angles-points", {
|
|
@@ -319,7 +319,7 @@ registerTool({
|
|
|
319
319
|
additionalProperties: false,
|
|
320
320
|
},
|
|
321
321
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
322
|
-
annotations: { title: "Aspect Check", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
322
|
+
annotations: { title: "Aspect Check", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
323
323
|
handler: async (args) => {
|
|
324
324
|
validateRequired(args, ["longitude_1", "longitude_2"]);
|
|
325
325
|
// Backend field names are longitude1 / longitude2 (no underscore)
|
|
@@ -49,7 +49,7 @@ registerTool({
|
|
|
49
49
|
additionalProperties: false,
|
|
50
50
|
},
|
|
51
51
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
52
|
-
annotations: { title: "Human Design Bodygraph", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
52
|
+
annotations: { title: "Human Design Bodygraph", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
53
53
|
handler: async (args) => {
|
|
54
54
|
validateRequired(args, ["datetime"]);
|
|
55
55
|
const body = {
|
|
@@ -58,7 +58,7 @@ registerTool({
|
|
|
58
58
|
additionalProperties: false,
|
|
59
59
|
},
|
|
60
60
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
61
|
-
annotations: { title: "HD Planetary Return", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
61
|
+
annotations: { title: "HD Planetary Return", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
62
62
|
handler: async (args) => {
|
|
63
63
|
validateRequired(args, ["planet", "datetime", "return_year"]);
|
|
64
64
|
return await getActiveClient().request("POST", "/human-design/cycles/return", {
|
|
@@ -112,7 +112,7 @@ registerTool({
|
|
|
112
112
|
additionalProperties: false,
|
|
113
113
|
},
|
|
114
114
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
115
|
-
annotations: { title: "HD Opposition Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
115
|
+
annotations: { title: "HD Opposition Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
116
116
|
handler: async (args) => {
|
|
117
117
|
validateRequired(args, ["planet", "datetime", "target_year"]);
|
|
118
118
|
return await getActiveClient().request("POST", "/human-design/cycles/opposition", {
|
|
@@ -53,7 +53,7 @@ registerTool({
|
|
|
53
53
|
additionalProperties: false,
|
|
54
54
|
},
|
|
55
55
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
56
|
-
annotations: { title: "HD Composite Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
56
|
+
annotations: { title: "HD Composite Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
57
57
|
handler: async (args) => {
|
|
58
58
|
validateRequired(args, ["person_a_datetime", "person_b_datetime"]);
|
|
59
59
|
const body = {
|
|
@@ -123,7 +123,7 @@ registerTool({
|
|
|
123
123
|
additionalProperties: false,
|
|
124
124
|
},
|
|
125
125
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
126
|
-
annotations: { title: "HD Penta Group Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
126
|
+
annotations: { title: "HD Penta Group Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
127
127
|
handler: async (args) => {
|
|
128
128
|
validateRequired(args, ["group_name", "members"]);
|
|
129
129
|
const members = await Promise.all(args.members.map(async (m, i) => ({
|
|
@@ -62,7 +62,7 @@ registerTool({
|
|
|
62
62
|
additionalProperties: false,
|
|
63
63
|
},
|
|
64
64
|
outputSchema: OUTPUT_SCHEMA_IMAGE_AND_JSON,
|
|
65
|
-
annotations: { title: "Human Design Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
65
|
+
annotations: { title: "Human Design Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
66
66
|
handler: async (args) => {
|
|
67
67
|
validateRequired(args, ["datetime"]);
|
|
68
68
|
const body = {
|
|
@@ -39,7 +39,7 @@ registerTool({
|
|
|
39
39
|
additionalProperties: false,
|
|
40
40
|
},
|
|
41
41
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
42
|
-
annotations: { title: "Moon Phase", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
42
|
+
annotations: { title: "Moon Phase", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
43
43
|
handler: async (args) => {
|
|
44
44
|
validateCoordinates(args, "latitude", "longitude");
|
|
45
45
|
const params = {};
|
|
@@ -104,7 +104,7 @@ registerTool({
|
|
|
104
104
|
additionalProperties: false,
|
|
105
105
|
},
|
|
106
106
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
107
|
-
annotations: { title: "Next Lunar Phase", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
107
|
+
annotations: { title: "Next Lunar Phase", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
108
108
|
handler: async (args) => {
|
|
109
109
|
const PHASE_LABELS = {
|
|
110
110
|
new_moon: "New Moon",
|
|
@@ -73,7 +73,7 @@ registerTool({
|
|
|
73
73
|
additionalProperties: false,
|
|
74
74
|
},
|
|
75
75
|
outputSchema: OUTPUT_SCHEMA_IMAGE_AND_JSON,
|
|
76
|
-
annotations: { title: "Natal Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
76
|
+
annotations: { title: "Natal Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
77
77
|
handler: async (args) => {
|
|
78
78
|
validateRequired(args, ["datetime", "latitude", "longitude"]);
|
|
79
79
|
assertZonedDatetime("datetime", args.datetime, args.timezone);
|
|
@@ -60,7 +60,7 @@ registerTool({
|
|
|
60
60
|
additionalProperties: false,
|
|
61
61
|
},
|
|
62
62
|
outputSchema: OUTPUT_SCHEMA_IMAGE_AND_JSON,
|
|
63
|
-
annotations: { title: "Progressed Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
63
|
+
annotations: { title: "Progressed Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
64
64
|
handler: async (args) => {
|
|
65
65
|
validateRequired(args, ["birth_datetime", "birth_latitude", "birth_longitude", "target_datetime"]);
|
|
66
66
|
assertZonedDatetime("birth_datetime", args.birth_datetime, args.timezone);
|
|
@@ -51,7 +51,7 @@ registerTool({
|
|
|
51
51
|
additionalProperties: false,
|
|
52
52
|
},
|
|
53
53
|
outputSchema: OUTPUT_SCHEMA_JSON,
|
|
54
|
-
annotations: { title: "Relocation Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
|
|
54
|
+
annotations: { title: "Relocation Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
55
55
|
handler: async (args) => {
|
|
56
56
|
validateRequired(args, ["natal_datetime", "natal_latitude", "natal_longitude", "relocation_latitude", "relocation_longitude"]);
|
|
57
57
|
assertZonedDatetime("natal_datetime", args.natal_datetime, args.timezone);
|