caelus-mcp 0.3.0 → 0.5.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 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: six chart tools over stdio. Computation only — positions, houses,
5
- aspects with orbs — the model does the interpreting. No API keys, no
6
- ephemeris files, no network calls; the engine data ships inside the package.
4
+ engine: seven chart tools over stdio. Computation only — positions, houses,
5
+ aspects with orbs, event search — the model does the interpreting. It needs
6
+ no API keys, ephemeris files, or network calls; the engine data ships inside
7
+ the 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. House systems:
36
- placidus (default), whole_sign, equal, porphyry. Placidus falls back to
37
- whole_sign above the polar circles and says so in the payload.
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″, nodes ≤1″. Tables:
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
@@ -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 outcome-level tools, not API wrappers),
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
  *
@@ -15,7 +15,7 @@ import { z } from "zod";
15
15
  export declare const chartOut: z.ZodObject<{
16
16
  utc: z.ZodString;
17
17
  houses: z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>;
18
- zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar"]>>;
18
+ zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar", "sidereal:galcent_0sag", "sidereal:true_citra"]>>;
19
19
  houses_requested: z.ZodOptional<z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>>;
20
20
  houses_fallback_reason: z.ZodOptional<z.ZodString>;
21
21
  bodies: z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -93,7 +93,7 @@ export declare const chartOut: z.ZodObject<{
93
93
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
94
94
  orb: number;
95
95
  }[];
96
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
96
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
97
97
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
98
98
  houses_fallback_reason?: string | undefined;
99
99
  }, {
@@ -119,7 +119,7 @@ export declare const chartOut: z.ZodObject<{
119
119
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
120
120
  orb: number;
121
121
  }[];
122
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
122
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
123
123
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
124
124
  houses_fallback_reason?: string | undefined;
125
125
  }>;
@@ -190,7 +190,7 @@ export declare const synastryOut: z.ZodObject<{
190
190
  a: z.ZodObject<{
191
191
  utc: z.ZodString;
192
192
  houses: z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>;
193
- zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar"]>>;
193
+ zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar", "sidereal:galcent_0sag", "sidereal:true_citra"]>>;
194
194
  houses_requested: z.ZodOptional<z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>>;
195
195
  houses_fallback_reason: z.ZodOptional<z.ZodString>;
196
196
  bodies: z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -268,7 +268,7 @@ export declare const synastryOut: z.ZodObject<{
268
268
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
269
269
  orb: number;
270
270
  }[];
271
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
271
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
272
272
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
273
273
  houses_fallback_reason?: string | undefined;
274
274
  }, {
@@ -294,14 +294,14 @@ export declare const synastryOut: z.ZodObject<{
294
294
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
295
295
  orb: number;
296
296
  }[];
297
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
297
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
298
298
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
299
299
  houses_fallback_reason?: string | undefined;
300
300
  }>;
301
301
  b: z.ZodObject<{
302
302
  utc: z.ZodString;
303
303
  houses: z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>;
304
- zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar"]>>;
304
+ zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar", "sidereal:galcent_0sag", "sidereal:true_citra"]>>;
305
305
  houses_requested: z.ZodOptional<z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>>;
306
306
  houses_fallback_reason: z.ZodOptional<z.ZodString>;
307
307
  bodies: z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -379,7 +379,7 @@ export declare const synastryOut: z.ZodObject<{
379
379
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
380
380
  orb: number;
381
381
  }[];
382
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
382
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
383
383
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
384
384
  houses_fallback_reason?: string | undefined;
385
385
  }, {
@@ -405,7 +405,7 @@ export declare const synastryOut: z.ZodObject<{
405
405
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
406
406
  orb: number;
407
407
  }[];
408
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
408
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
409
409
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
410
410
  houses_fallback_reason?: string | undefined;
411
411
  }>;
@@ -451,7 +451,7 @@ export declare const synastryOut: z.ZodObject<{
451
451
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
452
452
  orb: number;
453
453
  }[];
454
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
454
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
455
455
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
456
456
  houses_fallback_reason?: string | undefined;
457
457
  };
