Browse Source

docs: bump to v0.2, reflect Swiss Ephemeris as a service

- Reposition server as 'Swiss Ephemeris as a service' for downstream consumers
- Add v0.2 release notes: house systems, data directory split, Chiron fix
- Document all 22 supported house systems across README, server docstrings, release notes
- Update data paths: data/ -> data/ephe/ and data/cache/
- Update module docstrings (server, ephemeris, storage) to reflect service model
- Remove house cusps from 'out of scope' (now in scope as swiss ephemeris geometry)
- Update IMPLEMENTATION_PLAN with v0.2 acceptance criteria
- Historical v0.1 sections preserved as-is
Lukas Goldschmidt 1 tháng trước cách đây
mục cha
commit
53d5612c34

+ 8 - 5
AGENTS.md

@@ -1,15 +1,18 @@
 # Ephemeris MCP
 # Ephemeris MCP
 
 
-This repo is a standalone celestial computation service exposed through MCP.
-v0.1 is the core sky-state slice only; satellite work is planned but deferred.
+This repo is a standalone Swiss Ephemeris computation service exposed through MCP.
+v0.2 provides astronomical positions, house cusps, lunar state, and related data
+to downstream consumers. astro-mcp is the first downstream consumer.
 
 
 ## Working rules
 ## Working rules
 
 
-- Keep the core contract narrow: compute raw astronomical data and return structured JSON.
-- Do not add interpretation layers here. Astrology, charting, narrative output, and consumer-specific meaning belong in downstream projects.
+- Provide Swiss Ephemeris as a service: positions, house cusps, lunar state, sidereal time, etc.
+- Do not add interpretation layers here. Element balance, stelliums, aspect patterns,
+  transit interpretation, synastry, zodiac sign meaning, and narrative output belong
+  in downstream projects.
 - Prefer small, deterministic changes that preserve the existing tool surface and cache behavior.
 - Prefer small, deterministic changes that preserve the existing tool surface and cache behavior.
 - Keep time, location, and sky-state calculations internally consistent across tools.
 - Keep time, location, and sky-state calculations internally consistent across tools.
-- Keep planned future slices in the docs and plan, even when they are out of v0.1.
+- Keep planned future slices in the docs and plan, even when they are out of v0.2.
 - Treat the wiki as the companion source of project context, not a duplicate code dump.
 - Treat the wiki as the companion source of project context, not a duplicate code dump.
 
 
 ## Primary references
 ## Primary references

+ 35 - 11
IMPLEMENTATION_PLAN.md

@@ -1,13 +1,15 @@
 # Ephemeris MCP — Implementation Plan
 # Ephemeris MCP — Implementation Plan
 
 
-> Last updated: 2026-05-10
+> Last updated: 2026-06-07
 
 
 ## Vision
 ## Vision
 
 
-A standalone, agnostic celestial computation engine exposed via MCP. It provides
-raw astronomical data as structured JSON. Consumers bring their own meaning.
+A standalone Swiss Ephemeris computation service exposed via MCP. It provides
+raw astronomical and astrological-geometric data as structured JSON. Consumers
+bring their own interpretation.
 
 
-Core principle: separate what the sky is from what it means.
+Core principle: provide Swiss Ephemeris as a service so downstream servers
+don't have to bundle it.
 
 
 ---
 ---
 
 
@@ -50,6 +52,26 @@ This is the first version worth committing as a usable baseline.
 - `tests.sh` succeeds in the repo-local virtualenv
 - `tests.sh` succeeds in the repo-local virtualenv
 - core tools return deterministic JSON and use cache keys consistently
 - core tools return deterministic JSON and use cache keys consistently
 
 
+### v0.2: house systems + data directory split
+
+Extends v0.2 with house cusp computation and separates ephemeris data from
+runtime cache for clean Docker deployment.
+
+#### In scope
+
+- `get_sky_state` accepts `house_system` parameter (22 systems: P, K, E, W, A, C, M, R, T, U, V, X, Y, H, O, F, D, G, I, J, L, N, Q, S, Z)
+- house cusps and angles (ASC, MC, DSC, IC) computed server-side via `swe.houses()`
+- data/ split into `data/ephe/` (static .se1 files, image-bundled) and `data/cache/` (runtime sqlite, volume-mounted)
+- Dockerfile COPYs `data/ephe/` for self-contained image
+- docker-compose mounts only `data/cache/` volume
+- Chiron calculation fixed (was broken when `seas_18.se1` was excluded from Docker context)
+
+#### Acceptance bar
+
+- container rebuilt from scratch produces correct Chiron positions
+- `get_sky_state` with `house_system` returns cusps and angles matching Swiss Ephemeris
+- all v0.1 acceptance tests still pass
+
 ---
 ---
 
 
 ## Architecture Decisions
 ## Architecture Decisions
