ether-to-astro 1.1.0 → 1.2.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 (58) hide show
  1. package/.github/ISSUE_TEMPLATE/bug-report.yml +87 -0
  2. package/.github/ISSUE_TEMPLATE/capability-request.yml +117 -0
  3. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  4. package/.github/ISSUE_TEMPLATE/paper-cut.yml +59 -0
  5. package/.github/pull_request_template.md +1 -0
  6. package/AGENTS.md +32 -0
  7. package/DEVELOPER.md +78 -0
  8. package/README.md +117 -76
  9. package/SETUP.md +91 -44
  10. package/dist/astro-service.d.ts +51 -2
  11. package/dist/astro-service.js +660 -56
  12. package/dist/cli.js +31 -0
  13. package/dist/entrypoint.d.ts +13 -0
  14. package/dist/entrypoint.js +78 -0
  15. package/dist/ephemeris.d.ts +15 -0
  16. package/dist/ephemeris.js +33 -0
  17. package/dist/formatter.d.ts +5 -1
  18. package/dist/formatter.js +4 -1
  19. package/dist/index.d.ts +2 -1
  20. package/dist/index.js +63 -114
  21. package/dist/loader.d.ts +1 -1
  22. package/dist/loader.js +61 -23
  23. package/dist/mcp-alias.d.ts +2 -0
  24. package/dist/mcp-alias.js +8 -0
  25. package/dist/time-utils.d.ts +8 -0
  26. package/dist/time-utils.js +16 -0
  27. package/dist/tool-registry.js +111 -5
  28. package/dist/tool-result.d.ts +8 -0
  29. package/dist/tool-result.js +39 -0
  30. package/dist/types.d.ts +79 -1
  31. package/docs/product/adrs/0001-mcp-vs-skill-boundary.md +96 -0
  32. package/docs/product/architecture-boundaries.md +223 -0
  33. package/docs/product/product-tenets.md +174 -0
  34. package/docs/releases/1.2.0-draft.md +48 -0
  35. package/package.json +6 -6
  36. package/skills/.curated/daily-brief/SKILL.md +75 -0
  37. package/skills/.curated/electional-overlay/SKILL.md +67 -0
  38. package/skills/.curated/weekly-overview/SKILL.md +73 -0
  39. package/skills/.system/write-skill/SKILL.md +90 -0
  40. package/src/astro-service.ts +861 -60
  41. package/src/cli.ts +84 -0
  42. package/src/entrypoint.ts +118 -0
  43. package/src/ephemeris.ts +44 -0
  44. package/src/formatter.ts +13 -1
  45. package/src/index.ts +77 -121
  46. package/src/loader.ts +69 -25
  47. package/src/mcp-alias.ts +10 -0
  48. package/src/time-utils.ts +18 -0
  49. package/src/tool-registry.ts +129 -9
  50. package/src/tool-result.ts +44 -0
  51. package/src/types.ts +91 -1
  52. package/tests/unit/astro-service.test.ts +751 -5
  53. package/tests/unit/cli-commands.test.ts +13 -0
  54. package/tests/unit/entrypoint.test.ts +67 -0
  55. package/tests/unit/error-mapping.test.ts +20 -0
  56. package/tests/unit/formatter.test.ts +6 -0
  57. package/tests/unit/tool-registry.test.ts +114 -2
  58. package/setup.sh +0 -21
package/SETUP.md CHANGED
@@ -1,82 +1,129 @@
1
- # Quick Setup Guide
1
+ # Setup Guide
2
2
 
3
- ## Installation
3
+ This guide is for using `ether-to-astro` as a product, not for local development on the repo itself.
4
4
 
5
- ```bash
6
- ./setup.sh
7
- ```
5
+ For contributor setup, local builds, tests, and release workflow, see [DEVELOPER.md](/Users/salted/Code/astro-mcp/DEVELOPER.md).
8
6
 