@@ -478,7 +478,7 @@ export declare const synastryOut: z.ZodObject<{
478
478
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
479
479
  orb: number;
480
480
  }[];
481
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
481
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
482
482
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
483
483
  houses_fallback_reason?: string | undefined;
484
484
  };
@@ -514,7 +514,7 @@ export declare const synastryOut: z.ZodObject<{
514
514
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
515
515
  orb: number;
516
516
  }[];
517
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
517
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
518
518
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
519
519
  houses_fallback_reason?: string | undefined;
520
520
  };
@@ -541,7 +541,7 @@ export declare const synastryOut: z.ZodObject<{
541
541
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
542
542
  orb: number;
543
543
  }[];
544
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
544
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
545
545
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
546
546
  houses_fallback_reason?: string | undefined;
547
547
  };
@@ -603,11 +603,44 @@ 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", "solar_eclipse", "lunar_eclipse"]>;
612
+ detail: z.ZodOptional<z.ZodString>;
613
+ }, "strip", z.ZodTypeAny, {
614
+ t: string;
615
+ kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing" | "solar_eclipse" | "lunar_eclipse";
616
+ detail?: string | undefined;
617
+ }, {
618
+ t: string;
619
+ kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing" | "solar_eclipse" | "lunar_eclipse";
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" | "solar_eclipse" | "lunar_eclipse";
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" | "solar_eclipse" | "lunar_eclipse";
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;
609
642
  houses: z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>;
610
- zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar"]>>;
643
+ zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar", "sidereal:galcent_0sag", "sidereal:true_citra"]>>;
611
644
  houses_requested: z.ZodOptional<z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>>;
612
645
  houses_fallback_reason: z.ZodOptional<z.ZodString>;
613
646
  bodies: z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -685,7 +718,7 @@ export declare const OUTPUT_SCHEMAS: {
685
718
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
686
719
  orb: number;
687
720
  }[];
688
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
721
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
689
722
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
690
723
  houses_fallback_reason?: string | undefined;
691
724
  }, {
@@ -711,14 +744,14 @@ export declare const OUTPUT_SCHEMAS: {
711
744
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
712
745
  orb: number;
713
746
  }[];
714
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
747
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
715
748
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
716
749
  houses_fallback_reason?: string | undefined;
717
750
  }>;
718
751
  readonly current_sky: z.ZodObject<{
719
752
  utc: z.ZodString;
720
753
  houses: z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>;
721
- zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar"]>>;
754
+ zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar", "sidereal:galcent_0sag", "sidereal:true_citra"]>>;
722
755
  houses_requested: z.ZodOptional<z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>>;
723
756
  houses_fallback_reason: z.ZodOptional<z.ZodString>;
724
757
  bodies: z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -796,7 +829,7 @@ export declare const OUTPUT_SCHEMAS: {
796
829
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
797
830
  orb: number;
798
831
  }[];
799
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
832
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
800
833
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
801
834
  houses_fallback_reason?: string | undefined;
802
835
  }, {
@@ -822,7 +855,7 @@ export declare const OUTPUT_SCHEMAS: {
822
855
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
823
856
  orb: number;
824
857
  }[];
825
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
858
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
826
859
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
827
860
  houses_fallback_reason?: string | undefined;
828
861
  }>;
