@openephemeris/mcp-server 3.2.12 → 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/backend/client.d.ts +23 -1
- package/dist/backend/client.js +144 -25
- package/dist/index.js +94 -2
- package/dist/tools/dev.js +29 -21
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +38 -1
- package/dist/tools/specialized/acg.js +143 -0
- package/dist/tools/specialized/comparative.js +153 -0
- package/dist/tools/specialized/eclipse.js +20 -26
- package/dist/tools/specialized/electional.js +182 -3
- package/dist/tools/specialized/ephemeris_core.js +93 -0
- package/dist/tools/specialized/ephemeris_extended.js +234 -0
- package/dist/tools/specialized/hd_group.js +107 -0
- package/dist/tools/specialized/human_design.js +27 -11
- package/dist/tools/specialized/moon.js +3 -2
- package/dist/tools/specialized/natal.js +36 -15
- package/dist/tools/specialized/progressed.js +65 -0
- package/dist/tools/specialized/relocation.js +14 -10
- package/dist/tools/specialized/returns.js +144 -0
- package/dist/tools/specialized/synastry.js +22 -12
- package/dist/tools/specialized/transits.js +78 -28
- package/dist/tools/specialized/venus_star_points.js +187 -0
- package/package.json +4 -3
- package/dist/scripts/dev-allowlist.js +0 -287
- package/dist/scripts/pack-audit.js +0 -45
- package/dist/scripts/schema-packs.js +0 -150
- package/dist/scripts/smoke-dev-profile.js +0 -25
- package/dist/scripts/sync-readme.js +0 -141
- package/dist/scripts/test-all-tools.js +0 -104
- package/dist/scripts/test-client.js +0 -69
- package/dist/scripts/test-sse-client.js +0 -221
- package/dist/src/backend/client.d.ts +0 -67
- package/dist/src/backend/client.js +0 -363
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.js +0 -184
- package/dist/src/schema-packs/llm.d.ts +0 -105
- package/dist/src/schema-packs/llm.js +0 -429
- package/dist/src/tools/dev.d.ts +0 -1
- package/dist/src/tools/dev.js +0 -195
- package/dist/src/tools/index.d.ts +0 -33
- package/dist/src/tools/index.js +0 -60
- package/dist/src/tools/specialized/eclipse.d.ts +0 -1
- package/dist/src/tools/specialized/eclipse.js +0 -50
- package/dist/src/tools/specialized/electional.d.ts +0 -1
- package/dist/src/tools/specialized/electional.js +0 -80
- package/dist/src/tools/specialized/human_design.d.ts +0 -1
- package/dist/src/tools/specialized/human_design.js +0 -69
- package/dist/src/tools/specialized/moon.d.ts +0 -1
- package/dist/src/tools/specialized/moon.js +0 -51
- package/dist/src/tools/specialized/natal.d.ts +0 -1
- package/dist/src/tools/specialized/natal.js +0 -92
- package/dist/src/tools/specialized/relocation.d.ts +0 -1
- package/dist/src/tools/specialized/relocation.js +0 -76
- package/dist/src/tools/specialized/synastry.d.ts +0 -1
- package/dist/src/tools/specialized/synastry.js +0 -73
- package/dist/src/tools/specialized/transits.d.ts +0 -1
- package/dist/src/tools/specialized/transits.js +0 -130
- package/dist/test/allowlist-and-tools.test.d.ts +0 -1
- package/dist/test/allowlist-and-tools.test.js +0 -96
- package/dist/test/backend-client.test.d.ts +0 -1
- package/dist/test/backend-client.test.js +0 -284
- package/dist/test/credentials.test.d.ts +0 -1
- package/dist/test/credentials.test.js +0 -143
- /package/dist/{src/auth → auth}/credentials.d.ts +0 -0
- /package/dist/{src/auth → auth}/credentials.js +0 -0
- /package/dist/{src/auth → auth}/device-auth.d.ts +0 -0
- /package/dist/{src/auth → auth}/device-auth.js +0 -0
- /package/dist/{src/server-sse.d.ts → server-sse.d.ts} +0 -0
- /package/dist/{src/server-sse.js → server-sse.js} +0 -0
- /package/dist/{src/tools → tools}/auth.d.ts +0 -0
- /package/dist/{src/tools → tools}/auth.js +0 -0
- /package/dist/{scripts/dev-allowlist.d.ts → tools/specialized/acg.d.ts} +0 -0
- /package/dist/{src/tools → tools}/specialized/bazi.d.ts +0 -0
- /package/dist/{src/tools → tools}/specialized/bazi.js +0 -0
- /package/dist/{src/tools → tools}/specialized/bi_wheel.d.ts +0 -0
- /package/dist/{src/tools → tools}/specialized/bi_wheel.js +0 -0
- /package/dist/{src/tools → tools}/specialized/chart_wheel.d.ts +0 -0
- /package/dist/{src/tools → tools}/specialized/chart_wheel.js +0 -0
- /package/dist/{scripts/pack-audit.d.ts → tools/specialized/comparative.d.ts} +0 -0
- /package/dist/{scripts/schema-packs.d.ts → tools/specialized/ephemeris_core.d.ts} +0 -0
- /package/dist/{scripts/smoke-dev-profile.d.ts → tools/specialized/ephemeris_extended.d.ts} +0 -0
- /package/dist/{scripts/sync-readme.d.ts → tools/specialized/hd_group.d.ts} +0 -0
- /package/dist/{scripts/test-all-tools.d.ts → tools/specialized/progressed.d.ts} +0 -0
- /package/dist/{scripts/test-client.d.ts → tools/specialized/returns.d.ts} +0 -0
- /package/dist/{src/tools → tools}/specialized/vedic.d.ts +0 -0
- /package/dist/{src/tools → tools}/specialized/vedic.js +0 -0
- /package/dist/{scripts/test-sse-client.d.ts → tools/specialized/venus_star_points.d.ts} +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { registerTool, validateRequired } from "../index.js";
|
|
2
|
+
import { backendClient } from "../../backend/client.js";
|
|
3
|
+
// POST /predictive/returns/solar
|
|
4
|
+
registerTool({
|
|
5
|
+
name: "ephemeris_solar_return",
|
|
6
|
+
description: "Calculate the exact Solar Return date/time — when the Sun returns to its natal ecliptic longitude. " +
|
|
7
|
+
"Used to cast the Solar Return chart for the year ahead.\n\n" +
|
|
8
|
+
"CREDIT COST: 1 credit per call.\n\n" +
|
|
9
|
+
"EXAMPLE: Solar return for someone born 1985-06-21 near their 2026 birthday:\n" +
|
|
10
|
+
" birth_datetime='1985-06-21T14:00:00', target_datetime='2026-06-01'",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: "object",
|
|
13
|
+
properties: {
|
|
14
|
+
birth_datetime: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "ISO 8601 birth date/time (e.g. '1985-06-21T14:00:00').",
|
|
17
|
+
},
|
|
18
|
+
target_datetime: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "Date/time near which to find the Solar Return (ISO 8601). Required.",
|
|
21
|
+
},
|
|
22
|
+
birth_latitude: {
|
|
23
|
+
type: "number",
|
|
24
|
+
description: "Birth latitude in decimal degrees (optional, for location context).",
|
|
25
|
+
},
|
|
26
|
+
birth_longitude: {
|
|
27
|
+
type: "number",
|
|
28
|
+
description: "Birth longitude in decimal degrees (optional, for location context).",
|
|
29
|
+
},
|
|
30
|
+
return_latitude: {
|
|
31
|
+
type: "number",
|
|
32
|
+
description: "Location latitude for the return chart (optional).",
|
|
33
|
+
},
|
|
34
|
+
return_longitude: {
|
|
35
|
+
type: "number",
|
|
36
|
+
description: "Location longitude for the return chart (optional).",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
required: ["birth_datetime", "target_datetime"],
|
|
40
|
+
additionalProperties: false,
|
|
41
|
+
},
|
|
42
|
+
handler: async (args) => {
|
|
43
|
+
validateRequired(args, ["birth_datetime", "target_datetime"]);
|
|
44
|
+
const body = {
|
|
45
|
+
birth_datetime: { iso: args.birth_datetime },
|
|
46
|
+
target_datetime: { iso: args.target_datetime },
|
|
47
|
+
};
|
|
48
|
+
if (args.birth_latitude != null && args.birth_longitude != null) {
|
|
49
|
+
body.location = {
|
|
50
|
+
latitude: { decimal: args.birth_latitude },
|
|
51
|
+
longitude: { decimal: args.birth_longitude },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (args.return_latitude != null && args.return_longitude != null) {
|
|
55
|
+
body.return_location = {
|
|
56
|
+
latitude: { decimal: args.return_latitude },
|
|
57
|
+
longitude: { decimal: args.return_longitude },
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return await backendClient.post("/predictive/returns/solar", body);
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
// POST /predictive/returns/lunar
|
|
64
|
+
registerTool({
|
|
65
|
+
name: "ephemeris_lunar_return",
|
|
66
|
+
description: "Calculate the exact Lunar Return date/time — when the Moon returns to its natal ecliptic longitude (~every 27.3 days). " +
|
|
67
|
+
"Used to cast the monthly Lunar Return chart.\n\n" +
|
|
68
|
+
"CREDIT COST: 1 credit per call.\n\n" +
|
|
69
|
+
"EXAMPLE: Next lunar return after 2026-03-15 for someone born 1990-04-15:\n" +
|
|
70
|
+
" birth_datetime='1990-04-15T14:30:00', target_datetime='2026-03-15'",
|
|
71
|
+
inputSchema: {
|
|
72
|
+
type: "object",
|
|
73
|
+
properties: {
|
|
74
|
+
birth_datetime: {
|
|
75
|
+
type: "string",
|
|
76
|
+
description: "ISO 8601 birth date/time.",
|
|
77
|
+
},
|
|
78
|
+
target_datetime: {
|
|
79
|
+
type: "string",
|
|
80
|
+
description: "Date/time near which to find the Lunar Return (ISO 8601). Required.",
|
|
81
|
+
},
|
|
82
|
+
birth_latitude: {
|
|
83
|
+
type: "number",
|
|
84
|
+
description: "Birth latitude in decimal degrees (optional).",
|
|
85
|
+
},
|
|
86
|
+
birth_longitude: {
|
|
87
|
+
type: "number",
|
|
88
|
+
description: "Birth longitude in decimal degrees (optional).",
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
required: ["birth_datetime", "target_datetime"],
|
|
92
|
+
additionalProperties: false,
|
|
93
|
+
},
|
|
94
|
+
handler: async (args) => {
|
|
95
|
+
validateRequired(args, ["birth_datetime", "target_datetime"]);
|
|
96
|
+
const body = {
|
|
97
|
+
birth_datetime: { iso: args.birth_datetime },
|
|
98
|
+
target_datetime: { iso: args.target_datetime },
|
|
99
|
+
};
|
|
100
|
+
if (args.birth_latitude != null && args.birth_longitude != null) {
|
|
101
|
+
body.location = {
|
|
102
|
+
latitude: { decimal: args.birth_latitude },
|
|
103
|
+
longitude: { decimal: args.birth_longitude },
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return await backendClient.post("/predictive/returns/lunar", body);
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
// POST /predictive/returns (generic planetary return)
|
|
110
|
+
registerTool({
|
|
111
|
+
name: "ephemeris_planetary_return",
|
|
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), etc.\n\n" +
|
|
114
|
+
"CREDIT COST: 1 credit per call.\n\n" +
|
|
115
|
+
"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
|
+
inputSchema: {
|
|
118
|
+
type: "object",
|
|
119
|
+
properties: {
|
|
120
|
+
body: {
|
|
121
|
+
type: "string",
|
|
122
|
+
description: "Planet name: sun, moon, mercury, venus, mars, jupiter, saturn.",
|
|
123
|
+
},
|
|
124
|
+
birth_datetime: {
|
|
125
|
+
type: "string",
|
|
126
|
+
description: "ISO 8601 birth date/time.",
|
|
127
|
+
},
|
|
128
|
+
target_datetime: {
|
|
129
|
+
type: "string",
|
|
130
|
+
description: "Date/time near which to find the return (ISO 8601). Required.",
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
required: ["body", "birth_datetime", "target_datetime"],
|
|
134
|
+
additionalProperties: false,
|
|
135
|
+
},
|
|
136
|
+
handler: async (args) => {
|
|
137
|
+
validateRequired(args, ["body", "birth_datetime", "target_datetime"]);
|
|
138
|
+
return await backendClient.post("/predictive/returns", {
|
|
139
|
+
body: args.body,
|
|
140
|
+
birth_datetime: { iso: args.birth_datetime },
|
|
141
|
+
target_datetime: { iso: args.target_datetime },
|
|
142
|
+
});
|
|
143
|
+
},
|
|
144
|
+
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { registerTool } from "../index.js";
|
|
1
|
+
import { registerTool, validateRequired } from "../index.js";
|
|
2
2
|
import { backendClient } from "../../backend/client.js";
|
|
3
3
|
registerTool({
|
|
4
|
-
name: "
|
|
4
|
+
name: "ephemeris_synastry",
|
|
5
5
|
description: "Calculate a synastry chart comparing two people's natal charts. Returns inter-aspects " +
|
|
6
6
|
"(planetary connections between the two charts), composite points, and relationship indicators. " +
|
|
7
7
|
"Use this for compatibility analysis, relationship timing, or partnership insights.\n\n" +
|
|
8
|
-
"CREDIT COST:
|
|
8
|
+
"CREDIT COST: 3 credits per call.\n\n" +
|
|
9
9
|
"EXAMPLE: Compare two people's charts:\n" +
|
|
10
10
|
" person_a_datetime='1990-04-15T14:30:00', person_a_latitude=41.8781, person_a_longitude=-87.6298,\n" +
|
|
11
11
|
" person_b_datetime='1988-09-22T08:15:00', person_b_latitude=34.0522, person_b_longitude=-118.2437",
|
|
@@ -26,7 +26,7 @@ registerTool({
|
|
|
26
26
|
format: {
|
|
27
27
|
type: "string",
|
|
28
28
|
enum: ["json", "llm"],
|
|
29
|
-
description: "Output format. 'llm' is compact and token-efficient (
|
|
29
|
+
description: "Output format. 'llm' is compact and token-efficient (available on all tiers).",
|
|
30
30
|
},
|
|
31
31
|
},
|
|
32
32
|
required: [
|
|
@@ -36,16 +36,26 @@ registerTool({
|
|
|
36
36
|
additionalProperties: false,
|
|
37
37
|
},
|
|
38
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
|
+
]);
|
|
39
43
|
const body = {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
subject_a: {
|
|
45
|
+
name: "Person A",
|
|
46
|
+
birth_datetime: { iso: args.person_a_datetime },
|
|
47
|
+
birth_location: {
|
|
48
|
+
latitude: { decimal: args.person_a_latitude },
|
|
49
|
+
longitude: { decimal: args.person_a_longitude },
|
|
50
|
+
},
|
|
44
51
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
subject_b: {
|
|
53
|
+
name: "Person B",
|
|
54
|
+
birth_datetime: { iso: args.person_b_datetime },
|
|
55
|
+
birth_location: {
|
|
56
|
+
latitude: { decimal: args.person_b_latitude },
|
|
57
|
+
longitude: { decimal: args.person_b_longitude },
|
|
58
|
+
},
|
|
49
59
|
},
|
|
50
60
|
};
|
|
51
61
|
if (args.house_system)
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { registerTool } from "../index.js";
|
|
1
|
+
import { registerTool, validateRequired } from "../index.js";
|
|
2
2
|
import { backendClient } from "../../backend/client.js";
|
|
3
3
|
registerTool({
|
|
4
|
-
name: "
|
|
4
|
+
name: "ephemeris_transits",
|
|
5
5
|
description: "Search for astrological transit events affecting a natal chart over a date range. " +
|
|
6
6
|
"Returns a list of exact transit moments — when transiting planets form specified aspects " +
|
|
7
7
|
"to natal planet positions. Ideal for generating horoscope timelines, event forecasting, or " +
|
|
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
|
+
"ecliptic longitudes, then searches for transiting planets crossing those exact degrees.\n\n" +
|
|
11
|
+
"CREDIT COST: 6 credits per call (1 for natal + 5 for transit search).\n\n" +
|
|
10
12
|
"EXAMPLE: Find all Saturn transits to the natal Sun/Moon for the next 6 months:\n" +
|
|
11
13
|
" natal_datetime='1990-04-15T14:30:00', natal_latitude=41.8781, natal_longitude=-87.6298,\n" +
|
|
12
14
|
" start_date='2026-01-01', end_date='2026-06-30', transiting_planets=['saturn']",
|
|
@@ -42,39 +44,87 @@ registerTool({
|
|
|
42
44
|
natal_points: {
|
|
43
45
|
type: "array",
|
|
44
46
|
items: { type: "string" },
|
|
45
|
-
description: "Natal point IDs
|
|
46
|
-
},
|
|
47
|
-
aspects: {
|
|
48
|
-
type: "array",
|
|
49
|
-
items: { type: "string", enum: ["conjunction", "opposition", "trine", "square", "sextile"] },
|
|
50
|
-
description: "Aspect types to include in the search. Defaults to all major aspects.",
|
|
51
|
-
},
|
|
52
|
-
orb: {
|
|
53
|
-
type: "number",
|
|
54
|
-
description: "Maximum orb in degrees (default: 1.0).",
|
|
47
|
+
description: "Natal point IDs whose exact longitudes should be targeted. E.g. ['sun', 'moon', 'asc', 'mc']. Omit for all core points.",
|
|
55
48
|
},
|
|
56
49
|
},
|
|
57
50
|
required: ["natal_datetime", "natal_latitude", "natal_longitude", "start_date", "end_date"],
|
|
58
51
|
additionalProperties: false,
|
|
59
52
|
},
|
|
60
53
|
handler: async (args) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
validateRequired(args, ["natal_datetime", "natal_latitude", "natal_longitude", "start_date", "end_date"]);
|
|
55
|
+
// ── Step 1: Compute natal chart to extract real planetary longitudes ──
|
|
56
|
+
const natalBody = {
|
|
57
|
+
subject: {
|
|
58
|
+
name: "Transit Natal Subject",
|
|
59
|
+
birth_datetime: { iso: args.natal_datetime },
|
|
60
|
+
birth_location: {
|
|
61
|
+
latitude: { decimal: args.natal_latitude },
|
|
62
|
+
longitude: { decimal: args.natal_longitude }
|
|
63
|
+
},
|
|
66
64
|
},
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
};
|
|
66
|
+
const natalResult = await backendClient.post("/ephemeris/natal-chart", natalBody);
|
|
67
|
+
// Extract ecliptic longitudes from natal chart planets
|
|
68
|
+
const targetDegrees = [];
|
|
69
|
+
const natalPositionMap = {};
|
|
70
|
+
// The natal response typically has a `planets` array or object
|
|
71
|
+
const planets = natalResult?.planets || natalResult?.data?.planets || [];
|
|
72
|
+
const planetArray = Array.isArray(planets) ? planets : Object.values(planets);
|
|
73
|
+
// Filter to requested natal points if specified
|
|
74
|
+
const wantedPoints = args.natal_points
|
|
75
|
+
? new Set(args.natal_points.map((p) => p.toLowerCase()))
|
|
76
|
+
: null;
|
|
77
|
+
for (const planet of planetArray) {
|
|
78
|
+
const name = (planet.name || planet.id || "").toLowerCase();
|
|
79
|
+
const lon = planet.longitude ?? planet.ecliptic_longitude ?? planet.lon;
|
|
80
|
+
if (typeof lon !== "number" || !isFinite(lon))
|
|
81
|
+
continue;
|
|
82
|
+
if (wantedPoints && !wantedPoints.has(name))
|
|
83
|
+
continue;
|
|
84
|
+
targetDegrees.push(Math.round(lon * 100) / 100); // 2 decimal places
|
|
85
|
+
natalPositionMap[name] = lon;
|
|
86
|
+
}
|
|
87
|
+
// Also extract angles (ASC, MC, DSC, IC) if present
|
|
88
|
+
const angles = natalResult?.angles || natalResult?.data?.angles;
|
|
89
|
+
if (angles) {
|
|
90
|
+
const angleEntries = Array.isArray(angles) ? angles : Object.entries(angles).map(([k, v]) => ({ name: k, ...(typeof v === 'object' ? v : { longitude: v }) }));
|
|
91
|
+
for (const angle of angleEntries) {
|
|
92
|
+
const name = (angle.name || angle.id || "").toLowerCase();
|
|
93
|
+
const lon = angle.longitude ?? angle.ecliptic_longitude ?? angle.lon;
|
|
94
|
+
if (typeof lon !== "number" || !isFinite(lon))
|
|
95
|
+
continue;
|
|
96
|
+
if (wantedPoints && !wantedPoints.has(name))
|
|
97
|
+
continue;
|
|
98
|
+
targetDegrees.push(Math.round(lon * 100) / 100);
|
|
99
|
+
natalPositionMap[name] = lon;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (targetDegrees.length === 0) {
|
|
103
|
+
throw new Error("Could not extract natal planet longitudes from the natal chart calculation. " +
|
|
104
|
+
"Please verify your natal_datetime, natal_latitude, and natal_longitude are correct.");
|
|
105
|
+
}
|
|
106
|
+
// ── Step 2: Search transits against those real natal longitudes ──
|
|
107
|
+
let startStr = args.start_date;
|
|
108
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(startStr)) {
|
|
109
|
+
startStr += "T00:00:00Z";
|
|
110
|
+
}
|
|
111
|
+
let endStr = args.end_date;
|
|
112
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(endStr)) {
|
|
113
|
+
endStr += "T23:59:59Z";
|
|
114
|
+
}
|
|
115
|
+
const transitBody = {
|
|
116
|
+
start_date: startStr,
|
|
117
|
+
end_date: endStr,
|
|
118
|
+
target_degrees: targetDegrees,
|
|
69
119
|
};
|
|
70
120
|
if (args.transiting_planets)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
121
|
+
transitBody.planet_names = args.transiting_planets;
|
|
122
|
+
const transitResult = await backendClient.request("POST", "/predictive/transits/search", { data: transitBody });
|
|
123
|
+
// Return combined context so the LLM knows what natal positions were targeted
|
|
124
|
+
return {
|
|
125
|
+
natal_positions: natalPositionMap,
|
|
126
|
+
target_degrees_used: targetDegrees,
|
|
127
|
+
transit_results: transitResult,
|
|
128
|
+
};
|
|
79
129
|
},
|
|
80
130
|
});
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { registerTool, validateRequired } from "../index.js";
|
|
2
|
+
import { backendClient } from "../../backend/client.js";
|
|
3
|
+
function buildSubject(datetime, lat, lon) {
|
|
4
|
+
return {
|
|
5
|
+
name: "Subject",
|
|
6
|
+
birth_datetime: { iso: datetime },
|
|
7
|
+
birth_location: {
|
|
8
|
+
latitude: { decimal: lat },
|
|
9
|
+
longitude: { decimal: lon },
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
// POST /ephemeris/venus-star-points
|
|
14
|
+
registerTool({
|
|
15
|
+
name: "venus_star_points",
|
|
16
|
+
description: "Get Venus Star Points — the Sun-Venus conjunction events nearest to a birth date. " +
|
|
17
|
+
"Shows the quality of each conjunction (cazimi, combust, under beams) with zodiac details.\n\n" +
|
|
18
|
+
"CREDIT COST: 2 credits per call.\n\n" +
|
|
19
|
+
"EXAMPLE: Venus star points for someone born 1990-04-15:\n" +
|
|
20
|
+
" datetime='1990-04-15T14:30:00', latitude=41.88, longitude=-87.63",
|
|
21
|
+
inputSchema: {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: {
|
|
24
|
+
datetime: { type: "string", description: "Birth datetime (ISO 8601)." },
|
|
25
|
+
latitude: { type: "number", description: "Birth latitude." },
|
|
26
|
+
longitude: { type: "number", description: "Birth longitude." },
|
|
27
|
+
format: { type: "string", enum: ["json", "llm"], description: "Output format." },
|
|
28
|
+
},
|
|
29
|
+
required: ["datetime", "latitude", "longitude"],
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
handler: async (args) => {
|
|
33
|
+
validateRequired(args, ["datetime", "latitude", "longitude"]);
|
|
34
|
+
const query = {};
|
|
35
|
+
if (args.format)
|
|
36
|
+
query.format = args.format;
|
|
37
|
+
return await backendClient.request("POST", "/ephemeris/venus-star-points", {
|
|
38
|
+
data: { subject: buildSubject(args.datetime, args.latitude, args.longitude) },
|
|
39
|
+
params: query,
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
// POST /ephemeris/venus-star-points/conjunctions
|
|
44
|
+
registerTool({
|
|
45
|
+
name: "venus_star_points_conjunctions",
|
|
46
|
+
description: "Find all Sun-Venus conjunctions in a date range. Returns each conjunction with " +
|
|
47
|
+
"its exact timestamp, zodiac position, orb, visibility (morning/evening star), and dignity.\n\n" +
|
|
48
|
+
"CREDIT COST: 2 credits per call.\n\n" +
|
|
49
|
+
"EXAMPLE: Find Venus conjunctions in 2026:\n" +
|
|
50
|
+
" start_date='2026-01-01', end_date='2026-12-31'",
|
|
51
|
+
inputSchema: {
|
|
52
|
+
type: "object",
|
|
53
|
+
properties: {
|
|
54
|
+
start_date: { type: "string", description: "Start date (ISO 8601)." },
|
|
55
|
+
end_date: { type: "string", description: "End date (ISO 8601)." },
|
|
56
|
+
format: { type: "string", enum: ["json", "llm"], description: "Output format." },
|
|
57
|
+
},
|
|
58
|
+
required: ["start_date", "end_date"],
|
|
59
|
+
additionalProperties: false,
|
|
60
|
+
},
|
|
61
|
+
handler: async (args) => {
|
|
62
|
+
validateRequired(args, ["start_date", "end_date"]);
|
|
63
|
+
const query = {};
|
|
64
|
+
if (args.format)
|
|
65
|
+
query.format = args.format;
|
|
66
|
+
return await backendClient.request("POST", "/ephemeris/venus-star-points/conjunctions", {
|
|
67
|
+
data: { start_date: args.start_date, end_date: args.end_date },
|
|
68
|
+
params: query,
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
// POST /ephemeris/venus-star-points/eight-year-star
|
|
73
|
+
registerTool({
|
|
74
|
+
name: "venus_eight_year_star",
|
|
75
|
+
description: "Compute the 8-year Venus Star pattern — the pentagram of 5 Venus-Sun conjunctions " +
|
|
76
|
+
"that trace a near-perfect star over 8 years (the Venus synodic cycle). Returns the 5 " +
|
|
77
|
+
"vertices with their zodiac positions.\n\n" +
|
|
78
|
+
"CREDIT COST: 2 credits per call.\n\n" +
|
|
79
|
+
"EXAMPLE: 8-year star starting from 2020:\n" +
|
|
80
|
+
" date='2020-01-01'",
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: "object",
|
|
83
|
+
properties: {
|
|
84
|
+
date: { type: "string", description: "Start date for the 8-year cycle (ISO 8601)." },
|
|
85
|
+
format: { type: "string", enum: ["json", "llm"], description: "Output format." },
|
|
86
|
+
},
|
|
87
|
+
required: ["date"],
|
|
88
|
+
additionalProperties: false,
|
|
89
|
+
},
|
|
90
|
+
handler: async (args) => {
|
|
91
|
+
validateRequired(args, ["date"]);
|
|
92
|
+
const query = {};
|
|
93
|
+
if (args.format)
|
|
94
|
+
query.format = args.format;
|
|
95
|
+
return await backendClient.request("POST", "/ephemeris/venus-star-points/eight-year-star", {
|
|
96
|
+
data: { date: args.date },
|
|
97
|
+
params: query,
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
// POST /ephemeris/venus-star-points/phase
|
|
102
|
+
registerTool({
|
|
103
|
+
name: "venus_phase",
|
|
104
|
+
description: "Get the current Venus phase — morning star, evening star, or combust. Returns Venus " +
|
|
105
|
+
"longitude, Sun longitude, elongation, retrograde/cazimi status.\n\n" +
|
|
106
|
+
"CREDIT COST: 1 credit per call.\n\n" +
|
|
107
|
+
"EXAMPLE: Venus phase right now:\n" +
|
|
108
|
+
" date='2026-03-20'",
|
|
109
|
+
inputSchema: {
|
|
110
|
+
type: "object",
|
|
111
|
+
properties: {
|
|
112
|
+
date: { type: "string", description: "Date to check (ISO 8601). Defaults to now." },
|
|
113
|
+
format: { type: "string", enum: ["json", "llm"], description: "Output format." },
|
|
114
|
+
},
|
|
115
|
+
required: ["date"],
|
|
116
|
+
additionalProperties: false,
|
|
117
|
+
},
|
|
118
|
+
handler: async (args) => {
|
|
119
|
+
validateRequired(args, ["date"]);
|
|
120
|
+
const query = {};
|
|
121
|
+
if (args.format)
|
|
122
|
+
query.format = args.format;
|
|
123
|
+
return await backendClient.request("POST", "/ephemeris/venus-star-points/phase", {
|
|
124
|
+
data: { date: args.date },
|
|
125
|
+
params: query,
|
|
126
|
+
});
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
// POST /ephemeris/venus-star-points/elongations
|
|
130
|
+
registerTool({
|
|
131
|
+
name: "venus_elongations",
|
|
132
|
+
description: "Find Venus greatest elongation events (when Venus is farthest from the Sun in the sky). " +
|
|
133
|
+
"Returns east (evening star) and west (morning star) elongation peaks.\n\n" +
|
|
134
|
+
"CREDIT COST: 2 credits per call.",
|
|
135
|
+
inputSchema: {
|
|
136
|
+
type: "object",
|
|
137
|
+
properties: {
|
|
138
|
+
start_date: { type: "string", description: "Start date (ISO 8601)." },
|
|
139
|
+
end_date: { type: "string", description: "End date (ISO 8601)." },
|
|
140
|
+
format: { type: "string", enum: ["json", "llm"], description: "Output format." },
|
|
141
|
+
},
|
|
142
|
+
required: ["start_date", "end_date"],
|
|
143
|
+
additionalProperties: false,
|
|
144
|
+
},
|
|
145
|
+
handler: async (args) => {
|
|
146
|
+
validateRequired(args, ["start_date", "end_date"]);
|
|
147
|
+
const query = {};
|
|
148
|
+
if (args.format)
|
|
149
|
+
query.format = args.format;
|
|
150
|
+
return await backendClient.request("POST", "/ephemeris/venus-star-points/elongations", {
|
|
151
|
+
data: { start_date: args.start_date, end_date: args.end_date },
|
|
152
|
+
params: query,
|
|
153
|
+
});
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
// POST /ephemeris/venus-star-points/stations
|
|
157
|
+
registerTool({
|
|
158
|
+
name: "venus_stations",
|
|
159
|
+
description: "Find Venus retrograde and direct stations in a date range. Returns the exact " +
|
|
160
|
+
"moment Venus appears to stop and reverse direction.\n\n" +
|
|
161
|
+
"CREDIT COST: 2 credits per call.\n\n" +
|
|
162
|
+
"EXAMPLE: Venus stations in 2026:\n" +
|
|
163
|
+
" start_date='2026-01-01', end_date='2026-12-31'",
|
|
164
|
+
inputSchema: {
|
|
165
|
+
type: "object",
|
|
166
|
+
properties: {
|
|
167
|
+
start_date: { type: "string", description: "Start date (ISO 8601)." },
|
|
168
|
+
end_date: { type: "string", description: "End date (ISO 8601). Defaults to +1 year." },
|
|
169
|
+
format: { type: "string", enum: ["json", "llm"], description: "Output format." },
|
|
170
|
+
},
|
|
171
|
+
required: ["start_date"],
|
|
172
|
+
additionalProperties: false,
|
|
173
|
+
},
|
|
174
|
+
handler: async (args) => {
|
|
175
|
+
validateRequired(args, ["start_date"]);
|
|
176
|
+
const query = {};
|
|
177
|
+
if (args.format)
|
|
178
|
+
query.format = args.format;
|
|
179
|
+
return await backendClient.request("POST", "/ephemeris/venus-star-points/stations", {
|
|
180
|
+
data: {
|
|
181
|
+
start_date: args.start_date,
|
|
182
|
+
end_date: args.end_date || "",
|
|
183
|
+
},
|
|
184
|
+
params: query,
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openephemeris/mcp-server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Model Context Protocol server for the Open Ephemeris astronomical computation API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
"test": "test"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "tsc",
|
|
19
|
+
"build": "tsc -p tsconfig.build.json",
|
|
20
|
+
"prebuild": "node -e \"const fs=require('fs');fs.rmSync('dist',{recursive:true,force:true})\"",
|
|
20
21
|
"dev": "tsx watch src/index.ts",
|
|
21
22
|
"dev:sse": "tsx watch src/server-sse.ts",
|
|
22
23
|
"start": "node dist/index.js",
|
|
23
|
-
"start:sse": "node dist/
|
|
24
|
+
"start:sse": "node dist/server-sse.js",
|
|
24
25
|
"test": "vitest run --exclude \"dist/**\"",
|
|
25
26
|
"test:watch": "vitest --exclude \"dist/**\"",
|
|
26
27
|
"test:integration": "tsx scripts/test-client.ts",
|