Просмотр исходного кода

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 месяц назад
Родитель
Сommit
53d5612c34
7 измененных файлов с 123 добавлено и 65 удалено
  1. 8 5
      AGENTS.md
  2. 35 11
      IMPLEMENTATION_PLAN.md
  3. 38 35
      README.md
  4. 18 1
      RELEASE_NOTES.md
  5. 4 2
      src/ephemeris_mcp/ephemeris.py
  6. 17 8
      src/ephemeris_mcp/server.py
  7. 3 3
      src/ephemeris_mcp/storage.py

+ 8 - 5
AGENTS.md

@@ -1,15 +1,18 @@
 # 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
 
-- 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.
 - 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.
 
 ## Primary references

+ 35 - 11
IMPLEMENTATION_PLAN.md

@@ -1,13 +1,15 @@
 # Ephemeris MCP — Implementation Plan
 
-> Last updated: 2026-05-10
+> Last updated: 2026-06-07
 
 ## 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
 - 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
@@ -68,9 +90,10 @@ This is the first version worth committing as a usable baseline.
 
 ### Data files
 
-- Swiss Ephemeris data lives in `./data/`
+- Swiss Ephemeris data lives in `./data/ephe/`
 - `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 |
 | 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 |
-| 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)
 
@@ -123,7 +146,7 @@ Accepts a comma-separated string, defaults to `"planets,moon,sun"` (the most pro
 
 ## 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
 - Transit interpretation (meaning of planet hitting natal position) → 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
 
-### Phase 1 — v0.1 core slice
+### Phase 1 — v0.2 core slice
 
 - [x] Define the commit boundary for the first working version
 - [ ] 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
 
 - [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
-- [ ] 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 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
-`192.168.0.249:7015`.
+`192.168.0.200:7015`.
 
 ## 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 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
 
-- 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 finished satellite tracking stack in v0.1
+- Not a finished satellite tracking stack in v0.2
 
 ## Project direction
 
 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:
 
@@ -42,16 +41,14 @@ The current design and tool intent are described in:
 
 ## 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
 
@@ -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}'
 ```
 
-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`.
 
 ## Astro-client contract
 
 - `get_sky_state` is the preferred raw snapshot for downstream chart engines.
 - 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
 
-- 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 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
 
 - 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`.
 
 ## 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.
 - Prefer structured outputs over free-form text.
 - 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.
 

+ 4 - 2
src/ephemeris_mcp/ephemeris.py

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

+ 17 - 8
src/ephemeris_mcp/server.py

@@ -1,6 +1,11 @@
 """
 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
 ephemeris.py and storage.py respectively.
 """
@@ -329,7 +334,7 @@ def list_available_bodies(category: str | None = None) -> dict:
     """
     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 = []
     for name in BODIES:
@@ -388,8 +393,11 @@ def get_sky_state(
     Return a consolidated raw sky-state snapshot for downstream chart engines.
 
     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:
         datetime: ISO 8601 datetime (UTC). Defaults to now.
@@ -398,12 +406,13 @@ def get_sky_state(
         elevation: Observer elevation in meters.
         geocentric: If True, return geocentric positions instead of topocentric.
         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,
             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,
             Q=Pullen SR, S=Sripati, Z=APC houses.
     """
@@ -516,7 +525,7 @@ def get_sky_state(
 
 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)
     logging.basicConfig(

+ 3 - 3
src/ephemeris_mcp/storage.py

@@ -1,9 +1,9 @@
 """
 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