@@ -893,7 +926,7 @@ export declare const OUTPUT_SCHEMAS: {
893
926
  a: z.ZodObject<{
894
927
  utc: z.ZodString;
895
928
  houses: z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>;
896
- zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar"]>>;
929
+ zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar", "sidereal:galcent_0sag", "sidereal:true_citra"]>>;
897
930
  houses_requested: z.ZodOptional<z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>>;
898
931
  houses_fallback_reason: z.ZodOptional<z.ZodString>;
899
932
  bodies: z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -971,7 +1004,7 @@ export declare const OUTPUT_SCHEMAS: {
971
1004
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
972
1005
  orb: number;
973
1006
  }[];
974
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
1007
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
975
1008
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
976
1009
  houses_fallback_reason?: string | undefined;
977
1010
  }, {
@@ -997,14 +1030,14 @@ export declare const OUTPUT_SCHEMAS: {
997
1030
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
998
1031
  orb: number;
999
1032
  }[];
1000
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
1033
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
1001
1034
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
1002
1035
  houses_fallback_reason?: string | undefined;
1003
1036
  }>;
1004
1037
  b: z.ZodObject<{
1005
1038
  utc: z.ZodString;
1006
1039
  houses: z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>;
1007
- zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar"]>>;
1040
+ zodiac: z.ZodOptional<z.ZodEnum<["tropical", "sidereal:lahiri", "sidereal:fagan_bradley", "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar", "sidereal:galcent_0sag", "sidereal:true_citra"]>>;
1008
1041
  houses_requested: z.ZodOptional<z.ZodEnum<["placidus", "whole_sign", "equal", "porphyry", "koch", "regiomontanus", "campanus", "alcabitius", "morinus", "meridian", "polich_page", "vehlow"]>>;
1009
1042
  houses_fallback_reason: z.ZodOptional<z.ZodString>;
1010
1043
  bodies: z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -1082,7 +1115,7 @@ export declare const OUTPUT_SCHEMAS: {
1082
1115
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
1083
1116
  orb: number;
1084
1117
  }[];
1085
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
1118
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
1086
1119
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
1087
1120
  houses_fallback_reason?: string | undefined;
1088
1121
  }, {
@@ -1108,7 +1141,7 @@ export declare const OUTPUT_SCHEMAS: {
1108
1141
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
1109
1142
  orb: number;
1110
1143
  }[];
1111
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
1144
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
1112
1145
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
1113
1146
  houses_fallback_reason?: string | undefined;
1114
1147
  }>;
@@ -1154,7 +1187,7 @@ export declare const OUTPUT_SCHEMAS: {
1154
1187
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
1155
1188
  orb: number;
1156
1189
  }[];
1157
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
1190
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
1158
1191
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
1159
1192
  houses_fallback_reason?: string | undefined;
1160
1193
  };
@@ -1181,7 +1214,7 @@ export declare const OUTPUT_SCHEMAS: {
1181
1214
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
1182
1215
  orb: number;
1183
1216
  }[];
1184
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
1217
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
1185
1218
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
1186
1219
  houses_fallback_reason?: string | undefined;
1187
1220
  };
@@ -1217,7 +1250,7 @@ export declare const OUTPUT_SCHEMAS: {
1217
1250
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
1218
1251
  orb: number;
1219
1252
  }[];
1220
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
1253
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
1221
1254
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
1222
1255
  houses_fallback_reason?: string | undefined;
1223
1256
  };
@@ -1244,7 +1277,7 @@ export declare const OUTPUT_SCHEMAS: {
1244
1277
  aspect: "conjunction" | "sextile" | "square" | "trine" | "opposition";
1245
1278
  orb: number;
1246
1279
  }[];
1247
- zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | undefined;
1280
+ zodiac?: "tropical" | "sidereal:lahiri" | "sidereal:fagan_bradley" | "sidereal:krishnamurti" | "sidereal:raman" | "sidereal:yukteshwar" | "sidereal:galcent_0sag" | "sidereal:true_citra" | undefined;
1248
1281
  houses_requested?: "placidus" | "whole_sign" | "equal" | "porphyry" | "koch" | "regiomontanus" | "campanus" | "alcabitius" | "morinus" | "meridian" | "polich_page" | "vehlow" | undefined;
1249
1282
  houses_fallback_reason?: string | undefined;
1250
1283
  };
