caelus-mcp 0.3.0 → 0.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/README.md +14 -7
- package/dist/src/server.d.ts +67 -1
- package/dist/src/server.js +74 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# caelus-mcp
|
|
2
2
|
|
|
3
3
|
MCP server for the [caelus](https://github.com/heavyblotto/caelus) ephemeris
|
|
4
|
-
engine:
|
|
5
|
-
aspects with orbs — the model does the interpreting. No API
|
|
6
|
-
ephemeris files, no network calls; the engine data ships inside the
|
|
4
|
+
engine: seven chart tools over stdio. Computation only — positions, houses,
|
|
5
|
+
aspects with orbs, event search — the model does the interpreting. No API
|
|
6
|
+
keys, no ephemeris files, no network calls; the engine data ships inside the
|
|
7
|
+
package.
|
|
7
8
|
|
|
8
9
|
## Setup
|
|
9
10
|
|
|
@@ -31,10 +32,15 @@ Any MCP client that speaks stdio:
|
|
|
31
32
|
| `synastry` | Two charts compared: inter-chart aspects, house overlays both ways |
|
|
32
33
|
| `find_aspect_dates` | Exact dates a transiting body aspects a longitude or another body, retrograde re-hits included |
|
|
33
34
|
| `rectification_grid` | ASC/MC sweep across a window of hours for birth-time rectification |
|
|
35
|
+
| `sky_events` | Rise/set/meridian transits, lunar phases, stations, zodiac crossings in a date range (≤370 days) |
|
|
34
36
|
|
|
35
|
-
Bodies: sun through pluto, chiron, mean and true node.
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
Bodies (core chart): sun through pluto, chiron, mean and true node. Optional
|
|
38
|
+
bodies (mean/true Lilith, asteroids, Uranians) follow engine data on the Node
|
|
39
|
+
loader path. House systems: twelve total — placidus (default), whole_sign,
|
|
40
|
+
equal, porphyry, koch, regiomontanus, campanus, alcabitius, morinus,
|
|
41
|
+
meridian, polich_page, vehlow. Placidus and Koch fall back to whole_sign
|
|
42
|
+
above the polar circles and say so in the payload. `zodiac` supports tropical
|
|
43
|
+
(default) and five sidereal ayanamsas on chart tools.
|
|
38
44
|
|
|
39
45
|
## Output
|
|
40
46
|
|
|
@@ -66,7 +72,8 @@ east-positive everywhere; the Americas are negative.
|
|
|
66
72
|
|
|
67
73
|
Checked against Swiss Ephemeris across 1900–2099: Sun–Saturn ≤1″,
|
|
68
74
|
Uranus ≤1.9″, Neptune ≤4.6″, Moon ≤2.5″, Pluto ≤2.5″ (series valid
|
|
69
|
-
1885–2099), Chiron ≤1″,
|
|
75
|
+
1885–2099), Chiron ≤1″, mean node ≤1″, true node ≤1′ vs SE's built-in
|
|
76
|
+
ephemeris, asteroids ≤1″ (Horizons fits), Uranians ≤2.3″. Tables:
|
|
70
77
|
[ephemengine.com/validation](https://ephemengine.com/validation).
|
|
71
78
|
|
|
72
79
|
## The caelus packages
|
package/dist/src/server.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* caelus-mcp -- MCP server for the caelus ephemeris engine.
|
|
4
4
|
*
|
|
5
5
|
* Design (per 2026 MCP practice): one bounded context (chart computation),
|
|
6
|
-
* a small curated tool surface (
|
|
6
|
+
* a small curated tool surface (7 outcome-level tools, not API wrappers),
|
|
7
7
|
* and token-frugal outputs (positions to 0.01 deg, terse keys, no prose --
|
|
8
8
|
* the model does the interpreting, the server does the math).
|
|
9
9
|
*
|
|
@@ -603,6 +603,39 @@ export declare const rectificationGridOut: z.ZodObject<{
|
|
|
603
603
|
mc: string;
|
|
604
604
|
}[];
|
|
605
605
|
}>;
|
|
606
|
+
export declare const skyEventsOut: z.ZodObject<{
|
|
607
|
+
start: z.ZodString;
|
|
608
|
+
end: z.ZodString;
|
|
609
|
+
events: z.ZodArray<z.ZodObject<{
|
|
610
|
+
t: z.ZodString;
|
|
611
|
+
kind: z.ZodEnum<["rise", "set", "mtransit", "itransit", "phase", "station", "crossing"]>;
|
|
612
|
+
detail: z.ZodOptional<z.ZodString>;
|
|
613
|
+
}, "strip", z.ZodTypeAny, {
|
|
614
|
+
t: string;
|
|
615
|
+
kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing";
|
|
616
|
+
detail?: string | undefined;
|
|
617
|
+
}, {
|
|
618
|
+
t: string;
|
|
619
|
+
kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing";
|
|
620
|
+
detail?: string | undefined;
|
|
621
|
+
}>, "many">;
|
|
622
|
+
}, "strip", z.ZodTypeAny, {
|
|
623
|
+
start: string;
|
|
624
|
+
end: string;
|
|
625
|
+
events: {
|
|
626
|
+
t: string;
|
|
627
|
+
kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing";
|
|
628
|
+
detail?: string | undefined;
|
|
629
|
+
}[];
|
|
630
|
+
}, {
|
|
631
|
+
start: string;
|
|
632
|
+
end: string;
|
|
633
|
+
events: {
|
|
634
|
+
t: string;
|
|
635
|
+
kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing";
|
|
636
|
+
detail?: string | undefined;
|
|
637
|
+
}[];
|
|
638
|
+
}>;
|
|
606
639
|
export declare const OUTPUT_SCHEMAS: {
|
|
607
640
|
readonly natal_chart: z.ZodObject<{
|
|
608
641
|
utc: z.ZodString;
|
|
@@ -1306,5 +1339,38 @@ export declare const OUTPUT_SCHEMAS: {
|
|
|
1306
1339
|
mc: string;
|
|
1307
1340
|
}[];
|
|
1308
1341
|
}>;
|
|
1342
|
+
readonly sky_events: z.ZodObject<{
|
|
1343
|
+
start: z.ZodString;
|
|
1344
|
+
end: z.ZodString;
|
|
1345
|
+
events: z.ZodArray<z.ZodObject<{
|
|
1346
|
+
t: z.ZodString;
|
|
1347
|
+
kind: z.ZodEnum<["rise", "set", "mtransit", "itransit", "phase", "station", "crossing"]>;
|
|
1348
|
+
detail: z.ZodOptional<z.ZodString>;
|
|
1349
|
+
}, "strip", z.ZodTypeAny, {
|
|
1350
|
+
t: string;
|
|
1351
|
+
kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing";
|
|
1352
|
+
detail?: string | undefined;
|
|
1353
|
+
}, {
|
|
1354
|
+
t: string;
|
|
1355
|
+
kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing";
|
|
1356
|
+
detail?: string | undefined;
|
|
1357
|
+
}>, "many">;
|
|
1358
|
+
}, "strip", z.ZodTypeAny, {
|
|
1359
|
+
start: string;
|
|
1360
|
+
end: string;
|
|
1361
|
+
events: {
|
|
1362
|
+
t: string;
|
|
1363
|
+
kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing";
|
|
1364
|
+
detail?: string | undefined;
|
|
1365
|
+
}[];
|
|
1366
|
+
}, {
|
|
1367
|
+
start: string;
|
|
1368
|
+
end: string;
|
|
1369
|
+
events: {
|
|
1370
|
+
t: string;
|
|
1371
|
+
kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing";
|
|
1372
|
+
detail?: string | undefined;
|
|
1373
|
+
}[];
|
|
1374
|
+
}>;
|
|
1309
1375
|
};
|
|
1310
1376
|
export declare function buildServer(): McpServer;
|
package/dist/src/server.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* caelus-mcp -- MCP server for the caelus ephemeris engine.
|
|
4
4
|
*
|
|
5
5
|
* Design (per 2026 MCP practice): one bounded context (chart computation),
|
|
6
|
-
* a small curated tool surface (
|
|
6
|
+
* a small curated tool surface (7 outcome-level tools, not API wrappers),
|
|
7
7
|
* and token-frugal outputs (positions to 0.01 deg, terse keys, no prose --
|
|
8
8
|
* the model does the interpreting, the server does the math).
|
|
9
9
|
*
|
|
@@ -17,7 +17,7 @@ import { dirname, join } from "node:path";
|
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
18
18
|
import { createRequire } from "node:module";
|
|
19
19
|
import { realpathSync } from "node:fs";
|
|
20
|
-
import { Engine, BODIES, julianDay, mod } from "caelus";
|
|
20
|
+
import { Engine, BODIES, julianDay, mod, riseSet, crossings, lunarPhases, stations, } from "caelus";
|
|
21
21
|
import { loadNodeData } from "caelus/node";
|
|
22
22
|
const require = createRequire(import.meta.url);
|
|
23
23
|
const VERSION = require("caelus-mcp/package.json").version;
|
|
@@ -136,6 +136,15 @@ export const rectificationGridOut = z.object({
|
|
|
136
136
|
asc_sign_changes: z.array(z.string()),
|
|
137
137
|
grid: z.array(z.object({ utc: z.string(), asc: z.string(), mc: z.string() })),
|
|
138
138
|
});
|
|
139
|
+
export const skyEventsOut = z.object({
|
|
140
|
+
start: z.string(),
|
|
141
|
+
end: z.string(),
|
|
142
|
+
events: z.array(z.object({
|
|
143
|
+
t: z.string(),
|
|
144
|
+
kind: z.enum(["rise", "set", "mtransit", "itransit", "phase", "station", "crossing"]),
|
|
145
|
+
detail: z.string().optional(),
|
|
146
|
+
})),
|
|
147
|
+
});
|
|
139
148
|
export const OUTPUT_SCHEMAS = {
|
|
140
149
|
natal_chart: chartOut,
|
|
141
150
|
current_sky: chartOut,
|
|
@@ -143,12 +152,13 @@ export const OUTPUT_SCHEMAS = {
|
|
|
143
152
|
synastry: synastryOut,
|
|
144
153
|
find_aspect_dates: findAspectDatesOut,
|
|
145
154
|
rectification_grid: rectificationGridOut,
|
|
155
|
+
sky_events: skyEventsOut,
|
|
146
156
|
};
|
|
147
157
|
// ---------------------------------------------------------------- server
|
|
148
158
|
export function buildServer() {
|
|
149
159
|
const server = new McpServer({ name: "caelus", version: VERSION });
|
|
150
160
|
server.registerTool("natal_chart", {
|
|
151
|
-
description: "A person's birth chart. Requires their exact birth date+time and birthplace (all three: date, lat, lon). Use this — not current_sky — whenever the question is about someone's natal/birth chart. Returns 13 bodies (sun–pluto, chiron, nodes) with sign, house, retrograde, speed; ASC/MC; cusps; major aspects with orbs. Vs Swiss Ephemeris (1900–2099): Sun–Saturn ≤1″, Uranus ≤1.9″, Neptune ≤4.6″, Moon ≤2.5″, Pluto ≤2.5″ (series valid 1885–2099), Chiron ≤1″,
|
|
161
|
+
description: "A person's birth chart. Requires their exact birth date+time and birthplace (all three: date, lat, lon). Use this — not current_sky — whenever the question is about someone's natal/birth chart. Returns 13 bodies (sun–pluto, chiron, nodes) with sign, house, retrograde, speed; ASC/MC; cusps; major aspects with orbs. Vs Swiss Ephemeris (1900–2099): Sun–Saturn ≤1″, Uranus ≤1.9″, Neptune ≤4.6″, Moon ≤2.5″, Pluto ≤2.5″ (series valid 1885–2099), Chiron ≤1″, mean node ≤1″, true node ≤ 1′ vs SE's built-in ephemeris.",
|
|
152
162
|
inputSchema: { ...birth, house_system: houseSys, zodiac: zodiacSchema },
|
|
153
163
|
}, async ({ date, lat, lon, house_system, zodiac }) => text(chartPayload(date, lat, lon, house_system, zodiac)));
|
|
154
164
|
server.registerTool("current_sky", {
|
|
@@ -338,6 +348,67 @@ export function buildServer() {
|
|
|
338
348
|
}
|
|
339
349
|
return text({ date: date.slice(0, 10), lat, lon, asc_sign_changes: boundaries, grid });
|
|
340
350
|
});
|
|
351
|
+
server.registerTool("sky_events", {
|
|
352
|
+
description: "Sky events in a UTC date range: rise/set/meridian transits (need lat+lon+body), lunar phases (new/quarters/full), stations (body turns retrograde/direct; needs body), zodiac degree crossings (needs body + target_lon). Times to the second vs Swiss Ephemeris (stations to ~1 min: ill-conditioned by nature). Range <= 370 days.",
|
|
353
|
+
inputSchema: {
|
|
354
|
+
start: z.string().describe("UTC ISO start date (convert from local first)"),
|
|
355
|
+
end: z.string().describe("UTC ISO end date; range <= 370 days"),
|
|
356
|
+
kinds: z.array(z.enum(["rise", "set", "mtransit", "itransit", "phase", "station", "crossing"]))
|
|
357
|
+
.min(1).describe("Event kinds to include"),
|
|
358
|
+
body: z.enum(BODIES).optional()
|
|
359
|
+
.describe("Required for rise/set/transit/station/crossing"),
|
|
360
|
+
lat: latSchema.optional().describe("Required for rise/set/transit"),
|
|
361
|
+
lon: lonSchema.optional().describe("Required for rise/set/transit"),
|
|
362
|
+
target_lon: z.number().min(0).max(360).optional()
|
|
363
|
+
.describe("Zodiac longitude for 'crossing', degrees"),
|
|
364
|
+
zodiac: zodiacSchema.describe("Zodiac for 'crossing' longitudes"),
|
|
365
|
+
},
|
|
366
|
+
}, async ({ start, end, kinds, body, lat, lon, target_lon, zodiac }) => {
|
|
367
|
+
const jd0 = jdFromIso(start);
|
|
368
|
+
const jd1 = jdFromIso(end);
|
|
369
|
+
if (jd1 - jd0 > 370)
|
|
370
|
+
throw new Error("Range too large (max 370 days)");
|
|
371
|
+
const iso = (jd) => new Date((jd - 2440587.5) * 86400000).toISOString().slice(0, 19) + "Z";
|
|
372
|
+
const events = [];
|
|
373
|
+
const riseKinds = kinds.filter((k) => k === "rise" || k === "set" || k === "mtransit" || k === "itransit");
|
|
374
|
+
if (riseKinds.length) {
|
|
375
|
+
if (body === undefined || lat === undefined || lon === undefined) {
|
|
376
|
+
throw new Error("rise/set/transit need body, lat, lon");
|
|
377
|
+
}
|
|
378
|
+
for (const k of riseKinds) {
|
|
379
|
+
let t = jd0;
|
|
380
|
+
while (t < jd1 && events.length < 200) {
|
|
381
|
+
const hit = riseSet(engine, body, t, lat, lon, k);
|
|
382
|
+
if (hit === null || hit > jd1)
|
|
383
|
+
break;
|
|
384
|
+
events.push({ t: iso(hit), kind: k });
|
|
385
|
+
t = hit + 1e-4;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
if (kinds.includes("phase")) {
|
|
390
|
+
for (const [t, name] of lunarPhases(engine, jd0, jd1)) {
|
|
391
|
+
events.push({ t: iso(t), kind: "phase", detail: name });
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (kinds.includes("station")) {
|
|
395
|
+
if (body === undefined)
|
|
396
|
+
throw new Error("station needs body");
|
|
397
|
+
for (const [t, dir] of stations(engine, body, jd0, jd1)) {
|
|
398
|
+
events.push({ t: iso(t), kind: "station", detail: dir });
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if (kinds.includes("crossing")) {
|
|
402
|
+
if (body === undefined || target_lon === undefined) {
|
|
403
|
+
throw new Error("crossing needs body and target_lon");
|
|
404
|
+
}
|
|
405
|
+
for (const t of crossings(engine, body, target_lon, jd0, jd1, zodiac)) {
|
|
406
|
+
events.push({ t: iso(t), kind: "crossing", detail: `${target_lon}°` });
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
events.sort((a, b) => a.t.localeCompare(b.t));
|
|
410
|
+
return text({ start, end, events });
|
|
411
|
+
});
|
|
341
412
|
return server;
|
|
342
413
|
}
|
|
343
414
|
// ---------------------------------------------------------------- main
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "caelus-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "MCP server for caelus chart computation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
16
16
|
"zod": "^3.24.0",
|
|
17
|
-
"caelus": "^0.
|
|
17
|
+
"caelus": "^0.4.0"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"ajv": "^8.17.1"
|