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.
- timemap_mcp-0.1.0/.gitignore +19 -0
- timemap_mcp-0.1.0/CLAUDE.md +31 -0
- timemap_mcp-0.1.0/LICENSE +21 -0
- timemap_mcp-0.1.0/PKG-INFO +168 -0
- timemap_mcp-0.1.0/README.md +141 -0
- timemap_mcp-0.1.0/pyproject.toml +60 -0
- timemap_mcp-0.1.0/scripts/sync_engine.py +180 -0
- timemap_mcp-0.1.0/smithery.yaml +7 -0
- timemap_mcp-0.1.0/tests/__init__.py +0 -0
- timemap_mcp-0.1.0/tests/conftest.py +6 -0
- timemap_mcp-0.1.0/tests/engine/__init__.py +0 -0
- timemap_mcp-0.1.0/tests/engine/test_annual_stars.py +207 -0
- timemap_mcp-0.1.0/tests/engine/test_auxiliary_stars.py +118 -0
- timemap_mcp-0.1.0/tests/engine/test_bazi.py +165 -0
- timemap_mcp-0.1.0/tests/engine/test_constants.py +169 -0
- timemap_mcp-0.1.0/tests/engine/test_daily_briefing.py +159 -0
- timemap_mcp-0.1.0/tests/engine/test_emotional_profile.py +327 -0
- timemap_mcp-0.1.0/tests/engine/test_growth_phases_table.py +237 -0
- timemap_mcp-0.1.0/tests/engine/test_hexagram.py +259 -0
- timemap_mcp-0.1.0/tests/engine/test_hourly.py +474 -0
- timemap_mcp-0.1.0/tests/engine/test_interactions.py +225 -0
- timemap_mcp-0.1.0/tests/engine/test_interpretations.py +270 -0
- timemap_mcp-0.1.0/tests/engine/test_life_areas_helpers.py +148 -0
- timemap_mcp-0.1.0/tests/engine/test_life_areas_monthly.py +141 -0
- timemap_mcp-0.1.0/tests/engine/test_life_areas_structure.py +94 -0
- timemap_mcp-0.1.0/tests/engine/test_life_gua.py +229 -0
- timemap_mcp-0.1.0/tests/engine/test_luck_pillar.py +184 -0
- timemap_mcp-0.1.0/tests/engine/test_monthly.py +258 -0
- timemap_mcp-0.1.0/tests/engine/test_palaces.py +133 -0
- timemap_mcp-0.1.0/tests/engine/test_qi_men.py +246 -0
- timemap_mcp-0.1.0/tests/engine/test_qi_men_hourly.py +128 -0
- timemap_mcp-0.1.0/tests/engine/test_qi_men_interpret.py +168 -0
- timemap_mcp-0.1.0/tests/engine/test_scoring_base.py +149 -0
- timemap_mcp-0.1.0/tests/engine/test_scoring_integration.py +67 -0
- timemap_mcp-0.1.0/tests/engine/test_scoring_ten_gods.py +159 -0
- timemap_mcp-0.1.0/tests/engine/test_solar_time.py +142 -0
- timemap_mcp-0.1.0/tests/engine/test_ten_gods_mapping.py +95 -0
- timemap_mcp-0.1.0/tests/engine/test_ten_gods_strength.py +171 -0
- timemap_mcp-0.1.0/tests/engine/test_tong_shu.py +151 -0
- timemap_mcp-0.1.0/tests/engine/test_transformation.py +226 -0
- timemap_mcp-0.1.0/tests/test_converters.py +130 -0
- timemap_mcp-0.1.0/tests/test_tools.py +180 -0
- timemap_mcp-0.1.0/timemap_mcp/__init__.py +3 -0
- timemap_mcp-0.1.0/timemap_mcp/__main__.py +5 -0
- timemap_mcp-0.1.0/timemap_mcp/_converters.py +104 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/__init__.py +1 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/annual_stars.py +257 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/auxiliary_stars.py +93 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/bazi.py +184 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/constants.py +110 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/daily_briefing.py +528 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/emotional_profile.py +357 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/hexagram.py +334 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/hourly.py +208 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/interactions.py +107 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/interpretations.py +540 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/life_areas.py +454 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/life_gua.py +199 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/luck_pillar.py +147 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/monthly.py +295 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/palaces.py +44 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/qi_men.py +695 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/qi_men_interpret.py +332 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/scoring.py +163 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/solar_time.py +146 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/ten_gods.py +765 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/tong_shu.py +159 -0
- timemap_mcp-0.1.0/timemap_mcp/engine/transformation.py +118 -0
- timemap_mcp-0.1.0/timemap_mcp/server.py +470 -0
|
@@ -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
|
+
[](https://pypi.org/project/timemap-mcp/)
|
|
34
|
+
[](https://pypi.org/project/timemap-mcp/)
|
|
35
|
+
[](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
|
+
[](https://pypi.org/project/timemap-mcp/)
|
|
7
|
+
[](https://pypi.org/project/timemap-mcp/)
|
|
8
|
+
[](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()
|
|
File without changes
|
|
File without changes
|