@openephemeris/mcp-server 4.14.1 → 4.14.3
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
CHANGED
|
@@ -7,6 +7,47 @@ Version numbering follows [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [4.14.3] — 2026-09-02
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **`ephemeris_transits` silently dropped requested `asc`/`mc`/`dsc`/`ic` natal points.** The tool
|
|
14
|
+
matched `natal_points` against `/ephemeris/natal-chart`'s angle field names
|
|
15
|
+
(`ascendant`/`midheaven`/`descendant`/`imum_coeli`), which never matched the short forms the
|
|
16
|
+
tool itself documents — so a search for transits to the Ascendant silently returned zero hits,
|
|
17
|
+
with `success: true` and no indication anything was dropped. Added alias resolution both ways,
|
|
18
|
+
plus an `unresolved_points` field so a genuine mismatch surfaces instead of hiding.
|
|
19
|
+
- **`ephemeris_progressed_chart` hardcoded `subject.name` to `"Progressed Subject"`** on both the
|
|
20
|
+
natal and progressed blocks of the response, so no consumer could tell them apart by name. Now
|
|
21
|
+
an optional `name` argument, defaulting to a neutral label.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- `/ephemeris/progressed` responses now include `metadata.angle_method`
|
|
25
|
+
(`chart_for_progressed_moment` or `solar_arc_directed`), naming which algorithm produced the
|
|
26
|
+
progressed angles — previously undeclared and silently implied by
|
|
27
|
+
`progression_options.method`, which only ever described planetary progression.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## [4.14.2] — 2026-09-01
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
- **Two `CREDIT COST` figures baked into live tool descriptions were wrong** —
|
|
35
|
+
not just stale plugin docs, the actual strings Claude reads before deciding
|
|
36
|
+
to call a tool. `ephemeris_transits` claimed 6 credits (the real cost, per
|
|
37
|
+
the `/predictive/` billing tier, is 5); `acg_hits` claimed 15 (it falls to
|
|
38
|
+
the generic `/acg/` tier, which is 10 — the 15/20 figures belong to the
|
|
39
|
+
heatmap and relational-parans routes only). Verified directly against
|
|
40
|
+
`usage_meter.go` rather than the description strings themselves, since
|
|
41
|
+
those turned out to be the thing that was wrong.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
- Plugin marketing copy no longer leads with "sub-arcsecond" or "JPL DE440"
|
|
45
|
+
— reframed around the more concrete fact that this runs on NASA
|
|
46
|
+
mission-grade planetary data. The technical terms stay as backup detail
|
|
47
|
+
for readers who want them, not the opening line.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
10
51
|
## [4.14.1] — 2026-09-01
|
|
11
52
|
|
|
12
53
|
### Fixed
|
|
@@ -109,7 +109,7 @@ registerTool({
|
|
|
109
109
|
"✅ USE THIS TOOL FOR: 'Is [city] good for me?', 'What planets affect me in Tokyo?', " +
|
|
110
110
|
"'What ACG lines run through Paris for my chart?', 'Which cities are under my Jupiter line?'\n" +
|
|
111
111
|
"❌ NOT FOR: Full global map geometry → use acg_power_lines for that instead.\n\n" +
|
|
112
|
-
"CREDIT COST:
|
|
112
|
+
"CREDIT COST: 10 credits per call.\n\n" +
|
|
113
113
|
"EXAMPLE: All ACG lines within 3° of Paris for a chart born 1990-04-15 in Chicago:\n" +
|
|
114
114
|
" birth_datetime='1990-04-15T14:30:00', timezone='America/Chicago',\n" +
|
|
115
115
|
" birth_latitude=41.8781, birth_longitude=-87.6298,\n" +
|
|
@@ -36,6 +36,10 @@ registerTool({
|
|
|
36
36
|
enum: ["secondary", "solar_arc", "tertiary"],
|
|
37
37
|
description: "Progression method. Defaults to 'secondary' (1 day = 1 year).",
|
|
38
38
|
},
|
|
39
|
+
name: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description: "Optional label for the subject, echoed back in both natal_subject and progressed_subject. Defaults to a generic label if omitted.",
|
|
42
|
+
},
|
|
39
43
|
include_aspects: {
|
|
40
44
|
type: "boolean",
|
|
41
45
|
description: "Whether to include aspect grid in the response. Default false.",
|
|
@@ -67,7 +71,10 @@ registerTool({
|
|
|
67
71
|
assertZonedDatetime("target_datetime", args.target_datetime);
|
|
68
72
|
const body = {
|
|
69
73
|
subject: {
|
|
70
|
-
name
|
|
74
|
+
// Echoed verbatim into both natal_subject.name and progressed_subject.name
|
|
75
|
+
// by the API (same person, two instants) — never a role-specific label
|
|
76
|
+
// like "Progressed Subject", which would be wrong on the natal block.
|
|
77
|
+
name: args.name || "Subject",
|
|
71
78
|
birth_datetime: { iso: args.birth_datetime },
|
|
72
79
|
birth_location: {
|
|
73
80
|
latitude: { decimal: args.birth_latitude },
|
|
@@ -17,7 +17,7 @@ registerTool({
|
|
|
17
17
|
" Example: Outer planets to natal Sun/Moon → transiting_planets=['saturn','uranus','neptune','pluto'], natal_points=['sun','moon']\n\n" +
|
|
18
18
|
"DEFAULT natal_points (when omitted): sun, moon, mercury, venus, mars, jupiter, saturn.\n" +
|
|
19
19
|
"SEARCH RANGE LIMITS: Explorer/PayG tier → 1 year max; Pro → 5 years; Startup → 10 years.\n" +
|
|
20
|
-
"CREDIT COST:
|
|
20
|
+
"CREDIT COST: 5 credits per call.",
|
|
21
21
|
inputSchema: {
|
|
22
22
|
type: "object",
|
|
23
23
|
properties: {
|
|
@@ -96,6 +96,7 @@ registerTool({
|
|
|
96
96
|
const wantedPoints = args.natal_points
|
|
97
97
|
? new Set(args.natal_points.map((p) => p.toLowerCase()))
|
|
98
98
|
: CORE_BODIES_DEFAULT;
|
|
99
|
+
const resolvedPoints = new Set();
|
|
99
100
|
for (const planet of planetArray) {
|
|
100
101
|
const name = (planet.name || planet.id || "").toLowerCase();
|
|
101
102
|
const lon = planet.longitude ?? planet.ecliptic_longitude ?? planet.lon;
|
|
@@ -105,26 +106,54 @@ registerTool({
|
|
|
105
106
|
continue;
|
|
106
107
|
targetDegrees.push(Math.round(lon * 100) / 100);
|
|
107
108
|
natalPositionMap[name] = lon;
|
|
109
|
+
resolvedPoints.add(name);
|
|
108
110
|
}
|
|
109
|
-
// Extract angles (ASC, MC) only when explicitly requested
|
|
111
|
+
// Extract angles (ASC, MC, DSC, IC) only when explicitly requested.
|
|
112
|
+
// /ephemeris/natal-chart names these "ascendant", "midheaven", "descendant",
|
|
113
|
+
// "imum_coeli" — but the short forms below are what this tool documents and
|
|
114
|
+
// what natal_points is usually given as, so map both directions or a caller
|
|
115
|
+
// asking for "asc" silently gets nothing back (no error, no natal_positions
|
|
116
|
+
// entry) even though the point exists in the natal chart.
|
|
110
117
|
if (args.natal_points) {
|
|
118
|
+
const ANGLE_ALIASES = {
|
|
119
|
+
ascendant: "asc",
|
|
120
|
+
asc: "ascendant",
|
|
121
|
+
midheaven: "mc",
|
|
122
|
+
mc: "midheaven",
|
|
123
|
+
descendant: "dsc",
|
|
124
|
+
dsc: "descendant",
|
|
125
|
+
desc: "descendant",
|
|
126
|
+
imum_coeli: "ic",
|
|
127
|
+
ic: "imum_coeli",
|
|
128
|
+
};
|
|
111
129
|
const angles = natalResult?.angles || natalResult?.data?.angles;
|
|
112
130
|
if (angles) {
|
|
113
131
|
const angleEntries = Array.isArray(angles)
|
|
114
132
|
? angles
|
|
115
133
|
: Object.entries(angles).map(([k, v]) => ({ name: k, ...(typeof v === "object" ? v : { longitude: v }) }));
|
|
116
134
|
for (const angle of angleEntries) {
|
|
117
|
-
const
|
|
135
|
+
const apiName = (angle.name || angle.id || "").toLowerCase();
|
|
118
136
|
const lon = angle.longitude ?? angle.ecliptic_longitude ?? angle.lon;
|
|
119
137
|
if (typeof lon !== "number" || !isFinite(lon))
|
|
120
138
|
continue;
|
|
121
|
-
|
|
139
|
+
const matchedAs = wantedPoints.has(apiName)
|
|
140
|
+
? apiName
|
|
141
|
+
: (ANGLE_ALIASES[apiName] && wantedPoints.has(ANGLE_ALIASES[apiName]))
|
|
142
|
+
? ANGLE_ALIASES[apiName]
|
|
143
|
+
: null;
|
|
144
|
+
if (!matchedAs)
|
|
122
145
|
continue;
|
|
123
146
|
targetDegrees.push(Math.round(lon * 100) / 100);
|
|
124
|
-
natalPositionMap[
|
|
147
|
+
natalPositionMap[matchedAs] = lon;
|
|
148
|
+
resolvedPoints.add(matchedAs);
|
|
125
149
|
}
|
|
126
150
|
}
|
|
127
151
|
}
|
|
152
|
+
// Any requested point that never turned up in natal-chart planets or angles —
|
|
153
|
+
// surface it instead of silently returning fewer targets than asked for.
|
|
154
|
+
const unresolvedPoints = args.natal_points
|
|
155
|
+
? args.natal_points.filter((p) => !resolvedPoints.has(p.toLowerCase()))
|
|
156
|
+
: [];
|
|
128
157
|
// Hard cap: never send more than 12 target degrees
|
|
129
158
|
const MAX_TARGETS = 12;
|
|
130
159
|
if (targetDegrees.length > MAX_TARGETS) {
|
|
@@ -162,6 +191,7 @@ registerTool({
|
|
|
162
191
|
// Return combined context so the LLM knows what natal positions were targeted
|
|
163
192
|
return {
|
|
164
193
|
natal_positions: natalPositionMap,
|
|
194
|
+
...(unresolvedPoints.length > 0 ? { unresolved_points: unresolvedPoints } : {}),
|
|
165
195
|
target_degrees_used: effectiveTargets,
|
|
166
196
|
aspect_angle: args.aspect_angle ?? 0,
|
|
167
197
|
transit_results: transitResult,
|