@openephemeris/mcp-server 3.2.13 → 3.3.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 +2 -2
- package/dist/tools/index.js +8 -0
- package/dist/tools/specialized/acg.d.ts +1 -0
- package/dist/tools/specialized/acg.js +143 -0
- package/dist/tools/specialized/comparative.d.ts +1 -0
- package/dist/tools/specialized/comparative.js +153 -0
- package/dist/tools/specialized/electional.js +178 -0
- package/dist/tools/specialized/ephemeris_core.d.ts +1 -0
- package/dist/tools/specialized/ephemeris_core.js +93 -0
- package/dist/tools/specialized/ephemeris_extended.d.ts +1 -0
- package/dist/tools/specialized/ephemeris_extended.js +234 -0
- package/dist/tools/specialized/hd_group.d.ts +1 -0
- package/dist/tools/specialized/hd_group.js +107 -0
- package/dist/tools/specialized/progressed.d.ts +1 -0
- package/dist/tools/specialized/progressed.js +65 -0
- package/dist/tools/specialized/returns.js +67 -49
- package/dist/tools/specialized/venus_star_points.d.ts +1 -0
- package/dist/tools/specialized/venus_star_points.js +187 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -179,8 +179,8 @@ Generated by `npm run sync:readme` from `config/dev-allowlist.json` and the live
|
|
|
179
179
|
|
|
180
180
|
- Allowlisted operations: **97**
|
|
181
181
|
- Methods: `GET=41`, `POST=56`, `PUT=0`, `PATCH=0`, `DELETE=0`
|
|
182
|
-
- Registered tools (`OPENEPHEMERIS_PROFILE=dev`): **
|
|
183
|
-
- Typed tools: `auth_login`, `auth_logout`, `auth_status`, `chinese_bazi`, `dev_call`, `dev_list_allowed`, `ephemeris_bi_wheel`, `ephemeris_chart_wheel`, `ephemeris_electional`, `ephemeris_moon_phase`, `ephemeris_natal_chart`, `ephemeris_next_eclipse`, `ephemeris_relocation`, `ephemeris_synastry`, `ephemeris_transits`, `human_design_chart`, `vedic_chart`
|
|
182
|
+
- Registered tools (`OPENEPHEMERIS_PROFILE=dev`): **49**
|
|
183
|
+
- Typed tools: `acg_hits`, `acg_power_lines`, `auth_login`, `auth_logout`, `auth_status`, `chinese_bazi`, `dev_call`, `dev_list_allowed`, `electional_aspect_search`, `electional_ingress_calendar`, `electional_moment_analysis`, `electional_station_tracker`, `ephemeris_angles_points`, `ephemeris_aspect_check`, `ephemeris_bi_wheel`, `ephemeris_chart_wheel`, `ephemeris_composite`, `ephemeris_composite_midpoint`, `ephemeris_dignities`, `ephemeris_electional`, `ephemeris_fixed_stars`, `ephemeris_hermetic_lots`, `ephemeris_house_cusps`, `ephemeris_lunar_return`, `ephemeris_midpoints`, `ephemeris_moon_phase`, `ephemeris_natal_batch`, `ephemeris_natal_chart`, `ephemeris_natal_transits`, `ephemeris_next_eclipse`, `ephemeris_overlay`, `ephemeris_planet_position`, `ephemeris_planetary_return`, `ephemeris_progressed_chart`, `ephemeris_relocation`, `ephemeris_retrograde_status`, `ephemeris_solar_return`, `ephemeris_synastry`, `ephemeris_transits`, `human_design_chart`, `human_design_composite`, `human_design_penta`, `vedic_chart`, `venus_eight_year_star`, `venus_elongations`, `venus_phase`, `venus_star_points`, `venus_star_points_conjunctions`, `venus_stations`
|
|
184
184
|
- Generic tools:
|
|
185
185
|
|
|
186
186
|
### Allowlist Families
|
package/dist/tools/index.js
CHANGED
|
@@ -33,6 +33,14 @@ export async function initTools(profile) {
|
|
|
33
33
|
await import("./specialized/bazi.js");
|
|
34
34
|
await import("./specialized/chart_wheel.js");
|
|
35
35
|
await import("./specialized/bi_wheel.js");
|
|
36
|
+
await import("./specialized/returns.js");
|
|
37
|
+
await import("./specialized/progressed.js");
|
|
38
|
+
await import("./specialized/ephemeris_core.js");
|
|
39
|
+
await import("./specialized/acg.js");
|
|
40
|
+
await import("./specialized/comparative.js");
|
|
41
|
+
await import("./specialized/hd_group.js");
|
|
42
|
+
await import("./specialized/ephemeris_extended.js");
|
|
43
|
+
await import("./specialized/venus_star_points.js");
|
|
36
44
|
}
|
|
37
45
|
}
|
|
38
46
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { registerTool, validateRequired } from "../index.js";
|
|
2
|
+
import { backendClient } from "../../backend/client.js";
|
|
3
|
+
const ACG_BODY_DESCRIPTION = "List of celestial bodies for line calculation. " +
|
|
4
|
+
"E.g. ['Sun', 'Moon', 'Venus', 'Mars', 'Jupiter', 'Saturn']. " +
|
|
5
|
+
"Aliases: 'NorthNode'/'Node'/'Rahu' → MeanNode, 'SouthNode'/'Ketu' → SouthNode. " +
|
|
6
|
+
"Omit to use all classical planets.";
|
|
7
|
+
// POST /acg/power-lines — OE-018
|
|
8
|
+
registerTool({
|
|
9
|
+
name: "acg_power_lines",
|
|
10
|
+
description: "Calculate Astrocartography power lines (MC, IC, AC/ASC, DC/DSC) for a natal chart. " +
|
|
11
|
+
"Returns GeoJSON LineStrings tracing each planetary angle line around the globe. " +
|
|
12
|
+
"These are the latitudinal lines where a planet was rising (AC), setting (DC), " +
|
|
13
|
+
"culminating (MC), or anti-culminating (IC) at birth.\n\n" +
|
|
14
|
+
"CREDIT COST: 5 credits per call.\n\n" +
|
|
15
|
+
"EXAMPLE: Saturn and Jupiter power lines for a chart born 1990-04-15 in Chicago:\n" +
|
|
16
|
+
" birth_datetime='1990-04-15T14:30:00', birth_latitude=41.8781, birth_longitude=-87.6298,\n" +
|
|
17
|
+
" bodies=['Saturn', 'Jupiter']",
|
|
18
|
+
inputSchema: {
|
|
19
|
+
type: "object",
|
|
20
|
+
properties: {
|
|
21
|
+
birth_datetime: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "ISO 8601 natal birth date/time.",
|
|
24
|
+
},
|
|
25
|
+
birth_latitude: {
|
|
26
|
+
type: "number",
|
|
27
|
+
description: "Birth latitude in decimal degrees.",
|
|
28
|
+
},
|
|
29
|
+
birth_longitude: {
|
|
30
|
+
type: "number",
|
|
31
|
+
description: "Birth longitude in decimal degrees.",
|
|
32
|
+
},
|
|
33
|
+
bodies: {
|
|
34
|
+
type: "array",
|
|
35
|
+
items: { type: "string" },
|
|
36
|
+
description: ACG_BODY_DESCRIPTION,
|
|
37
|
+
},
|
|
38
|
+
query_latitude: {
|
|
39
|
+
type: "number",
|
|
40
|
+
description: "Filter lines near this latitude (optional, for hits mode).",
|
|
41
|
+
},
|
|
42
|
+
query_longitude: {
|
|
43
|
+
type: "number",
|
|
44
|
+
description: "Filter lines near this longitude (optional, for hits mode).",
|
|
45
|
+
},
|
|
46
|
+
radius_deg: {
|
|
47
|
+
type: "number",
|
|
48
|
+
description: "Search radius in degrees for hits filtering. Default 2°.",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
required: ["birth_datetime", "birth_latitude", "birth_longitude"],
|
|
52
|
+
additionalProperties: false,
|
|
53
|
+
},
|
|
54
|
+
handler: async (args) => {
|
|
55
|
+
validateRequired(args, ["birth_datetime", "birth_latitude", "birth_longitude"]);
|
|
56
|
+
const body = {
|
|
57
|
+
natal: {
|
|
58
|
+
birthplace_lat: args.birth_latitude,
|
|
59
|
+
birthplace_lon: args.birth_longitude,
|
|
60
|
+
},
|
|
61
|
+
epoch: args.birth_datetime,
|
|
62
|
+
};
|
|
63
|
+
if (args.bodies)
|
|
64
|
+
body.bodies = args.bodies;
|
|
65
|
+
if (args.query_latitude != null)
|
|
66
|
+
body.query_lat = args.query_latitude;
|
|
67
|
+
if (args.query_longitude != null)
|
|
68
|
+
body.query_lon = args.query_longitude;
|
|
69
|
+
if (args.radius_deg != null)
|
|
70
|
+
body.radius_deg = args.radius_deg;
|
|
71
|
+
return await backendClient.post("/acg/power-lines", body);
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
// POST /acg/hits — OE-018
|
|
75
|
+
registerTool({
|
|
76
|
+
name: "acg_hits",
|
|
77
|
+
description: "Find all Astrocartography lines (power lines + aspect lines) passing near a specific location. " +
|
|
78
|
+
"Returns features sorted by distance, making it easy to interpret planetary influences at a place.\n\n" +
|
|
79
|
+
"CREDIT COST: 5 credits per call.\n\n" +
|
|
80
|
+
"EXAMPLE: All ACG lines within 3° of Paris for a chart born 1990-04-15 in Chicago:\n" +
|
|
81
|
+
" birth_datetime='1990-04-15T14:30:00', birth_latitude=41.8781, birth_longitude=-87.6298,\n" +
|
|
82
|
+
" query_latitude=48.8566, query_longitude=2.3522, radius_deg=3",
|
|
83
|
+
inputSchema: {
|
|
84
|
+
type: "object",
|
|
85
|
+
properties: {
|
|
86
|
+
birth_datetime: {
|
|
87
|
+
type: "string",
|
|
88
|
+
description: "ISO 8601 natal birth date/time.",
|
|
89
|
+
},
|
|
90
|
+
birth_latitude: {
|
|
91
|
+
type: "number",
|
|
92
|
+
description: "Birth latitude in decimal degrees.",
|
|
93
|
+
},
|
|
94
|
+
birth_longitude: {
|
|
95
|
+
type: "number",
|
|
96
|
+
description: "Birth longitude in decimal degrees.",
|
|
97
|
+
},
|
|
98
|
+
query_latitude: {
|
|
99
|
+
type: "number",
|
|
100
|
+
description: "Latitude of the location to check for nearby lines.",
|
|
101
|
+
},
|
|
102
|
+
query_longitude: {
|
|
103
|
+
type: "number",
|
|
104
|
+
description: "Longitude of the location to check for nearby lines.",
|
|
105
|
+
},
|
|
106
|
+
radius_deg: {
|
|
107
|
+
type: "number",
|
|
108
|
+
description: "Search radius in degrees (default 2°, max 90°).",
|
|
109
|
+
},
|
|
110
|
+
bodies: {
|
|
111
|
+
type: "array",
|
|
112
|
+
items: { type: "string" },
|
|
113
|
+
description: ACG_BODY_DESCRIPTION,
|
|
114
|
+
},
|
|
115
|
+
include_aspects: {
|
|
116
|
+
type: "boolean",
|
|
117
|
+
description: "Include aspect lines in results (default true).",
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
required: ["birth_datetime", "birth_latitude", "birth_longitude", "query_latitude", "query_longitude"],
|
|
121
|
+
additionalProperties: false,
|
|
122
|
+
},
|
|
123
|
+
handler: async (args) => {
|
|
124
|
+
validateRequired(args, ["birth_datetime", "birth_latitude", "birth_longitude", "query_latitude", "query_longitude"]);
|
|
125
|
+
const body = {
|
|
126
|
+
natal: {
|
|
127
|
+
birthplace_lat: args.birth_latitude,
|
|
128
|
+
birthplace_lon: args.birth_longitude,
|
|
129
|
+
},
|
|
130
|
+
epoch: args.birth_datetime,
|
|
131
|
+
query_lat: args.query_latitude,
|
|
132
|
+
query_lon: args.query_longitude,
|
|
133
|
+
};
|
|
134
|
+
if (args.bodies)
|
|
135
|
+
body.bodies = args.bodies;
|
|
136
|
+
if (args.radius_deg != null)
|
|
137
|
+
body.radius_deg = args.radius_deg;
|
|
138
|
+
if (args.include_aspects != null) {
|
|
139
|
+
body.options = { include_aspects: args.include_aspects };
|
|
140
|
+
}
|
|
141
|
+
return await backendClient.post("/acg/hits", body);
|
|
142
|
+
},
|
|
143
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { registerTool, validateRequired } from "../index.js";
|
|
2
|
+
import { backendClient } from "../../backend/client.js";
|
|
3
|
+
function buildSubject(name, datetime, lat, lon) {
|
|
4
|
+
return {
|
|
5
|
+
name,
|
|
6
|
+
birth_datetime: { iso: datetime },
|
|
7
|
+
birth_location: {
|
|
8
|
+
latitude: { decimal: lat },
|
|
9
|
+
longitude: { decimal: lon },
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
// POST /comparative/composite
|
|
14
|
+
registerTool({
|
|
15
|
+
name: "ephemeris_composite",
|
|
16
|
+
description: "Calculate a composite chart from two or more natal charts. The composite " +
|
|
17
|
+
"uses midpoints of each planet pair to derive a single relationship chart.\n\n" +
|
|
18
|
+
"CREDIT COST: 3 credits per call.\n\n" +
|
|
19
|
+
"EXAMPLE: Composite for two people:\n" +
|
|
20
|
+
" person_a_datetime='1990-04-15T14:30:00', person_a_latitude=41.88, person_a_longitude=-87.63,\n" +
|
|
21
|
+
" person_b_datetime='1988-09-22T08:15:00', person_b_latitude=34.05, person_b_longitude=-118.24",
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {
|
|
25
|
+
person_a_datetime: { type: "string", description: "Person A birth datetime (ISO 8601)." },
|
|
26
|
+
person_a_latitude: { type: "number", description: "Person A birth latitude." },
|
|
27
|
+
person_a_longitude: { type: "number", description: "Person A birth longitude." },
|
|
28
|
+
person_b_datetime: { type: "string", description: "Person B birth datetime (ISO 8601)." },
|
|
29
|
+
person_b_latitude: { type: "number", description: "Person B birth latitude." },
|
|
30
|
+
person_b_longitude: { type: "number", description: "Person B birth longitude." },
|
|
31
|
+
},
|
|
32
|
+
required: [
|
|
33
|
+
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
34
|
+
"person_b_datetime", "person_b_latitude", "person_b_longitude",
|
|
35
|
+
],
|
|
36
|
+
additionalProperties: false,
|
|
37
|
+
},
|
|
38
|
+
handler: async (args) => {
|
|
39
|
+
validateRequired(args, [
|
|
40
|
+
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
41
|
+
"person_b_datetime", "person_b_latitude", "person_b_longitude",
|
|
42
|
+
]);
|
|
43
|
+
return await backendClient.post("/comparative/composite", {
|
|
44
|
+
subjects: [
|
|
45
|
+
buildSubject("Person A", args.person_a_datetime, args.person_a_latitude, args.person_a_longitude),
|
|
46
|
+
buildSubject("Person B", args.person_b_datetime, args.person_b_latitude, args.person_b_longitude),
|
|
47
|
+
],
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
// POST /comparative/composite/midpoint
|
|
52
|
+
registerTool({
|
|
53
|
+
name: "ephemeris_composite_midpoint",
|
|
54
|
+
description: "Calculate a midpoint composite chart — an alternative composite method " +
|
|
55
|
+
"using the midpoints of matching planet positions.\n\n" +
|
|
56
|
+
"CREDIT COST: 3 credits per call.",
|
|
57
|
+
inputSchema: {
|
|
58
|
+
type: "object",
|
|
59
|
+
properties: {
|
|
60
|
+
person_a_datetime: { type: "string", description: "Person A birth datetime (ISO 8601)." },
|
|
61
|
+
person_a_latitude: { type: "number", description: "Person A birth latitude." },
|
|
62
|
+
person_a_longitude: { type: "number", description: "Person A birth longitude." },
|
|
63
|
+
person_b_datetime: { type: "string", description: "Person B birth datetime (ISO 8601)." },
|
|
64
|
+
person_b_latitude: { type: "number", description: "Person B birth latitude." },
|
|
65
|
+
person_b_longitude: { type: "number", description: "Person B birth longitude." },
|
|
66
|
+
},
|
|
67
|
+
required: [
|
|
68
|
+
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
69
|
+
"person_b_datetime", "person_b_latitude", "person_b_longitude",
|
|
70
|
+
],
|
|
71
|
+
additionalProperties: false,
|
|
72
|
+
},
|
|
73
|
+
handler: async (args) => {
|
|
74
|
+
validateRequired(args, [
|
|
75
|
+
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
76
|
+
"person_b_datetime", "person_b_latitude", "person_b_longitude",
|
|
77
|
+
]);
|
|
78
|
+
return await backendClient.post("/comparative/composite/midpoint", {
|
|
79
|
+
subjects: [
|
|
80
|
+
buildSubject("Person A", args.person_a_datetime, args.person_a_latitude, args.person_a_longitude),
|
|
81
|
+
buildSubject("Person B", args.person_b_datetime, args.person_b_latitude, args.person_b_longitude),
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
// POST /comparative/overlay
|
|
87
|
+
registerTool({
|
|
88
|
+
name: "ephemeris_overlay",
|
|
89
|
+
description: "Calculate an overlay chart — place one person's planets in another person's houses. " +
|
|
90
|
+
"Shows how person A's energies impact person B's life areas and vice versa.\n\n" +
|
|
91
|
+
"CREDIT COST: 3 credits per call.",
|
|
92
|
+
inputSchema: {
|
|
93
|
+
type: "object",
|
|
94
|
+
properties: {
|
|
95
|
+
person_a_datetime: { type: "string", description: "Person A birth datetime (ISO 8601)." },
|
|
96
|
+
person_a_latitude: { type: "number", description: "Person A birth latitude." },
|
|
97
|
+
person_a_longitude: { type: "number", description: "Person A birth longitude." },
|
|
98
|
+
person_b_datetime: { type: "string", description: "Person B birth datetime (ISO 8601)." },
|
|
99
|
+
person_b_latitude: { type: "number", description: "Person B birth latitude." },
|
|
100
|
+
person_b_longitude: { type: "number", description: "Person B birth longitude." },
|
|
101
|
+
},
|
|
102
|
+
required: [
|
|
103
|
+
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
104
|
+
"person_b_datetime", "person_b_latitude", "person_b_longitude",
|
|
105
|
+
],
|
|
106
|
+
additionalProperties: false,
|
|
107
|
+
},
|
|
108
|
+
handler: async (args) => {
|
|
109
|
+
validateRequired(args, [
|
|
110
|
+
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
111
|
+
"person_b_datetime", "person_b_latitude", "person_b_longitude",
|
|
112
|
+
]);
|
|
113
|
+
return await backendClient.post("/comparative/overlay", {
|
|
114
|
+
subjects: [
|
|
115
|
+
buildSubject("Person A", args.person_a_datetime, args.person_a_latitude, args.person_a_longitude),
|
|
116
|
+
buildSubject("Person B", args.person_b_datetime, args.person_b_latitude, args.person_b_longitude),
|
|
117
|
+
],
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
// POST /comparative/natal-transits
|
|
122
|
+
registerTool({
|
|
123
|
+
name: "ephemeris_natal_transits",
|
|
124
|
+
description: "Calculate active transits to a natal chart — shows which current planets " +
|
|
125
|
+
"are aspecting natal positions. Essential for predictive astrology.\n\n" +
|
|
126
|
+
"CREDIT COST: 3 credits per call.\n\n" +
|
|
127
|
+
"EXAMPLE: Current transits to someone born 1990-04-15:\n" +
|
|
128
|
+
" natal_datetime='1990-04-15T14:30:00', natal_latitude=41.88, natal_longitude=-87.63",
|
|
129
|
+
inputSchema: {
|
|
130
|
+
type: "object",
|
|
131
|
+
properties: {
|
|
132
|
+
natal_datetime: { type: "string", description: "Natal birth datetime (ISO 8601)." },
|
|
133
|
+
natal_latitude: { type: "number", description: "Natal birth latitude." },
|
|
134
|
+
natal_longitude: { type: "number", description: "Natal birth longitude." },
|
|
135
|
+
transit_datetime: { type: "string", description: "Transit moment (ISO 8601). Defaults to now." },
|
|
136
|
+
},
|
|
137
|
+
required: ["natal_datetime", "natal_latitude", "natal_longitude"],
|
|
138
|
+
additionalProperties: false,
|
|
139
|
+
},
|
|
140
|
+
handler: async (args) => {
|
|
141
|
+
validateRequired(args, ["natal_datetime", "natal_latitude", "natal_longitude"]);
|
|
142
|
+
const subjects = [
|
|
143
|
+
buildSubject("Natal", args.natal_datetime, args.natal_latitude, args.natal_longitude),
|
|
144
|
+
];
|
|
145
|
+
// The transit subject uses the transit datetime or current time
|
|
146
|
+
if (args.transit_datetime) {
|
|
147
|
+
subjects.push(buildSubject("Transit", args.transit_datetime, args.natal_latitude, args.natal_longitude));
|
|
148
|
+
}
|
|
149
|
+
return await backendClient.post("/comparative/natal-transits", {
|
|
150
|
+
subjects,
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { registerTool, validateRequired } from "../index.js";
|
|
2
2
|
import { backendClient } from "../../backend/client.js";
|
|
3
|
+
// All electional endpoints are GET endpoints with query params.
|
|
4
|
+
// GET /electional/find-window — already existed, keeping it
|
|
3
5
|
registerTool({
|
|
4
6
|
name: "ephemeris_electional",
|
|
5
7
|
description: "Find optimal planetary timing windows (electional astrology). Scans a date range to find the " +
|
|
@@ -78,3 +80,179 @@ registerTool({
|
|
|
78
80
|
});
|
|
79
81
|
},
|
|
80
82
|
});
|
|
83
|
+
// GET /electional/moment-analysis
|
|
84
|
+
registerTool({
|
|
85
|
+
name: "electional_moment_analysis",
|
|
86
|
+
description: "Analyze the astrological quality of a specific moment: planet positions, aspects, " +
|
|
87
|
+
"void of course status, lunar phase, day ruler, and an overall electional score (0-100). " +
|
|
88
|
+
"Perfect for evaluating whether 'right now' or a specific date/time is good for action.\n\n" +
|
|
89
|
+
"CREDIT COST: 2 credits per call.\n\n" +
|
|
90
|
+
"EXAMPLE: Analyze March 21, 2026 at noon:\n" +
|
|
91
|
+
" date='2026-03-21T12:00:00'",
|
|
92
|
+
inputSchema: {
|
|
93
|
+
type: "object",
|
|
94
|
+
properties: {
|
|
95
|
+
date: {
|
|
96
|
+
type: "string",
|
|
97
|
+
description: "ISO 8601 datetime to analyze (e.g., '2026-03-21T12:00:00'). Defaults to now.",
|
|
98
|
+
},
|
|
99
|
+
format: {
|
|
100
|
+
type: "string",
|
|
101
|
+
enum: ["json", "llm"],
|
|
102
|
+
description: "Output format.",
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
required: [],
|
|
106
|
+
additionalProperties: false,
|
|
107
|
+
},
|
|
108
|
+
handler: async (args) => {
|
|
109
|
+
const query = {};
|
|
110
|
+
if (args.date)
|
|
111
|
+
query.date = args.date;
|
|
112
|
+
if (args.format)
|
|
113
|
+
query.format = args.format;
|
|
114
|
+
return await backendClient.request("GET", "/electional/moment-analysis", {
|
|
115
|
+
data: {},
|
|
116
|
+
params: query,
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
// GET /electional/station-tracker
|
|
121
|
+
registerTool({
|
|
122
|
+
name: "electional_station_tracker",
|
|
123
|
+
description: "Find all upcoming retrograde and direct stations for planets in a date range. " +
|
|
124
|
+
"Returns exact station times, longitudes, and signs. Essential for timing around " +
|
|
125
|
+
"Mercury retrograde, Venus retrograde, etc.\n\n" +
|
|
126
|
+
"CREDIT COST: 3 credits per call.\n\n" +
|
|
127
|
+
"EXAMPLE: Stations in the next 3 months:\n" +
|
|
128
|
+
" start_date='2026-03-01', end_date='2026-06-01'",
|
|
129
|
+
inputSchema: {
|
|
130
|
+
type: "object",
|
|
131
|
+
properties: {
|
|
132
|
+
start_date: {
|
|
133
|
+
type: "string",
|
|
134
|
+
description: "Start date (ISO 8601). Defaults to now.",
|
|
135
|
+
},
|
|
136
|
+
end_date: {
|
|
137
|
+
type: "string",
|
|
138
|
+
description: "End date (ISO 8601). Defaults to +90 days.",
|
|
139
|
+
},
|
|
140
|
+
planets: {
|
|
141
|
+
type: "string",
|
|
142
|
+
description: "Comma-separated planet IDs (e.g., '2,3,4'). Defaults to Mercury-Saturn.",
|
|
143
|
+
},
|
|
144
|
+
format: {
|
|
145
|
+
type: "string",
|
|
146
|
+
enum: ["json", "llm"],
|
|
147
|
+
description: "Output format.",
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
required: [],
|
|
151
|
+
additionalProperties: false,
|
|
152
|
+
},
|
|
153
|
+
handler: async (args) => {
|
|
154
|
+
const query = {};
|
|
155
|
+
if (args.start_date)
|
|
156
|
+
query.start_date = args.start_date;
|
|
157
|
+
if (args.end_date)
|
|
158
|
+
query.end_date = args.end_date;
|
|
159
|
+
if (args.planets)
|
|
160
|
+
query.planets = args.planets;
|
|
161
|
+
if (args.format)
|
|
162
|
+
query.format = args.format;
|
|
163
|
+
return await backendClient.request("GET", "/electional/station-tracker", {
|
|
164
|
+
data: {},
|
|
165
|
+
params: query,
|
|
166
|
+
});
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
// GET /electional/ingress-calendar
|
|
170
|
+
registerTool({
|
|
171
|
+
name: "electional_ingress_calendar",
|
|
172
|
+
description: "Get a calendar of sign ingresses — when planets change zodiac signs. " +
|
|
173
|
+
"Returns each ingress event with exact time, from/to signs, and retrograde flag.\n\n" +
|
|
174
|
+
"CREDIT COST: 3 credits per call.\n\n" +
|
|
175
|
+
"EXAMPLE: Ingresses in March 2026:\n" +
|
|
176
|
+
" start_date='2026-03-01', end_date='2026-03-31'",
|
|
177
|
+
inputSchema: {
|
|
178
|
+
type: "object",
|
|
179
|
+
properties: {
|
|
180
|
+
start_date: {
|
|
181
|
+
type: "string",
|
|
182
|
+
description: "Start date (ISO 8601). Defaults to now.",
|
|
183
|
+
},
|
|
184
|
+
end_date: {
|
|
185
|
+
type: "string",
|
|
186
|
+
description: "End date (ISO 8601). Defaults to +30 days.",
|
|
187
|
+
},
|
|
188
|
+
planets: {
|
|
189
|
+
type: "string",
|
|
190
|
+
description: "Comma-separated planet IDs. Defaults to all major planets.",
|
|
191
|
+
},
|
|
192
|
+
format: {
|
|
193
|
+
type: "string",
|
|
194
|
+
enum: ["json", "llm"],
|
|
195
|
+
description: "Output format.",
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
required: [],
|
|
199
|
+
additionalProperties: false,
|
|
200
|
+
},
|
|
201
|
+
handler: async (args) => {
|
|
202
|
+
const query = {};
|
|
203
|
+
if (args.start_date)
|
|
204
|
+
query.start_date = args.start_date;
|
|
205
|
+
if (args.end_date)
|
|
206
|
+
query.end_date = args.end_date;
|
|
207
|
+
if (args.planets)
|
|
208
|
+
query.planets = args.planets;
|
|
209
|
+
if (args.format)
|
|
210
|
+
query.format = args.format;
|
|
211
|
+
return await backendClient.request("GET", "/electional/ingress-calendar", {
|
|
212
|
+
data: {},
|
|
213
|
+
params: query,
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
// GET /electional/aspect-search
|
|
218
|
+
registerTool({
|
|
219
|
+
name: "electional_aspect_search",
|
|
220
|
+
description: "Find all active aspects between planets at a specific moment. Returns aspect type, " +
|
|
221
|
+
"orb, quality score, and whether it's applying or separating. Great for checking " +
|
|
222
|
+
"the 'weather' of a given day.\n\n" +
|
|
223
|
+
"CREDIT COST: 2 credits per call.\n\n" +
|
|
224
|
+
"EXAMPLE: What aspects are active on March 21, 2026?\n" +
|
|
225
|
+
" date='2026-03-21T12:00:00'",
|
|
226
|
+
inputSchema: {
|
|
227
|
+
type: "object",
|
|
228
|
+
properties: {
|
|
229
|
+
date: {
|
|
230
|
+
type: "string",
|
|
231
|
+
description: "ISO 8601 datetime to check. Defaults to now.",
|
|
232
|
+
},
|
|
233
|
+
max_orb: {
|
|
234
|
+
type: "number",
|
|
235
|
+
description: "Maximum orb in degrees. Default uses standard orbs per aspect type.",
|
|
236
|
+
},
|
|
237
|
+
aspects: {
|
|
238
|
+
type: "string",
|
|
239
|
+
description: "Comma-separated aspect types to filter (e.g., 'conjunction,trine,square'). Default all.",
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
required: [],
|
|
243
|
+
additionalProperties: false,
|
|
244
|
+
},
|
|
245
|
+
handler: async (args) => {
|
|
246
|
+
const query = {};
|
|
247
|
+
if (args.date)
|
|
248
|
+
query.date = args.date;
|
|
249
|
+
if (args.max_orb != null)
|
|
250
|
+
query.max_orb = args.max_orb;
|
|
251
|
+
if (args.aspects)
|
|
252
|
+
query.aspects = args.aspects;
|
|
253
|
+
return await backendClient.request("GET", "/electional/aspect-search", {
|
|
254
|
+
data: {},
|
|
255
|
+
params: query,
|
|
256
|
+
});
|
|
257
|
+
},
|
|
258
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { registerTool, validateRequired } from "../index.js";
|
|
2
|
+
import { backendClient } from "../../backend/client.js";
|
|
3
|
+
// POST /ephemeris/planet-position — OE-016
|
|
4
|
+
registerTool({
|
|
5
|
+
name: "ephemeris_planet_position",
|
|
6
|
+
description: "Get the precise ecliptic longitude, latitude, distance, speed, and retrograde status " +
|
|
7
|
+
"for a single planet/body at a given date and time. " +
|
|
8
|
+
"Planet IDs: 0=Sun, 1=Moon, 2=Mercury, 3=Venus, 4=Mars, 5=Jupiter, 6=Saturn, " +
|
|
9
|
+
"7=Uranus, 8=Neptune, 9=Pluto, 10=North Node, 11=South Node, 12=Lilith.\n\n" +
|
|
10
|
+
"CREDIT COST: 1 credit per call.\n\n" +
|
|
11
|
+
"EXAMPLE: Where is Mars on 2026-03-20 at noon UTC?\n" +
|
|
12
|
+
" planet_id=4, datetime='2026-03-20T12:00:00Z'",
|
|
13
|
+
inputSchema: {
|
|
14
|
+
type: "object",
|
|
15
|
+
properties: {
|
|
16
|
+
planet_id: {
|
|
17
|
+
type: "integer",
|
|
18
|
+
description: "Planet/body ID (0=Sun, 1=Moon, 2=Mercury, 3=Venus, 4=Mars, 5=Jupiter, 6=Saturn, 7=Uranus, 8=Neptune, 9=Pluto, 10=MeanNode, 11=TrueNode, 12=Lilith).",
|
|
19
|
+
},
|
|
20
|
+
datetime: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "ISO 8601 date/time (e.g. '2026-03-20T12:00:00Z').",
|
|
23
|
+
},
|
|
24
|
+
latitude: {
|
|
25
|
+
type: "number",
|
|
26
|
+
description: "Observer latitude for topocentric position (optional). Omit for geocentric.",
|
|
27
|
+
},
|
|
28
|
+
longitude: {
|
|
29
|
+
type: "number",
|
|
30
|
+
description: "Observer longitude for topocentric position (optional). Omit for geocentric.",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
required: ["planet_id", "datetime"],
|
|
34
|
+
additionalProperties: false,
|
|
35
|
+
},
|
|
36
|
+
handler: async (args) => {
|
|
37
|
+
validateRequired(args, ["planet_id", "datetime"]);
|
|
38
|
+
const body = {
|
|
39
|
+
planet_id: args.planet_id,
|
|
40
|
+
date_time: { iso: args.datetime },
|
|
41
|
+
};
|
|
42
|
+
if (args.latitude != null)
|
|
43
|
+
body.latitude = args.latitude;
|
|
44
|
+
if (args.longitude != null)
|
|
45
|
+
body.longitude = args.longitude;
|
|
46
|
+
return await backendClient.post("/ephemeris/planet-position", body);
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
// POST /ephemeris/house-cusps — OE-017
|
|
50
|
+
registerTool({
|
|
51
|
+
name: "ephemeris_house_cusps",
|
|
52
|
+
description: "Calculate house cusps and angles (ASC, MC, DSC, IC) for a given date, time, and location " +
|
|
53
|
+
"using one or more house systems.\n\n" +
|
|
54
|
+
"House system codes: P=Placidus, K=Koch, O=Porphyry, R=Regiomontanus, C=Campanus, E=Equal, W=Whole Sign.\n\n" +
|
|
55
|
+
"CREDIT COST: 1 credit per call.\n\n" +
|
|
56
|
+
"EXAMPLE: Placidus houses for London at 2026-03-20 noon UTC:\n" +
|
|
57
|
+
" datetime='2026-03-20T12:00:00Z', latitude=51.5074, longitude=-0.1278, house_systems=['P']",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: {
|
|
61
|
+
datetime: {
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "ISO 8601 date/time.",
|
|
64
|
+
},
|
|
65
|
+
latitude: {
|
|
66
|
+
type: "number",
|
|
67
|
+
description: "Observer latitude in decimal degrees.",
|
|
68
|
+
},
|
|
69
|
+
longitude: {
|
|
70
|
+
type: "number",
|
|
71
|
+
description: "Observer longitude in decimal degrees.",
|
|
72
|
+
},
|
|
73
|
+
house_systems: {
|
|
74
|
+
type: "array",
|
|
75
|
+
items: { type: "string" },
|
|
76
|
+
description: "List of house system codes. E.g. ['P', 'W']. Defaults to ['P'] (Placidus).",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
required: ["datetime", "latitude", "longitude"],
|
|
80
|
+
additionalProperties: false,
|
|
81
|
+
},
|
|
82
|
+
handler: async (args) => {
|
|
83
|
+
validateRequired(args, ["datetime", "latitude", "longitude"]);
|
|
84
|
+
const body = {
|
|
85
|
+
date_time: { iso: args.datetime },
|
|
86
|
+
latitude: args.latitude,
|
|
87
|
+
longitude: args.longitude,
|
|
88
|
+
};
|
|
89
|
+
if (args.house_systems)
|
|
90
|
+
body.house_systems = args.house_systems;
|
|
91
|
+
return await backendClient.post("/ephemeris/house-cusps", body);
|
|
92
|
+
},
|
|
93
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|