9
- This will:
10
- 1. Install npm dependencies (including native `sweph`)
11
- 2. Build TypeScript to JavaScript
7
+ ## Quick Start
12
8
 
13
- ## Add to Claude Desktop
9
+ ### Use as an MCP server
14
10
 
15
- Edit your Claude Desktop config file:
16
- - **Mac**: `~/Library/Application Support/Claude/claude_desktop_config.json`
17
- - **Linux**: `~/.config/Claude/claude_desktop_config.json`
18
-
19
- Add this MCP server:
11
+ Add this to your MCP client config:
20
12
 
21
13
  ```json
22
14
  {
23
15
  "mcpServers": {
24
16
  "astro": {
25
17
  "command": "npx",
26
- "args": ["--yes", "--package=ether-to-astro", "e2a-mcp"]
18
+ "args": ["--yes", "--package=ether-to-astro", "e2a", "--mcp"]
27
19
  }
28
20
  }
29
21
  }
30
22
  ```
31
23
 
32
- Alternative (after global install):
24
+ Alternative after global install:
33
25
 
34
26
  ```json
35
27
  {
36
28
  "mcpServers": {
37
29
  "astro": {
38
- "command": "e2a-mcp"
30
+ "command": "e2a",
31
+ "args": ["--mcp"]
39
32
  }
40
33
  }
41
34
  }
42
35
  ```
43
36
 
44
- ## First Use
37
+ Then restart your MCP client and call `set_natal_chart` before requesting transits or charts.
45
38
 
46
- 1. Restart Claude Desktop
47
- 2. Set your wife's natal chart:
39
+ ### Use as a CLI
48
40
 
41
+ Run directly with `npx`:
42
+
43
+ ```bash
44
+ npx --yes --package=ether-to-astro e2a --help
49
45
  ```
50
- Please set my natal chart:
51
- - Name: [Name]
52
- - Birth: [Month] [Day], [Year] at [Hour]:[Minute]
53
- - Location: [City] ([Latitude], [Longitude])
54
- - Timezone: [e.g., America/Los_Angeles]
46
+
47
+ Or install globally:
48
+
49
+ ```bash
50
+ npm install -g ether-to-astro
51
+ e2a --help
52
+ e2a --mcp --help
55
53
  ```
56
54
 
57
- 3. Query transits:
55
+ ## Notes
56
+
57
+ - You do not need to run `npm run build` when installing from npm.
58
+ - `npx e2a` does not work by itself because npm resolves package names first. Use `npx --package=ether-to-astro e2a`.
59
+ - The package downloads Swiss Ephemeris data during install unless you choose `EPHEMERIS_VERSION=moshier`.
60
+
61
+ ## Ephemeris Data Options
62
+
63
+ The package downloads Swiss Ephemeris data files during installation. You can control which version with `EPHEMERIS_VERSION`.
58
64
 
65
+ - `long` (default): 6000 years, recommended for professional use
66
+ - `short`: 600 years, smaller download for modern charts
67
+ - `moshier`: no ephemeris download, lower precision fallback
68
+
69
+ Examples:
70
+
71
+ ```bash
72
+ npm install -g ether-to-astro
73
+ EPHEMERIS_VERSION=short npm install -g ether-to-astro
74
+ EPHEMERIS_VERSION=moshier npm install -g ether-to-astro
59
75
  ```
60
- What are my transits today?
61
- Show me upcoming transits this week
62
- When will the Moon conjunct my Venus be exact?
76
+
77
+ ## First Use
78
+
79
+ Typical flow:
80
+
81
+ 1. Start the MCP server or use the CLI.
82
+ 2. Set the natal chart.
83
+ 3. Request transits, houses, or chart rendering.
84
+
85
+ Example CLI call:
86
+
87
+ ```bash
88
+ npx --yes --package=ether-to-astro e2a set-natal-chart \
89
+ --name "Test" \
90
+ --year 1990 \
91
+ --month 1 \
92
+ --day 1 \
93
+ --hour 12 \
94
+ --minute 0 \
95
+ --latitude 40.7 \
96
+ --longitude -74.0 \
97
+ --timezone America/New_York
63
98
  ```
