timemap-mcp 0.1.0__tar.gz

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 (69) hide show
  1. timemap_mcp-0.1.0/.gitignore +19 -0
  2. timemap_mcp-0.1.0/CLAUDE.md +31 -0
  3. timemap_mcp-0.1.0/LICENSE +21 -0
  4. timemap_mcp-0.1.0/PKG-INFO +168 -0
  5. timemap_mcp-0.1.0/README.md +141 -0
  6. timemap_mcp-0.1.0/pyproject.toml +60 -0
  7. timemap_mcp-0.1.0/scripts/sync_engine.py +180 -0
  8. timemap_mcp-0.1.0/smithery.yaml +7 -0
  9. timemap_mcp-0.1.0/tests/__init__.py +0 -0
  10. timemap_mcp-0.1.0/tests/conftest.py +6 -0
  11. timemap_mcp-0.1.0/tests/engine/__init__.py +0 -0
  12. timemap_mcp-0.1.0/tests/engine/test_annual_stars.py +207 -0
  13. timemap_mcp-0.1.0/tests/engine/test_auxiliary_stars.py +118 -0
  14. timemap_mcp-0.1.0/tests/engine/test_bazi.py +165 -0
  15. timemap_mcp-0.1.0/tests/engine/test_constants.py +169 -0
  16. timemap_mcp-0.1.0/tests/engine/test_daily_briefing.py +159 -0
  17. timemap_mcp-0.1.0/tests/engine/test_emotional_profile.py +327 -0
  18. timemap_mcp-0.1.0/tests/engine/test_growth_phases_table.py +237 -0
  19. timemap_mcp-0.1.0/tests/engine/test_hexagram.py +259 -0
  20. timemap_mcp-0.1.0/tests/engine/test_hourly.py +474 -0
  21. timemap_mcp-0.1.0/tests/engine/test_interactions.py +225 -0
  22. timemap_mcp-0.1.0/tests/engine/test_interpretations.py +270 -0
  23. timemap_mcp-0.1.0/tests/engine/test_life_areas_helpers.py +148 -0
  24. timemap_mcp-0.1.0/tests/engine/test_life_areas_monthly.py +141 -0
  25. timemap_mcp-0.1.0/tests/engine/test_life_areas_structure.py +94 -0
  26. timemap_mcp-0.1.0/tests/engine/test_life_gua.py +229 -0
  27. timemap_mcp-0.1.0/tests/engine/test_luck_pillar.py +184 -0
  28. timemap_mcp-0.1.0/tests/engine/test_monthly.py +258 -0
  29. timemap_mcp-0.1.0/tests/engine/test_palaces.py +133 -0
  30. timemap_mcp-0.1.0/tests/engine/test_qi_men.py +246 -0
  31. timemap_mcp-0.1.0/tests/engine/test_qi_men_hourly.py +128 -0
  32. timemap_mcp-0.1.0/tests/engine/test_qi_men_interpret.py +168 -0
  33. timemap_mcp-0.1.0/tests/engine/test_scoring_base.py +149 -0
  34. timemap_mcp-0.1.0/tests/engine/test_scoring_integration.py +67 -0
  35. timemap_mcp-0.1.0/tests/engine/test_scoring_ten_gods.py +159 -0
  36. timemap_mcp-0.1.0/tests/engine/test_solar_time.py +142 -0
  37. timemap_mcp-0.1.0/tests/engine/test_ten_gods_mapping.py +95 -0
  38. timemap_mcp-0.1.0/tests/engine/test_ten_gods_strength.py +171 -0
  39. timemap_mcp-0.1.0/tests/engine/test_tong_shu.py +151 -0
  40. timemap_mcp-0.1.0/tests/engine/test_transformation.py +226 -0
  41. timemap_mcp-0.1.0/tests/test_converters.py +130 -0
  42. timemap_mcp-0.1.0/tests/test_tools.py +180 -0
  43. timemap_mcp-0.1.0/timemap_mcp/__init__.py +3 -0
  44. timemap_mcp-0.1.0/timemap_mcp/__main__.py +5 -0
  45. timemap_mcp-0.1.0/timemap_mcp/_converters.py +104 -0
  46. timemap_mcp-0.1.0/timemap_mcp/engine/__init__.py +1 -0
  47. timemap_mcp-0.1.0/timemap_mcp/engine/annual_stars.py +257 -0
  48. timemap_mcp-0.1.0/timemap_mcp/engine/auxiliary_stars.py +93 -0
  49. timemap_mcp-0.1.0/timemap_mcp/engine/bazi.py +184 -0
  50. timemap_mcp-0.1.0/timemap_mcp/engine/constants.py +110 -0
  51. timemap_mcp-0.1.0/timemap_mcp/engine/daily_briefing.py +528 -0
  52. timemap_mcp-0.1.0/timemap_mcp/engine/emotional_profile.py +357 -0
  53. timemap_mcp-0.1.0/timemap_mcp/engine/hexagram.py +334 -0
  54. timemap_mcp-0.1.0/timemap_mcp/engine/hourly.py +208 -0
  55. timemap_mcp-0.1.0/timemap_mcp/engine/interactions.py +107 -0
  56. timemap_mcp-0.1.0/timemap_mcp/engine/interpretations.py +540 -0
  57. timemap_mcp-0.1.0/timemap_mcp/engine/life_areas.py +454 -0
  58. timemap_mcp-0.1.0/timemap_mcp/engine/life_gua.py +199 -0
  59. timemap_mcp-0.1.0/timemap_mcp/engine/luck_pillar.py +147 -0
  60. timemap_mcp-0.1.0/timemap_mcp/engine/monthly.py +295 -0
  61. timemap_mcp-0.1.0/timemap_mcp/engine/palaces.py +44 -0
  62. timemap_mcp-0.1.0/timemap_mcp/engine/qi_men.py +695 -0
  63. timemap_mcp-0.1.0/timemap_mcp/engine/qi_men_interpret.py +332 -0
  64. timemap_mcp-0.1.0/timemap_mcp/engine/scoring.py +163 -0
  65. timemap_mcp-0.1.0/timemap_mcp/engine/solar_time.py +146 -0
  66. timemap_mcp-0.1.0/timemap_mcp/engine/ten_gods.py +765 -0
  67. timemap_mcp-0.1.0/timemap_mcp/engine/tong_shu.py +159 -0
  68. timemap_mcp-0.1.0/timemap_mcp/engine/transformation.py +118 -0
  69. timemap_mcp-0.1.0/timemap_mcp/server.py +470 -0