@@ -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", "solar_eclipse", "lunar_eclipse"]>;
1348
+ detail: z.ZodOptional<z.ZodString>;
1349
+ }, "strip", z.ZodTypeAny, {
1350
+ t: string;
1351
+ kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing" | "solar_eclipse" | "lunar_eclipse";
1352
+ detail?: string | undefined;
1353
+ }, {
1354
+ t: string;
1355
+ kind: "set" | "rise" | "mtransit" | "itransit" | "phase" | "station" | "crossing" | "solar_eclipse" | "lunar_eclipse";
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" | "solar_eclipse" | "lunar_eclipse";
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" | "solar_eclipse" | "lunar_eclipse";
1372
+ detail?: string | undefined;
1373
+ }[];
1374
+ }>;
1309
1375
  };
1310
1376
  export declare function buildServer(): McpServer;
@@ -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 outcome-level tools, not API wrappers),
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, lunarEclipses, solarEclipses, } 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;
@@ -46,6 +46,7 @@ const houseSys = z.enum(HOUSE_SYSTEMS).default("placidus");
46
46
  const ZODIACS = [
47
47
  "tropical", "sidereal:lahiri", "sidereal:fagan_bradley",
48
48
  "sidereal:krishnamurti", "sidereal:raman", "sidereal:yukteshwar",
49
+ "sidereal:galcent_0sag", "sidereal:true_citra",
49
50
  ];
50
51
  const zodiacSchema = z.enum(ZODIACS).default("tropical")
51
52
  .describe("tropical (default) or sidereal:<ayanamsa>");
@@ -136,6 +137,16 @@ export const rectificationGridOut = z.object({
136
137
  asc_sign_changes: z.array(z.string()),
137
138
  grid: z.array(z.object({ utc: z.string(), asc: z.string(), mc: z.string() })),
138
139
  });
140
+ export const skyEventsOut = z.object({
141
+ start: z.string(),
142
+ end: z.string(),
143
+ events: z.array(z.object({
144
+ t: z.string(),
145
+ kind: z.enum(["rise", "set", "mtransit", "itransit", "phase", "station",
146
+ "crossing", "solar_eclipse", "lunar_eclipse"]),
147
+ detail: z.string().optional(),
148
+ })),
149
+ });
139
150
  export const OUTPUT_SCHEMAS = {
140
151
  natal_chart: chartOut,
141
152
  current_sky: chartOut,
@@ -143,12 +154,13 @@ export const OUTPUT_SCHEMAS = {
143
154
  synastry: synastryOut,
144
155
  find_aspect_dates: findAspectDatesOut,
145
156
  rectification_grid: rectificationGridOut,
157
+ sky_events: skyEventsOut,
146
158
  };
147
159
  // ---------------------------------------------------------------- server
148
160
  export function buildServer() {
149
161
  const server = new McpServer({ name: "caelus", version: VERSION });
150
162
  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″, nodes ≤1″.",
163
+ 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
164
  inputSchema: { ...birth, house_system: houseSys, zodiac: zodiacSchema },
153
165
  }, async ({ date, lat, lon, house_system, zodiac }) => text(chartPayload(date, lat, lon, house_system, zodiac)));
154
166
  server.registerTool("current_sky", {
@@ -338,6 +350,80 @@ export function buildServer() {
338
350
  }
339
351
  return text({ date: date.slice(0, 10), lat, lon, asc_sign_changes: boundaries, grid });
340
352
  });