64
99
 
65
- ## MCP Tools Available
100
+ Then:
66
101
 
67
- - `set_natal_chart` - Store birth data
68
- - `get_transits` - Category-filtered transit analysis with optional exact-time data
69
- - `get_houses` - House cusps plus angles (ASC/MC)
70
- - `get_retrograde_planets` - Current retrograde status
71
- - `get_rise_set_times` - Rise/set and meridian events
72
- - `get_asteroid_positions` - Asteroids and nodes
73
- - `get_next_eclipses` - Next solar/lunar eclipses
74
- - `generate_natal_chart` - Render natal chart (SVG/PNG/WebP)
75
- - `generate_transit_chart` - Render transit chart (SVG/PNG/WebP)
76
- - `get_server_status` - MCP-side loaded-chart and service status
102
+ ```bash
103
+ npx --yes --package=ether-to-astro e2a get-transits --natal-file ./natal.json --date 2026-03-27 --pretty
104
+ ```
105
+
106
+ ## Product Surfaces
107
+
108
+ - `e2a --mcp`: canonical stateful MCP server launch
109
+ - `e2a-mcp`: compatibility alias for MCP launch
110
+ - `e2a`: stateless CLI
77
111
 
78
- ## Technical Notes
112
+ Optional MCP startup defaults:
113
+
114
+ ```bash
115
+ e2a --mcp --preferred-tz America/Los_Angeles --preferred-house-style W --weekday-labels
116
+ ```
79
117
 
80
- - Uses native `sweph` bindings for Swiss Ephemeris calculations
81
- - Ephemeris files are downloaded/configured during install
82
- - Works on macOS/Linux (Node.js 22+)
118
+ ## Available Tools
119
+
120
+ - `set_natal_chart`
121
+ - `get_transits`
122
+ - `get_houses`
123
+ - `get_retrograde_planets`
124
+ - `get_rise_set_times`
125
+ - `get_asteroid_positions`
126
+ - `get_next_eclipses`
127
+ - `generate_natal_chart`
128
+ - `generate_transit_chart`
129
+ - `get_server_status`
@@ -1,11 +1,12 @@
1
1
  import { ChartRenderer } from './charts.js';
2
2
  import { EclipseCalculator } from './eclipses.js';
3
+ import type { McpStartupDefaults } from './entrypoint.js';
3
4
  import { EphemerisCalculator } from './ephemeris.js';
4
5
  import { HouseCalculator } from './houses.js';
5
6
  import { RiseSetCalculator } from './riseset.js';
6
7
  import { type Disambiguation } from './time-utils.js';
7
8
  import { TransitCalculator } from './transits.js';
