ether-to-astro 1.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.
Files changed (138) hide show
  1. package/.env.example +13 -0
  2. package/.github/pull_request_template.md +16 -0
  3. package/.github/workflows/release.yml +35 -0
  4. package/.github/workflows/test.yml +32 -0
  5. package/AGENTS.md +99 -0
  6. package/LICENSE +18 -0
  7. package/NOTICE.md +45 -0
  8. package/README.md +301 -0
  9. package/SETUP.md +70 -0
  10. package/TESTING_SUMMARY.md +238 -0
  11. package/TEST_SUITE_STATUS.md +218 -0
  12. package/biome.json +48 -0
  13. package/dist/astro-service.d.ts +98 -0
  14. package/dist/astro-service.js +496 -0
  15. package/dist/chart-types.d.ts +52 -0
  16. package/dist/chart-types.js +51 -0
  17. package/dist/charts.d.ts +125 -0
  18. package/dist/charts.js +324 -0
  19. package/dist/cli.d.ts +7 -0
  20. package/dist/cli.js +472 -0
  21. package/dist/constants.d.ts +81 -0
  22. package/dist/constants.js +76 -0
  23. package/dist/eclipses.d.ts +85 -0
  24. package/dist/eclipses.js +184 -0
  25. package/dist/ephemeris.d.ts +120 -0
  26. package/dist/ephemeris.js +379 -0
  27. package/dist/formatter.d.ts +2 -0
  28. package/dist/formatter.js +22 -0
  29. package/dist/houses.d.ts +82 -0
  30. package/dist/houses.js +169 -0
  31. package/dist/index.d.ts +14 -0
  32. package/dist/index.js +150 -0
  33. package/dist/loader.d.ts +2 -0
  34. package/dist/loader.js +31 -0
  35. package/dist/logger.d.ts +25 -0
  36. package/dist/logger.js +73 -0
  37. package/dist/profile-store.d.ts +48 -0
  38. package/dist/profile-store.js +156 -0
  39. package/dist/riseset.d.ts +82 -0
  40. package/dist/riseset.js +185 -0
  41. package/dist/storage.d.ts +10 -0
  42. package/dist/storage.js +40 -0
  43. package/dist/time-utils.d.ts +68 -0
  44. package/dist/time-utils.js +136 -0
  45. package/dist/tool-registry.d.ts +35 -0
  46. package/dist/tool-registry.js +307 -0
  47. package/dist/tool-result.d.ts +175 -0
  48. package/dist/tool-result.js +188 -0
  49. package/dist/transits.d.ts +108 -0
  50. package/dist/transits.js +263 -0
  51. package/dist/types.d.ts +450 -0
  52. package/dist/types.js +161 -0
  53. package/example-usage.md +131 -0
  54. package/natal-chart.json +187 -0
  55. package/package.json +61 -0
  56. package/scripts/download-ephemeris.js +115 -0
  57. package/setup.sh +21 -0
  58. package/src/astro-service.ts +710 -0
  59. package/src/chart-types.ts +125 -0
  60. package/src/charts.ts +399 -0
  61. package/src/cli.ts +694 -0
  62. package/src/constants.ts +89 -0
  63. package/src/eclipses.ts +226 -0
  64. package/src/ephemeris.ts +437 -0
  65. package/src/formatter.ts +25 -0
  66. package/src/houses.ts +202 -0
  67. package/src/index.ts +170 -0
  68. package/src/loader.ts +36 -0
  69. package/src/logger.ts +104 -0
  70. package/src/profile-store.ts +285 -0
  71. package/src/riseset.ts +229 -0
  72. package/src/time-utils.ts +167 -0
  73. package/src/tool-registry.ts +357 -0
  74. package/src/tool-result.ts +283 -0
  75. package/src/transits.ts +352 -0
  76. package/src/types.ts +547 -0
  77. package/tests/README.md +173 -0
  78. package/tests/TESTING_STRATEGY.md +178 -0
  79. package/tests/fixtures/bowen-yang-chart.ts +69 -0
  80. package/tests/fixtures/calculate-expected.ts +81 -0
  81. package/tests/fixtures/expected-results.ts +117 -0
  82. package/tests/fixtures/generate-expected-simple.ts +94 -0
  83. package/tests/helpers/date-fixtures.ts +15 -0
  84. package/tests/helpers/ephem.ts +11 -0
  85. package/tests/helpers/temp.ts +9 -0
  86. package/tests/setup.ts +11 -0
  87. package/tests/unit/astro-service.test.ts +323 -0
  88. package/tests/unit/chart-types.test.ts +18 -0
  89. package/tests/unit/charts-errors.test.ts +42 -0
  90. package/tests/unit/charts.test.ts +157 -0
  91. package/tests/unit/cli-commands.test.ts +82 -0
  92. package/tests/unit/cli-profiles.test.ts +128 -0
  93. package/tests/unit/cli.test.ts +191 -0
  94. package/tests/unit/constants.test.ts +26 -0
  95. package/tests/unit/correctness-critical.test.ts +408 -0
  96. package/tests/unit/eclipses.test.ts +108 -0
  97. package/tests/unit/ephemeris.test.ts +213 -0
  98. package/tests/unit/error-handling.test.ts +116 -0
  99. package/tests/unit/formatter.test.ts +29 -0
  100. package/tests/unit/houses-errors.test.ts +27 -0
  101. package/tests/unit/houses-validation.test.ts +164 -0
  102. package/tests/unit/houses.test.ts +205 -0
  103. package/tests/unit/profile-store.test.ts +163 -0
  104. package/tests/unit/real-user-charts.test.ts +148 -0
  105. package/tests/unit/riseset.test.ts +106 -0
  106. package/tests/unit/solver-edges.test.ts +197 -0
  107. package/tests/unit/time-utils-temporal.test.ts +303 -0
  108. package/tests/unit/time-utils.test.ts +173 -0
  109. package/tests/unit/tool-registry.test.ts +222 -0
  110. package/tests/unit/tool-result.test.ts +45 -0
  111. package/tests/unit/transit-correctness.test.ts +78 -0
  112. package/tests/unit/transits.test.ts +238 -0
  113. package/tests/validation/README.md +32 -0
  114. package/tests/validation/adapters/astrolog.ts +306 -0
  115. package/tests/validation/adapters/internal.ts +184 -0
  116. package/tests/validation/compare/eclipses.ts +47 -0
  117. package/tests/validation/compare/houses.ts +76 -0
  118. package/tests/validation/compare/positions.ts +104 -0
  119. package/tests/validation/compare/riseSet.ts +48 -0
  120. package/tests/validation/compare/roots.ts +90 -0
  121. package/tests/validation/compare/transits.ts +69 -0
  122. package/tests/validation/fixtures/astrolog-parity/core.ts +194 -0
  123. package/tests/validation/fixtures/eclipses/core.ts +14 -0
  124. package/tests/validation/fixtures/houses/core.ts +47 -0
  125. package/tests/validation/fixtures/positions/core.ts +159 -0
  126. package/tests/validation/fixtures/rise-set/core.ts +20 -0
  127. package/tests/validation/fixtures/roots/core.ts +47 -0
  128. package/tests/validation/fixtures/transits/core.ts +61 -0
  129. package/tests/validation/fixtures/transits/dst.ts +21 -0
  130. package/tests/validation/oracle.spec.ts +129 -0
  131. package/tests/validation/utils/denseRootOracle.ts +269 -0
  132. package/tests/validation/utils/fixtureTypes.ts +146 -0
  133. package/tests/validation/utils/report.ts +60 -0
  134. package/tests/validation/utils/tolerances.ts +23 -0
  135. package/tests/validation/validation.spec.ts +836 -0
  136. package/tools/color-picker.html +388 -0
  137. package/tsconfig.json +17 -0
  138. package/vitest.config.ts +31 -0