353
+ server.registerTool("sky_events", {
354
+ description: "Sky events in a UTC date range: rise/set/meridian transits (need lat+lon+body), lunar phases (new/quarters/full), solar and lunar eclipses (global circumstances: type, magnitude, gamma), 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.",
355
+ inputSchema: {
356
+ start: z.string().describe("UTC ISO start date (convert from local first)"),
357
+ end: z.string().describe("UTC ISO end date; range <= 370 days"),
358
+ kinds: z.array(z.enum(["rise", "set", "mtransit", "itransit", "phase",
359
+ "station", "crossing", "solar_eclipse", "lunar_eclipse"]))
360
+ .min(1).describe("Event kinds to include"),
361
+ body: z.enum(BODIES).optional()
362
+ .describe("Required for rise/set/transit/station/crossing"),
363
+ lat: latSchema.optional().describe("Required for rise/set/transit"),
364
+ lon: lonSchema.optional().describe("Required for rise/set/transit"),
365
+ target_lon: z.number().min(0).max(360).optional()
366
+ .describe("Zodiac longitude for 'crossing', degrees"),
367
+ zodiac: zodiacSchema.describe("Zodiac for 'crossing' longitudes"),
368
+ },
369
+ }, async ({ start, end, kinds, body, lat, lon, target_lon, zodiac }) => {
370
+ const jd0 = jdFromIso(start);
371
+ const jd1 = jdFromIso(end);
372
+ if (jd1 - jd0 > 370)
373
+ throw new Error("Range too large (max 370 days)");
374
+ const iso = (jd) => new Date((jd - 2440587.5) * 86400000).toISOString().slice(0, 19) + "Z";
375
+ const events = [];
376
+ const riseKinds = kinds.filter((k) => k === "rise" || k === "set" || k === "mtransit" || k === "itransit");
377
+ if (riseKinds.length) {
378
+ if (body === undefined || lat === undefined || lon === undefined) {
379
+ throw new Error("rise/set/transit need body, lat, lon");
380
+ }
381
+ for (const k of riseKinds) {
382
+ let t = jd0;
383
+ while (t < jd1 && events.length < 200) {
384
+ const hit = riseSet(engine, body, t, lat, lon, k);
385
+ if (hit === null || hit > jd1)
386
+ break;
387
+ events.push({ t: iso(hit), kind: k });
388
+ t = hit + 1e-4;
389
+ }
390
+ }
391
+ }
392
+ if (kinds.includes("phase")) {
393
+ for (const [t, name] of lunarPhases(engine, jd0, jd1)) {
394
+ events.push({ t: iso(t), kind: "phase", detail: name });
395
+ }
396
+ }
397
+ if (kinds.includes("station")) {
398
+ if (body === undefined)
399
+ throw new Error("station needs body");
400
+ for (const [t, dir] of stations(engine, body, jd0, jd1)) {
401
+ events.push({ t: iso(t), kind: "station", detail: dir });
402
+ }
403
+ }
404
+ if (kinds.includes("lunar_eclipse")) {
405
+ for (const e of lunarEclipses(engine, jd0, jd1)) {
406
+ events.push({ t: iso(e.tMax), kind: "lunar_eclipse",
407
+ detail: `${e.type}, mag ${e.magUmbral > 0 ? e.magUmbral.toFixed(2) : e.magPenumbral.toFixed(2) + " penumbral"}` });
408
+ }
409
+ }
410
+ if (kinds.includes("solar_eclipse")) {
411
+ for (const e of solarEclipses(engine, jd0, jd1)) {
412
+ events.push({ t: iso(e.tMax), kind: "solar_eclipse",
413
+ detail: `${e.type}, gamma ${e.gamma.toFixed(2)}` });
414
+ }
415
+ }
416
+ if (kinds.includes("crossing")) {
417
+ if (body === undefined || target_lon === undefined) {
418
+ throw new Error("crossing needs body and target_lon");
419
+ }
420
+ for (const t of crossings(engine, body, target_lon, jd0, jd1, zodiac)) {
421
+ events.push({ t: iso(t), kind: "crossing", detail: `${target_lon}°` });
422
+ }
423
+ }
424
+ events.sort((a, b) => a.t.localeCompare(b.t));
425
+ return text({ start, end, events });
426
+ });
341
427
  return server;
342
428
  }
343
429
  // ---------------------------------------------------------------- main
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "caelus-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.5.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.3.0"
17
+ "caelus": "^0.5.0"
18
18
  },
19
19
  "devDependencies": {
20
20
  "ajv": "^8.17.1"