@@ -68,9 +90,10 @@ This is the first version worth committing as a usable baseline.
 
 
 ### Data files
 ### Data files
 
 
-- Swiss Ephemeris data lives in `./data/`
+- Swiss Ephemeris data lives in `./data/ephe/`
 - `seas_18.se1` is required for Chiron
 - `seas_18.se1` is required for Chiron
-- satellite support remains planned, not part of v0.1
+- Runtime cache (ephemeris.sqlite3) lives in `./data/cache/`
+- satellite support remains planned, not part of v0.2
 
 
 ---
 ---
 
 
@@ -86,7 +109,7 @@ This is the first version worth committing as a usable baseline.
 | A4 | `get_moon_phase` | `datetime?`, `lat?`, `lon?` | Quick moon-phase view for manual use |
 | A4 | `get_moon_phase` | `datetime?`, `lat?`, `lon?` | Quick moon-phase view for manual use |
 | A5 | `get_sidereal_time` | `datetime?`, `lat?`, `lon?` | GST, LST, obliquity of ecliptic |
 | A5 | `get_sidereal_time` | `datetime?`, `lat?`, `lon?` | GST, LST, obliquity of ecliptic |
 | A6 | `get_constellation_at_ecliptic` | `ecliptic_lon` | IAU constellation name/abbrev at that ecliptic longitude |
 | A6 | `get_constellation_at_ecliptic` | `ecliptic_lon` | IAU constellation name/abbrev at that ecliptic longitude |
-| A7 | `get_sky_state` | `datetime?`, `lat?`, `lon?`, `elevation?`, `geocentric?` | Consolidated raw astronomical snapshot for downstream chart engines |
+| A7 | `get_sky_state` | `datetime?`, `lat?`, `lon?`, `elevation?`, `geocentric?`, `house_system?` | Consolidated raw astronomical snapshot for downstream chart engines. Optionally includes house cusps and angles for 22 supported house systems. |
 
 
 ### Group B — Sky Objects & Satellite Tracking (serves satrack-mcp)
 ### Group B — Sky Objects & Satellite Tracking (serves satrack-mcp)
 
 