@@ -0,0 +1,19 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .venv/
8
+
9
+ # Ephemeris (downloaded on first run, ~31MB)
10
+ de421.bsp
11
+
12
+ # IDE
13
+ .vscode/
14
+ .idea/
15
+
16
+ # Test
17
+ .pytest_cache/
18
+ .coverage
19
+ htmlcov/
@@ -0,0 +1,31 @@
1
+ # timemap-mcp
2
+
3
+ MCP server wrapping TimeMap's Chinese metaphysics engine.
4
+
5
+ ## Commands
6
+
7
+ | Command | Description |
8
+ |---------|-------------|
9
+ | `.venv/Scripts/python -m pytest -q` | Run all tests (740+) |
10
+ | `.venv/Scripts/python -m pytest tests/test_tools.py -v` | Run MCP tool tests only |
11
+ | `python scripts/sync_engine.py` | Sync engine from TimeMap repo |
12
+
13
+ ## Architecture
14
+
15
+ - `timemap_mcp/engine/` — Pure calculation modules (synced from TimeMap)
16
+ - `timemap_mcp/server.py` — FastMCP tool definitions (8 tools)
17
+ - `timemap_mcp/_converters.py` — Human-readable input parsing
18
+ - `tests/engine/` — Engine unit tests (synced from TimeMap)
19
+ - `tests/test_tools.py` — MCP tool integration tests
20
+ - `scripts/sync_engine.py` — Engine sync script
21
+
22
+ ## Engine Sync
23
+
24
+ Engine modules are copied from `../TimeMap/backend/app/engine/` with import path fixup.
25
+ Run `python scripts/sync_engine.py` after engine changes in TimeMap.
26
+
27
+ ## Code Style
28
+
29
+ - Python 3.11+, snake_case, frozen dataclasses
30
+ - Engine modules are PURE functions — no I/O, no DB
31
+ - MCP tools return JSON strings (FastMCP handles protocol)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nick
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,168 @@
1
+ Metadata-Version: 2.4
2
+ Name: timemap-mcp
3
+ Version: 0.1.0
4
+ Summary: Chinese metaphysics MCP server — BaZi, Tong Shu, Feng Shui tools for AI agents
5
+ Project-URL: Homepage, https://github.com/cnick26/timemap-mcp
6
+ Project-URL: Repository, https://github.com/cnick26/timemap-mcp
7
+ Project-URL: Buy Me a Coffee, https://buymeacoffee.com/nicktimemap
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: ai-agent,bazi,chinese-metaphysics,feng-shui,four-pillars,mcp,tong-shu
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
18
+ Requires-Python: >=3.11
19
+ Requires-Dist: mcp[cli]>=1.0.0
20
+ Requires-Dist: skyfield>=1.49
21
+ Requires-Dist: tzdata>=2024.1
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
24
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
25
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # timemap-mcp
29
+
30
+ > Chinese metaphysics calculations for AI agents — BaZi, Tong Shu, Feng Shui, and more.
31
+
32
+ <!-- Badges — uncomment after PyPI publish
33
+ [![PyPI](https://img.shields.io/pypi/v/timemap-mcp)](https://pypi.org/project/timemap-mcp/)
34
+ [![Python](https://img.shields.io/pypi/pyversions/timemap-mcp)](https://pypi.org/project/timemap-mcp/)
35
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
36
+ -->
37
+
38
+ An MCP (Model Context Protocol) server that gives AI agents access to accurate Chinese metaphysics calculations. Built on a verified engine with 740+ tests checked against Joey Yap reference data.
39
+
40
+ ## About
41
+
42
+ I discovered BaZi in 2017 and approached it with healthy skepticism — it wasn't the first system of correspondences I'd studied. But this one stayed with me.
43
+
44
+ Over the years I've studied under Master Joey Yap through courses, seminars, his Telegram community, and many books. As a developer, I naturally started building tools — small "clocks" that map the cyclic energy movements described in Chinese metaphysics.
45
+
46
+ **timemap-mcp** is born from those years of study and building. I wanted to make these calculations accessible to everyone through AI, with the accuracy that practitioners expect. A full interactive app (TimeMap) is on the way — this MCP server is the engine that powers it, now available for any AI agent to use.
47
+
48
+ ## Quick Start
49
+
50
+ ### Claude Desktop
51
+
52
+ Add to your `claude_desktop_config.json`:
53
+
54
+ ```json
55
+ {
56
+ "mcpServers": {
57
+ "timemap": {
58
+ "command": "uvx",
59
+ "args": ["timemap-mcp"]
60
+ }
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### Cursor
66
+
67
+ Add to `.cursor/mcp.json`:
68
+
69
+ ```json
70
+ {
71
+ "mcpServers": {
72
+ "timemap": {
73
+ "command": "uvx",
74
+ "args": ["timemap-mcp"]
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ That's it. No API keys, no config needed.
81
+
82
+ > **Note:** The first run downloads the DE421 ephemeris file (~31 MB) for precise solar term calculations. This is a one-time download cached in `~/.skyfield/`.
83
+
84
+ ## Tools
85
+
86
+ | Tool | Description | Natal needed? |
87
+ |------|-------------|:---:|
88
+ | `get_natal_chart` | Complete BaZi chart — Four Pillars, Luck Pillars, Life Gua, 10 Gods, auxiliary stars | Yes |
89
+ | `get_daily_pillars` | Year, Month, Day pillars for any date | No |
90
+ | `get_day_quality` | Tong Shu indicators — Day Officer, 28 Constellation, Flying Star | No |
91
+ | `get_daily_interactions` | Check natal clashes, combinations, and breakers for a date | Yes |
92
+ | `get_hourly_pillars` | 12 two-hour energy blocks for any day | No |
93
+ | `get_luck_pillars` | 10-year Luck Pillar timeline (decades of fortune) | Yes |
94
+ | `lookup_hexagram` | Xuan Kong Da Gua hexagram by stem-branch pair | No |
95
+ | `get_solar_term` | Exact date of any of the 24 solar terms | No |
96
+
97
+ ## Example Prompts
98
+
99
+ Try asking your AI agent:
100
+
101
+ - *"Calculate my BaZi chart. I was born January 26, 1994 at 7:11 AM, male."*
102
+ - *"What's the day quality for today?"*
103
+ - *"Show me the hourly pillars for tomorrow."*
104
+ - *"What are my luck pillars? Born March 15, 1985 at 10:30 AM, female."*
105
+ - *"Look up the hexagram for Ren Zi."*
106
+ - *"When is Lichun (Start of Spring) in 2026?"*
107
+ - *"Check if today has any clashes with my natal chart."*
108
+
109
+ ## Input Formats
110
+
111
+ - **Dates**: ISO 8601 — `1994-01-26`
112
+ - **Times**: 24-hour local time — `07:11`
113
+ - **Gender**: `male` or `female`
114
+ - **Stems**: Chinese (`壬`), pinyin (`Ren`), or index (`8`)
115
+ - **Branches**: Chinese (`子`), pinyin (`Zi`), animal (`Rat`), or index (`0`)
116
+ - **Timezone** (optional): IANA format — `Asia/Kuala_Lumpur`, `Europe/Bucharest`
117
+
118
+ ## Engine Accuracy
119
+
120
+ The calculation engine behind this server is not a toy:
121
+
122
+ - **740+ automated tests** covering every module
123
+ - **Verified against Joey Yap's Power Planner** — pillar characters, Day Officers, 10 Gods mappings
124
+ - **Solar term boundaries** computed via NASA JPL DE421 ephemeris (not table approximations)
125
+ - **Month boundaries follow Jie Qi** (solar terms), not Gregorian dates — February pillar may start Feb 3 or 4 depending on the year
126
+
127
+ ## Roadmap
128
+
129
+ The free tier covers the fundamentals. Coming in v2 (premium):
130
+
131
+ - **10 Gods Strength** — proprietary percentage algorithm (reverse-engineered, MSE=0.5)
132
+ - **Daily Score (0-100)** — composite score with transparent 6-factor breakdown
133
+ - **Qi Men Dun Jia** — destiny palace, annual chart, hourly interpretation
134
+ - **Monthly Energy** — 10 Gods deltas, life area radar, emotional profiling
135
+ - **Daily Briefing** — complete orchestrated daily digest
136
+
137
+ ## Development
138
+
139
+ ```bash
140
+ git clone https://github.com/cnick26/timemap-mcp.git
141
+ cd timemap-mcp
142
+ python -m venv .venv
143
+ .venv/Scripts/pip install -e ".[dev]" # Windows
144
+ # or: .venv/bin/pip install -e ".[dev]" # Linux/macOS
145
+ pytest -q # 740+ tests
146
+ ```
147
+
148
+ ### Syncing the engine from TimeMap
149
+
150
+ ```bash
151
+ python scripts/sync_engine.py --source ../TimeMap/backend/app/engine
152
+ pytest -q # Verify everything still passes
153
+ ```
154
+
155
+ ## Support
156
+
157
+ If this project helps you, consider:
158
+
159
+ - Starring the repo
160
+ - [Buy Me a Coffee](https://buymeacoffee.com/nicktimemap)
161
+
162
+ ## License
163
+
164
+ [MIT](LICENSE)
165
+
166
+ ---
167
+
168
+ *Built with care, verified with rigor, shared with humility.*
@@ -0,0 +1,141 @@
1
+ # timemap-mcp
2
+
3
+ > Chinese metaphysics calculations for AI agents — BaZi, Tong Shu, Feng Shui, and more.
4
+
5
+ <!-- Badges — uncomment after PyPI publish
6
+ [![PyPI](https://img.shields.io/pypi/v/timemap-mcp)](https://pypi.org/project/timemap-mcp/)
7
+ [![Python](https://img.shields.io/pypi/pyversions/timemap-mcp)](https://pypi.org/project/timemap-mcp/)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
9
+ -->
10
+
11
+ An MCP (Model Context Protocol) server that gives AI agents access to accurate Chinese metaphysics calculations. Built on a verified engine with 740+ tests checked against Joey Yap reference data.
12
+
13
+ ## About
14
+
15
+ I discovered BaZi in 2017 and approached it with healthy skepticism — it wasn't the first system of correspondences I'd studied. But this one stayed with me.
16
+
17
+ Over the years I've studied under Master Joey Yap through courses, seminars, his Telegram community, and many books. As a developer, I naturally started building tools — small "clocks" that map the cyclic energy movements described in Chinese metaphysics.
18
+
19
+ **timemap-mcp** is born from those years of study and building. I wanted to make these calculations accessible to everyone through AI, with the accuracy that practitioners expect. A full interactive app (TimeMap) is on the way — this MCP server is the engine that powers it, now available for any AI agent to use.
20
+
21
+ ## Quick Start
22
+
23
+ ### Claude Desktop
24
+
25
+ Add to your `claude_desktop_config.json`:
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "timemap": {
31
+ "command": "uvx",
32
+ "args": ["timemap-mcp"]
33
+ }
34
+ }
35
+ }
36
+ ```
37
+
38
+ ### Cursor
39
+
40
+ Add to `.cursor/mcp.json`:
41
+
42
+ ```json
43
+ {
44
+ "mcpServers": {
45
+ "timemap": {
46
+ "command": "uvx",
47
+ "args": ["timemap-mcp"]
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ That's it. No API keys, no config needed.
54
+
55
+ > **Note:** The first run downloads the DE421 ephemeris file (~31 MB) for precise solar term calculations. This is a one-time download cached in `~/.skyfield/`.
56
+
57
+ ## Tools
58
+
59
+ | Tool | Description | Natal needed? |
60
+ |------|-------------|:---:|
61
+ | `get_natal_chart` | Complete BaZi chart — Four Pillars, Luck Pillars, Life Gua, 10 Gods, auxiliary stars | Yes |
62
+ | `get_daily_pillars` | Year, Month, Day pillars for any date | No |
63
+ | `get_day_quality` | Tong Shu indicators — Day Officer, 28 Constellation, Flying Star | No |
64
+ | `get_daily_interactions` | Check natal clashes, combinations, and breakers for a date | Yes |
65
+ | `get_hourly_pillars` | 12 two-hour energy blocks for any day | No |
66
+ | `get_luck_pillars` | 10-year Luck Pillar timeline (decades of fortune) | Yes |
67
+ | `lookup_hexagram` | Xuan Kong Da Gua hexagram by stem-branch pair | No |
68
+ | `get_solar_term` | Exact date of any of the 24 solar terms | No |
69
+
70
+ ## Example Prompts
71
+
72
+ Try asking your AI agent:
73
+
74
+ - *"Calculate my BaZi chart. I was born January 26, 1994 at 7:11 AM, male."*
75
+ - *"What's the day quality for today?"*
76
+ - *"Show me the hourly pillars for tomorrow."*
77
+ - *"What are my luck pillars? Born March 15, 1985 at 10:30 AM, female."*
78
+ - *"Look up the hexagram for Ren Zi."*
79
+ - *"When is Lichun (Start of Spring) in 2026?"*
80
+ - *"Check if today has any clashes with my natal chart."*
81
+
82
+ ## Input Formats
83
+
84
+ - **Dates**: ISO 8601 — `1994-01-26`
85
+ - **Times**: 24-hour local time — `07:11`
86
+ - **Gender**: `male` or `female`
87
+ - **Stems**: Chinese (`壬`), pinyin (`Ren`), or index (`8`)
88
+ - **Branches**: Chinese (`子`), pinyin (`Zi`), animal (`Rat`), or index (`0`)
89
+ - **Timezone** (optional): IANA format — `Asia/Kuala_Lumpur`, `Europe/Bucharest`
90
+
91
+ ## Engine Accuracy
92
+
93
+ The calculation engine behind this server is not a toy:
94
+
95
+ - **740+ automated tests** covering every module
96
+ - **Verified against Joey Yap's Power Planner** — pillar characters, Day Officers, 10 Gods mappings
97
+ - **Solar term boundaries** computed via NASA JPL DE421 ephemeris (not table approximations)
98
+ - **Month boundaries follow Jie Qi** (solar terms), not Gregorian dates — February pillar may start Feb 3 or 4 depending on the year
99
+
100
+ ## Roadmap
101
+
102
+ The free tier covers the fundamentals. Coming in v2 (premium):
103
+
104
+ - **10 Gods Strength** — proprietary percentage algorithm (reverse-engineered, MSE=0.5)
105
+ - **Daily Score (0-100)** — composite score with transparent 6-factor breakdown
106
+ - **Qi Men Dun Jia** — destiny palace, annual chart, hourly interpretation
107
+ - **Monthly Energy** — 10 Gods deltas, life area radar, emotional profiling
108
+ - **Daily Briefing** — complete orchestrated daily digest
109
+
110
+ ## Development
111
+
112
+ ```bash
113
+ git clone https://github.com/cnick26/timemap-mcp.git
114
+ cd timemap-mcp
115
+ python -m venv .venv
116
+ .venv/Scripts/pip install -e ".[dev]" # Windows
117
+ # or: .venv/bin/pip install -e ".[dev]" # Linux/macOS
118
+ pytest -q # 740+ tests
119
+ ```
120
+
121
+ ### Syncing the engine from TimeMap
122
+
123
+ ```bash
124
+ python scripts/sync_engine.py --source ../TimeMap/backend/app/engine
125
+ pytest -q # Verify everything still passes
126
+ ```
127
+
128
+ ## Support
129
+
130
+ If this project helps you, consider:
131
+
132
+ - Starring the repo
133
+ - [Buy Me a Coffee](https://buymeacoffee.com/nicktimemap)
134
+
135
+ ## License
136
+
137
+ [MIT](LICENSE)
138
+
139
+ ---
140
+
141
+ *Built with care, verified with rigor, shared with humility.*
@@ -0,0 +1,60 @@
1
+ [project]
2
+ name = "timemap-mcp"
3
+ version = "0.1.0"
4
+ description = "Chinese metaphysics MCP server — BaZi, Tong Shu, Feng Shui tools for AI agents"
5
+ readme = "README.md"
6
+ license = {text = "MIT"}
7
+ requires-python = ">=3.11"
8
+ keywords = [
9
+ "mcp",
10
+ "bazi",
11
+ "chinese-metaphysics",
12
+ "feng-shui",
13
+ "four-pillars",
14
+ "tong-shu",
15
+ "ai-agent",
16
+ ]
17
+ classifiers = [
18
+ "Development Status :: 4 - Beta",
19
+ "Intended Audience :: Developers",
20
+ "Topic :: Scientific/Engineering :: Astronomy",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ ]
26
+ dependencies = [
27
+ "mcp[cli]>=1.0.0",
28
+ "skyfield>=1.49",
29
+ "tzdata>=2024.1",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/cnick26/timemap-mcp"
34
+ Repository = "https://github.com/cnick26/timemap-mcp"
35
+ "Buy Me a Coffee" = "https://buymeacoffee.com/nicktimemap"
36
+
37
+ [project.scripts]
38
+ timemap-mcp = "timemap_mcp.server:main"
39
+
40
+ [project.optional-dependencies]
41
+ dev = [
42
+ "pytest>=8.0.0",
43
+ "pytest-asyncio>=0.24.0",
44
+ "ruff>=0.4.0",
45
+ ]
46
+
47
+ [build-system]
48
+ requires = ["hatchling"]
49
+ build-backend = "hatchling.build"
50
+
51
+ [tool.hatch.build.targets.wheel]
52
+ packages = ["timemap_mcp"]
53
+
54
+ [tool.pytest.ini_options]
55
+ testpaths = ["tests"]
56
+ asyncio_mode = "auto"
57
+
58
+ [tool.ruff]
59
+ line-length = 100
60
+ target-version = "py311"
@@ -0,0 +1,180 @@
1
+ """
2
+ Sync engine modules from the TimeMap repo into timemap_mcp/engine/.
3
+
4
+ Usage:
5
+ python scripts/sync_engine.py
6
+ python scripts/sync_engine.py --source /path/to/TimeMap/backend/app/engine
7
+ python scripts/sync_engine.py --include-tests --test-source /path/to/TimeMap/backend/tests
8
+ """
9
+
10
+ import argparse
11
+ import re
12
+ from pathlib import Path
13
+
14
+ SCRIPT_DIR = Path(__file__).parent
15
+ PROJECT_ROOT = SCRIPT_DIR.parent
16
+ DEFAULT_ENGINE_SOURCE = PROJECT_ROOT.parent / "TimeMap" / "backend" / "app" / "engine"
17
+ DEFAULT_TEST_SOURCE = PROJECT_ROOT.parent / "TimeMap" / "backend" / "tests"
18
+ ENGINE_DEST = PROJECT_ROOT / "timemap_mcp" / "engine"
19
+ TEST_DEST = PROJECT_ROOT / "tests" / "engine"
20
+
21
+ # Engine modules to sync (all .py files)
22
+ ENGINE_MODULES = [
23
+ "constants.py",
24
+ "solar_time.py",
25
+ "bazi.py",
26
+ "luck_pillar.py",
27
+ "tong_shu.py",
28
+ "life_gua.py",
29
+ "ten_gods.py",
30
+ "interactions.py",
31
+ "hexagram.py",
32
+ "hourly.py",
33
+ "transformation.py",
34
+ "auxiliary_stars.py",
35
+ "palaces.py",
36
+ "scoring.py",
37
+ "annual_stars.py",
38
+ "monthly.py",
39
+ "life_areas.py",
40
+ "emotional_profile.py",
41
+ "qi_men.py",
42
+ "qi_men_interpret.py",
43
+ "interpretations.py",
44
+ "daily_briefing.py",
45
+ ]
46
+
47
+ # Test files to sync (map: source name -> dest name)
48
+ ENGINE_TEST_FILES = [
49
+ "test_bazi.py",
50
+ "test_solar_time.py",
51
+ "test_luck_pillar.py",
52
+ "test_tong_shu.py",
53
+ "test_life_gua.py",
54
+ "test_ten_gods.py",
55
+ "test_interactions.py",
56
+ "test_hexagram.py",
57
+ "test_hourly.py",
58
+ "test_transformation.py",
59
+ "test_auxiliary_stars.py",
60
+ "test_palaces.py",
61
+ "test_scoring.py",
62
+ "test_annual_stars.py",
63
+ "test_monthly.py",
64
+ "test_life_areas.py",
65
+ "test_emotional_profile.py",
66
+ "test_qi_men.py",
67
+ "test_qi_men_interpret.py",
68
+ "test_interpretations.py",
69
+ "test_daily_briefing.py",
70
+ ]
71
+
72
+
73
+ def fix_imports(text: str) -> str:
74
+ """Replace TimeMap import paths with timemap_mcp paths."""
75
+ text = re.sub(r"from app\.engine\.", "from timemap_mcp.engine.", text)
76
+ text = re.sub(r"import app\.engine\.", "import timemap_mcp.engine.", text)
77
+ return text
78
+
79
+
80
+ def fix_ephemeris_path(text: str) -> str:
81
+ """Update solar_time.py ephemeris path for standalone package."""
82
+ # Replace the repo-relative path with ~/.skyfield/
83
+ text = re.sub(
84
+ r'_EPHEMERIS_PATH\s*=\s*Path\(__file__\).*?\.bsp"?\)',
85
+ '_EPHEMERIS_PATH = Path.home() / ".skyfield" / "de421.bsp"',
86
+ text,
87
+ )
88
+ return text
89
+
90
+
91
+ def sync_engine(source: Path, dest: Path) -> int:
92
+ """Copy engine modules with import fixes. Returns count of synced files."""
93
+ count = 0
94
+ for module in ENGINE_MODULES:
95
+ src_file = source / module
96
+ if not src_file.exists():
97
+ print(f" SKIP {module} (not found)")
98
+ continue
99
+
100
+ text = src_file.read_text(encoding="utf-8")
101
+ text = fix_imports(text)
102
+
103
+ if module == "solar_time.py":
104
+ text = fix_ephemeris_path(text)
105
+
106
+ (dest / module).write_text(text, encoding="utf-8")
107
+ print(f" synced {module}")
108
+ count += 1
109
+
110
+ return count
111
+
112
+
113
+ def sync_tests(source: Path, dest: Path) -> int:
114
+ """Copy test files with import fixes. Returns count of synced files."""
115
+ # Discover all test_*.py files in the engine test directory
116
+ test_dir = source / "engine"
117
+ if not test_dir.exists():
118
+ print(f" Test directory not found: {test_dir}")
119
+ return 0
120
+
121
+ count = 0
122
+ for src_file in sorted(test_dir.glob("test_*.py")):
123
+ text = src_file.read_text(encoding="utf-8")
124
+ text = fix_imports(text)
125
+ text = re.sub(r"from app\.engine ", "from timemap_mcp.engine ", text)
126
+
127
+ (dest / src_file.name).write_text(text, encoding="utf-8")
128
+ print(f" synced {src_file.name}")
129
+ count += 1
130
+
131
+ # Also copy conftest.py if it exists in engine test dir
132
+ conftest = test_dir / "conftest.py"
133
+ if conftest.exists():
134
+ text = conftest.read_text(encoding="utf-8")
135
+ text = fix_imports(text)
136
+ (dest / "conftest.py").write_text(text, encoding="utf-8")
137
+ print(" synced conftest.py")
138
+ count += 1
139
+
140
+ return count
141
+
142
+
143
+ def main():
144
+ parser = argparse.ArgumentParser(description="Sync TimeMap engine to timemap-mcp")
145
+ parser.add_argument(
146
+ "--source",
147
+ type=Path,
148
+ default=DEFAULT_ENGINE_SOURCE,
149
+ help="Path to TimeMap engine directory",
150
+ )
151
+ parser.add_argument(
152
+ "--include-tests",
153
+ action="store_true",
154
+ default=True,
155
+ help="Also sync test files",
156
+ )
157
+ parser.add_argument(
158
+ "--test-source",
159
+ type=Path,
160
+ default=DEFAULT_TEST_SOURCE,
161
+ help="Path to TimeMap tests directory",
162
+ )
163
+ args = parser.parse_args()
164
+
165
+ print(f"Syncing engine from: {args.source}")
166
+ print(f"Syncing to: {ENGINE_DEST}")
167
+ engine_count = sync_engine(args.source, ENGINE_DEST)
168
+ print(f"\nEngine: {engine_count} modules synced")
169
+
170
+ if args.include_tests:
171
+ print(f"\nSyncing tests from: {args.test_source}")
172
+ print(f"Syncing to: {TEST_DEST}")
173
+ test_count = sync_tests(args.test_source, TEST_DEST)
174
+ print(f"\nTests: {test_count} files synced")
175
+
176
+ print("\nDone. Run `pytest tests/engine/` to validate.")
177
+
178
+
179
+ if __name__ == "__main__":
180
+ main()
@@ -0,0 +1,7 @@
1
+ startCommand:
2
+ type: stdio
3
+ configSchema:
4
+ type: object
5
+ properties: {}
6
+ commandFunction: |-
7
+ () => ({ command: "uvx", args: ["timemap-mcp"] })
File without changes
@@ -0,0 +1,6 @@
1
+ """Shared test fixtures for timemap-mcp."""
2
+
3
+ # Nick's natal data — the gold standard for verification
4
+ NICK_BIRTH_DATE = "1994-01-26"
5
+ NICK_BIRTH_TIME = "07:11"
6
+ NICK_GENDER = "male"
File without changes