@openephemeris/mcp-server 3.3.2 → 3.4.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/dist/backend/client.js
CHANGED
|
@@ -277,6 +277,8 @@ export class BackendClient {
|
|
|
277
277
|
return new BackendError(`Resource not found: ${msg}`, 404, "not_found", false);
|
|
278
278
|
if (status === 400)
|
|
279
279
|
return new BackendError(`Invalid request: ${msg}`, 400, "bad_request", false);
|
|
280
|
+
if (status === 422)
|
|
281
|
+
return new BackendError(`Validation error: ${msg}`, 422, "unprocessable_entity", false);
|
|
280
282
|
if (status >= 500)
|
|
281
283
|
return new BackendError(`Backend error (${status}): ${msg}`, status, "server_error", true);
|
|
282
284
|
}
|
|
@@ -34,6 +34,7 @@ registerTool({
|
|
|
34
34
|
person_b_timezone: { type: "string", description: "IANA timezone name for Person B, e.g. 'Europe/London'." },
|
|
35
35
|
person_b_latitude: { type: "number", description: "Person B birth latitude." },
|
|
36
36
|
person_b_longitude: { type: "number", description: "Person B birth longitude." },
|
|
37
|
+
format: { type: "string", enum: ["json", "llm"], description: "Use 'llm' for token-efficient LLM projection." },
|
|
37
38
|
},
|
|
38
39
|
required: [
|
|
39
40
|
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
@@ -46,11 +47,17 @@ registerTool({
|
|
|
46
47
|
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
47
48
|
"person_b_datetime", "person_b_latitude", "person_b_longitude",
|
|
48
49
|
]);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
const query = {};
|
|
51
|
+
if (args.format)
|
|
52
|
+
query.format = args.format;
|
|
53
|
+
return await backendClient.request("POST", "/comparative/composite", {
|
|
54
|
+
params: query,
|
|
55
|
+
data: {
|
|
56
|
+
subjects: [
|
|
57
|
+
buildSubject("Person A", args.person_a_datetime, args.person_a_latitude, args.person_a_longitude, args.person_a_timezone),
|
|
58
|
+
buildSubject("Person B", args.person_b_datetime, args.person_b_latitude, args.person_b_longitude, args.person_b_timezone),
|
|
59
|
+
],
|
|
60
|
+
}
|
|
54
61
|
});
|
|
55
62
|
},
|
|
56
63
|
});
|
|
@@ -71,6 +78,7 @@ registerTool({
|
|
|
71
78
|
person_b_timezone: { type: "string", description: "IANA timezone name for Person B, e.g. 'Europe/London'." },
|
|
72
79
|
person_b_latitude: { type: "number", description: "Person B birth latitude." },
|
|
73
80
|
person_b_longitude: { type: "number", description: "Person B birth longitude." },
|
|
81
|
+
format: { type: "string", enum: ["json", "llm"], description: "Use 'llm' for token-efficient LLM projection." },
|
|
74
82
|
},
|
|
75
83
|
required: [
|
|
76
84
|
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
@@ -83,11 +91,17 @@ registerTool({
|
|
|
83
91
|
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
84
92
|
"person_b_datetime", "person_b_latitude", "person_b_longitude",
|
|
85
93
|
]);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
94
|
+
const query = {};
|
|
95
|
+
if (args.format)
|
|
96
|
+
query.format = args.format;
|
|
97
|
+
return await backendClient.request("POST", "/comparative/composite/midpoint", {
|
|
98
|
+
params: query,
|
|
99
|
+
data: {
|
|
100
|
+
subjects: [
|
|
101
|
+
buildSubject("Person A", args.person_a_datetime, args.person_a_latitude, args.person_a_longitude, args.person_a_timezone),
|
|
102
|
+
buildSubject("Person B", args.person_b_datetime, args.person_b_latitude, args.person_b_longitude, args.person_b_timezone),
|
|
103
|
+
],
|
|
104
|
+
}
|
|
91
105
|
});
|
|
92
106
|
},
|
|
93
107
|
});
|
|
@@ -108,6 +122,7 @@ registerTool({
|
|
|
108
122
|
person_b_timezone: { type: "string", description: "IANA timezone name for Person B, e.g. 'Europe/London'." },
|
|
109
123
|
person_b_latitude: { type: "number", description: "Person B birth latitude." },
|
|
110
124
|
person_b_longitude: { type: "number", description: "Person B birth longitude." },
|
|
125
|
+
format: { type: "string", enum: ["json", "llm"], description: "Use 'llm' for token-efficient LLM projection." },
|
|
111
126
|
},
|
|
112
127
|
required: [
|
|
113
128
|
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
@@ -120,11 +135,17 @@ registerTool({
|
|
|
120
135
|
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
121
136
|
"person_b_datetime", "person_b_latitude", "person_b_longitude",
|
|
122
137
|
]);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
138
|
+
const query = {};
|
|
139
|
+
if (args.format)
|
|
140
|
+
query.format = args.format;
|
|
141
|
+
return await backendClient.request("POST", "/comparative/overlay", {
|
|
142
|
+
params: query,
|
|
143
|
+
data: {
|
|
144
|
+
subjects: [
|
|
145
|
+
buildSubject("Person A", args.person_a_datetime, args.person_a_latitude, args.person_a_longitude, args.person_a_timezone),
|
|
146
|
+
buildSubject("Person B", args.person_b_datetime, args.person_b_latitude, args.person_b_longitude, args.person_b_timezone),
|
|
147
|
+
],
|
|
148
|
+
}
|
|
128
149
|
});
|
|
129
150
|
},
|
|
130
151
|
});
|
|
@@ -145,6 +166,7 @@ registerTool({
|
|
|
145
166
|
natal_longitude: { type: "number", description: "Natal birth longitude." },
|
|
146
167
|
transit_datetime: { type: "string", description: "Transit moment (ISO 8601). Defaults to now." },
|
|
147
168
|
transit_timezone: { type: "string", description: "IANA timezone name for Transit, e.g. 'America/Denver'. Only applicable if transit_datetime is provided without offset." },
|
|
169
|
+
format: { type: "string", enum: ["json", "llm"], description: "Use 'llm' for token-efficient LLM projection." },
|
|
148
170
|
},
|
|
149
171
|
required: ["natal_datetime", "natal_latitude", "natal_longitude"],
|
|
150
172
|
additionalProperties: false,
|
|
@@ -154,12 +176,15 @@ registerTool({
|
|
|
154
176
|
const subjects = [
|
|
155
177
|
buildSubject("Natal", args.natal_datetime, args.natal_latitude, args.natal_longitude, args.natal_timezone),
|
|
156
178
|
];
|
|
157
|
-
// The transit subject uses the transit datetime or current time
|
|
158
179
|
if (args.transit_datetime) {
|
|
159
180
|
subjects.push(buildSubject("Transit", args.transit_datetime, args.natal_latitude, args.natal_longitude, args.transit_timezone));
|
|
160
181
|
}
|
|
161
|
-
|
|
162
|
-
|
|
182
|
+
const query = {};
|
|
183
|
+
if (args.format)
|
|
184
|
+
query.format = args.format;
|
|
185
|
+
return await backendClient.request("POST", "/comparative/natal-transits", {
|
|
186
|
+
params: query,
|
|
187
|
+
data: { subjects }
|
|
163
188
|
});
|
|
164
189
|
},
|
|
165
190
|
});
|
|
@@ -110,16 +110,19 @@ registerTool({
|
|
|
110
110
|
registerTool({
|
|
111
111
|
name: "ephemeris_planetary_return",
|
|
112
112
|
description: "Calculate a planetary return — when any planet returns to its natal longitude. " +
|
|
113
|
-
"Useful for Jupiter returns (~12 years), Saturn returns (~29 years),
|
|
113
|
+
"Useful for Jupiter returns (~12 years), Saturn returns (~29 years), Chiron returns (~50 years), " +
|
|
114
|
+
"Uranus returns (~84 years), etc.\n\n" +
|
|
114
115
|
"CREDIT COST: 1 credit per call.\n\n" +
|
|
115
116
|
"EXAMPLE: Saturn return for birth 1990-04-15 near year 2019:\n" +
|
|
116
|
-
" body='saturn', birth_datetime='1990-04-15T14:30:00', target_datetime='2019-01-01'"
|
|
117
|
+
" body='saturn', birth_datetime='1990-04-15T14:30:00', target_datetime='2019-01-01'\n" +
|
|
118
|
+
"EXAMPLE: Chiron return for birth 1975-03-10 near age 50:\n" +
|
|
119
|
+
" body='chiron', birth_datetime='1975-03-10T08:00:00', target_datetime='2025-01-01'",
|
|
117
120
|
inputSchema: {
|
|
118
121
|
type: "object",
|
|
119
122
|
properties: {
|
|
120
123
|
body: {
|
|
121
124
|
type: "string",
|
|
122
|
-
description: "Planet name: sun, moon, mercury, venus, mars, jupiter, saturn.",
|
|
125
|
+
description: "Planet name: sun, moon, mercury, venus, mars, jupiter, saturn, uranus, neptune, pluto, chiron, pholus.",
|
|
123
126
|
},
|
|
124
127
|
birth_datetime: {
|
|
125
128
|
type: "string",
|
|
@@ -8,6 +8,13 @@ registerTool({
|
|
|
8
8
|
"finding optimal timing windows.\n\n" +
|
|
9
9
|
"HOW IT WORKS: This tool first calculates the natal chart to extract your actual planetary " +
|
|
10
10
|
"ecliptic longitudes, then searches for transiting planets crossing those exact degrees.\n\n" +
|
|
11
|
+
"ASPECT ANGLES: Use aspect_angle to search for specific aspects to natal positions:\n" +
|
|
12
|
+
" 0 = conjunction/return (default), 180 = opposition, 90 = square, 120 = trine.\n" +
|
|
13
|
+
" Example: Saturn Return → transiting_planets=['saturn'], natal_points=['saturn'], aspect_angle=0\n" +
|
|
14
|
+
" Example: Uranus Opposition → transiting_planets=['uranus'], natal_points=['uranus'], aspect_angle=180\n" +
|
|
15
|
+
" Example: Chiron Return → transiting_planets=['chiron'], natal_points=['chiron'], aspect_angle=0\n\n" +
|
|
16
|
+
"SUPPORTED BODIES: Sun, Moon, Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, " +
|
|
17
|
+
"Pluto, Chiron, Pholus, Ceres, Pallas, Juno, Vesta, MeanNode.\n\n" +
|
|
11
18
|
"CREDIT COST: 6 credits per call (1 for natal + 5 for transit search).\n\n" +
|
|
12
19
|
"EXAMPLE: Find all Saturn transits to the natal Sun/Moon for the next 6 months:\n" +
|
|
13
20
|
" natal_datetime='1990-04-15T14:30:00', natal_latitude=41.8781, natal_longitude=-87.6298,\n" +
|
|
@@ -38,13 +45,19 @@ registerTool({
|
|
|
38
45
|
transiting_planets: {
|
|
39
46
|
type: "array",
|
|
40
47
|
items: { type: "string" },
|
|
41
|
-
description: "List of transiting planet IDs to search. E.g. ['saturn', 'jupiter', 'uranus', 'pluto']. " +
|
|
48
|
+
description: "List of transiting planet IDs to search. E.g. ['saturn', 'jupiter', 'uranus', 'pluto', 'chiron']. " +
|
|
42
49
|
"Omit to search all outer planets.",
|
|
43
50
|
},
|
|
44
51
|
natal_points: {
|
|
45
52
|
type: "array",
|
|
46
53
|
items: { type: "string" },
|
|
47
|
-
description: "Natal point IDs whose exact longitudes should be targeted. E.g. ['sun', 'moon', 'asc', 'mc']. Omit for all core points.",
|
|
54
|
+
description: "Natal point IDs whose exact longitudes should be targeted. E.g. ['sun', 'moon', 'asc', 'mc', 'saturn', 'chiron']. Omit for all core points.",
|
|
55
|
+
},
|
|
56
|
+
aspect_angle: {
|
|
57
|
+
type: "number",
|
|
58
|
+
description: "Aspect angle in degrees to apply to each natal longitude. 0 = conjunction/return (default), " +
|
|
59
|
+
"180 = opposition, 90 = square, 120 = trine. The effective search target becomes " +
|
|
60
|
+
"(natal_longitude + aspect_angle) mod 360.",
|
|
48
61
|
},
|
|
49
62
|
},
|
|
50
63
|
required: ["natal_datetime", "natal_latitude", "natal_longitude", "start_date", "end_date"],
|
|
@@ -119,11 +132,21 @@ registerTool({
|
|
|
119
132
|
};
|
|
120
133
|
if (args.transiting_planets)
|
|
121
134
|
transitBody.planet_names = args.transiting_planets;
|
|
135
|
+
// When aspect_angle is provided, apply offset to compute effective target degrees
|
|
136
|
+
// (natal_lon + aspect_angle) mod 360 for each natal point
|
|
137
|
+
let effectiveTargets = targetDegrees;
|
|
138
|
+
if (typeof args.aspect_angle === "number" && args.aspect_angle !== 0) {
|
|
139
|
+
effectiveTargets = targetDegrees.map((deg) => ((deg + args.aspect_angle) % 360 + 360) % 360);
|
|
140
|
+
transitBody.target_degrees = effectiveTargets;
|
|
141
|
+
// Also include aspect metadata for labeling in results
|
|
142
|
+
transitBody.search_criteria = { aspect_angle: args.aspect_angle };
|
|
143
|
+
}
|
|
122
144
|
const transitResult = await backendClient.request("POST", "/predictive/transits/search", { data: transitBody });
|
|
123
145
|
// Return combined context so the LLM knows what natal positions were targeted
|
|
124
146
|
return {
|
|
125
147
|
natal_positions: natalPositionMap,
|
|
126
|
-
target_degrees_used:
|
|
148
|
+
target_degrees_used: effectiveTargets,
|
|
149
|
+
aspect_angle: args.aspect_angle ?? 0,
|
|
127
150
|
transit_results: transitResult,
|
|
128
151
|
};
|
|
129
152
|
},
|