@morphemeris/mcp 0.4.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/dist/index.js CHANGED
@@ -68,23 +68,31 @@ var MorphemerisClient = class {
68
68
  // src/tools/calculate-positions.ts
69
69
  import { z } from "zod";
70
70
  function registerCalculatePositions(server2, client) {
71
- server2.tool(
71
+ server2.registerTool(
72
72
  "calculate_positions",
73
- "Calculates ecliptic positions (longitude, latitude, distance, daily motion) for celestial bodies at a given moment. Supports tropical and sidereal zodiacs, heliocentric and topocentric corrections, and equatorial coordinates.",
74
73
  {
75
- datetime: z.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
76
- jd: z.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
77
- bodies: z.string().optional().describe("Comma-separated body names, or group name: 'planets' (default), 'asteroids', 'all'. Use list_available_values to see all options."),
78
- lat: z.number().min(-90).max(90).optional().describe("Observer latitude in decimal degrees (-90 to 90). Required for topocentric correction."),
79
- lon: z.number().min(-180).max(180).optional().describe("Observer longitude in decimal degrees (-180 to 180, east positive). Required for topocentric correction."),
80
- alt: z.number().optional().describe("Observer altitude in meters above sea level."),
81
- sidereal: z.string().optional().describe("Ayanamsha system name or ID for sidereal positions. Use list_available_values to see options."),
82
- equatorial: z.boolean().optional().describe("If true, return Right Ascension / Declination instead of ecliptic longitude/latitude."),
83
- speed: z.boolean().optional().describe("Include daily motion in the response. Default: true."),
84
- topocentric: z.boolean().optional().describe("Apply topocentric correction (requires lat and lon)."),
85
- heliocentric: z.boolean().optional().describe("Return heliocentric positions instead of geocentric."),
86
- no_nutation: z.boolean().optional().describe("Skip nutation correction."),
87
- j2000: z.boolean().optional().describe("Use J2000 reference frame instead of ecliptic of date.")
74
+ title: "Calculate Planetary Positions",
75
+ description: "Calculates ecliptic positions (longitude, latitude, distance, daily motion) for celestial bodies at a given moment. Supports tropical and sidereal zodiacs, heliocentric and topocentric corrections, and equatorial coordinates.",
76
+ inputSchema: {
77
+ datetime: z.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
78
+ jd: z.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
79
+ bodies: z.string().optional().describe("Comma-separated body names, or group name: 'planets' (default), 'asteroids', 'all'. Use list_available_values to see all options."),
80
+ lat: z.number().min(-90).max(90).optional().describe("Observer latitude in decimal degrees (-90 to 90). Required for topocentric correction."),
81
+ lon: z.number().min(-180).max(180).optional().describe("Observer longitude in decimal degrees (-180 to 180, east positive). Required for topocentric correction."),
82
+ alt: z.number().optional().describe("Observer altitude in meters above sea level."),
83
+ sidereal: z.string().optional().describe("Ayanamsha system name or ID for sidereal positions. Use list_available_values to see options."),
84
+ equatorial: z.boolean().optional().describe("If true, return Right Ascension / Declination instead of ecliptic longitude/latitude."),
85
+ speed: z.boolean().optional().describe("Include daily motion in the response. Default: true."),
86
+ topocentric: z.boolean().optional().describe("Apply topocentric correction (requires lat and lon)."),
87
+ heliocentric: z.boolean().optional().describe("Return heliocentric positions instead of geocentric."),
88
+ no_nutation: z.boolean().optional().describe("Skip nutation correction."),
89
+ j2000: z.boolean().optional().describe("Use J2000 reference frame instead of ecliptic of date.")
90
+ },
91
+ annotations: {
92
+ readOnlyHint: true,
93
+ idempotentHint: true,
94
+ openWorldHint: true
95
+ }
88
96
  },
89
97
  async ({ datetime, jd, bodies, lat, lon, alt, sidereal, equatorial, speed, topocentric, heliocentric, no_nutation, j2000 }) => {
90
98
  if (!datetime && jd === void 0) {
@@ -118,16 +126,24 @@ function registerCalculatePositions(server2, client) {
118
126
  // src/tools/calculate-houses.ts
119
127
  import { z as z2 } from "zod";
120
128
  function registerCalculateHouses(server2, client) {
121
- server2.tool(
129
+ server2.registerTool(
122
130
  "calculate_houses",
123
- "Calculates house cusps and angles (Ascendant, MC, etc.) for a given moment and location. Supports 21 house systems and sidereal mode. Use list_available_values with category 'house_systems' to see all options.",
124
131
  {
125
- datetime: z2.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
126
- jd: z2.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
127
- lat: z2.number().min(-90).max(90).describe("Observer latitude in decimal degrees (-90 to 90). REQUIRED."),
128
- lon: z2.number().min(-180).max(180).describe("Observer longitude in decimal degrees (-180 to 180, east positive). REQUIRED."),
129
- system: z2.string().optional().describe("House system name or single-letter code. Default: 'placidus'. Use list_available_values to see options."),
130
- sidereal: z2.string().optional().describe("Ayanamsha system name or ID for sidereal house cusps.")
132
+ title: "Calculate House Cusps",
133
+ description: "Calculates house cusps and angles (Ascendant, MC, etc.) for a given moment and location. Supports 21 house systems and sidereal mode. Use list_available_values with category 'house_systems' to see all options.",
134
+ inputSchema: {
135
+ datetime: z2.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
136
+ jd: z2.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
137
+ lat: z2.number().min(-90).max(90).describe("Observer latitude in decimal degrees (-90 to 90). REQUIRED."),
138
+ lon: z2.number().min(-180).max(180).describe("Observer longitude in decimal degrees (-180 to 180, east positive). REQUIRED."),
139
+ system: z2.string().optional().describe("House system name or single-letter code. Default: 'placidus'. Use list_available_values to see options."),
140
+ sidereal: z2.string().optional().describe("Ayanamsha system name or ID for sidereal house cusps.")
141
+ },
142
+ annotations: {
143
+ readOnlyHint: true,
144
+ idempotentHint: true,
145
+ openWorldHint: true
146
+ }
131
147
  },
132
148
  async ({ datetime, jd, lat, lon, system, sidereal }) => {
133
149
  if (!datetime && jd === void 0) {
@@ -152,24 +168,32 @@ function registerCalculateHouses(server2, client) {
152
168
  // src/tools/calculate-chart.ts
153
169
  import { z as z3 } from "zod";
154
170
  function registerCalculateChart(server2, client) {
155
- server2.tool(
171
+ server2.registerTool(
156
172
  "calculate_chart",
157
- "Calculates a complete astrological chart: planetary positions, house cusps, and angles for a given moment and location. Combines calculate_positions and calculate_houses into one call. This is the most commonly used tool for natal charts, transits, and event charts.",
158
173
  {
159
- datetime: z3.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
160
- jd: z3.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
161
- lat: z3.number().min(-90).max(90).describe("Observer latitude in decimal degrees (-90 to 90). REQUIRED."),
162
- lon: z3.number().min(-180).max(180).describe("Observer longitude in decimal degrees (-180 to 180, east positive). REQUIRED."),
163
- bodies: z3.string().optional().describe("Comma-separated body names, or group name: 'planets' (default), 'asteroids', 'all'."),
164
- alt: z3.number().optional().describe("Observer altitude in meters above sea level."),
165
- system: z3.string().optional().describe("House system name or single-letter code. Default: 'placidus'."),
166
- sidereal: z3.string().optional().describe("Ayanamsha system name or ID for sidereal positions and house cusps."),
167
- equatorial: z3.boolean().optional().describe("If true, return Right Ascension / Declination instead of ecliptic coordinates."),
168
- speed: z3.boolean().optional().describe("Include daily motion. Default: true."),
169
- topocentric: z3.boolean().optional().describe("Apply topocentric correction."),
170
- heliocentric: z3.boolean().optional().describe("Return heliocentric positions."),
171
- no_nutation: z3.boolean().optional().describe("Skip nutation correction."),
172
- j2000: z3.boolean().optional().describe("Use J2000 reference frame.")
174
+ title: "Calculate Complete Chart",
175
+ description: "Calculates a complete astrological chart: planetary positions, house cusps, and angles for a given moment and location. Combines calculate_positions and calculate_houses into one call. This is the most commonly used tool for natal charts, transits, and event charts.",
176
+ inputSchema: {
177
+ datetime: z3.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
178
+ jd: z3.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
179
+ lat: z3.number().min(-90).max(90).describe("Observer latitude in decimal degrees (-90 to 90). REQUIRED."),
180
+ lon: z3.number().min(-180).max(180).describe("Observer longitude in decimal degrees (-180 to 180, east positive). REQUIRED."),
181
+ bodies: z3.string().optional().describe("Comma-separated body names, or group name: 'planets' (default), 'asteroids', 'all'."),
182
+ alt: z3.number().optional().describe("Observer altitude in meters above sea level."),
183
+ system: z3.string().optional().describe("House system name or single-letter code. Default: 'placidus'."),
184
+ sidereal: z3.string().optional().describe("Ayanamsha system name or ID for sidereal positions and house cusps."),
185
+ equatorial: z3.boolean().optional().describe("If true, return Right Ascension / Declination instead of ecliptic coordinates."),
186
+ speed: z3.boolean().optional().describe("Include daily motion. Default: true."),
187
+ topocentric: z3.boolean().optional().describe("Apply topocentric correction."),
188
+ heliocentric: z3.boolean().optional().describe("Return heliocentric positions."),
189
+ no_nutation: z3.boolean().optional().describe("Skip nutation correction."),
190
+ j2000: z3.boolean().optional().describe("Use J2000 reference frame.")
191
+ },
192
+ annotations: {
193
+ readOnlyHint: true,
194
+ idempotentHint: true,
195
+ openWorldHint: true
196
+ }
173
197
  },
174
198
  async ({ datetime, jd, lat, lon, bodies, alt, system, sidereal, equatorial, speed, topocentric, heliocentric, no_nutation, j2000 }) => {
175
199
  if (!datetime && jd === void 0) {
@@ -202,16 +226,24 @@ function registerCalculateChart(server2, client) {
202
226
  // src/tools/get-fixed-stars.ts
203
227
  import { z as z4 } from "zod";
204
228
  function registerGetFixedStars(server2, client) {
205
- server2.tool(
229
+ server2.registerTool(
206
230
  "get_fixed_stars",
207
- "Returns position data for one or all fixed stars at a given moment. Includes ecliptic coordinates, magnitude, and spectral type. Use star name (e.g. 'Aldebaran') or Bayer designation (e.g. 'alTau'), or 'all' for the full catalog.",
208
231
  {
209
- datetime: z4.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
210
- jd: z4.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
211
- star: z4.string().describe("Star name (e.g. 'Aldebaran', 'Regulus'), Bayer designation (e.g. 'alTau'), or 'all' for every star."),
212
- lat: z4.number().min(-90).max(90).optional().describe("Observer latitude in decimal degrees (-90 to 90)."),
213
- lon: z4.number().min(-180).max(180).optional().describe("Observer longitude in decimal degrees (-180 to 180, east positive)."),
214
- equatorial: z4.boolean().optional().describe("If true, return Right Ascension / Declination instead of ecliptic coordinates.")
232
+ title: "Get Fixed Star Positions",
233
+ description: "Returns position data for one or all fixed stars at a given moment. Includes ecliptic coordinates, magnitude, and spectral type. Use star name (e.g. 'Aldebaran') or Bayer designation (e.g. 'alTau'), or 'all' for the full catalog.",
234
+ inputSchema: {
235
+ datetime: z4.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
236
+ jd: z4.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
237
+ star: z4.string().describe("Star name (e.g. 'Aldebaran', 'Regulus'), Bayer designation (e.g. 'alTau'), or 'all' for every star."),
238
+ lat: z4.number().min(-90).max(90).optional().describe("Observer latitude in decimal degrees (-90 to 90)."),
239
+ lon: z4.number().min(-180).max(180).optional().describe("Observer longitude in decimal degrees (-180 to 180, east positive)."),
240
+ equatorial: z4.boolean().optional().describe("If true, return Right Ascension / Declination instead of ecliptic coordinates.")
241
+ },
242
+ annotations: {
243
+ readOnlyHint: true,
244
+ idempotentHint: true,
245
+ openWorldHint: true
246
+ }
215
247
  },
216
248
  async ({ datetime, jd, star, lat, lon, equatorial }) => {
217
249
  if (!datetime && jd === void 0) {
@@ -237,13 +269,21 @@ function registerGetFixedStars(server2, client) {
237
269
  // src/tools/get-ayanamsha.ts
238
270
  import { z as z5 } from "zod";
239
271
  function registerGetAyanamsha(server2, client) {
240
- server2.tool(
272
+ server2.registerTool(
241
273
  "get_ayanamsha",
242
- "Returns the ayanamsha value (precession offset) for a given moment and system. Used to convert between tropical and sidereal zodiacs. Use list_available_values with category 'ayanamsha_systems' to see all 47 supported systems.",
243
274
  {
244
- datetime: z5.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
245
- jd: z5.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
246
- system: z5.string().optional().describe("Ayanamsha system name or numeric ID. Default: 'lahiri'. Use 'all' to return all 47 systems.")
275
+ title: "Get Ayanamsha Value",
276
+ description: "Returns the ayanamsha value (precession offset) for a given moment and system. Used to convert between tropical and sidereal zodiacs. Use list_available_values with category 'ayanamsha_systems' to see all 47 supported systems.",
277
+ inputSchema: {
278
+ datetime: z5.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
279
+ jd: z5.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
280
+ system: z5.string().optional().describe("Ayanamsha system name or numeric ID. Default: 'lahiri'. Use 'all' to return all 47 systems.")
281
+ },
282
+ annotations: {
283
+ readOnlyHint: true,
284
+ idempotentHint: true,
285
+ openWorldHint: true
286
+ }
247
287
  },
248
288
  async ({ datetime, jd, system }) => {
249
289
  if (!datetime && jd === void 0) {
@@ -267,12 +307,20 @@ function registerGetAyanamsha(server2, client) {
267
307
  // src/tools/get-delta-t.ts
268
308
  import { z as z6 } from "zod";
269
309
  function registerGetDeltaT(server2, client) {
270
- server2.tool(
310
+ server2.registerTool(
271
311
  "get_delta_t",
272
- "Returns Delta T (the difference between Terrestrial Time and Universal Time) for a given moment. Useful for converting between time scales in astronomical calculations.",
273
312
  {
274
- datetime: z6.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
275
- jd: z6.number().optional().describe("Julian Day number in UT1, e.g. 2460310.0. Provide either datetime or jd.")
313
+ title: "Get Delta T",
314
+ description: "Returns Delta T (the difference between Terrestrial Time and Universal Time) for a given moment. Useful for converting between time scales in astronomical calculations.",
315
+ inputSchema: {
316
+ datetime: z6.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
317
+ jd: z6.number().optional().describe("Julian Day number in UT1, e.g. 2460310.0. Provide either datetime or jd.")
318
+ },
319
+ annotations: {
320
+ readOnlyHint: true,
321
+ idempotentHint: true,
322
+ openWorldHint: true
323
+ }
276
324
  },
277
325
  async ({ datetime, jd }) => {
278
326
  if (!datetime && jd === void 0) {
@@ -295,13 +343,21 @@ function registerGetDeltaT(server2, client) {
295
343
  // src/tools/get-sidereal-time.ts
296
344
  import { z as z7 } from "zod";
297
345
  function registerGetSiderealTime(server2, client) {
298
- server2.tool(
346
+ server2.registerTool(
299
347
  "get_sidereal_time",
300
- "Returns Greenwich Apparent Sidereal Time (GAST) and optionally Local Sidereal Time (LST) for a given moment. LST is included when longitude is provided.",
301
348
  {
302
- datetime: z7.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
303
- jd: z7.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
304
- lon: z7.number().min(-180).max(180).optional().describe("Observer longitude in decimal degrees (-180 to 180, east positive). If provided, Local Sidereal Time is included.")
349
+ title: "Get Sidereal Time",
350
+ description: "Returns Greenwich Apparent Sidereal Time (GAST) and optionally Local Sidereal Time (LST) for a given moment. LST is included when longitude is provided.",
351
+ inputSchema: {
352
+ datetime: z7.string().optional().describe("ISO 8601 UTC datetime, e.g. '2024-01-01T12:00:00Z'. Provide either datetime or jd."),
353
+ jd: z7.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
354
+ lon: z7.number().min(-180).max(180).optional().describe("Observer longitude in decimal degrees (-180 to 180, east positive). If provided, Local Sidereal Time is included.")
355
+ },
356
+ annotations: {
357
+ readOnlyHint: true,
358
+ idempotentHint: true,
359
+ openWorldHint: true
360
+ }
305
361
  },
306
362
  async ({ datetime, jd, lon }) => {
307
363
  if (!datetime && jd === void 0) {
@@ -325,18 +381,26 @@ function registerGetSiderealTime(server2, client) {
325
381
  // src/tools/find-eclipses-solar.ts
326
382
  import { z as z8 } from "zod";
327
383
  function registerFindSolarEclipses(server2, client) {
328
- server2.tool(
384
+ server2.registerTool(
329
385
  "find_solar_eclipses",
330
- "Finds upcoming or past solar eclipses from a given date. Returns global eclipse data by default, or location-specific data (magnitude, obscuration) when observer coordinates are provided. Supports filtering by eclipse type and returning multiple results.",
331
386
  {
332
- datetime: z8.string().optional().describe("ISO 8601 UTC datetime to search from. Provide either datetime or jd."),
333
- jd: z8.number().optional().describe("Julian Day number in UT1 to search from. Provide either datetime or jd."),
334
- lat: z8.number().min(-90).max(90).optional().describe("Observer latitude (-90 to 90). Enables local mode with magnitude and obscuration."),
335
- lon: z8.number().min(-180).max(180).optional().describe("Observer longitude (-180 to 180, east positive)."),
336
- alt: z8.number().optional().describe("Observer altitude in meters above sea level."),
337
- type: z8.string().optional().describe("Filter by eclipse type: 'total', 'annular', 'partial', 'annular_total' (comma-separated)."),
338
- backward: z8.boolean().optional().describe("If true, search backward in time. Default: false."),
339
- count: z8.number().min(1).max(10).optional().describe("Number of eclipses to return (1-10). Default: 1.")
387
+ title: "Find Solar Eclipses",
388
+ description: "Finds upcoming or past solar eclipses from a given date. Returns global eclipse data by default, or location-specific data (magnitude, obscuration) when observer coordinates are provided. Supports filtering by eclipse type and returning multiple results.",
389
+ inputSchema: {
390
+ datetime: z8.string().optional().describe("ISO 8601 UTC datetime to search from. Provide either datetime or jd."),
391
+ jd: z8.number().optional().describe("Julian Day number in UT1 to search from. Provide either datetime or jd."),
392
+ lat: z8.number().min(-90).max(90).optional().describe("Observer latitude (-90 to 90). Enables local mode with magnitude and obscuration."),
393
+ lon: z8.number().min(-180).max(180).optional().describe("Observer longitude (-180 to 180, east positive)."),
394
+ alt: z8.number().optional().describe("Observer altitude in meters above sea level."),
395
+ type: z8.string().optional().describe("Filter by eclipse type: 'total', 'annular', 'partial', 'annular_total' (comma-separated)."),
396
+ backward: z8.boolean().optional().describe("If true, search backward in time. Default: false."),
397
+ count: z8.number().min(1).max(10).optional().describe("Number of eclipses to return (1-10). Default: 1.")
398
+ },
399
+ annotations: {
400
+ readOnlyHint: true,
401
+ idempotentHint: true,
402
+ openWorldHint: true
403
+ }
340
404
  },
341
405
  async ({ datetime, jd, lat, lon, alt, type, backward, count }) => {
342
406
  if (!datetime && jd === void 0) {
@@ -365,18 +429,26 @@ function registerFindSolarEclipses(server2, client) {
365
429
  // src/tools/find-eclipses-lunar.ts
366
430
  import { z as z9 } from "zod";
367
431
  function registerFindLunarEclipses(server2, client) {
368
- server2.tool(
432
+ server2.registerTool(
369
433
  "find_lunar_eclipses",
370
- "Finds upcoming or past lunar eclipses from a given date. Returns eclipse phase times (penumbral, partial, total). When observer coordinates are provided, includes a visibility flag. Supports filtering by type and returning multiple results.",
371
434
  {
372
- datetime: z9.string().optional().describe("ISO 8601 UTC datetime to search from. Provide either datetime or jd."),
373
- jd: z9.number().optional().describe("Julian Day number in UT1 to search from. Provide either datetime or jd."),
374
- lat: z9.number().min(-90).max(90).optional().describe("Observer latitude (-90 to 90). Enables visibility check."),
375
- lon: z9.number().min(-180).max(180).optional().describe("Observer longitude (-180 to 180, east positive)."),
376
- alt: z9.number().optional().describe("Observer altitude in meters above sea level."),
377
- type: z9.string().optional().describe("Filter by eclipse type: 'total', 'partial', 'penumbral' (comma-separated)."),
378
- backward: z9.boolean().optional().describe("If true, search backward in time. Default: false."),
379
- count: z9.number().min(1).max(10).optional().describe("Number of eclipses to return (1-10). Default: 1.")
435
+ title: "Find Lunar Eclipses",
436
+ description: "Finds upcoming or past lunar eclipses from a given date. Returns eclipse phase times (penumbral, partial, total). When observer coordinates are provided, includes a visibility flag. Supports filtering by type and returning multiple results.",
437
+ inputSchema: {
438
+ datetime: z9.string().optional().describe("ISO 8601 UTC datetime to search from. Provide either datetime or jd."),
439
+ jd: z9.number().optional().describe("Julian Day number in UT1 to search from. Provide either datetime or jd."),
440
+ lat: z9.number().min(-90).max(90).optional().describe("Observer latitude (-90 to 90). Enables visibility check."),
441
+ lon: z9.number().min(-180).max(180).optional().describe("Observer longitude (-180 to 180, east positive)."),
442
+ alt: z9.number().optional().describe("Observer altitude in meters above sea level."),
443
+ type: z9.string().optional().describe("Filter by eclipse type: 'total', 'partial', 'penumbral' (comma-separated)."),
444
+ backward: z9.boolean().optional().describe("If true, search backward in time. Default: false."),
445
+ count: z9.number().min(1).max(10).optional().describe("Number of eclipses to return (1-10). Default: 1.")
446
+ },
447
+ annotations: {
448
+ readOnlyHint: true,
449
+ idempotentHint: true,
450
+ openWorldHint: true
451
+ }
380
452
  },
381
453
  async ({ datetime, jd, lat, lon, alt, type, backward, count }) => {
382
454
  if (!datetime && jd === void 0) {
@@ -405,33 +477,41 @@ function registerFindLunarEclipses(server2, client) {
405
477
  // src/tools/find-heliacal-event.ts
406
478
  import { z as z10 } from "zod";
407
479
  function registerFindHeliacalEvent(server2, client) {
408
- server2.tool(
480
+ server2.registerTool(
409
481
  "find_heliacal_event",
410
- "Finds the next heliacal rising or setting of a planet \u2014 when it first becomes visible in the morning or evening sky. Requires observer location. Uses the Schaefer sky brightness model with configurable atmospheric and observer parameters. Sun and Moon are excluded. Outer planets cannot have evening_first or morning_last events.",
411
482
  {
412
- datetime: z10.string().optional().describe("ISO 8601 UTC datetime to search from. Provide either datetime or jd."),
413
- jd: z10.number().optional().describe("Julian Day number in UT1 to search from. Provide either datetime or jd."),
414
- body: z10.string().describe("Planet name (not sun or moon). E.g., 'venus', 'mars', 'jupiter'."),
415
- event: z10.enum([
416
- "morning_first",
417
- "evening_last",
418
- "evening_first",
419
- "morning_last",
420
- "acronychal_rising",
421
- "acronychal_setting"
422
- ]).describe("Heliacal event type. evening_first and morning_last are for inner planets only."),
423
- lat: z10.number().min(-90).max(90).describe("Observer latitude in decimal degrees (-90 to 90). Required."),
424
- lon: z10.number().min(-180).max(180).describe("Observer longitude in decimal degrees (-180 to 180, east positive). Required."),
425
- alt: z10.number().optional().describe("Observer altitude in meters above sea level. Default: 0."),
426
- pressure_mbar: z10.number().optional().describe("Atmospheric pressure in mbar. Default: 1013.25."),
427
- temp_celsius: z10.number().optional().describe("Temperature in Celsius. Default: 15.0."),
428
- humidity_pct: z10.number().optional().describe("Relative humidity (0-100). Default: 40.0."),
429
- visibility_range_km: z10.number().optional().describe("Visibility range in km (0 = model default). Default: 0.0."),
430
- age_years: z10.number().optional().describe("Observer age in years. Default: 36.0."),
431
- snellen_ratio: z10.number().optional().describe("Visual acuity (1.0 = normal). Default: 1.0."),
432
- binoculars: z10.boolean().optional().describe("Binocular vision. Default: true."),
433
- telescope_aperture_cm: z10.number().optional().describe("Telescope aperture in cm (0 = naked eye). Default: 0.0."),
434
- telescope_magnification: z10.number().optional().describe("Telescope magnification (1.0 = naked eye). Default: 1.0.")
483
+ title: "Find Heliacal Event",
484
+ description: "Finds the next heliacal rising or setting of a planet \u2014 when it first becomes visible in the morning or evening sky. Requires observer location. Uses the Schaefer sky brightness model with configurable atmospheric and observer parameters. Sun and Moon are excluded. Outer planets cannot have evening_first or morning_last events.",
485
+ inputSchema: {
486
+ datetime: z10.string().optional().describe("ISO 8601 UTC datetime to search from. Provide either datetime or jd."),
487
+ jd: z10.number().optional().describe("Julian Day number in UT1 to search from. Provide either datetime or jd."),
488
+ body: z10.string().describe("Planet name (not sun or moon). E.g., 'venus', 'mars', 'jupiter'."),
489
+ event: z10.enum([
490
+ "morning_first",
491
+ "evening_last",
492
+ "evening_first",
493
+ "morning_last",
494
+ "acronychal_rising",
495
+ "acronychal_setting"
496
+ ]).describe("Heliacal event type. evening_first and morning_last are for inner planets only."),
497
+ lat: z10.number().min(-90).max(90).describe("Observer latitude in decimal degrees (-90 to 90). Required."),
498
+ lon: z10.number().min(-180).max(180).describe("Observer longitude in decimal degrees (-180 to 180, east positive). Required."),
499
+ alt: z10.number().optional().describe("Observer altitude in meters above sea level. Default: 0."),
500
+ pressure_mbar: z10.number().optional().describe("Atmospheric pressure in mbar. Default: 1013.25."),
501
+ temp_celsius: z10.number().optional().describe("Temperature in Celsius. Default: 15.0."),
502
+ humidity_pct: z10.number().optional().describe("Relative humidity (0-100). Default: 40.0."),
503
+ visibility_range_km: z10.number().optional().describe("Visibility range in km (0 = model default). Default: 0.0."),
504
+ age_years: z10.number().optional().describe("Observer age in years. Default: 36.0."),
505
+ snellen_ratio: z10.number().optional().describe("Visual acuity (1.0 = normal). Default: 1.0."),
506
+ binoculars: z10.boolean().optional().describe("Binocular vision. Default: true."),
507
+ telescope_aperture_cm: z10.number().optional().describe("Telescope aperture in cm (0 = naked eye). Default: 0.0."),
508
+ telescope_magnification: z10.number().optional().describe("Telescope magnification (1.0 = naked eye). Default: 1.0.")
509
+ },
510
+ annotations: {
511
+ readOnlyHint: true,
512
+ idempotentHint: true,
513
+ openWorldHint: true
514
+ }
435
515
  },
436
516
  async ({
437
517
  datetime,
@@ -485,17 +565,25 @@ function registerFindHeliacalEvent(server2, client) {
485
565
  // src/tools/find-ingresses.ts
486
566
  import { z as z11 } from "zod";
487
567
  function registerFindIngresses(server2, client) {
488
- server2.tool(
568
+ server2.registerTool(
489
569
  "find_ingresses",
490
- "Finds when a planet crosses into a zodiac sign or reaches a specific ecliptic longitude. Useful for tracking equinoxes, solstices, and zodiac ingresses. Provide either 'sign' (e.g., 'aries') or 'longitude' (0-360), not both. Supported bodies: sun, moon, mercury, venus, mars, jupiter, saturn, uranus, neptune, pluto.",
491
570
  {
492
- datetime: z11.string().optional().describe("ISO 8601 UTC datetime to search from. Provide either datetime or jd."),
493
- jd: z11.number().optional().describe("Julian Day number in UT1 to search from. Provide either datetime or jd."),
494
- body: z11.string().describe("Body name: sun, moon, mercury, venus, mars, jupiter, saturn, uranus, neptune, pluto."),
495
- sign: z11.string().optional().describe("Zodiac sign name (e.g., 'aries', 'taurus'). Provide either sign or longitude."),
496
- longitude: z11.number().min(0).max(360).optional().describe("Target ecliptic longitude (0-360). Provide either sign or longitude."),
497
- backward: z11.boolean().optional().describe("If true, search backward in time. Default: false."),
498
- count: z11.number().min(1).max(10).optional().describe("Number of ingresses to return (1-10). Default: 1.")
571
+ title: "Find Zodiac Ingresses",
572
+ description: "Finds when a planet crosses into a zodiac sign or reaches a specific ecliptic longitude. Useful for tracking equinoxes, solstices, and zodiac ingresses. Provide either 'sign' (e.g., 'aries') or 'longitude' (0-360), not both. Supported bodies: sun, moon, mercury, venus, mars, jupiter, saturn, uranus, neptune, pluto.",
573
+ inputSchema: {
574
+ datetime: z11.string().optional().describe("ISO 8601 UTC datetime to search from. Provide either datetime or jd."),
575
+ jd: z11.number().optional().describe("Julian Day number in UT1 to search from. Provide either datetime or jd."),
576
+ body: z11.string().describe("Body name: sun, moon, mercury, venus, mars, jupiter, saturn, uranus, neptune, pluto."),
577
+ sign: z11.string().optional().describe("Zodiac sign name (e.g., 'aries', 'taurus'). Provide either sign or longitude."),
578
+ longitude: z11.number().min(0).max(360).optional().describe("Target ecliptic longitude (0-360). Provide either sign or longitude."),
579
+ backward: z11.boolean().optional().describe("If true, search backward in time. Default: false."),
580
+ count: z11.number().min(1).max(10).optional().describe("Number of ingresses to return (1-10). Default: 1.")
581
+ },
582
+ annotations: {
583
+ readOnlyHint: true,
584
+ idempotentHint: true,
585
+ openWorldHint: true
586
+ }
499
587
  },
500
588
  async ({ datetime, jd, body: bodyName, sign, longitude, backward, count }) => {
501
589
  if (!datetime && jd === void 0) {
@@ -693,20 +781,28 @@ var VALID_SIGN_NAMES = new Set(ZODIAC_SIGNS.map((s) => s.name));
693
781
 
694
782
  // src/tools/list-available-values.ts
695
783
  function registerListAvailableValues(server2) {
696
- server2.tool(
784
+ server2.registerTool(
697
785
  "list_available_values",
698
- "Lists valid values for celestial bodies, house systems, ayanamsha systems, eclipse types, heliacal events, or zodiac signs. Use this to discover what values are accepted by other tools.",
699
786
  {
700
- category: z12.enum([
701
- "bodies",
702
- "house_systems",
703
- "ayanamsha_systems",
704
- "eclipse_types",
705
- "heliacal_events",
706
- "zodiac_signs"
707
- ]).describe(
708
- "Which category to list: 'bodies', 'house_systems', 'ayanamsha_systems', 'eclipse_types', 'heliacal_events', or 'zodiac_signs'"
709
- )
787
+ title: "List Available Values",
788
+ description: "Lists valid values for celestial bodies, house systems, ayanamsha systems, eclipse types, heliacal events, or zodiac signs. Use this to discover what values are accepted by other tools.",
789
+ inputSchema: {
790
+ category: z12.enum([
791
+ "bodies",
792
+ "house_systems",
793
+ "ayanamsha_systems",
794
+ "eclipse_types",
795
+ "heliacal_events",
796
+ "zodiac_signs"
797
+ ]).describe(
798
+ "Which category to list: 'bodies', 'house_systems', 'ayanamsha_systems', 'eclipse_types', 'heliacal_events', or 'zodiac_signs'"
799
+ )
800
+ },
801
+ annotations: {
802
+ readOnlyHint: true,
803
+ idempotentHint: true,
804
+ openWorldHint: false
805
+ }
710
806
  },
711
807
  async ({ category }) => {
712
808
  let result;
@@ -783,13 +879,21 @@ function registerListAvailableValues(server2) {
783
879
  // src/tools/batch-requests.ts
784
880
  import { z as z13 } from "zod";
785
881
  function registerBatchRequests(server2, client) {
786
- server2.tool(
882
+ server2.registerTool(
787
883
  "batch_requests",
788
- "Send up to 50 sub-requests in a single API call. Each sub-request specifies an endpoint and its parameters. Sub-requests execute sequentially; individual failures do not abort the batch. Credit cost is the sum of individual endpoint costs. Counts as 1 rate-limit request. Ideal for computing positions across a date range, fetching a full chart (positions + houses + stars), or any workflow that would otherwise require many sequential API calls.",
789
884
  {
790
- requests_json: z13.string().describe(
791
- 'JSON array of sub-requests. Each element: {"endpoint": "/v1/positions", "params": {...}}. Allowed endpoints: /v1/positions, /v1/houses, /v1/chart, /v1/stars, /v1/ayanamsha, /v1/delta-t, /v1/sidereal-time, /v1/eclipses/solar, /v1/eclipses/lunar, /v1/heliacal, /v1/ingresses. Max 50 sub-requests. Nested /v1/batch is NOT allowed. Example: [{"endpoint":"/v1/positions","params":{"datetime":"2024-01-01T00:00:00Z","bodies":"sun,moon"}}]'
792
- )
885
+ title: "Batch API Requests",
886
+ description: "Send up to 50 sub-requests in a single API call. Each sub-request specifies an endpoint and its parameters. Sub-requests execute sequentially; individual failures do not abort the batch. Credit cost is the sum of individual endpoint costs. Counts as 1 rate-limit request. Ideal for computing positions across a date range, fetching a full chart (positions + houses + stars), or any workflow that would otherwise require many sequential API calls.",
887
+ inputSchema: {
888
+ requests_json: z13.string().describe(
889
+ 'JSON array of sub-requests. Each element: {"endpoint": "/v1/positions", "params": {...}}. Allowed endpoints: /v1/positions, /v1/houses, /v1/chart, /v1/stars, /v1/ayanamsha, /v1/delta-t, /v1/sidereal-time, /v1/eclipses/solar, /v1/eclipses/lunar, /v1/heliacal, /v1/ingresses. Max 50 sub-requests. Nested /v1/batch is NOT allowed. Example: [{"endpoint":"/v1/positions","params":{"datetime":"2024-01-01T00:00:00Z","bodies":"sun,moon"}}]'
890
+ )
891
+ },
892
+ annotations: {
893
+ readOnlyHint: true,
894
+ idempotentHint: true,
895
+ openWorldHint: true
896
+ }
793
897
  },
794
898
  async ({ requests_json }) => {
795
899
  let requests;
@@ -840,22 +944,30 @@ function registerBatchRequests(server2, client) {
840
944
  // src/tools/natal-chart.ts
841
945
  import { z as z14 } from "zod";
842
946
  function registerNatalChart(server2, client) {
843
- server2.tool(
947
+ server2.registerTool(
844
948
  "natal_chart",
845
- "Computes a full natal chart with positions (sign, house, retrograde, out-of-bounds), house cusps, aspects, and parallels. This is the recommended tool for complete chart analysis \u2014 it returns everything in one call. Cost: 2 credits.",
846
949
  {
847
- datetime: z14.string().optional().describe("ISO 8601 UTC datetime. Provide either datetime or jd."),
848
- jd: z14.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
849
- lat: z14.number().min(-90).max(90).describe("Observer latitude in decimal degrees. REQUIRED."),
850
- lon: z14.number().min(-180).max(180).describe("Observer longitude in decimal degrees (east positive). REQUIRED."),
851
- bodies: z14.string().optional().describe("Comma-separated body names, or 'planets' (default), 'asteroids', 'all'."),
852
- system: z14.string().optional().describe("House system name or code. Default: 'placidus'."),
853
- sidereal: z14.string().optional().describe("Ayanamsha system for sidereal positions."),
854
- aspects: z14.string().optional().describe("Comma-separated aspect types. Default: conjunction,opposition,trine,square,sextile,semi_sextile,quincunx."),
855
- orb: z14.number().optional().describe("Default orb in degrees for all aspects (0-30)."),
856
- applying: z14.boolean().optional().describe("Compute applying/separating status. Default: true."),
857
- parallels: z14.boolean().optional().describe("Include parallels/contraparallels. Default: true."),
858
- parallel_orb: z14.number().optional().describe("Parallel orb in degrees (0-5). Default: 1.0.")
950
+ title: "Compute Natal Chart",
951
+ description: "Computes a full natal chart with positions (sign, house, retrograde, out-of-bounds), house cusps, aspects, and parallels. This is the recommended tool for complete chart analysis \u2014 it returns everything in one call. Cost: 2 credits.",
952
+ inputSchema: {
953
+ datetime: z14.string().optional().describe("ISO 8601 UTC datetime. Provide either datetime or jd."),
954
+ jd: z14.number().optional().describe("Julian Day number in UT1. Provide either datetime or jd."),
955
+ lat: z14.number().min(-90).max(90).describe("Observer latitude in decimal degrees. REQUIRED."),
956
+ lon: z14.number().min(-180).max(180).describe("Observer longitude in decimal degrees (east positive). REQUIRED."),
957
+ bodies: z14.string().optional().describe("Comma-separated body names, or 'planets' (default), 'asteroids', 'all'."),
958
+ system: z14.string().optional().describe("House system name or code. Default: 'placidus'."),
959
+ sidereal: z14.string().optional().describe("Ayanamsha system for sidereal positions."),
960
+ aspects: z14.string().optional().describe("Comma-separated aspect types. Default: conjunction,opposition,trine,square,sextile,semi_sextile,quincunx."),
961
+ orb: z14.number().optional().describe("Default orb in degrees for all aspects (0-30)."),
962
+ applying: z14.boolean().optional().describe("Compute applying/separating status. Default: true."),
963
+ parallels: z14.boolean().optional().describe("Include parallels/contraparallels. Default: true."),
964
+ parallel_orb: z14.number().optional().describe("Parallel orb in degrees (0-5). Default: 1.0.")
965
+ },
966
+ annotations: {
967
+ readOnlyHint: true,
968
+ idempotentHint: true,
969
+ openWorldHint: true
970
+ }
859
971
  },
860
972
  async ({ datetime, jd, lat, lon, bodies, system, sidereal, aspects, orb, applying, parallels, parallel_orb }) => {
861
973
  if (!datetime && jd === void 0) {
@@ -881,19 +993,27 @@ function registerNatalChart(server2, client) {
881
993
  // src/tools/aspects.ts
882
994
  import { z as z15 } from "zod";
883
995
  function registerAspects(server2, client) {
884
- server2.tool(
996
+ server2.registerTool(
885
997
  "calculate_aspects",
886
- "Computes aspects (angular relationships) and optionally parallels between bodies at a given time. No location or houses required. Returns aspect type, orb, and applying/separating status. Cost: 1 credit.",
887
998
  {
888
- datetime: z15.string().optional().describe("ISO 8601 UTC datetime. Provide either datetime or jd."),
889
- jd: z15.number().optional().describe("Julian Day number in UT1."),
890
- bodies: z15.string().optional().describe("Comma-separated body names, or 'planets' (default), 'asteroids', 'all'."),
891
- aspects: z15.string().optional().describe("Comma-separated aspect types. Default: major aspects. Available: conjunction, opposition, trine, square, sextile, semi_sextile, quincunx, semi_square, sesquiquadrate, quintile, bi_quintile, septile, bi_septile, tri_septile, quindecile."),
892
- orb: z15.number().optional().describe("Default orb in degrees for all aspects (0-30)."),
893
- applying: z15.boolean().optional().describe("Compute applying/separating status. Default: true."),
894
- parallels: z15.boolean().optional().describe("Include parallels/contraparallels. Default: true."),
895
- parallel_orb: z15.number().optional().describe("Parallel orb in degrees (0-5). Default: 1.0."),
896
- contraparallel: z15.boolean().optional().describe("Include contraparallels. Default: true.")
999
+ title: "Calculate Aspects",
1000
+ description: "Computes aspects (angular relationships) and optionally parallels between bodies at a given time. No location or houses required. Returns aspect type, orb, and applying/separating status. Cost: 1 credit.",
1001
+ inputSchema: {
1002
+ datetime: z15.string().optional().describe("ISO 8601 UTC datetime. Provide either datetime or jd."),
1003
+ jd: z15.number().optional().describe("Julian Day number in UT1."),
1004
+ bodies: z15.string().optional().describe("Comma-separated body names, or 'planets' (default), 'asteroids', 'all'."),
1005
+ aspects: z15.string().optional().describe("Comma-separated aspect types. Default: major aspects. Available: conjunction, opposition, trine, square, sextile, semi_sextile, quincunx, semi_square, sesquiquadrate, quintile, bi_quintile, septile, bi_septile, tri_septile, quindecile."),
1006
+ orb: z15.number().optional().describe("Default orb in degrees for all aspects (0-30)."),
1007
+ applying: z15.boolean().optional().describe("Compute applying/separating status. Default: true."),
1008
+ parallels: z15.boolean().optional().describe("Include parallels/contraparallels. Default: true."),
1009
+ parallel_orb: z15.number().optional().describe("Parallel orb in degrees (0-5). Default: 1.0."),
1010
+ contraparallel: z15.boolean().optional().describe("Include contraparallels. Default: true.")
1011
+ },
1012
+ annotations: {
1013
+ readOnlyHint: true,
1014
+ idempotentHint: true,
1015
+ openWorldHint: true
1016
+ }
897
1017
  },
898
1018
  async ({ datetime, jd, bodies, aspects, orb, applying, parallels, parallel_orb, contraparallel }) => {
899
1019
  if (!datetime && jd === void 0) {
@@ -918,16 +1038,24 @@ function registerAspects(server2, client) {
918
1038
  // src/tools/dignities.ts
919
1039
  import { z as z16 } from "zod";
920
1040
  function registerDignities(server2, client) {
921
- server2.tool(
1041
+ server2.registerTool(
922
1042
  "calculate_dignities",
923
- "Computes essential dignities (domicile, exaltation, triplicity, term, face) with Lilly-style scores. Optionally includes dispositorship chains, mutual receptions, and final dispositors. Cost: 1 credit.",
924
1043
  {
925
- datetime: z16.string().optional().describe("ISO 8601 UTC datetime. Provide either datetime or jd."),
926
- jd: z16.number().optional().describe("Julian Day number in UT1."),
927
- bodies: z16.string().optional().describe("Comma-separated body names, or 'planets' (default)."),
928
- rulership: z16.string().optional().describe("Rulership scheme: 'modern' (default, includes outer planets) or 'classical' (visible planets only)."),
929
- day_chart: z16.string().optional().describe("Is this a day chart? 'true', 'false', or 'auto' (default, skips triplicity)."),
930
- dispositors: z16.boolean().optional().describe("Include dispositorship chains, mutual receptions, final dispositors. Default: false.")
1044
+ title: "Calculate Essential Dignities",
1045
+ description: "Computes essential dignities (domicile, exaltation, triplicity, term, face) with Lilly-style scores. Optionally includes dispositorship chains, mutual receptions, and final dispositors. Cost: 1 credit.",
1046
+ inputSchema: {
1047
+ datetime: z16.string().optional().describe("ISO 8601 UTC datetime. Provide either datetime or jd."),
1048
+ jd: z16.number().optional().describe("Julian Day number in UT1."),
1049
+ bodies: z16.string().optional().describe("Comma-separated body names, or 'planets' (default)."),
1050
+ rulership: z16.string().optional().describe("Rulership scheme: 'modern' (default, includes outer planets) or 'classical' (visible planets only)."),
1051
+ day_chart: z16.string().optional().describe("Is this a day chart? 'true', 'false', or 'auto' (default, skips triplicity)."),
1052
+ dispositors: z16.boolean().optional().describe("Include dispositorship chains, mutual receptions, final dispositors. Default: false.")
1053
+ },
1054
+ annotations: {
1055
+ readOnlyHint: true,
1056
+ idempotentHint: true,
1057
+ openWorldHint: true
1058
+ }
931
1059
  },
932
1060
  async ({ datetime, jd, bodies, rulership, day_chart, dispositors }) => {
933
1061
  if (!datetime && jd === void 0) {
@@ -949,23 +1077,31 @@ function registerDignities(server2, client) {
949
1077
  // src/tools/synastry.ts
950
1078
  import { z as z17 } from "zod";
951
1079
  function registerSynastry(server2, client) {
952
- server2.tool(
1080
+ server2.registerTool(
953
1081
  "calculate_synastry",
954
- "Computes synastry between two natal charts: each chart's positions, houses, and aspects, plus inter-chart aspects and parallels. Requires two sets of datetime and location (suffixed _a and _b). Cost: 3 credits.",
955
1082
  {
956
- datetime_a: z17.string().optional().describe("Chart A datetime (ISO 8601 UTC). Provide either datetime_a or jd_a."),
957
- jd_a: z17.number().optional().describe("Chart A Julian Day in UT1."),
958
- lat_a: z17.number().min(-90).max(90).describe("Chart A latitude. REQUIRED."),
959
- lon_a: z17.number().min(-180).max(180).describe("Chart A longitude (east positive). REQUIRED."),
960
- datetime_b: z17.string().optional().describe("Chart B datetime (ISO 8601 UTC). Provide either datetime_b or jd_b."),
961
- jd_b: z17.number().optional().describe("Chart B Julian Day in UT1."),
962
- lat_b: z17.number().min(-90).max(90).describe("Chart B latitude. REQUIRED."),
963
- lon_b: z17.number().min(-180).max(180).describe("Chart B longitude (east positive). REQUIRED."),
964
- bodies: z17.string().optional().describe("Comma-separated body names. Default: 'planets'."),
965
- system: z17.string().optional().describe("House system. Default: 'placidus'."),
966
- aspects: z17.string().optional().describe("Comma-separated aspect types."),
967
- orb: z17.number().optional().describe("Default orb in degrees."),
968
- parallels: z17.boolean().optional().describe("Include parallels. Default: true.")
1083
+ title: "Calculate Synastry",
1084
+ description: "Computes synastry between two natal charts: each chart's positions, houses, and aspects, plus inter-chart aspects and parallels. Requires two sets of datetime and location (suffixed _a and _b). Cost: 3 credits.",
1085
+ inputSchema: {
1086
+ datetime_a: z17.string().optional().describe("Chart A datetime (ISO 8601 UTC). Provide either datetime_a or jd_a."),
1087
+ jd_a: z17.number().optional().describe("Chart A Julian Day in UT1."),
1088
+ lat_a: z17.number().min(-90).max(90).describe("Chart A latitude. REQUIRED."),
1089
+ lon_a: z17.number().min(-180).max(180).describe("Chart A longitude (east positive). REQUIRED."),
1090
+ datetime_b: z17.string().optional().describe("Chart B datetime (ISO 8601 UTC). Provide either datetime_b or jd_b."),
1091
+ jd_b: z17.number().optional().describe("Chart B Julian Day in UT1."),
1092
+ lat_b: z17.number().min(-90).max(90).describe("Chart B latitude. REQUIRED."),
1093
+ lon_b: z17.number().min(-180).max(180).describe("Chart B longitude (east positive). REQUIRED."),
1094
+ bodies: z17.string().optional().describe("Comma-separated body names. Default: 'planets'."),
1095
+ system: z17.string().optional().describe("House system. Default: 'placidus'."),
1096
+ aspects: z17.string().optional().describe("Comma-separated aspect types."),
1097
+ orb: z17.number().optional().describe("Default orb in degrees."),
1098
+ parallels: z17.boolean().optional().describe("Include parallels. Default: true.")
1099
+ },
1100
+ annotations: {
1101
+ readOnlyHint: true,
1102
+ idempotentHint: true,
1103
+ openWorldHint: true
1104
+ }
969
1105
  },
970
1106
  async ({ datetime_a, jd_a, lat_a, lon_a, datetime_b, jd_b, lat_b, lon_b, bodies, system, aspects, orb, parallels }) => {
971
1107
  if (!datetime_a && jd_a === void 0) {
@@ -993,22 +1129,30 @@ function registerSynastry(server2, client) {
993
1129
  // src/tools/composite.ts
994
1130
  import { z as z18 } from "zod";
995
1131
  function registerComposite(server2, client) {
996
- server2.tool(
1132
+ server2.registerTool(
997
1133
  "calculate_composite",
998
- "Computes a midpoint composite chart from two natal charts. Each position is the shortest-arc midpoint of the two charts' positions. Cost: 3 credits.",
999
1134
  {
1000
- datetime_a: z18.string().optional().describe("Chart A datetime (ISO 8601 UTC)."),
1001
- jd_a: z18.number().optional().describe("Chart A Julian Day."),
1002
- lat_a: z18.number().min(-90).max(90).describe("Chart A latitude. REQUIRED."),
1003
- lon_a: z18.number().min(-180).max(180).describe("Chart A longitude. REQUIRED."),
1004
- datetime_b: z18.string().optional().describe("Chart B datetime (ISO 8601 UTC)."),
1005
- jd_b: z18.number().optional().describe("Chart B Julian Day."),
1006
- lat_b: z18.number().min(-90).max(90).describe("Chart B latitude. REQUIRED."),
1007
- lon_b: z18.number().min(-180).max(180).describe("Chart B longitude. REQUIRED."),
1008
- bodies: z18.string().optional().describe("Comma-separated body names. Default: 'planets'."),
1009
- system: z18.string().optional().describe("House system. Default: 'placidus'."),
1010
- aspects: z18.string().optional().describe("Comma-separated aspect types."),
1011
- resolution: z18.string().optional().describe("Midpoint resolution: 'lower' (default) or 'higher'.")
1135
+ title: "Calculate Composite Chart",
1136
+ description: "Computes a midpoint composite chart from two natal charts. Each position is the shortest-arc midpoint of the two charts' positions. Cost: 3 credits.",
1137
+ inputSchema: {
1138
+ datetime_a: z18.string().optional().describe("Chart A datetime (ISO 8601 UTC)."),
1139
+ jd_a: z18.number().optional().describe("Chart A Julian Day."),
1140
+ lat_a: z18.number().min(-90).max(90).describe("Chart A latitude. REQUIRED."),
1141
+ lon_a: z18.number().min(-180).max(180).describe("Chart A longitude. REQUIRED."),
1142
+ datetime_b: z18.string().optional().describe("Chart B datetime (ISO 8601 UTC)."),
1143
+ jd_b: z18.number().optional().describe("Chart B Julian Day."),
1144
+ lat_b: z18.number().min(-90).max(90).describe("Chart B latitude. REQUIRED."),
1145
+ lon_b: z18.number().min(-180).max(180).describe("Chart B longitude. REQUIRED."),
1146
+ bodies: z18.string().optional().describe("Comma-separated body names. Default: 'planets'."),
1147
+ system: z18.string().optional().describe("House system. Default: 'placidus'."),
1148
+ aspects: z18.string().optional().describe("Comma-separated aspect types."),
1149
+ resolution: z18.string().optional().describe("Midpoint resolution: 'lower' (default) or 'higher'.")
1150
+ },
1151
+ annotations: {
1152
+ readOnlyHint: true,
1153
+ idempotentHint: true,
1154
+ openWorldHint: true
1155
+ }
1012
1156
  },
1013
1157
  async ({ datetime_a, jd_a, lat_a, lon_a, datetime_b, jd_b, lat_b, lon_b, bodies, system, aspects, resolution }) => {
1014
1158
  if (!datetime_a && jd_a === void 0) {
@@ -1035,21 +1179,29 @@ function registerComposite(server2, client) {
1035
1179
  // src/tools/davison.ts
1036
1180
  import { z as z19 } from "zod";
1037
1181
  function registerDavison(server2, client) {
1038
- server2.tool(
1182
+ server2.registerTool(
1039
1183
  "calculate_davison",
1040
- "Computes a Davison relationship chart \u2014 a natal chart cast at the time-space midpoint of two charts. Uses great-circle geographic midpoint and Julian Day midpoint. Cost: 3 credits.",
1041
1184
  {
1042
- datetime_a: z19.string().optional().describe("Chart A datetime (ISO 8601 UTC)."),
1043
- jd_a: z19.number().optional().describe("Chart A Julian Day."),
1044
- lat_a: z19.number().min(-90).max(90).describe("Chart A latitude. REQUIRED."),
1045
- lon_a: z19.number().min(-180).max(180).describe("Chart A longitude. REQUIRED."),
1046
- datetime_b: z19.string().optional().describe("Chart B datetime (ISO 8601 UTC)."),
1047
- jd_b: z19.number().optional().describe("Chart B Julian Day."),
1048
- lat_b: z19.number().min(-90).max(90).describe("Chart B latitude. REQUIRED."),
1049
- lon_b: z19.number().min(-180).max(180).describe("Chart B longitude. REQUIRED."),
1050
- bodies: z19.string().optional().describe("Comma-separated body names. Default: 'planets'."),
1051
- system: z19.string().optional().describe("House system. Default: 'placidus'."),
1052
- aspects: z19.string().optional().describe("Comma-separated aspect types.")
1185
+ title: "Calculate Davison Chart",
1186
+ description: "Computes a Davison relationship chart \u2014 a natal chart cast at the time-space midpoint of two charts. Uses great-circle geographic midpoint and Julian Day midpoint. Cost: 3 credits.",
1187
+ inputSchema: {
1188
+ datetime_a: z19.string().optional().describe("Chart A datetime (ISO 8601 UTC)."),
1189
+ jd_a: z19.number().optional().describe("Chart A Julian Day."),
1190
+ lat_a: z19.number().min(-90).max(90).describe("Chart A latitude. REQUIRED."),
1191
+ lon_a: z19.number().min(-180).max(180).describe("Chart A longitude. REQUIRED."),
1192
+ datetime_b: z19.string().optional().describe("Chart B datetime (ISO 8601 UTC)."),
1193
+ jd_b: z19.number().optional().describe("Chart B Julian Day."),
1194
+ lat_b: z19.number().min(-90).max(90).describe("Chart B latitude. REQUIRED."),
1195
+ lon_b: z19.number().min(-180).max(180).describe("Chart B longitude. REQUIRED."),
1196
+ bodies: z19.string().optional().describe("Comma-separated body names. Default: 'planets'."),
1197
+ system: z19.string().optional().describe("House system. Default: 'placidus'."),
1198
+ aspects: z19.string().optional().describe("Comma-separated aspect types.")
1199
+ },
1200
+ annotations: {
1201
+ readOnlyHint: true,
1202
+ idempotentHint: true,
1203
+ openWorldHint: true
1204
+ }
1053
1205
  },
1054
1206
  async ({ datetime_a, jd_a, lat_a, lon_a, datetime_b, jd_b, lat_b, lon_b, bodies, system, aspects }) => {
1055
1207
  if (!datetime_a && jd_a === void 0) {
@@ -1075,19 +1227,27 @@ function registerDavison(server2, client) {
1075
1227
  // src/tools/progressed.ts
1076
1228
  import { z as z20 } from "zod";
1077
1229
  function registerProgressed(server2, client) {
1078
- server2.tool(
1230
+ server2.registerTool(
1079
1231
  "calculate_progressed",
1080
- "Computes a secondary progressed chart using the day-for-a-year method. Provide the natal birth datetime and a target date to progress to. Returns a full chart at the progressed datetime. Cost: 2 credits.",
1081
1232
  {
1082
- datetime: z20.string().optional().describe("Natal birth datetime (ISO 8601 UTC). Provide either datetime or jd."),
1083
- jd: z20.number().optional().describe("Natal birth Julian Day."),
1084
- target_datetime: z20.string().optional().describe("Target date to progress to (ISO 8601 UTC). Provide either target_datetime or target_jd."),
1085
- target_jd: z20.number().optional().describe("Target Julian Day to progress to."),
1086
- lat: z20.number().min(-90).max(90).describe("Birth location latitude. REQUIRED."),
1087
- lon: z20.number().min(-180).max(180).describe("Birth location longitude. REQUIRED."),
1088
- bodies: z20.string().optional().describe("Comma-separated body names. Default: 'planets'."),
1089
- system: z20.string().optional().describe("House system. Default: 'placidus'."),
1090
- aspects: z20.string().optional().describe("Comma-separated aspect types.")
1233
+ title: "Calculate Progressed Chart",
1234
+ description: "Computes a secondary progressed chart using the day-for-a-year method. Provide the natal birth datetime and a target date to progress to. Returns a full chart at the progressed datetime. Cost: 2 credits.",
1235
+ inputSchema: {
1236
+ datetime: z20.string().optional().describe("Natal birth datetime (ISO 8601 UTC). Provide either datetime or jd."),
1237
+ jd: z20.number().optional().describe("Natal birth Julian Day."),
1238
+ target_datetime: z20.string().optional().describe("Target date to progress to (ISO 8601 UTC). Provide either target_datetime or target_jd."),
1239
+ target_jd: z20.number().optional().describe("Target Julian Day to progress to."),
1240
+ lat: z20.number().min(-90).max(90).describe("Birth location latitude. REQUIRED."),
1241
+ lon: z20.number().min(-180).max(180).describe("Birth location longitude. REQUIRED."),
1242
+ bodies: z20.string().optional().describe("Comma-separated body names. Default: 'planets'."),
1243
+ system: z20.string().optional().describe("House system. Default: 'placidus'."),
1244
+ aspects: z20.string().optional().describe("Comma-separated aspect types.")
1245
+ },
1246
+ annotations: {
1247
+ readOnlyHint: true,
1248
+ idempotentHint: true,
1249
+ openWorldHint: true
1250
+ }
1091
1251
  },
1092
1252
  async ({ datetime, jd, target_datetime, target_jd, lat, lon, bodies, system, aspects }) => {
1093
1253
  if (!datetime && jd === void 0) {
@@ -1113,18 +1273,26 @@ function registerProgressed(server2, client) {
1113
1273
  // src/tools/draconic.ts
1114
1274
  import { z as z21 } from "zod";
1115
1275
  function registerDraconic(server2, client) {
1116
- server2.tool(
1276
+ server2.registerTool(
1117
1277
  "calculate_draconic",
1118
- "Computes a draconic chart by rotating all positions so the North Node falls at 0\xB0 Aries. Make sure to include mean_node or true_node in the bodies list. Cost: 2 credits.",
1119
1278
  {
1120
- datetime: z21.string().optional().describe("ISO 8601 UTC datetime. Provide either datetime or jd."),
1121
- jd: z21.number().optional().describe("Julian Day number in UT1."),
1122
- lat: z21.number().min(-90).max(90).describe("Observer latitude. REQUIRED."),
1123
- lon: z21.number().min(-180).max(180).describe("Observer longitude. REQUIRED."),
1124
- bodies: z21.string().optional().describe("Comma-separated body names. Must include mean_node or true_node. Default: 'planets' (includes mean_node)."),
1125
- system: z21.string().optional().describe("House system. Default: 'placidus'."),
1126
- node: z21.string().optional().describe("Node body for rotation: 'mean_node' (default) or 'true_node'."),
1127
- aspects: z21.string().optional().describe("Comma-separated aspect types.")
1279
+ title: "Calculate Draconic Chart",
1280
+ description: "Computes a draconic chart by rotating all positions so the North Node falls at 0\xB0 Aries. Make sure to include mean_node or true_node in the bodies list. Cost: 2 credits.",
1281
+ inputSchema: {
1282
+ datetime: z21.string().optional().describe("ISO 8601 UTC datetime. Provide either datetime or jd."),
1283
+ jd: z21.number().optional().describe("Julian Day number in UT1."),
1284
+ lat: z21.number().min(-90).max(90).describe("Observer latitude. REQUIRED."),
1285
+ lon: z21.number().min(-180).max(180).describe("Observer longitude. REQUIRED."),
1286
+ bodies: z21.string().optional().describe("Comma-separated body names. Must include mean_node or true_node. Default: 'planets' (includes mean_node)."),
1287
+ system: z21.string().optional().describe("House system. Default: 'placidus'."),
1288
+ node: z21.string().optional().describe("Node body for rotation: 'mean_node' (default) or 'true_node'."),
1289
+ aspects: z21.string().optional().describe("Comma-separated aspect types.")
1290
+ },
1291
+ annotations: {
1292
+ readOnlyHint: true,
1293
+ idempotentHint: true,
1294
+ openWorldHint: true
1295
+ }
1128
1296
  },
1129
1297
  async ({ datetime, jd, lat, lon, bodies, system, node, aspects }) => {
1130
1298
  if (!datetime && jd === void 0) {
@@ -1143,6 +1311,55 @@ function registerDraconic(server2, client) {
1143
1311
  );
1144
1312
  }
1145
1313
 
1314
+ // src/tools/returns.ts
1315
+ import { z as z22 } from "zod";
1316
+ function registerReturns(server2, client) {
1317
+ server2.registerTool(
1318
+ "find_returns",
1319
+ {
1320
+ title: "Find Planetary Returns",
1321
+ description: "Finds the moment(s) when a transiting body returns to its natal ecliptic longitude and computes a full chart at each return moment. Supports solar, lunar, and planetary returns. Cost: 2 credits.",
1322
+ inputSchema: {
1323
+ body: z22.string().describe("Body to find the return for (e.g., 'sun', 'moon', 'saturn'). REQUIRED."),
1324
+ datetime: z22.string().optional().describe("Natal birth datetime (ISO 8601 UTC). Provide either datetime or jd."),
1325
+ jd: z22.number().optional().describe("Natal birth Julian Day."),
1326
+ search_start: z22.string().optional().describe("When to start searching for the return (ISO 8601 UTC). Provide either search_start or search_start_jd."),
1327
+ search_start_jd: z22.number().optional().describe("Search start Julian Day."),
1328
+ lat: z22.number().min(-90).max(90).describe("Return chart location latitude (typically current residence). REQUIRED."),
1329
+ lon: z22.number().min(-180).max(180).describe("Return chart location longitude. REQUIRED."),
1330
+ count: z22.number().min(1).max(13).optional().describe("Number of consecutive returns to find (default 1, max 13 for Moon, 5 for others)."),
1331
+ bodies: z22.string().optional().describe("Comma-separated body names for the return chart. Default: 'planets'."),
1332
+ system: z22.string().optional().describe("House system. Default: 'placidus'."),
1333
+ aspects: z22.string().optional().describe("Comma-separated aspect types.")
1334
+ },
1335
+ annotations: {
1336
+ readOnlyHint: true,
1337
+ idempotentHint: true,
1338
+ openWorldHint: true
1339
+ }
1340
+ },
1341
+ async ({ body: returnBody, datetime, jd, search_start, search_start_jd, lat, lon, count, bodies, system, aspects }) => {
1342
+ if (!datetime && jd === void 0) {
1343
+ return { isError: true, content: [{ type: "text", text: "Natal birth time required: provide either 'datetime' or 'jd'." }] };
1344
+ }
1345
+ if (!search_start && search_start_jd === void 0) {
1346
+ return { isError: true, content: [{ type: "text", text: "Search start required: provide either 'search_start' or 'search_start_jd'." }] };
1347
+ }
1348
+ const reqBody = { body: returnBody, lat, lon };
1349
+ if (datetime) reqBody.datetime = datetime;
1350
+ if (jd !== void 0) reqBody.jd = jd;
1351
+ if (search_start) reqBody.search_start = search_start;
1352
+ if (search_start_jd !== void 0) reqBody.search_start_jd = search_start_jd;
1353
+ if (count !== void 0) reqBody.count = count;
1354
+ if (bodies) reqBody.bodies = bodies;
1355
+ if (system) reqBody.system = system;
1356
+ if (aspects) reqBody.aspects = aspects;
1357
+ const response = await client.callEndpoint("/v1/returns", reqBody);
1358
+ return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
1359
+ }
1360
+ );
1361
+ }
1362
+
1146
1363
  // src/tools/index.ts
1147
1364
  function registerAllTools(server2, client) {
1148
1365
  registerCalculatePositions(server2, client);
@@ -1165,6 +1382,7 @@ function registerAllTools(server2, client) {
1165
1382
  registerDavison(server2, client);
1166
1383
  registerProgressed(server2, client);
1167
1384
  registerDraconic(server2, client);
1385
+ registerReturns(server2, client);
1168
1386
  registerListAvailableValues(server2);
1169
1387
  }
1170
1388
 
@@ -1177,7 +1395,7 @@ function createServer(options) {
1177
1395
  });
1178
1396
  const server2 = new McpServer({
1179
1397
  name: "morphemeris",
1180
- version: "0.1.0"
1398
+ version: "0.5.0"
1181
1399
  });
1182
1400
  registerAllTools(server2, client);
1183
1401
  return server2;