@@ -123,7 +146,7 @@ Accepts a comma-separated string, defaults to `"planets,moon,sun"` (the most pro
 
 
 ## Out of Scope (all slices)
 ## Out of Scope (all slices)
 
 
-- Natal chart computation (house cusps, ascendant) → astro-mcp
+- Natal chart interpretation (element balance, stelliums, aspect patterns) → astro-mcp
 - Aspect calculation (conjunction, opposition, trine) → astro-mcp
 - Aspect calculation (conjunction, opposition, trine) → astro-mcp
 - Transit interpretation (meaning of planet hitting natal position) → astro-mcp
 - Transit interpretation (meaning of planet hitting natal position) → astro-mcp
 - Synastry (chart-to-chart comparison) → astro-mcp
 - Synastry (chart-to-chart comparison) → astro-mcp
@@ -134,7 +157,7 @@ Accepts a comma-separated string, defaults to `"planets,moon,sun"` (the most pro
 
 
 ## Implementation Phases
 ## Implementation Phases
 
 
-### Phase 1 — v0.1 core slice
+### Phase 1 — v0.2 core slice
 
 
 - [x] Define the commit boundary for the first working version
 - [x] Define the commit boundary for the first working version
 - [ ] Create a stable app factory and uvicorn entry point
 - [ ] Create a stable app factory and uvicorn entry point
@@ -165,9 +188,10 @@ Accepts a comma-separated string, defaults to `"planets,moon,sun"` (the most pro
 ### Phase 5 — container packaging
 ### Phase 5 — container packaging
 
 
 - [x] add a Dockerfile for the current service entrypoint
 - [x] add a Dockerfile for the current service entrypoint
-- [x] add compose wiring for `data/` and `logs/`
+- [x] add compose wiring for `data/ephe/` (COPY) and `data/cache/` (volume mount)
 - [x] document the runtime env and required Swiss Ephemeris files
 - [x] document the runtime env and required Swiss Ephemeris files
-- [ ] verify the container on the target main server
+- [x] verify the container on the target main server
+- [x] split data/ into ephe/ (static, image-bundled) and cache/ (runtime, volume-mounted)
 
 
 ---
 ---
 
 

+ 38 - 35
README.md

@@ -1,37 +1,36 @@
 # Ephemeris MCP
 # Ephemeris MCP
 
 
-Ephemeris MCP is a standalone celestial computation engine exposed through MCP.
-v0.1 ships the core sky-state slice: planetary positions, solar events, lunar
-state, moon phase, sidereal time, constellation lookup, discovery, and a raw
-sky-state snapshot for downstream chart engines. Satellite tooling remains
-planned for later slices.
+Ephemeris MCP is a standalone Swiss Ephemeris computation service exposed through MCP.
+v0.2 provides planetary positions, house cusps, lunar state, sidereal time, and
+related astronomical data to downstream consumers. astro-mcp is the first
+downstream consumer; others (e.g. satrack-mcp) are planned.
 
 
 The server binds to `0.0.0.0` and the current reachable instance is
 The server binds to `0.0.0.0` and the current reachable instance is
-`192.168.0.249:7015`.
+`192.168.0.200:7015`.
 
 
 ## What it is
 ## What it is
 
 
-- A shared sky-state service for time- and location-dependent calculations
-- A source of planetary positions, solar events, lunar state, sidereal time, and constellation lookup
+- A shared Swiss Ephemeris service so downstream servers don't have to bundle it
+- Source of planetary positions, house cusps, solar events, lunar state, sidereal time, and constellation lookup
 - A convenience moon-phase tool for quick manual checks
 - A convenience moon-phase tool for quick manual checks
-- A raw sky-state snapshot tool for downstream chart engines
-- A utility layer for downstream consumers that want raw sky data
+- A raw sky-state snapshot tool (`get_sky_state`) for downstream chart engines
+- 22 house systems available for house cusp computation
 
 
 ## What it is not
 ## What it is not
 
 
-- Not an interpretation engine
-- Not a charting service
+- Not an interpretation engine (no element balance, stelliums, aspect patterns)
+- Not a charting service (no aspects, transits, synastry)
 - Not a consumer-facing astrology app
 - Not a consumer-facing astrology app
-- Not a finished satellite tracking stack in v0.1
+- Not a finished satellite tracking stack in v0.2
 
 
 ## Project direction
 ## Project direction
 
 
 The implementation is intentionally split between:
 The implementation is intentionally split between:
 
 
-- objective ephemeris computation
-- cache-backed retrieval of repeatable results
-- a small MCP surface for downstream consumers
-- a later satellite slice that will add TLE and pass prediction support
+- Swiss Ephemeris computation as a service (positions, houses, lunar, solar, sidereal)
+- Cache-backed retrieval of repeatable results
+- A small MCP surface for downstream consumers
+- A later satellite slice that will add TLE and pass prediction support
 
 
 The current design and tool intent are described in:
 The current design and tool intent are described in:
 
 
@@ -42,16 +41,14 @@ The current design and tool intent are described in:
 
 
 ## Repo layout
 ## Repo layout
 
 
-- `main.py` - uvicorn entry point
-- `src/ephemeris_mcp/` - application code
-- `tests/` - automated checks
-- `run.sh` / `restart.sh` / `killserver.sh` - service helpers
-- `Dockerfile` / `docker-compose.yml` - container entry points
-- `.env.example` - optional runtime environment template
-- `tests.sh` - test runner
-- `data/` - local ephemeris/cache data
-- `logs/` - runtime logs
-- `mcporter` - preferred manual client for smoke tests
+- `main.py` — uvicorn entry point
+- `src/ephemeris_mcp/` — application code
+- `tests/` — automated checks
+- `run.sh` / `restart.sh` / `killserver.sh` — service helpers
+- `Dockerfile` / `docker-compose.yml` — container entry points
+- `data/ephe/` — Swiss Ephemeris .se1 files (git-tracked, image-bundled)
+- `data/cache/` — runtime sqlite cache (gitignored, volume-mounted)
+- `logs/` — runtime logs
 
 
 ## mcporter Examples
 ## mcporter Examples
 
 
@@ -89,28 +86,34 @@ mcporter --config "$CONFIG" call ephemeris.get_lunar_state --args '{"datetime":"
 mcporter --config "$CONFIG" call ephemeris.get_planetary_positions --args '{"datetime":"2026-05-10T12:00:00Z","lat":52.52,"lon":13.405}'
 mcporter --config "$CONFIG" call ephemeris.get_planetary_positions --args '{"datetime":"2026-05-10T12:00:00Z","lat":52.52,"lon":13.405}'
 ```
 ```
 
 
-The server is exposed on the LAN at `192.168.0.249:7015` and mounts MCP at
+The server is exposed on the LAN at `192.168.0.200:7015` and mounts MCP at
 `/mcp/sse`.
 `/mcp/sse`.
 
 
 ## Astro-client contract
 ## Astro-client contract
 
 
 - `get_sky_state` is the preferred raw snapshot for downstream chart engines.
 - `get_sky_state` is the preferred raw snapshot for downstream chart engines.
 - It contains planetary positions, lunar state, sidereal time, and solar events.
 - It contains planetary positions, lunar state, sidereal time, and solar events.
-- Houses, Placidus, and zodiac-sign placement stay outside this repo.
+- When `house_system` is provided, it also includes house cusps and angles.
+- 22 house systems: P=Placidus, K=Koch, E=Equal, W=Whole Sign, A=Alcabitius,
+  C=Campanus, M=Morinus, R=Porphyry, T=Polich/Page, U=Krusinski-Pisa,
+  V=Vehlow Equal, X=Meridian, Y=Horizontal, H=Azimuthal, O=Equal/MC,
+  F=Carter poli-eq, D=Equal (15° Aries), G=Gauquelin sectors, I=Sunshine,
+  J=Sunshine alt, L=Pullen SD, N=Equal/1, Q=Pullen SR, S=Sripati, Z=APC houses.
 
 
 ## Data files
 ## Data files
 
 
-- Chiron requires Swiss Ephemeris asteroid ephemeris files in `./data/`.
+- Swiss Ephemeris data lives in `./data/ephe/` and is bundled into the Docker image.
+- Chiron requires `seas_18.se1` (and related `seas_*.se1` files) — all included.
 - The time-segmented files `seas_00.se1` through `seas_168.se1` cover Chiron from ~675 CE to ~4650 CE.
 - The time-segmented files `seas_00.se1` through `seas_168.se1` cover Chiron from ~675 CE to ~4650 CE.
 - The files `sepl_*.se1` and `semo_*.se1` are needed for far-future dates (beyond 3000 CE).
 - The files `sepl_*.se1` and `semo_*.se1` are needed for far-future dates (beyond 3000 CE).
-- If any of these files are missing, `get_planetary_positions` will still return the other bodies, but Chiron will error until the files are present.
-- All files are from the Swiss Ephemeris distribution (based on JPL DE441), available at https://github.com/aloistr/swisseph/tree/master/ephe
+- Runtime cache (`ephemeris.sqlite3`) lives in `./data/cache/` and is NOT bundled — it's volume-mounted at runtime.
+- All .se1 files are from the Swiss Ephemeris distribution (based on JPL DE441), available at https://github.com/aloistr/swisseph/tree/master/ephe
 
 
 ## Docker
 ## Docker
 
 
 - Build and run the service with `docker compose up --build`.
 - Build and run the service with `docker compose up --build`.
-- The compose file mounts `./data` and `./logs` into the container.
-- Keep `seas_18.se1` in `./data` before starting the container if you want Chiron in the response set.
+- `data/ephe/` is COPY'd into the image (self-contained, no volume mount needed).
+- `data/cache/` is volume-mounted for persistent runtime cache.
 - The container listens on port `7015` and serves MCP at `/mcp/sse`.
 - The container listens on port `7015` and serves MCP at `/mcp/sse`.
 
 
 ## Working notes
 ## Working notes
@@ -118,4 +121,4 @@ The server is exposed on the LAN at `192.168.0.249:7015` and mounts MCP at
 - Keep the server deterministic and easy to reason about.
 - Keep the server deterministic and easy to reason about.
 - Prefer structured outputs over free-form text.
 - Prefer structured outputs over free-form text.
 - Keep the repo docs and wiki reference aligned when the scope changes.
 - Keep the repo docs and wiki reference aligned when the scope changes.
-- Keep future ideas in the plan even if they are not in v0.1 yet.
+- Keep future ideas in the plan even if they are not in v0.2 yet.

+ 18 - 1
RELEASE_NOTES.md

@@ -1,4 +1,21 @@
-# v0.1
+# Release Notes
+
+## v0.2
+
+- `get_sky_state` now accepts `house_system` parameter for server-side house cusp computation
+  - 22 house systems supported: P=Placidus, K=Koch, E=Equal, W=Whole Sign, A=Alcabitius,
+    C=Campanus, M=Morinus, R=Porphyry, T=Polich/Page, U=Krusinski-Pisa, V=Vehlow Equal,
+    X=Meridian, Y=Horizontal, H=Azimuthal, O=Equal/MC, F=Carter poli-eq,
+    D=Equal from 15° Aries, G=Gauquelin sectors, I=Sunshine, J=Sunshine alt,
+    L=Pullen SD, N=Equal/1, Q=Pullen SR, S=Sripati, Z=APC houses
+  - Returns house cusps and angles (ASC, MC, DSC, IC) computed via `swe.houses()`
+- Data directory restructured: `data/ephe/` (static .se1 files, git-tracked, image-bundled)
+  and `data/cache/` (runtime sqlite, volume-mounted, gitignored)
+- Dockerfile now COPYs `data/ephe/` for self-contained deployment
+- Chiron calculation fixed (was broken in Docker when `seas_18.se1` was excluded from build context)
+- Positioned as "Swiss Ephemeris as a service" for downstream consumers (astro-mcp, etc.)
+
+## v0.1
 
 
 First commit of the ephemeris-mcp core sky-state slice.
 First commit of the ephemeris-mcp core sky-state slice.
 
 

+ 4 - 2
src/ephemeris_mcp/ephemeris.py

@@ -1,15 +1,17 @@
 """
 """
 Swiss Ephemeris computation core for ephemeris-mcp.
 Swiss Ephemeris computation core for ephemeris-mcp.
 
 
-Thin wrapper around pyswisseph providing:
+Shared computation layer for all MCP tools. Provides:
   - Planetary positions (ecliptic + equatorial)
   - Planetary positions (ecliptic + equatorial)
+  - House cusps and angles (22 house systems via swe.houses)
   - Solar events (rise/set/noon/twilight)
   - Solar events (rise/set/noon/twilight)
-  - Lunar state (phase, position)
+  - Lunar state (phase, position, age)
   - Sidereal time
   - Sidereal time
   - Constellation lookup
   - Constellation lookup
   - Satellite positions from TLE
   - Satellite positions from TLE
 
 
 All calculations are deterministic and reproducible.
 All calculations are deterministic and reproducible.
+Consumers call these functions through the MCP tool surface.
 """
 """
 
 
 from __future__ import annotations
 from __future__ import annotations

+ 17 - 8
src/ephemeris_mcp/server.py

@@ -1,6 +1,11 @@
 """
 """
 Ephemeris MCP server — FastAPI + FastMCP entry point.
 Ephemeris MCP server — FastAPI + FastMCP entry point.
 
 
+Provides Swiss Ephemeris computation as a service: planetary positions,
+house cusps, lunar state, sidereal time, solar events, and more.
+Downstream consumers (e.g. astro-mcp, satrack-mcp) call these tools
+instead of bundling the Swiss Ephemeris themselves.
+
 All MCP tools are defined here. The ephemeris engine and cache are in
 All MCP tools are defined here. The ephemeris engine and cache are in
 ephemeris.py and storage.py respectively.
 ephemeris.py and storage.py respectively.
 """
 """
@@ -329,7 +334,7 @@ def list_available_bodies(category: str | None = None) -> dict:
     """
     """
     List all computable celestial bodies.
     List all computable celestial bodies.
 
 
-    This is a lightweight discovery tool for the v0.1 core slice.
+    This is a lightweight discovery tool for the v0.2 core slice.
     """
     """
     bodies = []
     bodies = []
     for name in BODIES:
     for name in BODIES:
@@ -388,8 +393,11 @@ def get_sky_state(
     Return a consolidated raw sky-state snapshot for downstream chart engines.
     Return a consolidated raw sky-state snapshot for downstream chart engines.
 
 
     Combines planetary positions, lunar state, sidereal time, and solar events
     Combines planetary positions, lunar state, sidereal time, and solar events
-    into a single response. Optionally includes house cusps and angles when
-    a house system is specified.
+    into a single response. Optionally includes house cusps and angles computed
+    server-side via the Swiss Ephemeris when a house system is specified.
+
+    This is the primary tool for downstream consumers (e.g. astro-mcp) that
+    need a full sky-state from a single call.
 
 
     Args:
     Args:
         datetime: ISO 8601 datetime (UTC). Defaults to now.
         datetime: ISO 8601 datetime (UTC). Defaults to now.
@@ -398,12 +406,13 @@ def get_sky_state(
         elevation: Observer elevation in meters.
         elevation: Observer elevation in meters.
         geocentric: If True, return geocentric positions instead of topocentric.
         geocentric: If True, return geocentric positions instead of topocentric.
         house_system: Optional house system code (single uppercase letter).
         house_system: Optional house system code (single uppercase letter).
-            When provided, includes 'houses' key with cusps and angles.
-            Supported: P=Placidus, K=Koch, E=Equal, W=Whole Sign,
+            When provided, includes 'houses' key with 12 cusps and angles
+            (ASC, MC, DSC, IC). All 22 Swiss Ephemeris house systems:
+            P=Placidus, K=Koch, E=Equal (0° Aries), W=Whole Sign,
             A=Alcabitius, C=Campanus, M=Morinus, R=Porphyry,
             A=Alcabitius, C=Campanus, M=Morinus, R=Porphyry,
             T=Polich/Page, U=Krusinski-Pisa, V=Vehlow Equal,
             T=Polich/Page, U=Krusinski-Pisa, V=Vehlow Equal,
-            X=Meridian, Y=Horizontal, H=Azimuthal, O=Equal/MC,
-            F=Carter poli-eq, D=Equal from 15° Aries, G=Gauquelin sectors,
+            X=Meridian, Y=Horizontal, H=Azimuthal, O=Equal (MC),
+            F=Carter poli-eq, D=Equal (15° Aries), G=Gauquelin sectors,
             I=Sunshine, J=Sunshine alt, L=Pullen SD, N=Equal/1,
             I=Sunshine, J=Sunshine alt, L=Pullen SD, N=Equal/1,
             Q=Pullen SR, S=Sripati, Z=APC houses.
             Q=Pullen SR, S=Sripati, Z=APC houses.
     """
     """
@@ -516,7 +525,7 @@ def get_sky_state(
 
 
 def create_app() -> FastAPI:
 def create_app() -> FastAPI:
     """
     """
-    Build the FastAPI app for the v0.1 core slice.
+    Build the FastAPI app for the v0.2 core slice.
     """
     """
     config.LOG_DIR.mkdir(parents=True, exist_ok=True)
     config.LOG_DIR.mkdir(parents=True, exist_ok=True)
     logging.basicConfig(
     logging.basicConfig(

+ 3 - 3
src/ephemeris_mcp/storage.py

@@ -1,9 +1,9 @@
 """
 """
 SQLite cache layer for ephemeris-mcp.
 SQLite cache layer for ephemeris-mcp.
 
 
-Provides TTL-based caching to avoid redundant computations.
-Ephemeris data files themselves are ~50-100 MB and loaded by swisseph directly.
-This cache stores computed RESULTS (positions, events, etc.).
+Provides TTL-based caching to avoid redundant Swiss Ephemeris computations.
+Ephemeris data files live in ./data/ephe/ and are loaded by swisseph directly.
+This cache stores computed RESULTS (positions, events, etc.) in ./data/cache/.
 """
 """
 
 
 from __future__ import annotations
 from __future__ import annotations