8
- import { type HouseSystem, type NatalChart } from './types.js';
9
+ import { type AspectType, type ElectionalHouseSystem, type HouseSystem, type NatalChart, type PlanetPosition } from './types.js';
9
10
  interface AstroServiceDependencies {
10
11
  ephem?: EphemerisCalculator;
11
12
  transitCalc?: TransitCalculator;
@@ -13,6 +14,7 @@ interface AstroServiceDependencies {
13
14
  riseSetCalc?: RiseSetCalculator;
14
15
  eclipseCalc?: EclipseCalculator;
15
16
  chartRenderer?: ChartRenderer;
17
+ mcpStartupDefaults?: McpStartupDefaults;
16
18
  now?: () => Date;
17
19
  writeFile?: (path: string, data: string | Buffer, encoding?: BufferEncoding) => Promise<void>;
18
20
  }
@@ -34,13 +36,32 @@ export interface GetTransitsInput {
34
36
  categories?: string[];
35
37
  include_mundane?: boolean;
36
38
  days_ahead?: number;
39
+ mode?: 'snapshot' | 'best_hit' | 'forecast';
37
40
  max_orb?: number;
38
41
  exact_only?: boolean;
39
42
  applying_only?: boolean;
40
43
  }
44
+ export interface GetElectionalContextInput {
45
+ date: string;
46
+ time: string;
47
+ timezone: string;
48
+ latitude: number;
49
+ longitude: number;
50
+ house_system?: ElectionalHouseSystem;
51
+ include_ruler_basics?: boolean;
52
+ include_planetary_applications?: boolean;
53
+ orb_degrees?: number;
54
+ }
41
55
  export interface GetHousesInput {
42
56
  system?: string;
43
57
  }
58
+ export interface GetRisingSignWindowsInput {
59
+ date: string;
60
+ latitude: number;
61
+ longitude: number;
62
+ timezone: string;
63
+ mode?: 'approximate' | 'exact';
64
+ }
44
65
  export interface GenerateChartInput {
45
66
  theme?: 'light' | 'dark';
46
67
  format?: 'svg' | 'png' | 'webp';
@@ -53,7 +74,17 @@ export interface ServiceResult<T> {
53
74
  data: T;
54
75
  text: string;
55
76
  }
56
- export interface ChartServiceResult {
77
+ export interface MundaneAspect {
78
+ id: string;
79
+ planetA: PlanetPosition['planet'];
80
+ planetB: PlanetPosition['planet'];
81
+ aspect: AspectType;
82
+ orb: number;
83
+ isApplying: boolean;
84
+ longitudeA: number;
85
+ longitudeB: number;
86
+ }
87
+ interface ChartServiceResult {
57
88
  format: 'svg' | 'png' | 'webp';
58
89
  outputPath?: string;
59
90
  text: string;
@@ -77,16 +108,34 @@ export declare class AstroService {
77
108
  readonly riseSetCalc: RiseSetCalculator;
78
109
  readonly eclipseCalc: EclipseCalculator;
79
110
  readonly chartRenderer: ChartRenderer;
111
+ readonly mcpStartupDefaults: Readonly<McpStartupDefaults>;
80
112
  private readonly now;
81
113
  private readonly writeFileFn;
82
114
  constructor(deps?: AstroServiceDependencies);
115
+ private formatTimestamp;
116
+ private normalizeLongitude;
117
+ private getSignAndDegree;
118
+ private getHouseNumber;
119
+ private resolveHouseSystem;
120
+ private resolveTimezones;
121
+ resolveReportingTimezone(explicitTimezone?: string, natalTimezone?: string): string;
83
122
  init(): Promise<void>;
84
123
  isInitialized(): boolean;
85
124
  setNatalChart(input: SetNatalChartInput): ServiceResult<Record<string, unknown>> & {
86
125
  chart: NatalChart;
87
126
  };
88
127
  getTransits(natalChart: NatalChart, input?: GetTransitsInput): ServiceResult<Record<string, unknown>>;
128
+ private getMundaneWeather;
129
+ private getMundaneAspects;
130
+ private getMundaneDay;
131
+ getElectionalContext(input: GetElectionalContextInput): ServiceResult<Record<string, unknown>>;
89
132
  getHouses(natalChart: NatalChart, input?: GetHousesInput): ServiceResult<Record<string, unknown>>;
133
+ getRisingSignWindows(input: GetRisingSignWindowsInput): ServiceResult<Record<string, unknown>>;
134
+ private getElectionalApplyingAspects;
135
+ private isElectionalAspectApplying;
136
+ private getSignedAngularDifference;
137
+ private getElectionalPhaseName;
138
+ private getTraditionalSignRuler;
90
139
  getRetrogradePlanets(timezone?: string): ServiceResult<Record<string, unknown>>;
91
140
  getRiseSetTimes(natalChart: NatalChart): Promise<ServiceResult<Record<string, unknown>>>;
92
141
  getAsteroidPositions(timezone?: string): ServiceResult<Record<string, unknown>>;