@@ -0,0 +1,131 @@
1
+ # Example Usage
2
+
3
+ This document shows how to use the Astro MCP server with an AI agent like Claude.
4
+
5
+ **Note:** The natal chart is stored in memory for the duration of your session. If you disconnect and reconnect, you'll need to call `set_natal_chart` again.
6
+
7
+ ## Important: Time Handling
8
+
9
+ **Always provide birth time in LOCAL time** (not UTC):
10
+ - Use the time as it appeared on the clock at the birth location
11
+ - Specify the IANA timezone (e.g., `America/New_York`, not `EST`)
12
+ - The server will convert to UTC and handle DST automatically
13
+ - You'll receive verification feedback showing both local and UTC times
14
+
15
+ ## Setting Up Your Wife's Natal Chart
16
+
17
+ First, she needs to provide her birth data. Ask your AI agent:
18
+
19
+ ```
20
+ Please set my natal chart:
21
+ - Name: Jane
22
+ - Birth: January 15, 1985 at 14:30 (2:30 PM)
23
+ - Location: Los Angeles, CA (34.0522°N, 118.2437°W)
24
+ - Timezone: America/Los_Angeles
25
+ ```
26
+
27
+ The agent will call `set_natal_chart` with:
28
+ ```json
29
+ {
30
+ "name": "Jane",
31
+ "year": 1985,
32
+ "month": 1,
33
+ "day": 15,
34
+ "hour": 14,
35
+ "minute": 30,
36
+ "latitude": 34.0522,
37
+ "longitude": -118.2437,
38
+ "timezone": "America/Los_Angeles",
39
+ "house_system": "P"
40
+ }
41
+ ```
42
+
43
+ **Note:** Hour is in LOCAL time (14:30 = 2:30 PM). The server converts to UTC automatically.
44
+
45
+ The server responds with verification:
46
+ ```
47
+ Natal chart saved for Jane
48
+
49
+ Birth Details:
50
+ - Local Time: 1/15/1985 14:30 (America/Los_Angeles)
51
+ - UTC Time: 1/15/1985 22:30 UTC
52
+ - Location: 34.05°N, -118.24°W
53
+
54
+ Chart Angles:
55
+ - Sun: 25° Capricorn
56
+ - Moon: 12° Gemini
57
+ - Ascendant: 8° Taurus
58
+ - MC: 15° Capricorn
59
+
60
+ House System: Placidus
61
+ ```
62
+
63
+ ## Daily Transit Queries
64
+
65
+ ### Morning Check-In
66
+ "What are my transits for today?"
67
+
68
+ The agent will call:
69
+ - `get_daily_transits` - Current planetary positions
70
+ - `get_moon_transits` - Moon aspects to natal planets
71
+ - `get_personal_planet_transits` - Sun/Mercury/Venus/Mars aspects
72
+ - `get_outer_planet_transits` - Slower moving planets
73
+
74
+ ### Specific Questions
75
+
76
+ **"When will the Moon conjunct my Venus be exact?"**
77
+ - Agent calls `get_exact_transit_times`
78
+ - Returns precise time when aspect is 0° orb
79
+
80
+ **"What transits are coming up this week?"**
81
+ - Agent calls `get_upcoming_transits` with `days: 7`
82
+ - Shows all transits approaching within 2° orb
83
+
84
+ **"Show me just the outer planet transits"**
85
+ - Agent calls `get_outer_planet_transits`
86
+ - Returns Jupiter, Saturn, Uranus, Neptune, Pluto aspects
87
+
88
+ ## Sample Output
89
+
90
+ ### Moon Transits
91
+ ```
92
+ Moon Transits:
93
+
94
+ Moon conjunction Venus: 0.45° orb (applying) - Exact: 2026-03-27T03:24:15.000Z
95
+ Moon sextile Mars: 1.23° orb (separating)
96
+ Moon trine Jupiter: 2.87° orb (applying)
97
+ ```
98
+
99
+ ### Personal Planet Transits
100
+ ```
101
+ Personal Planet Transits:
102
+
103
+ Sun square natal Moon: 0.89° orb (applying) - Exact: 2026-03-27T18:45:32.000Z
104
+ Venus trine natal Sun: 3.21° orb (separating)
105
+ Mars opposition natal Mercury: 5.67° orb (applying)
106
+ ```
107
+
108
+ ### Upcoming Transits (7 days)
109
+ ```
110
+ Upcoming Transits (next 7 days):
111
+
112
+ Jupiter trine natal Venus: 1.45° orb (applying) - Exact: 2026-03-29T12:30:00.000Z
113
+ Saturn square natal Mars: 1.89° orb (applying) - Exact: 2026-04-01T08:15:45.000Z
114
+ ```
115
+
116
+ ## Understanding the Output
117
+
118
+ - **Orb**: How close the aspect is (0° = exact)
119
+ - **Applying**: Transit is getting closer to exact
120
+ - **Separating**: Transit is moving away from exact
121
+ - **Exact time**: When the aspect becomes 0° orb (only shown for transits within 2°)
122
+
123
+ ## Tips for Your Wife
124
+
125
+ 1. **Morning routine**: Check daily transits each morning
126
+ 2. **Plan ahead**: Use `get_upcoming_transits` to see what's coming
127
+ 3. **Track exact times**: Important transits show exact timing for planning
128
+ 4. **Focus on what matters**:
129
+ - Moon transits change quickly (every few hours)
130
+ - Personal planets change daily/weekly
131
+ - Outer planets can last weeks/months
@@ -0,0 +1,187 @@
1
+ {
2
+ "name": "User Whole Sign",
3
+ "birthDate": {
4
+ "year": 1977,
5
+ "month": 10,
6
+ "day": 17,
7
+ "hour": 13,
8
+ "minute": 6
9
+ },
10
+ "location": {
11
+ "latitude": 40.7526,
12
+ "longitude": -80.3198,
13
+ "timezone": "America/New_York"
14
+ },
15
+ "planets": [
16
+ {
17
+ "planet": "Sun",
18
+ "longitude": 204.05218050976873,
19
+ "latitude": 0.0001615388556612532,
20
+ "distance": 0.9964210583337456,
21
+ "speed": 0.9928259050042711,
22
+ "sign": "Libra",
23
+ "degree": 24.052180509768732,
24
+ "isRetrograde": false
25
+ },
26
+ {
27
+ "planet": "Moon",
28
+ "longitude": 267.7474069899507,
29
+ "latitude": 5.03828787700736,
30
+ "distance": 0.0024531797587498657,
31
+ "speed": 14.457512480190383,
32
+ "sign": "Sagittarius",
33
+ "degree": 27.74740698995072,
34
+ "isRetrograde": false
35
+ },
36
+ {
37
+ "planet": "Mercury",
38
+ "longitude": 203.05615113717954,
39
+ "latitude": 0.956300075310156,
40
+ "distance": 1.4134856844175427,
41
+ "speed": 1.7001421021313727,
42
+ "sign": "Libra",
43
+ "degree": 23.05615113717954,
44
+ "isRetrograde": false
45
+ },
46
+ {
47
+ "planet": "Venus",
48
+ "longitude": 180.59233174758765,
49
+ "latitude": 1.520411261036414,
50
+ "distance": 1.5124130040316783,
51
+ "speed": 1.2383468359522916,
52
+ "sign": "Libra",
53
+ "degree": 0.5923317475876502,
54
+ "isRetrograde": false
55
+ },
56
+ {
57
+ "planet": "Mars",
58
+ "longitude": 115.83306761812116,
59
+ "latitude": 1.0377403010723354,
60
+ "distance": 1.1984622765651196,
61
+ "speed": 0.47310831677259674,
62
+ "sign": "Cancer",
63
+ "degree": 25.833067618121163,
64
+ "isRetrograde": false
65
+ },
66
+ {
67
+ "planet": "Jupiter",
68
+ "longitude": 96.06324009530363,
69
+ "latitude": -0.3624170362523381,
70
+ "distance": 4.715321463223517,
71
+ "speed": 0.022806312817944503,
72
+ "sign": "Cancer",
73
+ "degree": 6.063240095303627,
74
+ "isRetrograde": false
75
+ },
76
+ {
77
+ "planet": "Saturn",
78
+ "longitude": 147.9183963947238,
79
+ "latitude": 1.1514198531366935,
80
+ "distance": 9.71241768931636,
81
+ "speed": 0.08930814127132901,
82
+ "sign": "Leo",
83
+ "degree": 27.9183963947238,
84
+ "isRetrograde": false
85
+ },
86
+ {
87
+ "planet": "Uranus",
88
+ "longitude": 220.99220136598956,
89
+ "latitude": 0.39006096397372564,
90
+ "distance": 19.547124554119833,
91
+ "speed": 0.06054899513110079,
92
+ "sign": "Scorpio",
93
+ "degree": 10.992201365989558,
94
+ "isRetrograde": false
95
+ },
96
+ {
97
+ "planet": "Neptune",
98
+ "longitude": 254.1099953294147,
99
+ "latitude": 1.4392507913670756,
100
+ "distance": 30.91780788606139,
101
+ "speed": 0.026698768271311017,
102
+ "sign": "Sagittarius",
103
+ "degree": 14.109995329414687,
104
+ "isRetrograde": false
105
+ },
106
+ {
107
+ "planet": "Pluto",
108
+ "longitude": 194.47902308697212,
109
+ "latitude": 16.530727897276424,
110
+ "distance": 31.37683977306858,
111
+ "speed": 0.038963569772553476,
112
+ "sign": "Libra",
113
+ "degree": 14.47902308697212,
114
+ "isRetrograde": false
115
+ },
116
+ {
117
+ "planet": "North Node (Mean)",
118
+ "longitude": 194.5511103273211,
119
+ "latitude": 0,
120
+ "distance": 0.0025695552897999903,
121
+ "speed": -0.05293530033441037,
122
+ "sign": "Libra",
123
+ "degree": 14.551110327321112,
124
+ "isRetrograde": true
125
+ },
126
+ {
127
+ "planet": "North Node (True)",
128
+ "longitude": 195.2274831010368,
129
+ "latitude": 0,
130
+ "distance": 0.0024556133228558225,
131
+ "speed": -0.013109185725915731,
132
+ "sign": "Libra",
133
+ "degree": 15.227483101036796,
134
+ "isRetrograde": true
135
+ },
136
+ {
137
+ "planet": "Chiron",
138
+ "longitude": 33.86707264166279,
139
+ "latitude": -0.5386594883172258,
140
+ "distance": 16.867648288381556,
141
+ "speed": -0.046728100146171576,
142
+ "sign": "Taurus",
143
+ "degree": 3.867072641662787,
144
+ "isRetrograde": true
145
+ },
146
+ {
147
+ "planet": "Ceres",
148
+ "longitude": 225.17925484526404,
149
+ "latitude": 3.722322777056521,
150
+ "distance": 3.6128220583215915,
151
+ "speed": 0.42320521586905213,
152
+ "sign": "Scorpio",
153
+ "degree": 15.17925484526404,
154
+ "isRetrograde": false
155
+ },
156
+ {
157
+ "planet": "Pallas",
158
+ "longitude": 204.86164458449048,
159
+ "latitude": 14.672306160015758,
160
+ "distance": 3.548347696867575,
161
+ "speed": 0.4450325558858604,
162
+ "sign": "Libra",
163
+ "degree": 24.861644584490477,
164
+ "isRetrograde": false
165
+ },
166
+ {
167
+ "planet": "Juno",
168
+ "longitude": 243.42276981356122,
169
+ "latitude": 10.664052131434042,
170
+ "distance": 3.9911632546316698,
171
+ "speed": 0.313194206647786,
172
+ "sign": "Sagittarius",
173
+ "degree": 3.4227698135612172,
174
+ "isRetrograde": false
175
+ },
176
+ {
177
+ "planet": "Vesta",
178
+ "longitude": 188.4269007577168,
179
+ "latitude": 4.9410232440203075,
180
+ "distance": 3.2207217522128566,
181
+ "speed": 0.5021548471029085,
182
+ "sign": "Libra",
183
+ "degree": 8.426900757716794,
184
+ "isRetrograde": false
185
+ }
186
+ ]
187
+ }
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "ether-to-astro",
3
+ "version": "1.0.0",
4
+ "description": "Local-first astrology toolkit with a CLI (e2a) and MCP server (e2a-mcp) for charts, transits, rendering, and agent workflows.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
10
+ "bin": {
11
+ "e2a-mcp": "dist/loader.js",
12
+ "e2a": "dist/cli.js"
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "dev:watch": "tsx watch src/loader.ts",
18
+ "start": "node dist/loader.js",
19
+ "start:cli": "node dist/cli.js",
20
+ "postinstall": "node scripts/download-ephemeris.js",
21
+ "test": "vitest tests/unit",
22
+ "validate:astro": "vitest run tests/validation",
23
+ "test:ui": "vitest --ui",
24
+ "test:coverage": "vitest run tests/unit --coverage",
25
+ "calculate-expected": "tsx tests/fixtures/calculate-expected.ts",
26
+ "quality:gate": "npm run build && npm run lint && npm test -- --run",
27
+ "lint": "biome check .",
28
+ "lint:fix": "biome check --write .",
29
+ "format": "biome format --write ."
30
+ },
31
+ "keywords": [
32
+ "mcp",
33
+ "astrology",
34
+ "swiss-ephemeris",
35
+ "transits"
36
+ ],
37
+ "author": "",
38
+ "license": "AGPL-3.0-or-later",
39
+ "dependencies": {
40
+ "@astrodraw/astrochart": "^3.0.2",
41
+ "@js-temporal/polyfill": "^0.5.1",
42
+ "@modelcontextprotocol/sdk": "^1.0.0",
43
+ "@std/datetime": "npm:@jsr/std__datetime@^0.225.7",
44
+ "commander": "^14.0.3",
45
+ "picocolors": "^1.1.1",
46
+ "sharp": "^0.34.5",
47
+ "sweph": "2.10.3-b-1"
48
+ },
49
+ "devDependencies": {
50
+ "@biomejs/biome": "^2.4.9",
51
+ "@types/jsdom": "^28.0.1",
52
+ "@types/node": "^20.0.0",
53
+ "@vitest/coverage-v8": "^4.1.2",
54
+ "@vitest/ui": "^4.1.2",
55
+ "happy-dom": "^20.8.9",
56
+ "jsdom": "^29.0.1",
57
+ "tsx": "^4.21.0",
58
+ "typescript": "^5.0.0",
59
+ "vitest": "^4.1.2"
60
+ }
61
+ }
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { access, mkdir, writeFile } from 'node:fs/promises';
4
+ import { dirname, join } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const DATA_DIR = join(__dirname, '..', 'data', 'ephemeris');
9
+
10
+ // Environment variable controls which version to download
11
+ // EPHEMERIS_VERSION=short (600 years, ~2MB) | long (6000 years, ~5MB, DEFAULT) | moshier (none, use built-in)
12
+ const VERSION = (process.env.EPHEMERIS_VERSION || 'long').toLowerCase();
13
+
14
+ const SHORT_FILES = [
15
+ { name: 'sepl_18.se1', desc: 'Main planets (Sun-Pluto) [600yr]' },
16
+ { name: 'semo_18.se1', desc: 'High-precision Moon [600yr]' },
17
+ { name: 'seas_18.se1', desc: 'Asteroids [600yr]' },
18
+ ];
19
+
20
+ const LONG_FILES = [
21
+ { name: 'sepl_18.se1', desc: 'Main planets (Sun-Pluto) [6000yr]' },
22
+ { name: 'semo_18.se1', desc: 'High-precision Moon [6000yr]' },
23
+ { name: 'seas_18.se1', desc: 'Asteroids [6000yr]' },
24
+ ];
25
+
26
+ const BASE_URL_SHORT = 'https://raw.githubusercontent.com/aloistr/swisseph/master/ephe';
27
+ const BASE_URL_LONG = 'https://raw.githubusercontent.com/aloistr/swisseph/master/ephe';
28
+
29
+ async function fileExists(path) {
30
+ try {
31
+ await access(path);
32
+ return true;
33
+ } catch {
34
+ return false;
35
+ }
36
+ }
37
+
38
+ async function downloadFile(filename, description, baseUrl) {
39
+ const filePath = join(DATA_DIR, filename);
40
+
41
+ if (await fileExists(filePath)) {
42
+ console.log(`✓ ${description} already exists`);
43
+ return true;
44
+ }
45
+
46
+ const url = `${baseUrl}/${filename}`;
47
+ console.log(`Downloading ${description}...`);
48
+
49
+ try {
50
+ const response = await fetch(url);
51
+ if (!response.ok) {
52
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
53
+ }
54
+
55
+ const buffer = await response.arrayBuffer();
56
+ await writeFile(filePath, Buffer.from(buffer));
57
+
58
+ const sizeMB = (buffer.byteLength / 1024 / 1024).toFixed(2);
59
+ console.log(`✓ Downloaded ${description} (${sizeMB}MB)`);
60
+ return true;
61
+ } catch (error) {
62
+ console.warn(`⚠ Failed to download ${description}: ${error.message}`);
63
+ return false;
64
+ }
65
+ }
66
+
67
+ async function main() {
68
+ console.log(`Setting up Swiss Ephemeris data files (${VERSION} version)...\n`);
69
+
70
+ // Moshier mode - skip downloads entirely
71
+ if (VERSION === 'moshier') {
72
+ console.log('✓ Using Moshier ephemeris (built-in approximation, no downloads)');
73
+ console.log(' Lower precision but works offline\n');
74
+ process.exit(0);
75
+ }
76
+
77
+ // Determine which files to download
78
+ const FILES = VERSION === 'short' ? SHORT_FILES : LONG_FILES;
79
+ const BASE_URL = VERSION === 'short' ? BASE_URL_SHORT : BASE_URL_LONG;
80
+
81
+ if (!['short', 'long'].includes(VERSION)) {
82
+ console.warn(`⚠ Unknown EPHEMERIS_VERSION: "${VERSION}"`);
83
+ console.warn('Valid options: short, long (default), moshier');
84
+ console.warn('Defaulting to long version...\n');
85
+ }
86
+
87
+ try {
88
+ await mkdir(DATA_DIR, { recursive: true });
89
+ } catch (error) {
90
+ console.error(`Failed to create data directory: ${error.message}`);
91
+ process.exit(0); // Fail silently - will use Moshier fallback
92
+ }
93
+
94
+ let successCount = 0;
95
+ for (const file of FILES) {
96
+ const success = await downloadFile(file.name, file.desc, BASE_URL);
97
+ if (success) successCount++;
98
+ }
99
+
100
+ console.log(`\n${successCount}/${FILES.length} ephemeris files ready`);
101
+
102
+ if (successCount === 0) {
103
+ console.warn('\n⚠ Warning: No ephemeris files downloaded.');
104
+ console.warn('The server will use Moshier ephemeris (lower precision).');
105
+ console.warn('You can manually download files from:');
106
+ console.warn('https://github.com/aloistr/swisseph/tree/master/ephe\n');
107
+ } else {
108
+ const rangeDesc = VERSION === 'short' ? '1800-2400 AD' : '3000 BC - 3000 AD';
109
+ console.log(`Date range: ${rangeDesc}\n`);
110
+ }
111
+
112
+ process.exit(0);
113
+ }
114
+
115
+ main();
package/setup.sh ADDED
@@ -0,0 +1,21 @@
1
+ #!/bin/bash
2
+
3
+ echo "Setting up Astro MCP Server..."
4
+
5
+ echo "Installing npm dependencies..."
6
+ npm install
7
+
8
+ echo "Building TypeScript..."
9
+ npm run build
10
+
11
+ echo ""
12
+ echo "✅ Setup complete!"
13
+ echo ""
14
+ echo "The server uses WebAssembly Swiss Ephemeris - no data files needed!"
15
+ echo ""
16
+ echo "Next steps:"
17
+ echo "1. Add this server to your MCP settings"
18
+ echo "2. Use set_natal_chart to store birth data"
19
+ echo "3. Query transits with your AI agent"
20
+ echo ""
21
+ echo "See README.md for detailed usage instructions."