@openephemeris/mcp-server 3.0.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.
@@ -0,0 +1,56 @@
1
+ import { registerTool } from "../index.js";
2
+ import { backendClient } from "../../backend/client.js";
3
+ registerTool({
4
+ name: "ephemeris.next_eclipse",
5
+ description: "Find the next solar or lunar eclipse visible from a given location (or globally). " +
6
+ "Returns the eclipse type, date/time of maximum, magnitude, duration of totality (if any), " +
7
+ "and local contact times if coordinates are provided.\n\n" +
8
+ "CREDIT COST: 1 credit per call.\n\n" +
9
+ "EXAMPLE: Find the next solar eclipse visible from New York:\n" +
10
+ " eclipse_type='solar', latitude=40.7128, longitude=-74.006\n\n" +
11
+ "EXAMPLE: Find the next lunar eclipse globally:\n" +
12
+ " eclipse_type='lunar'",
13
+ inputSchema: {
14
+ type: "object",
15
+ properties: {
16
+ eclipse_type: {
17
+ type: "string",
18
+ enum: ["solar", "lunar"],
19
+ description: "Eclipse type to search for.",
20
+ },
21
+ latitude: {
22
+ type: "number",
23
+ description: "Observer latitude in decimal degrees. If provided, returns local visibility and contact times.",
24
+ },
25
+ longitude: {
26
+ type: "number",
27
+ description: "Observer longitude in decimal degrees.",
28
+ },
29
+ after_date: {
30
+ type: "string",
31
+ description: "ISO 8601 date to search after (e.g. '2026-01-01'). Defaults to today if omitted.",
32
+ },
33
+ },
34
+ required: ["eclipse_type"],
35
+ additionalProperties: false,
36
+ },
37
+ handler: async (args) => {
38
+ const params = {};
39
+ if (args.latitude != null)
40
+ params.latitude = args.latitude;
41
+ if (args.longitude != null)
42
+ params.longitude = args.longitude;
43
+ if (args.after_date)
44
+ params.date = args.after_date;
45
+ if (args.eclipse_type === "solar") {
46
+ // Use local endpoint if coordinates provided, otherwise global
47
+ if (args.latitude != null && args.longitude != null) {
48
+ return await backendClient.request("GET", "/eclipse/solar/local", { params, timeoutMs: 60_000 });
49
+ }
50
+ return await backendClient.request("GET", "/eclipse/solar/global", { params, timeoutMs: 60_000 });
51
+ }
52
+ else {
53
+ return await backendClient.request("GET", "/eclipse/lunar/global", { params, timeoutMs: 60_000 });
54
+ }
55
+ },
56
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,79 @@
1
+ import { registerTool } from "../index.js";
2
+ import { backendClient } from "../../backend/client.js";
3
+ registerTool({
4
+ name: "ephemeris.electional",
5
+ description: "Find optimal planetary timing windows (electional astrology). Scans a date range to find the " +
6
+ "best times for an event based on essential dignity, aspect quality, sect, and void-of-course " +
7
+ "moon penalties. Evaluates every hour and clusters the best continuous windows.\n\n" +
8
+ "CREDIT COST: 5 credits per call (heavy calculation).\n\n" +
9
+ "EXAMPLE: Find the best time to launch a business in early March 2026.\n" +
10
+ " start_date='2026-03-01', end_date='2026-03-10', latitude=40.7128, longitude=-74.0060,\n" +
11
+ " avoid_voc=true, lunar_phase='waxing'",
12
+ inputSchema: {
13
+ type: "object",
14
+ properties: {
15
+ start_date: {
16
+ type: "string",
17
+ description: "ISO 8601 start date or datetime for the search window (e.g., 2026-03-01).",
18
+ },
19
+ end_date: {
20
+ type: "string",
21
+ description: "ISO 8601 end date or datetime for the search window.",
22
+ },
23
+ latitude: {
24
+ type: "number",
25
+ description: "Latitude of location in decimal degrees (positive = North).",
26
+ },
27
+ longitude: {
28
+ type: "number",
29
+ description: "Longitude of location in decimal degrees (positive = East).",
30
+ },
31
+ max_results: {
32
+ type: "number",
33
+ description: "Maximum number of top windows to return (default 5).",
34
+ },
35
+ avoid_retrograde: {
36
+ type: "string",
37
+ description: "Comma-separated list of planets to avoid when retrograde (e.g., 'mercury,venus').",
38
+ },
39
+ lunar_phase: {
40
+ type: "string",
41
+ enum: ["waxing", "waning", "new", "full", "any"],
42
+ description: "Filter windows by lunar phase. Defaults to 'any'.",
43
+ },
44
+ avoid_voc: {
45
+ type: "boolean",
46
+ description: "If true, strictly ignores any moments where the Moon is Void of Course.",
47
+ },
48
+ format: {
49
+ type: "string",
50
+ enum: ["json", "llm"],
51
+ description: "Output format. 'llm' = compact token-efficient output (Startup tier).",
52
+ },
53
+ },
54
+ required: ["start_date", "end_date", "latitude", "longitude"],
55
+ additionalProperties: false,
56
+ },
57
+ handler: async (args) => {
58
+ const query = {
59
+ start_date: args.start_date,
60
+ end_date: args.end_date,
61
+ latitude: args.latitude,
62
+ longitude: args.longitude,
63
+ };
64
+ if (args.max_results !== undefined)
65
+ query.max_results = args.max_results;
66
+ if (args.avoid_retrograde)
67
+ query.avoid_retrograde = args.avoid_retrograde;
68
+ if (args.lunar_phase)
69
+ query.lunar_phase = args.lunar_phase;
70
+ if (args.avoid_voc !== undefined)
71
+ query.avoid_voc = args.avoid_voc;
72
+ if (args.format)
73
+ query.format = args.format;
74
+ return await backendClient.request("GET", "/electional/find-window", {
75
+ data: {},
76
+ params: query,
77
+ });
78
+ },
79
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,53 @@
1
+ import { registerTool } from "../index.js";
2
+ import { backendClient } from "../../backend/client.js";
3
+ registerTool({
4
+ name: "human_design.chart",
5
+ description: "Calculate a full Human Design bodygraph chart from birth data. Returns the person's Type " +
6
+ "(Generator, Manifesting Generator, Projector, Manifestor, Reflector), Strategy, Authority, " +
7
+ "Profile (e.g. 1/3, 2/4), defined and undefined Centers, activated Gates and Channels, " +
8
+ "Incarnation Cross, and both Personality (conscious) and Design (unconscious) planetary positions.\n\n" +
9
+ "CREDIT COST: 1 credit per call.\n\n" +
10
+ "Human Design uses two calculation moments: the birth time (Personality) and ~88° of Sun motion " +
11
+ "before birth (~3 months prior, the Design calculation). The API handles this automatically.\n\n" +
12
+ "EXAMPLE: Get the Human Design chart for someone born April 15, 1990 at 2:30 PM in Chicago:\n" +
13
+ " datetime='1990-04-15T14:30:00', latitude=41.8781, longitude=-87.6298",
14
+ inputSchema: {
15
+ type: "object",
16
+ properties: {
17
+ datetime: {
18
+ type: "string",
19
+ description: "ISO 8601 birth datetime (local time at birth location), e.g. '1990-04-15T14:30:00'.",
20
+ },
21
+ latitude: {
22
+ type: "number",
23
+ description: "Latitude of birth location in decimal degrees (positive = North).",
24
+ },
25
+ longitude: {
26
+ type: "number",
27
+ description: "Longitude of birth location in decimal degrees (positive = East).",
28
+ },
29
+ format: {
30
+ type: "string",
31
+ enum: ["json", "llm"],
32
+ description: "Output format. 'llm' returns compact array projection for token efficiency (Pro tier). " +
33
+ "'json' returns verbose full output.",
34
+ },
35
+ },
36
+ required: ["datetime", "latitude", "longitude"],
37
+ additionalProperties: false,
38
+ },
39
+ handler: async (args) => {
40
+ const body = {
41
+ datetime: args.datetime,
42
+ latitude: args.latitude,
43
+ longitude: args.longitude,
44
+ };
45
+ const query = {};
46
+ if (args.format)
47
+ query.format = args.format;
48
+ return await backendClient.request("POST", "/human-design/chart", {
49
+ data: body,
50
+ params: query,
51
+ });
52
+ },
53
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
1
+ import { registerTool } from "../index.js";
2
+ import { backendClient } from "../../backend/client.js";
3
+ registerTool({
4
+ name: "ephemeris.moon_phase",
5
+ description: "Get the current Moon phase and void-of-course status. Returns the Moon's sign, phase name " +
6
+ "(New, Waxing Crescent, First Quarter, Waxing Gibbous, Full, Waning Gibbous, Last Quarter, " +
7
+ "Waning Crescent), exact phase angle, illumination percentage, and the next void-of-course period.\n\n" +
8
+ "CREDIT COST: 1 credit per call.\n\n" +
9
+ "If no datetime is provided, returns the current (live) moon phase.\n\n" +
10
+ "EXAMPLE: Get moon phase for a specific date/time:\n" +
11
+ " datetime='2026-03-20T12:00:00Z'\n\n" +
12
+ "EXAMPLE: Get the current moon phase right now:\n" +
13
+ " (call with no arguments)",
14
+ inputSchema: {
15
+ type: "object",
16
+ properties: {
17
+ datetime: {
18
+ type: "string",
19
+ description: "ISO 8601 datetime to query. If omitted, returns the current live moon phase (UTC now).",
20
+ },
21
+ latitude: {
22
+ type: "number",
23
+ description: "Observer latitude (optional, used for local void-of-course calculations).",
24
+ },
25
+ longitude: {
26
+ type: "number",
27
+ description: "Observer longitude (optional, used for local void-of-course calculations).",
28
+ },
29
+ },
30
+ required: [],
31
+ additionalProperties: false,
32
+ },
33
+ handler: async (args) => {
34
+ const params = {};
35
+ if (args.datetime)
36
+ params.datetime = args.datetime;
37
+ if (args.latitude != null)
38
+ params.latitude = args.latitude;
39
+ if (args.longitude != null)
40
+ params.longitude = args.longitude;
41
+ const [phase, voc] = await Promise.allSettled([
42
+ backendClient.request("GET", "/ephemeris/moon/phase", { params }),
43
+ backendClient.request("GET", "/ephemeris/moon/void-of-course", { params }),
44
+ ]);
45
+ return {
46
+ phase: phase.status === "fulfilled" ? phase.value : { error: phase.reason?.message },
47
+ void_of_course: voc.status === "fulfilled" ? voc.value : { error: voc.reason?.message },
48
+ };
49
+ },
50
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,71 @@
1
+ import { registerTool } from "../index.js";
2
+ import { backendClient } from "../../backend/client.js";
3
+ const DATETIME_DESC = "ISO 8601 datetime string, e.g. '1990-04-15T14:30:00' (local time at birth location). " +
4
+ "Include timezone offset if known, e.g. '1990-04-15T14:30:00-05:00'.";
5
+ registerTool({
6
+ name: "ephemeris.natal_chart",
7
+ description: "Calculate a full natal (birth) chart for a person. Returns planetary positions, house cusps, " +
8
+ "aspects, and chart patterns. Use format='llm' for a compact, token-efficient output ideal for " +
9
+ "interpretation (requires Pro tier). The result includes all major planets, angles (ASC/MC/DSC/IC), " +
10
+ "essential dignities, retrograde status, house system data, and major aspect grid.\n\n" +
11
+ "CREDIT COST: 1 credit per call.\n\n" +
12
+ "EXAMPLE: Calculate the natal chart for someone born April 15, 1990 at 2:30 PM in Chicago:\n" +
13
+ " datetime='1990-04-15T14:30:00', latitude=41.8781, longitude=-87.6298",
14
+ inputSchema: {
15
+ type: "object",
16
+ properties: {
17
+ datetime: {
18
+ type: "string",
19
+ description: DATETIME_DESC,
20
+ },
21
+ latitude: {
22
+ type: "number",
23
+ description: "Geographic latitude of birth location in decimal degrees (positive = North).",
24
+ },
25
+ longitude: {
26
+ type: "number",
27
+ description: "Geographic longitude of birth location in decimal degrees (positive = East).",
28
+ },
29
+ house_system: {
30
+ type: "string",
31
+ enum: ["placidus", "whole_sign", "equal", "koch", "campanus", "regiomontanus", "porphyry", "alcabitius", "morinus"],
32
+ description: "House system to use. Defaults to 'placidus' if omitted.",
33
+ },
34
+ format: {
35
+ type: "string",
36
+ enum: ["json", "llm"],
37
+ description: "Output format. 'llm' returns a compact array-based projection optimized for LLM token efficiency (Pro tier required). 'json' returns full verbose JSON.",
38
+ },
39
+ include_arabic_parts: {
40
+ type: "boolean",
41
+ description: "If true, include Hermetic Lots (Arabic Parts) in the response.",
42
+ },
43
+ include_fixed_stars: {
44
+ type: "boolean",
45
+ description: "If true, include fixed star conjunctions in the response.",
46
+ },
47
+ },
48
+ required: ["datetime", "latitude", "longitude"],
49
+ additionalProperties: false,
50
+ },
51
+ handler: async (args) => {
52
+ const body = {
53
+ datetime: args.datetime,
54
+ latitude: args.latitude,
55
+ longitude: args.longitude,
56
+ };
57
+ if (args.house_system)
58
+ body.house_system = args.house_system;
59
+ if (args.include_arabic_parts)
60
+ body.include_arabic_parts = args.include_arabic_parts;
61
+ if (args.include_fixed_stars)
62
+ body.include_fixed_stars = args.include_fixed_stars;
63
+ const query = {};
64
+ if (args.format)
65
+ query.format = args.format;
66
+ return await backendClient.request("POST", "/ephemeris/natal-chart", {
67
+ data: body,
68
+ params: query,
69
+ });
70
+ },
71
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,71 @@
1
+ import { registerTool } from "../index.js";
2
+ import { backendClient } from "../../backend/client.js";
3
+ registerTool({
4
+ name: "ephemeris.relocation",
5
+ description: "Calculate a relocation chart — the same natal planetary positions re-cast for a different " +
6
+ "geographic location. Used to understand how living in a different city shifts house placements " +
7
+ "and angles, without changing the planetary longitudes in the chart.\n\n" +
8
+ "CREDIT COST: 1 credit per call.\n\n" +
9
+ "EXAMPLE: How does moving from Chicago to London change someone's chart?\n" +
10
+ " natal_datetime='1990-04-15T14:30:00', natal_latitude=41.8781, natal_longitude=-87.6298,\n" +
11
+ " relocation_latitude=51.5074, relocation_longitude=-0.1278",
12
+ inputSchema: {
13
+ type: "object",
14
+ properties: {
15
+ natal_datetime: {
16
+ type: "string",
17
+ description: "ISO 8601 birth datetime (local time at birth location).",
18
+ },
19
+ natal_latitude: {
20
+ type: "number",
21
+ description: "Latitude of birth location in decimal degrees.",
22
+ },
23
+ natal_longitude: {
24
+ type: "number",
25
+ description: "Longitude of birth location in decimal degrees.",
26
+ },
27
+ relocation_latitude: {
28
+ type: "number",
29
+ description: "Latitude of the relocation city in decimal degrees (positive = North).",
30
+ },
31
+ relocation_longitude: {
32
+ type: "number",
33
+ description: "Longitude of the relocation city in decimal degrees (positive = East).",
34
+ },
35
+ house_system: {
36
+ type: "string",
37
+ enum: ["placidus", "whole_sign", "equal", "koch", "campanus", "regiomontanus", "porphyry"],
38
+ description: "House system to use. Defaults to 'placidus'.",
39
+ },
40
+ format: {
41
+ type: "string",
42
+ enum: ["json", "llm"],
43
+ description: "Output format. 'llm' = compact token-efficient output (Startup tier).",
44
+ },
45
+ },
46
+ required: ["natal_datetime", "natal_latitude", "natal_longitude", "relocation_latitude", "relocation_longitude"],
47
+ additionalProperties: false,
48
+ },
49
+ handler: async (args) => {
50
+ const body = {
51
+ natal: {
52
+ datetime: args.natal_datetime,
53
+ latitude: args.natal_latitude,
54
+ longitude: args.natal_longitude,
55
+ },
56
+ relocation: {
57
+ latitude: args.relocation_latitude,
58
+ longitude: args.relocation_longitude,
59
+ },
60
+ };
61
+ if (args.house_system)
62
+ body.house_system = args.house_system;
63
+ const query = {};
64
+ if (args.format)
65
+ query.format = args.format;
66
+ return await backendClient.request("POST", "/ephemeris/relocation", {
67
+ data: body,
68
+ params: query,
69
+ });
70
+ },
71
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,61 @@
1
+ import { registerTool } from "../index.js";
2
+ import { backendClient } from "../../backend/client.js";
3
+ registerTool({
4
+ name: "ephemeris.synastry",
5
+ description: "Calculate a synastry chart comparing two people's natal charts. Returns inter-aspects " +
6
+ "(planetary connections between the two charts), composite points, and relationship indicators. " +
7
+ "Use this for compatibility analysis, relationship timing, or partnership insights.\n\n" +
8
+ "CREDIT COST: 5 credits per call.\n\n" +
9
+ "EXAMPLE: Compare two people's charts:\n" +
10
+ " person_a_datetime='1990-04-15T14:30:00', person_a_latitude=41.8781, person_a_longitude=-87.6298,\n" +
11
+ " person_b_datetime='1988-09-22T08:15:00', person_b_latitude=34.0522, person_b_longitude=-118.2437",
12
+ inputSchema: {
13
+ type: "object",
14
+ properties: {
15
+ person_a_datetime: { type: "string", description: "Person A birth datetime (ISO 8601)." },
16
+ person_a_latitude: { type: "number", description: "Person A birth latitude." },
17
+ person_a_longitude: { type: "number", description: "Person A birth longitude." },
18
+ person_b_datetime: { type: "string", description: "Person B birth datetime (ISO 8601)." },
19
+ person_b_latitude: { type: "number", description: "Person B birth latitude." },
20
+ person_b_longitude: { type: "number", description: "Person B birth longitude." },
21
+ house_system: {
22
+ type: "string",
23
+ enum: ["placidus", "whole_sign", "equal", "koch"],
24
+ description: "House system for both charts. Defaults to 'placidus'.",
25
+ },
26
+ format: {
27
+ type: "string",
28
+ enum: ["json", "llm"],
29
+ description: "Output format. 'llm' is compact and token-efficient (Pro tier).",
30
+ },
31
+ },
32
+ required: [
33
+ "person_a_datetime", "person_a_latitude", "person_a_longitude",
34
+ "person_b_datetime", "person_b_latitude", "person_b_longitude",
35
+ ],
36
+ additionalProperties: false,
37
+ },
38
+ handler: async (args) => {
39
+ const body = {
40
+ natal_a: {
41
+ datetime: args.person_a_datetime,
42
+ latitude: args.person_a_latitude,
43
+ longitude: args.person_a_longitude,
44
+ },
45
+ natal_b: {
46
+ datetime: args.person_b_datetime,
47
+ latitude: args.person_b_latitude,
48
+ longitude: args.person_b_longitude,
49
+ },
50
+ };
51
+ if (args.house_system)
52
+ body.house_system = args.house_system;
53
+ const query = {};
54
+ if (args.format)
55
+ query.format = args.format;
56
+ return await backendClient.request("POST", "/comparative/synastry", {
57
+ data: body,
58
+ params: query,
59
+ });
60
+ },
61
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
1
+ import { registerTool } from "../index.js";
2
+ import { backendClient } from "../../backend/client.js";
3
+ registerTool({
4
+ name: "ephemeris.transits",
5
+ description: "Search for astrological transit events affecting a natal chart over a date range. " +
6
+ "Returns a list of exact transit moments — when transiting planets form specified aspects " +
7
+ "to natal planet positions. Ideal for generating horoscope timelines, event forecasting, or " +
8
+ "finding optimal timing windows.\n\n" +
9
+ "CREDIT COST: 5 credits per call.\n\n" +
10
+ "EXAMPLE: Find all Saturn transits to the natal Sun/Moon for the next 6 months:\n" +
11
+ " natal_datetime='1990-04-15T14:30:00', natal_latitude=41.8781, natal_longitude=-87.6298,\n" +
12
+ " start_date='2026-01-01', end_date='2026-06-30', transiting_planets=['saturn']",
13
+ inputSchema: {
14
+ type: "object",
15
+ properties: {
16
+ natal_datetime: {
17
+ type: "string",
18
+ description: "ISO 8601 birth datetime for the natal chart.",
19
+ },
20
+ natal_latitude: {
21
+ type: "number",
22
+ description: "Latitude of birth location in decimal degrees.",
23
+ },
24
+ natal_longitude: {
25
+ type: "number",
26
+ description: "Longitude of birth location in decimal degrees.",
27
+ },
28
+ start_date: {
29
+ type: "string",
30
+ description: "Start of the transit search window, ISO 8601 date or datetime (e.g. '2026-01-01').",
31
+ },
32
+ end_date: {
33
+ type: "string",
34
+ description: "End of the transit search window, ISO 8601 date or datetime (e.g. '2026-06-30').",
35
+ },
36
+ transiting_planets: {
37
+ type: "array",
38
+ items: { type: "string" },
39
+ description: "List of transiting planet IDs to search. E.g. ['saturn', 'jupiter', 'uranus', 'pluto']. " +
40
+ "Omit to search all outer planets.",
41
+ },
42
+ natal_points: {
43
+ type: "array",
44
+ items: { type: "string" },
45
+ description: "Natal point IDs to receive transits. E.g. ['sun', 'moon', 'asc', 'mc']. Omit for all core points.",
46
+ },
47
+ aspects: {
48
+ type: "array",
49
+ items: { type: "string", enum: ["conjunction", "opposition", "trine", "square", "sextile"] },
50
+ description: "Aspect types to include in the search. Defaults to all major aspects.",
51
+ },
52
+ orb: {
53
+ type: "number",
54
+ description: "Maximum orb in degrees (default: 1.0).",
55
+ },
56
+ },
57
+ required: ["natal_datetime", "natal_latitude", "natal_longitude", "start_date", "end_date"],
58
+ additionalProperties: false,
59
+ },
60
+ handler: async (args) => {
61
+ const body = {
62
+ natal: {
63
+ datetime: args.natal_datetime,
64
+ latitude: args.natal_latitude,
65
+ longitude: args.natal_longitude,
66
+ },
67
+ start_date: args.start_date,
68
+ end_date: args.end_date,
69
+ };
70
+ if (args.transiting_planets)
71
+ body.transiting_planets = args.transiting_planets;
72
+ if (args.natal_points)
73
+ body.natal_points = args.natal_points;
74
+ if (args.aspects)
75
+ body.aspects = args.aspects;
76
+ if (args.orb != null)
77
+ body.orb = args.orb;
78
+ return await backendClient.request("POST", "/predictive/transits/search", { data: body });
79
+ },
80
+ });
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@openephemeris/mcp-server",
3
+ "version": "3.0.0",
4
+ "description": "Model Context Protocol server for the Open Ephemeris astronomical computation API",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "files": [
8
+ "dist",
9
+ "config/dev-allowlist.json",
10
+ "README.md"
11
+ ],
12
+ "bin": {
13
+ "openephemeris-mcp": "dist/index.js"
14
+ },
15
+ "directories": {
16
+ "test": "test"
17
+ },
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "dev": "tsx watch src/index.ts",
21
+ "start": "node dist/index.js",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "typecheck": "tsc --noEmit",
25
+ "regen:dev-allowlist": "tsx scripts/dev-allowlist.ts --write",
26
+ "check:dev-allowlist": "tsx scripts/dev-allowlist.ts --check",
27
+ "regen:schema-packs": "tsx scripts/schema-packs.ts --write",
28
+ "check:schema-packs": "tsx scripts/schema-packs.ts --check",
29
+ "sync:readme": "tsx scripts/sync-readme.ts --write",
30
+ "check:readme": "tsx scripts/sync-readme.ts --check",
31
+ "check:pack": "tsx scripts/pack-audit.ts",
32
+ "verify:release": "npm run check:dev-allowlist && npm run check:schema-packs && npm run check:readme && npm run typecheck && npm test && npm run build && npm run check:pack",
33
+ "prepack": "npm run build",
34
+ "prepublishOnly": "npm run verify:release"
35
+ },
36
+ "keywords": [
37
+ "mcp",
38
+ "astrology",
39
+ "astronomy",
40
+ "ephemeris",
41
+ "openephemeris"
42
+ ],
43
+ "author": "Open Ephemeris",
44
+ "license": "MIT",
45
+ "engines": {
46
+ "node": ">=18.0.0"
47
+ },
48
+ "dependencies": {
49
+ "@modelcontextprotocol/sdk": "^1.24.3",
50
+ "axios": "^1.13.2",
51
+ "zod": "^4.1.13"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^25.0.1",
55
+ "tsx": "^4.21.0",
56
+ "typescript": "^5.9.3",
57
+ "vitest": "^4.0.15"
58
+ },
59
+ "packageManager": "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a"
60
+ }