mingpan 0.1.2 → 0.1.4

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 (194) hide show
  1. package/README.md +120 -47
  2. package/dist/core/bazi/BaziCore.d.ts +7 -1
  3. package/dist/core/bazi/BaziCore.d.ts.map +1 -1
  4. package/dist/core/bazi/BaziCore.js +37 -11
  5. package/dist/core/bazi/BaziCore.js.map +1 -1
  6. package/dist/core/bazi/types.d.ts +4 -0
  7. package/dist/core/bazi/types.d.ts.map +1 -1
  8. package/dist/core/qimen/FlyingRule.d.ts +60 -0
  9. package/dist/core/qimen/FlyingRule.d.ts.map +1 -0
  10. package/dist/core/qimen/FlyingRule.js +94 -0
  11. package/dist/core/qimen/FlyingRule.js.map +1 -0
  12. package/dist/core/qimen/GongMapping.d.ts +29 -0
  13. package/dist/core/qimen/GongMapping.d.ts.map +1 -0
  14. package/dist/core/qimen/GongMapping.js +83 -0
  15. package/dist/core/qimen/GongMapping.js.map +1 -0
  16. package/dist/core/qimen/RotatingRule.d.ts +76 -0
  17. package/dist/core/qimen/RotatingRule.d.ts.map +1 -0
  18. package/dist/core/qimen/RotatingRule.js +126 -0
  19. package/dist/core/qimen/RotatingRule.js.map +1 -0
  20. package/dist/core/qimen/YinYangDunCalculator.d.ts +28 -0
  21. package/dist/core/qimen/YinYangDunCalculator.d.ts.map +1 -0
  22. package/dist/core/qimen/YinYangDunCalculator.js +79 -0
  23. package/dist/core/qimen/YinYangDunCalculator.js.map +1 -0
  24. package/dist/core/qimen/index.d.ts +10 -0
  25. package/dist/core/qimen/index.d.ts.map +1 -0
  26. package/dist/core/qimen/index.js +58 -0
  27. package/dist/core/qimen/index.js.map +1 -0
  28. package/dist/core/qimen/types.d.ts +19 -0
  29. package/dist/core/qimen/types.d.ts.map +1 -0
  30. package/dist/core/qimen/types.js +7 -0
  31. package/dist/core/qimen/types.js.map +1 -0
  32. package/dist/index.d.ts +10 -5
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +14 -1311
  35. package/dist/index.js.map +1 -1
  36. package/dist/output/fortuneTextRenderer.d.ts +8 -7
  37. package/dist/output/fortuneTextRenderer.d.ts.map +1 -1
  38. package/dist/output/fortuneTextRenderer.js +83 -21
  39. package/dist/output/fortuneTextRenderer.js.map +1 -1
  40. package/dist/output/qimenTextRenderer.d.ts +36 -0
  41. package/dist/output/qimenTextRenderer.d.ts.map +1 -0
  42. package/dist/output/qimenTextRenderer.js +230 -0
  43. package/dist/output/qimenTextRenderer.js.map +1 -0
  44. package/dist/server.d.ts +11 -0
  45. package/dist/server.d.ts.map +1 -0
  46. package/dist/server.js +33 -0
  47. package/dist/server.js.map +1 -0
  48. package/dist/services/bazi/BaziService.d.ts +1 -17
  49. package/dist/services/bazi/BaziService.d.ts.map +1 -1
  50. package/dist/services/bazi/BaziService.js +9 -194
  51. package/dist/services/bazi/BaziService.js.map +1 -1
  52. package/dist/services/bazi/analyzers/TenGodsAnalyzer.js +12 -12
  53. package/dist/services/bazi/analyzers/TenGodsAnalyzer.js.map +1 -1
  54. package/dist/services/bazi/index.d.ts +0 -2
  55. package/dist/services/bazi/index.d.ts.map +1 -1
  56. package/dist/services/bazi/index.js +1 -5
  57. package/dist/services/bazi/index.js.map +1 -1
  58. package/dist/services/bazi/types.d.ts +4 -112
  59. package/dist/services/bazi/types.d.ts.map +1 -1
  60. package/dist/services/bazi/types.js +3 -102
  61. package/dist/services/bazi/types.js.map +1 -1
  62. package/dist/services/daliuren/DaliurenService.d.ts +11 -1
  63. package/dist/services/daliuren/DaliurenService.d.ts.map +1 -1
  64. package/dist/services/daliuren/DaliurenService.js +30 -0
  65. package/dist/services/daliuren/DaliurenService.js.map +1 -1
  66. package/dist/services/daliuren/calculators/TianDiPanCalculator.d.ts.map +1 -1
  67. package/dist/services/daliuren/calculators/TianDiPanCalculator.js +3 -4
  68. package/dist/services/daliuren/calculators/TianDiPanCalculator.js.map +1 -1
  69. package/dist/services/daliuren/data/constants.d.ts +7 -0
  70. package/dist/services/daliuren/data/constants.d.ts.map +1 -1
  71. package/dist/services/daliuren/data/constants.js +17 -1
  72. package/dist/services/daliuren/data/constants.js.map +1 -1
  73. package/dist/services/daliuren/types.d.ts +13 -0
  74. package/dist/services/daliuren/types.d.ts.map +1 -1
  75. package/dist/services/meihua/calculators/TiyongCalculator.d.ts.map +1 -1
  76. package/dist/services/meihua/calculators/TiyongCalculator.js +6 -5
  77. package/dist/services/meihua/calculators/TiyongCalculator.js.map +1 -1
  78. package/dist/services/qimen/QimenService.d.ts +76 -0
  79. package/dist/services/qimen/QimenService.d.ts.map +1 -0
  80. package/dist/services/qimen/QimenService.js +393 -0
  81. package/dist/services/qimen/QimenService.js.map +1 -0
  82. package/dist/services/qimen/calculators/BaMenCalculator.d.ts +45 -0
  83. package/dist/services/qimen/calculators/BaMenCalculator.d.ts.map +1 -0
  84. package/dist/services/qimen/calculators/BaMenCalculator.js +87 -0
  85. package/dist/services/qimen/calculators/BaMenCalculator.js.map +1 -0
  86. package/dist/services/qimen/calculators/BaShenCalculator.d.ts +34 -0
  87. package/dist/services/qimen/calculators/BaShenCalculator.d.ts.map +1 -0
  88. package/dist/services/qimen/calculators/BaShenCalculator.js +57 -0
  89. package/dist/services/qimen/calculators/BaShenCalculator.js.map +1 -0
  90. package/dist/services/qimen/calculators/GeJuCalculator.d.ts +141 -0
  91. package/dist/services/qimen/calculators/GeJuCalculator.d.ts.map +1 -0
  92. package/dist/services/qimen/calculators/GeJuCalculator.js +711 -0
  93. package/dist/services/qimen/calculators/GeJuCalculator.js.map +1 -0
  94. package/dist/services/qimen/calculators/JiuGongCalculator.d.ts +49 -0
  95. package/dist/services/qimen/calculators/JiuGongCalculator.d.ts.map +1 -0
  96. package/dist/services/qimen/calculators/JiuGongCalculator.js +68 -0
  97. package/dist/services/qimen/calculators/JiuGongCalculator.js.map +1 -0
  98. package/dist/services/qimen/calculators/JiuXingCalculator.d.ts +44 -0
  99. package/dist/services/qimen/calculators/JiuXingCalculator.d.ts.map +1 -0
  100. package/dist/services/qimen/calculators/JiuXingCalculator.js +72 -0
  101. package/dist/services/qimen/calculators/JiuXingCalculator.js.map +1 -0
  102. package/dist/services/qimen/calculators/JuShuCalculator.d.ts +60 -0
  103. package/dist/services/qimen/calculators/JuShuCalculator.d.ts.map +1 -0
  104. package/dist/services/qimen/calculators/JuShuCalculator.js +110 -0
  105. package/dist/services/qimen/calculators/JuShuCalculator.js.map +1 -0
  106. package/dist/services/qimen/calculators/PanTypeCalculator.d.ts +117 -0
  107. package/dist/services/qimen/calculators/PanTypeCalculator.d.ts.map +1 -0
  108. package/dist/services/qimen/calculators/PanTypeCalculator.js +237 -0
  109. package/dist/services/qimen/calculators/PanTypeCalculator.js.map +1 -0
  110. package/dist/services/qimen/calculators/SanQiLiuYiCalculator.d.ts +41 -0
  111. package/dist/services/qimen/calculators/SanQiLiuYiCalculator.d.ts.map +1 -0
  112. package/dist/services/qimen/calculators/SanQiLiuYiCalculator.js +73 -0
  113. package/dist/services/qimen/calculators/SanQiLiuYiCalculator.js.map +1 -0
  114. package/dist/services/qimen/calculators/ShenShaCalculator.d.ts +80 -0
  115. package/dist/services/qimen/calculators/ShenShaCalculator.d.ts.map +1 -0
  116. package/dist/services/qimen/calculators/ShenShaCalculator.js +300 -0
  117. package/dist/services/qimen/calculators/ShenShaCalculator.js.map +1 -0
  118. package/dist/services/qimen/calculators/YongShenCalculator.d.ts +78 -0
  119. package/dist/services/qimen/calculators/YongShenCalculator.d.ts.map +1 -0
  120. package/dist/services/qimen/calculators/YongShenCalculator.js +497 -0
  121. package/dist/services/qimen/calculators/YongShenCalculator.js.map +1 -0
  122. package/dist/services/qimen/calculators/ZhuanPanCalculator.d.ts +111 -0
  123. package/dist/services/qimen/calculators/ZhuanPanCalculator.d.ts.map +1 -0
  124. package/dist/services/qimen/calculators/ZhuanPanCalculator.js +232 -0
  125. package/dist/services/qimen/calculators/ZhuanPanCalculator.js.map +1 -0
  126. package/dist/services/qimen/data/constants.d.ts +105 -0
  127. package/dist/services/qimen/data/constants.d.ts.map +1 -0
  128. package/dist/services/qimen/data/constants.js +295 -0
  129. package/dist/services/qimen/data/constants.js.map +1 -0
  130. package/dist/services/qimen/data/shensha-rules.d.ts +177 -0
  131. package/dist/services/qimen/data/shensha-rules.d.ts.map +1 -0
  132. package/dist/services/qimen/data/shensha-rules.js +397 -0
  133. package/dist/services/qimen/data/shensha-rules.js.map +1 -0
  134. package/dist/services/qimen/data/yongshen-rules.d.ts +115 -0
  135. package/dist/services/qimen/data/yongshen-rules.d.ts.map +1 -0
  136. package/dist/services/qimen/data/yongshen-rules.js +365 -0
  137. package/dist/services/qimen/data/yongshen-rules.js.map +1 -0
  138. package/dist/services/qimen/index.d.ts +20 -0
  139. package/dist/services/qimen/index.d.ts.map +1 -0
  140. package/dist/services/qimen/index.js +43 -0
  141. package/dist/services/qimen/index.js.map +1 -0
  142. package/dist/services/qimen/types.d.ts +316 -0
  143. package/dist/services/qimen/types.d.ts.map +1 -0
  144. package/dist/services/qimen/types.js +21 -0
  145. package/dist/services/qimen/types.js.map +1 -0
  146. package/dist/services/qimen/utils/gongUtils.d.ts +80 -0
  147. package/dist/services/qimen/utils/gongUtils.d.ts.map +1 -0
  148. package/dist/services/qimen/utils/gongUtils.js +164 -0
  149. package/dist/services/qimen/utils/gongUtils.js.map +1 -0
  150. package/dist/shared/logger.d.ts +5 -0
  151. package/dist/shared/logger.d.ts.map +1 -1
  152. package/dist/shared/logger.js +11 -4
  153. package/dist/shared/logger.js.map +1 -1
  154. package/dist/tools/baziTools.d.ts +13 -0
  155. package/dist/tools/baziTools.d.ts.map +1 -0
  156. package/dist/tools/baziTools.js +331 -0
  157. package/dist/tools/baziTools.js.map +1 -0
  158. package/dist/tools/divinationTools.d.ts +9 -0
  159. package/dist/tools/divinationTools.d.ts.map +1 -0
  160. package/dist/tools/divinationTools.js +209 -0
  161. package/dist/tools/divinationTools.js.map +1 -0
  162. package/dist/tools/qimenTools.d.ts +10 -0
  163. package/dist/tools/qimenTools.d.ts.map +1 -0
  164. package/dist/tools/qimenTools.js +132 -0
  165. package/dist/tools/qimenTools.js.map +1 -0
  166. package/dist/tools/schemas.d.ts +99 -0
  167. package/dist/tools/schemas.d.ts.map +1 -0
  168. package/dist/tools/schemas.js +162 -0
  169. package/dist/tools/schemas.js.map +1 -0
  170. package/dist/tools/ziweiTools.d.ts +14 -0
  171. package/dist/tools/ziweiTools.d.ts.map +1 -0
  172. package/dist/tools/ziweiTools.js +483 -0
  173. package/dist/tools/ziweiTools.js.map +1 -0
  174. package/dist/utils/timeNormalization.d.ts +42 -17
  175. package/dist/utils/timeNormalization.d.ts.map +1 -1
  176. package/dist/utils/timeNormalization.js +99 -41
  177. package/dist/utils/timeNormalization.js.map +1 -1
  178. package/package.json +15 -9
  179. package/dist/services/bazi/analyzers/HiddenStemsAnalyzer.d.ts +0 -16
  180. package/dist/services/bazi/analyzers/HiddenStemsAnalyzer.d.ts.map +0 -1
  181. package/dist/services/bazi/analyzers/HiddenStemsAnalyzer.js +0 -60
  182. package/dist/services/bazi/analyzers/HiddenStemsAnalyzer.js.map +0 -1
  183. package/dist/services/bazi/analyzers/NaYinAnalyzer.d.ts +0 -33
  184. package/dist/services/bazi/analyzers/NaYinAnalyzer.d.ts.map +0 -1
  185. package/dist/services/bazi/analyzers/NaYinAnalyzer.js +0 -209
  186. package/dist/services/bazi/analyzers/NaYinAnalyzer.js.map +0 -1
  187. package/dist/services/bazi/analyzers/ShenShaAnalyzer.d.ts +0 -236
  188. package/dist/services/bazi/analyzers/ShenShaAnalyzer.d.ts.map +0 -1
  189. package/dist/services/bazi/analyzers/ShenShaAnalyzer.js +0 -2079
  190. package/dist/services/bazi/analyzers/ShenShaAnalyzer.js.map +0 -1
  191. package/dist/services/bazi/analyzers/TraditionalAnalyzer.d.ts +0 -46
  192. package/dist/services/bazi/analyzers/TraditionalAnalyzer.d.ts.map +0 -1
  193. package/dist/services/bazi/analyzers/TraditionalAnalyzer.js +0 -260
  194. package/dist/services/bazi/analyzers/TraditionalAnalyzer.js.map +0 -1
package/dist/index.js CHANGED
@@ -3,1330 +3,33 @@
3
3
  /**
4
4
  * Mingpan MCP Server
5
5
  *
6
- * MCP service for accurate BaZi (八字) and ZiWei (紫微) chart calculations.
7
- * Takes birth date/time and outputs structured fortune-telling information.
6
+ * 中華傳統術數 MCP 服務:八字、紫微斗數、六爻、梅花易數、大六壬、奇門遁甲。
7
+ * AI 應用提供確定性排盤與占卜起卦的計算能力。
8
8
  *
9
- * Version 1.1.0: Added fortune list tools for DaYun, LiuNian, LiuYue, LiuRi
10
- * - 八字流月 uses 干支月 (solar term months)
11
- * - 紫微流月 uses 农历月 (lunar months)
9
+ * 架構:
10
+ * - src/tools/ MCP 工具註冊(按領域拆分,共享 schema tools/schemas.ts)
11
+ * - src/services/ 業務計算服務
12
+ * - src/core/ 純計算核心(曆法、規則)
13
+ * - src/output/ 文本渲染
14
+ *
15
+ * 時間口徑:內部規範表示為北京時間(UTC+8);
16
+ * 入口層統一完成農曆轉換與時區換算(見 utils/timeNormalization.ts)。
12
17
  */
13
18
  Object.defineProperty(exports, "__esModule", { value: true });
14
- const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
15
19
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
16
- const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
17
- const zod_1 = require("zod");
18
- const zod_to_json_schema_1 = require("zod-to-json-schema");
19
- const lunar_javascript_1 = require("lunar-javascript");
20
20
  const timeNormalization_1 = require("./utils/timeNormalization");
21
- const BaziService_1 = require("./services/bazi/BaziService");
22
- const ZiweiService_1 = require("./services/ziwei/ZiweiService");
23
- const LiuyaoService_1 = require("./services/liuyao/LiuyaoService");
24
- const liuyaoTextRenderer_1 = require("./output/liuyaoTextRenderer");
25
- const MeihuaService_1 = require("./services/meihua/MeihuaService");
26
- const meihuaTextRenderer_1 = require("./output/meihuaTextRenderer");
27
- const DaliurenService_1 = require("./services/daliuren/DaliurenService");
28
- const daliurenTextRenderer_1 = require("./output/daliurenTextRenderer");
29
- const LiuNianCalculator_1 = require("./services/bazi/calculators/LiuNianCalculator");
30
- const DaYunCalculator_1 = require("./services/bazi/calculators/DaYunCalculator");
31
- const LuckCycleCalculator_1 = require("./services/bazi/calculators/LuckCycleCalculator");
32
- const LiuYueCalculator_1 = require("./services/bazi/calculators/LiuYueCalculator");
33
- const LiuRiCalculator_1 = require("./services/bazi/calculators/LiuRiCalculator");
34
- const YearlyCalculator_1 = require("./services/ziwei/calculators/YearlyCalculator");
35
- const fortuneTextRenderer_1 = require("./output/fortuneTextRenderer");
36
- const listTextRenderer_1 = require("./output/listTextRenderer");
37
21
  const logger_1 = require("./shared/logger");
38
- const MutagenCore_1 = require("./core/ziwei/MutagenCore");
22
+ const server_1 = require("./server");
39
23
  const logger = new logger_1.Logger("mingpan");
40
- // ============================================
41
- // Timezone Configuration
42
- // ============================================
43
24
  // Force deterministic timezone behavior (Beijing Time) across environments.
44
- // This ensures lunar-javascript and Date operations behave consistently
25
+ // This ensures Date-based code paths in services behave consistently
45
26
  // regardless of the host machine's timezone setting.
46
- // TODO: Remove when multi-timezone support is implemented (M4 milestone)
47
27
  process.env.TZ = timeNormalization_1.BEIJING_TZ;
48
- // Helper to avoid TypeScript's excessively deep type instantiation error
49
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
- function schemaToJson(schema) {
51
- return (0, zod_to_json_schema_1.zodToJsonSchema)(schema);
52
- }
53
- // ============================================
54
- // Zod Schemas for Tool Inputs
55
- // ============================================
56
- // isLunar field schema (reusable)
57
- const isLunarField = zod_1.z.boolean().optional().default(false).describe("Whether the input date is in lunar calendar (農曆). If true, will be converted to solar calendar internally.");
58
- // Base birth info schema
59
- const BaseBirthInfoSchema = zod_1.z.object({
60
- year: zod_1.z.number().int().min(1900).max(2100).describe("Birth year (e.g., 1990)"),
61
- month: zod_1.z.number().int().min(1).max(12).describe("Birth month (1-12)"),
62
- day: zod_1.z.number().int().min(1).max(31).describe("Birth day (1-31)"),
63
- hour: zod_1.z.number().int().min(0).max(23).describe("Birth hour in 24-hour format (0-23)"),
64
- minute: zod_1.z.number().int().min(0).max(59).optional().default(0).describe("Birth minute (0-59)"),
65
- gender: zod_1.z.enum(["male", "female"]).describe("Gender for fortune direction calculation"),
66
- longitude: zod_1.z.number().min(-180).max(180).optional().describe("Birth location longitude for true solar time adjustment"),
67
- isLunar: isLunarField,
68
- name: zod_1.z.string().optional().describe("Subject name (optional)"),
69
- });
70
- /**
71
- * Normalize birth info: handle lunar-to-solar conversion
72
- * Call this at the start of each handler to get consistent, normalized values
73
- */
74
- function normalizeBirthInfo(input) {
75
- const normalized = (0, timeNormalization_1.normalizeBirthDateTime)({
76
- year: input.year,
77
- month: input.month,
78
- day: input.day,
79
- hour: input.hour,
80
- minute: input.minute,
81
- isLunar: input.isLunar,
82
- });
83
- return {
84
- ...input,
85
- year: normalized.year,
86
- month: normalized.month,
87
- day: normalized.day,
88
- hour: normalized.hour,
89
- minute: normalized.minute,
90
- isLunar: false, // After normalization, always use solar calendar
91
- _isLunarInput: normalized.isLunarInput,
92
- };
93
- }
94
- const BaziCalculateSchema = zod_1.z.object({
95
- year: zod_1.z.number().int().min(1900).max(2100).describe("Birth year (e.g., 1990)"),
96
- month: zod_1.z.number().int().min(1).max(12).describe("Birth month (1-12)"),
97
- day: zod_1.z.number().int().min(1).max(31).describe("Birth day (1-31)"),
98
- hour: zod_1.z.number().int().min(0).max(23).describe("Birth hour in 24-hour format (0-23)"),
99
- minute: zod_1.z.number().int().min(0).max(59).optional().default(0).describe("Birth minute (0-59)"),
100
- gender: zod_1.z.enum(["male", "female"]).optional().default("male").describe("Gender for DaYun calculation direction"),
101
- longitude: zod_1.z.number().min(-180).max(180).optional().describe("Birth location longitude for true solar time adjustment"),
102
- isLunar: isLunarField,
103
- detail: zod_1.z.enum(["simple", "standard", "detailed"]).optional().default("standard").describe("Output detail level"),
104
- includeAnalysis: zod_1.z.boolean().optional().default(true).describe("Include strength and pattern analysis"),
105
- includeDaYun: zod_1.z.boolean().optional().default(true).describe("Include decade fortune (大運)"),
106
- targetYear: zod_1.z.number().int().optional().describe("Calculate LiuNian (流年) for this specific year"),
107
- });
108
- const ZiweiCalculateSchema = zod_1.z.object({
109
- year: zod_1.z.number().int().min(1900).max(2100).describe("Birth year (e.g., 1990)"),
110
- month: zod_1.z.number().int().min(1).max(12).describe("Birth month (1-12)"),
111
- day: zod_1.z.number().int().min(1).max(31).describe("Birth day (1-31)"),
112
- hour: zod_1.z.number().int().min(0).max(23).describe("Birth hour in 24-hour format (0-23)"),
113
- minute: zod_1.z.number().int().min(0).max(59).optional().default(0).describe("Birth minute (0-59)"),
114
- gender: zod_1.z.enum(["male", "female"]).describe("Gender (required for ZiWei calculation)"),
115
- isLunar: isLunarField,
116
- detail: zod_1.z.enum(["simple", "standard", "detailed"]).optional().default("standard").describe("Output detail level"),
117
- targetYear: zod_1.z.number().int().optional().describe("Calculate yearly fortune for this specific year"),
118
- includeDecades: zod_1.z.boolean().optional().default(true).describe("Include decade fortune (大限)"),
119
- includeMutagen: zod_1.z.boolean().optional().default(true).describe("Include four mutagens (四化)"),
120
- });
121
- const CombinedCalculateSchema = zod_1.z.object({
122
- year: zod_1.z.number().int().min(1900).max(2100).describe("Birth year (e.g., 1990)"),
123
- month: zod_1.z.number().int().min(1).max(12).describe("Birth month (1-12)"),
124
- day: zod_1.z.number().int().min(1).max(31).describe("Birth day (1-31)"),
125
- hour: zod_1.z.number().int().min(0).max(23).describe("Birth hour in 24-hour format (0-23)"),
126
- minute: zod_1.z.number().int().min(0).max(59).optional().default(0).describe("Birth minute (0-59)"),
127
- gender: zod_1.z.enum(["male", "female"]).describe("Gender (required for both calculations)"),
128
- longitude: zod_1.z.number().min(-180).max(180).optional().describe("Birth location longitude for true solar time adjustment"),
129
- isLunar: isLunarField,
130
- detail: zod_1.z.enum(["simple", "standard", "detailed"]).optional().default("standard").describe("Output detail level"),
131
- targetYear: zod_1.z.number().int().optional().describe("Calculate yearly fortune for this specific year"),
132
- systems: zod_1.z.array(zod_1.z.enum(["bazi", "ziwei"])).optional().default(["bazi", "ziwei"]).describe("Which systems to calculate"),
133
- });
134
- // ============================================
135
- // 六爻 Schema
136
- // ============================================
137
- const LiuyaoBasicSchema = zod_1.z.object({
138
- yaoValues: zod_1.z.tuple([
139
- zod_1.z.union([zod_1.z.literal(6), zod_1.z.literal(7), zod_1.z.literal(8), zod_1.z.literal(9)]),
140
- zod_1.z.union([zod_1.z.literal(6), zod_1.z.literal(7), zod_1.z.literal(8), zod_1.z.literal(9)]),
141
- zod_1.z.union([zod_1.z.literal(6), zod_1.z.literal(7), zod_1.z.literal(8), zod_1.z.literal(9)]),
142
- zod_1.z.union([zod_1.z.literal(6), zod_1.z.literal(7), zod_1.z.literal(8), zod_1.z.literal(9)]),
143
- zod_1.z.union([zod_1.z.literal(6), zod_1.z.literal(7), zod_1.z.literal(8), zod_1.z.literal(9)]),
144
- zod_1.z.union([zod_1.z.literal(6), zod_1.z.literal(7), zod_1.z.literal(8), zod_1.z.literal(9)]),
145
- ]).describe("六個爻值(自下而上,初爻到上爻)。6=老陰(動), 7=少陽(靜), 8=少陰(靜), 9=老陽(動)"),
146
- year: zod_1.z.number().int().min(1900).max(2100).describe("起卦年份(公曆)"),
147
- month: zod_1.z.number().int().min(1).max(12).describe("起卦月份(1-12)"),
148
- day: zod_1.z.number().int().min(1).max(31).describe("起卦日期(1-31)"),
149
- hour: zod_1.z.number().int().min(0).max(23).describe("起卦時辰(0-23)"),
150
- isLunar: isLunarField,
151
- });
152
- // ============================================
153
- // 梅花易數 Schema
154
- // ============================================
155
- const MeihuaBasicSchema = zod_1.z.object({
156
- method: zod_1.z.enum(['time', 'number']).describe("起卦方式:time=時間起卦,number=數字起卦"),
157
- // time 模式參數
158
- year: zod_1.z.number().int().min(1900).max(2100).optional().describe("起卦年份(公曆,time 模式必填)"),
159
- month: zod_1.z.number().int().min(1).max(12).optional().describe("起卦月份(1-12,time 模式必填)"),
160
- day: zod_1.z.number().int().min(1).max(31).optional().describe("起卦日期(1-31,time 模式必填)"),
161
- hour: zod_1.z.number().int().min(0).max(23).optional().describe("起卦時辰(0-23,time 模式必填)"),
162
- isLunar: isLunarField,
163
- // number 模式參數
164
- upperNumber: zod_1.z.number().int().min(1).optional().describe("上卦數(number 模式必填)"),
165
- lowerNumber: zod_1.z.number().int().min(1).optional().describe("下卦數(number 模式必填)"),
166
- yaoNumber: zod_1.z.number().int().min(1).optional().describe("動爻數(可選,默認用上下卦數之和)"),
167
- });
168
- // ============================================
169
- // 大六壬 Schema
170
- // ============================================
171
- const DaliurenBasicSchema = zod_1.z.object({
172
- jieqi: zod_1.z.string().describe("節氣(如:立春、雨水、驚蟄等)"),
173
- lunarMonth: zod_1.z.number().int().min(1).max(12).describe("農曆月份(1-12)"),
174
- dayGanZhi: zod_1.z.string().describe("日干支(如:甲子、乙丑等)"),
175
- hourGanZhi: zod_1.z.string().describe("時干支(如:甲子、乙丑等)"),
176
- guirenMethod: zod_1.z.union([zod_1.z.literal(0), zod_1.z.literal(1)]).optional().default(0).describe("貴人起法:0=標準, 1=另一種"),
177
- });
178
- // ============================================
179
- // List Tool Schemas
180
- // ============================================
181
- // 八字大运列表
182
- const BaziDaYunListSchema = BaseBirthInfoSchema.extend({
183
- count: zod_1.z.number().int().min(1).max(12).optional().default(10).describe("Number of DaYun periods to display (default 10)"),
184
- });
185
- // 八字流年列表
186
- const BaziLiuNianListSchema = BaseBirthInfoSchema.extend({
187
- startYear: zod_1.z.number().int().min(1900).max(2100).describe("Start year for the range"),
188
- endYear: zod_1.z.number().int().min(1900).max(2100).describe("End year for the range"),
189
- });
190
- // 八字流月列表(干支月/节气月)
191
- const BaziLiuYueListSchema = BaseBirthInfoSchema.extend({
192
- ganzhiYear: zod_1.z.union([
193
- zod_1.z.string().describe("GanZhi year like '乙巳'"),
194
- zod_1.z.number().int().min(1900).max(2100).describe("Gregorian year like 2025")
195
- ]).describe("The year to query (either GanZhi string or Gregorian year)"),
196
- });
197
- // 八字流日列表
198
- const BaziLiuRiListSchema = BaseBirthInfoSchema.extend({
199
- ganzhiYear: zod_1.z.union([
200
- zod_1.z.string().describe("GanZhi year like '乙巳'"),
201
- zod_1.z.number().int().min(1900).max(2100).describe("Gregorian year like 2025")
202
- ]).describe("The year of the month"),
203
- ganzhiMonth: zod_1.z.union([
204
- zod_1.z.string().describe("GanZhi month like '丙寅' (month 1 = 寅月)"),
205
- zod_1.z.number().int().min(1).max(12).describe("Month number (1=寅月, 2=卯月, ..., 12=丑月)")
206
- ]).describe("The month to query (either GanZhi string or month number 1-12)"),
207
- });
208
- // 紫微大限列表
209
- const ZiweiDaXianListSchema = BaseBirthInfoSchema.extend({
210
- count: zod_1.z.number().int().min(1).max(12).optional().default(10).describe("Number of decade periods to display (default 10)"),
211
- });
212
- // 紫微小限列表
213
- const ZiweiXiaoXianListSchema = BaseBirthInfoSchema.extend({
214
- startAge: zod_1.z.number().int().min(1).max(120).describe("Start age (nominal age) for the range"),
215
- endAge: zod_1.z.number().int().min(1).max(120).describe("End age (nominal age) for the range"),
216
- });
217
- // 紫微流年列表
218
- const ZiweiLiuNianListSchema = BaseBirthInfoSchema.extend({
219
- startYear: zod_1.z.number().int().min(1900).max(2100).describe("Start year for the range"),
220
- endYear: zod_1.z.number().int().min(1900).max(2100).describe("End year for the range"),
221
- });
222
- // 紫微流月列表(农历月)
223
- const ZiweiLiuYueListSchema = BaseBirthInfoSchema.extend({
224
- lunarYear: zod_1.z.number().int().min(1900).max(2100).describe("The lunar year (Gregorian year) to query"),
225
- });
226
- // 紫微流日列表(农历日)
227
- const ZiweiLiuRiListSchema = BaseBirthInfoSchema.extend({
228
- lunarYear: zod_1.z.number().int().min(1900).max(2100).describe("The lunar year (Gregorian year)"),
229
- lunarMonth: zod_1.z.number().int().min(-12).max(12).describe("Lunar month (1-12, use negative for leap month, e.g. -6 for leap 6th month)"),
230
- });
231
- // ============================================
232
- // Create Server
233
- // ============================================
234
- const server = new index_js_1.Server({
235
- name: "mingpan",
236
- version: "0.1.2",
237
- }, {
238
- capabilities: {
239
- tools: {},
240
- },
241
- });
242
- // ============================================
243
- // Tool Definitions
244
- // ============================================
245
- server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
246
- return {
247
- tools: [
248
- {
249
- name: "bazi_basic",
250
- description: `计算八字命盘(基础排盘)。
251
-
252
- 输入出生时间,返回完整的八字命盘信息:
253
- - 四柱(年柱、月柱、日柱、时柱)干支
254
- - 各柱藏干
255
- - 十神配置
256
- - 五行力量分析(360分制)
257
- - 日主强弱判定
258
- - 格局识别
259
- - 神煞标注
260
-
261
- 输出为结构化文本,便于 AI 分析解读。`,
262
- inputSchema: schemaToJson(BaziCalculateSchema),
263
- },
264
- {
265
- name: "ziwei_basic",
266
- description: `计算紫微斗数命盘(基础排盘)。
267
-
268
- 输入出生时间,返回完整的紫微命盘信息:
269
- - 十二宫位排布及干支
270
- - 各宫主星及亮度(庙/旺/得/利/平/不/陷)
271
- - 各宫辅星配置
272
- - 命宫与身宫位置
273
- - 本命四化(化禄/权/科/忌)
274
-
275
- 输出为结构化文本,便于 AI 分析解读。`,
276
- inputSchema: schemaToJson(ZiweiCalculateSchema),
277
- },
278
- {
279
- name: "bazi_dayun",
280
- description: `八字大运列表。
281
-
282
- 返回命主一生的大运周期(十年一运):
283
- - 大运干支
284
- - 起止虚岁
285
- - 对应公历年份
286
- - 起运方向(顺行/逆行)
287
- - 起运年龄
288
-
289
- 用于了解人生各阶段的运势大框架。`,
290
- inputSchema: schemaToJson(BaziDaYunListSchema),
291
- },
292
- {
293
- name: "bazi_liunian",
294
- description: `八字流年列表。
295
-
296
- 返回指定年份范围内的流年信息:
297
- - 公历年份
298
- - 干支年
299
- - 虚岁
300
- - 所属大运
301
-
302
- 用于分析多年运势趋势。`,
303
- inputSchema: schemaToJson(BaziLiuNianListSchema),
304
- },
305
- {
306
- name: "bazi_liuyue",
307
- description: `八字流月列表。
308
-
309
- 重要:八字流月使用【节气月】,非农历月!
310
- - 以节气为边界(立春起算)
311
- - 寅月(正月)从立春开始,约2月4日
312
- - 丑月(腊月)跨越公历年界
313
-
314
- 返回指定年份的12个月运势:
315
- - 干支月
316
- - 节气起止
317
- - 公历日期范围
318
-
319
- 用于规划年度活动时机。`,
320
- inputSchema: schemaToJson(BaziLiuYueListSchema),
321
- },
322
- {
323
- name: "bazi_liuri",
324
- description: `八字流日列表。
325
-
326
- 返回指定月份内的每日运势(含上下文):
327
- - 当前大运、流年、流月资讯
328
- - 公历日期
329
- - 干支日
330
-
331
- 用于精细的日期选择。`,
332
- inputSchema: schemaToJson(BaziLiuRiListSchema),
333
- },
334
- {
335
- name: "ziwei_daxian",
336
- description: `紫微大限列表。
337
-
338
- 返回命主一生的大限周期(十年一限):
339
- - 起止虚岁
340
- - 对应公历年份
341
- - 大限宫位名称
342
- - 宫内主星配置
343
- - 大限四化
344
-
345
- 用于了解人生各阶段的运势大框架。`,
346
- inputSchema: schemaToJson(ZiweiDaXianListSchema),
347
- },
348
- {
349
- name: "ziwei_xiaoxian",
350
- description: `紫微小限列表。
351
-
352
- 小限是紫微斗数中的年度运限单位,每年一宫:
353
- - 虚岁(1岁起)
354
- - 对应公历年份
355
- - 小限宫位(根据出生年支起宫,男顺女逆)
356
- - 宫内主星
357
- - 所属大限
358
- - 小限四化
359
-
360
- 小限与流年并列但计算方式不同:
361
- - 小限:以出生年支定起宫,逐年移宫
362
- - 流年:以该年地支定宫位
363
-
364
- 层级顺序:大限 > 小限 > 流年 > 流月 > 流日`,
365
- inputSchema: schemaToJson(ZiweiXiaoXianListSchema),
366
- },
367
- {
368
- name: "ziwei_liunian",
369
- description: `紫微流年列表。
370
-
371
- 返回指定年份范围内的流年信息:
372
- - 公历年份
373
- - 干支年
374
- - 虚岁
375
- - 流年宫位
376
- - 宫内主星
377
- - 所属大限
378
- - 流年四化
379
-
380
- 用于分析多年运势趋势。`,
381
- inputSchema: schemaToJson(ZiweiLiuNianListSchema),
382
- },
383
- {
384
- name: "ziwei_liuyue",
385
- description: `紫微流月列表。
386
-
387
- 重要:紫微流月使用【农历月】,非节气月!
388
- - 以农历初一为边界
389
- - 正月从春节开始
390
- - 闰月单独显示(如"闰六月")
391
-
392
- 返回指定年份的流月运势(含上下文):
393
- - 当前大限、小限、流年资讯
394
- - 农历月份及公历日期范围
395
- - 流月宫位及宫内主星
396
- - 完整四化系统(本命/大限/小限/流年/流月)
397
-
398
- 用于规划年度活动时机。`,
399
- inputSchema: schemaToJson(ZiweiLiuYueListSchema),
400
- },
401
- {
402
- name: "ziwei_liuri",
403
- description: `紫微流日列表。
404
-
405
- 返回指定农历月内的每日运势(含上下文):
406
- - 当前大限、小限、流年、流月资讯
407
- - 农历日期与公历日期对照
408
- - 干支日及流日宫位
409
- - 完整四化系统(本命/大限/小限/流年/流月/流日)
410
-
411
- 闰月使用负数表示(如 -6 表示闰六月)。
412
-
413
- 用于精细的日期选择。`,
414
- inputSchema: schemaToJson(ZiweiLiuRiListSchema),
415
- },
416
- {
417
- name: "liuyao_basic",
418
- description: `六爻排盤(基礎排盤)。
419
-
420
- 輸入六個爻值和起卦時間,返回完整的六爻盤面:
421
- - 本卦/變卦(含卦名、卦宮、五行)
422
- - 六爻納甲(每爻地支及五行)
423
- - 六親(父母/兄弟/子孫/妻財/官鬼)
424
- - 六神(青龍/朱雀/勾陳/螣蛇/白虎/玄武)
425
- - 世應位置
426
- - 動爻標註
427
- - 日干支、月建、旬空
428
-
429
- 爻值說明:
430
- - 6 = 老陰(動爻,陰變陽)
431
- - 7 = 少陽(靜爻,陽)
432
- - 8 = 少陰(靜爻,陰)
433
- - 9 = 老陽(動爻,陽變陰)
434
-
435
- 輸入順序:自下而上(初爻到上爻)
436
-
437
- 輸出為 Markdown 格式,便於 AI 分析解讀。`,
438
- inputSchema: schemaToJson(LiuyaoBasicSchema),
439
- },
440
- {
441
- name: "meihua_basic",
442
- description: `梅花易數排盤(基礎排盤)。
443
-
444
- 支持兩種起卦方式:
445
- 1. 時間起卦(method='time'):根據農曆年月日時起卦
446
- 2. 數字起卦(method='number'):根據兩個數字起卦
447
-
448
- 返回完整的梅花盤面:
449
- - 本卦/變卦/互卦
450
- - 上卦/下卦(含卦象、五行)
451
- - 動爻位置
452
- - 體用分析(體卦、用卦、五行生剋關係)
453
- - 起卦數據詳情
454
-
455
- 時間起卦算法(農曆):
456
- - 上卦 = (年干支序數 + 月 + 日) % 8
457
- - 下卦 = (年干支序數 + 月 + 日 + 時辰序數) % 8
458
- - 動爻 = (年干支序數 + 月 + 日 + 時辰序數) % 6
459
-
460
- 輸出為 Markdown 格式,便於 AI 分析解讀。`,
461
- inputSchema: schemaToJson(MeihuaBasicSchema),
462
- },
463
- {
464
- name: "daliuren_basic",
465
- description: `大六壬排盤(基礎排盤)。
466
-
467
- 大六壬是中國古老三大占卜術之一,與奇門遁甲、太乙神數並稱三式。
468
-
469
- 輸入節氣、農曆月、日干支、時干支,返回完整的六壬盤面:
470
- - 天地盤(月將加時辰起盤)
471
- - 四課(日干支推演)
472
- - 三傳(九宗門推演:賊尅、比用、涉害、遙尅、昴星、別責、八專、伏吟、返吟)
473
- - 十二天將(貴人、螣蛇、朱雀、六合、勾陳、青龍、天空、白虎、太常、玄武、太陰、天后)
474
- - 格局判斷
475
- - 神煞(日馬、月馬、丁馬、華蓋、閃電)
476
-
477
- 注意:
478
- - 需要提供節氣(如:立春、雨水、驚蟄等)
479
- - 日干支和時干支需要是完整的干支(如:甲子、乙丑)
480
- - 本工具只負責排盤,斷課解讀交給 Agent
481
-
482
- 輸出為 Markdown 格式,便於 AI 分析解讀。`,
483
- inputSchema: schemaToJson(DaliurenBasicSchema),
484
- },
485
- ],
486
- };
487
- });
488
- // ============================================
489
- // Tool Handlers
490
- // ============================================
491
- const baziService = new BaziService_1.BaziService({ debug: false });
492
- const ziweiService = new ZiweiService_1.ZiweiService();
493
- const liuyaoService = new LiuyaoService_1.LiuyaoService();
494
- const meihuaService = new MeihuaService_1.MeihuaService();
495
- // Helper: Calculate year stem and branch
496
- function getYearStemBranch(year) {
497
- const STEMS = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
498
- const BRANCHES = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'];
499
- const baseYear = 1984; // 甲子年
500
- const yearDiff = year - baseYear;
501
- const stemIndex = ((yearDiff % 10) + 10) % 10;
502
- const branchIndex = ((yearDiff % 12) + 12) % 12;
503
- return { stem: STEMS[stemIndex], branch: BRANCHES[branchIndex] };
504
- }
505
- // Helper: Parse GanZhi year input
506
- function parseGanzhiYear(input) {
507
- if (typeof input === 'number') {
508
- const { stem, branch } = getYearStemBranch(input);
509
- return { year: input, ganzhi: stem + branch };
510
- }
511
- // Parse GanZhi string to find year - search nearby years
512
- const currentYear = new Date().getFullYear();
513
- for (let y = currentYear - 60; y <= currentYear + 60; y++) {
514
- const { stem, branch } = getYearStemBranch(y);
515
- if (stem + branch === input) {
516
- return { year: y, ganzhi: input };
517
- }
518
- }
519
- // Default to current year if not found
520
- const { stem, branch } = getYearStemBranch(currentYear);
521
- return { year: currentYear, ganzhi: stem + branch };
522
- }
523
- // Helper: Parse GanZhi month input
524
- function parseGanzhiMonth(input) {
525
- if (typeof input === 'number') {
526
- return input; // 1-12
527
- }
528
- // Parse GanZhi month string to get month index
529
- const BRANCHES = ['寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥', '子', '丑'];
530
- const branch = input.substring(1, 2);
531
- const idx = BRANCHES.indexOf(branch);
532
- return idx >= 0 ? idx + 1 : 1;
533
- }
534
- // Helper: Get month stem branch for a given year and month
535
- function getMonthStemBranch(year, monthNum) {
536
- const STEMS = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
537
- const BRANCHES = ['寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥', '子', '丑'];
538
- // Month branch: monthNum 1 = 寅, 2 = 卯, ..., 12 = 丑
539
- const branch = BRANCHES[(monthNum - 1) % 12];
540
- // Month stem depends on year stem
541
- const { stem: yearStem } = getYearStemBranch(year);
542
- const yearStemIndex = STEMS.indexOf(yearStem);
543
- // 五虎遁年起月诀
544
- const firstMonthStemMap = {
545
- 0: 2, // 甲年 -> 丙寅月
546
- 1: 4, // 乙年 -> 戊寅月
547
- 2: 6, // 丙年 -> 庚寅月
548
- 3: 8, // 丁年 -> 壬寅月
549
- 4: 0, // 戊年 -> 甲寅月
550
- 5: 2, // 己年 -> 丙寅月
551
- 6: 4, // 庚年 -> 戊寅月
552
- 7: 6, // 辛年 -> 庚寅月
553
- 8: 8, // 壬年 -> 壬寅月
554
- 9: 0 // 癸年 -> 甲寅月
555
- };
556
- const firstMonthStemIndex = firstMonthStemMap[yearStemIndex];
557
- const monthStemIndex = (firstMonthStemIndex + monthNum - 1) % 10;
558
- return { stem: STEMS[monthStemIndex], branch };
559
- }
560
- server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
561
- const { name, arguments: args } = request.params;
562
- logger.info(`Tool called: ${name}`, args);
563
- try {
564
- // === Existing Chart Calculation Handlers ===
565
- if (name === "bazi_basic") {
566
- const validated = BaziCalculateSchema.parse(args);
567
- const normalized = normalizeBirthInfo(validated);
568
- const result = await baziService.calculate({
569
- year: normalized.year,
570
- month: normalized.month,
571
- day: normalized.day,
572
- hour: normalized.hour,
573
- minute: normalized.minute,
574
- gender: normalized.gender,
575
- longitude: normalized.longitude,
576
- useLunar: false, // Already converted to solar if needed
577
- });
578
- // If targetYear is specified, calculate LiuNian
579
- let liuNianInfo = "";
580
- if (validated.targetYear && result.chart) {
581
- const liuNians = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, normalized.year, validated.targetYear, validated.targetYear);
582
- if (liuNians.length > 0) {
583
- const liunian = liuNians[0];
584
- liuNianInfo = `\n\n=== 流年 ${validated.targetYear} ===\n干支:${liunian.stem}${liunian.branch}`;
585
- }
586
- }
587
- const options = {
588
- detail: validated.detail,
589
- includePersonal: false,
590
- includeLocation: !!validated.longitude,
591
- };
592
- const birthDate = new Date(normalized.year, normalized.month - 1, normalized.day, normalized.hour, normalized.minute);
593
- const text = (0, fortuneTextRenderer_1.renderBaziText)({ bazi: result, gender: normalized.gender, birthDate }, options);
594
- return {
595
- content: [
596
- {
597
- type: "text",
598
- text: text + liuNianInfo,
599
- },
600
- ],
601
- };
602
- }
603
- if (name === "ziwei_basic") {
604
- const validated = ZiweiCalculateSchema.parse(args);
605
- const normalized = normalizeBirthInfo(validated);
606
- const result = await ziweiService.calculate({
607
- year: normalized.year,
608
- month: normalized.month,
609
- day: normalized.day,
610
- hour: normalized.hour,
611
- gender: normalized.gender,
612
- });
613
- const options = {
614
- detail: validated.detail,
615
- includePersonal: false,
616
- };
617
- const birthDate = new Date(normalized.year, normalized.month - 1, normalized.day, normalized.hour, normalized.minute);
618
- const text = (0, fortuneTextRenderer_1.renderZiweiText)({
619
- ziwei: result,
620
- gender: normalized.gender,
621
- birthDate,
622
- mutagen: result.mutagenInfo // 傳入四化信息
623
- }, options);
624
- return {
625
- content: [
626
- {
627
- type: "text",
628
- text,
629
- },
630
- ],
631
- };
632
- }
633
- // === 六爻工具處理器 ===
634
- if (name === "liuyao_basic") {
635
- const validated = LiuyaoBasicSchema.parse(args);
636
- const result = liuyaoService.calculate({
637
- yaoValues: validated.yaoValues,
638
- year: validated.year,
639
- month: validated.month,
640
- day: validated.day,
641
- hour: validated.hour,
642
- isLunar: validated.isLunar,
643
- });
644
- const text = (0, liuyaoTextRenderer_1.renderLiuyaoText)(result);
645
- return {
646
- content: [
647
- {
648
- type: "text",
649
- text,
650
- },
651
- ],
652
- };
653
- }
654
- // === 梅花易數工具處理器 ===
655
- if (name === "meihua_basic") {
656
- const validated = MeihuaBasicSchema.parse(args);
657
- const result = meihuaService.calculate({
658
- method: validated.method,
659
- year: validated.year,
660
- month: validated.month,
661
- day: validated.day,
662
- hour: validated.hour,
663
- isLunar: validated.isLunar,
664
- upperNumber: validated.upperNumber,
665
- lowerNumber: validated.lowerNumber,
666
- yaoNumber: validated.yaoNumber,
667
- });
668
- const text = (0, meihuaTextRenderer_1.renderMeihuaText)(result);
669
- return {
670
- content: [
671
- {
672
- type: "text",
673
- text,
674
- },
675
- ],
676
- };
677
- }
678
- // === 大六壬工具處理器 ===
679
- if (name === "daliuren_basic") {
680
- const validated = DaliurenBasicSchema.parse(args);
681
- const daliurenService = new DaliurenService_1.DaliurenService();
682
- const result = daliurenService.calculate({
683
- jieqi: validated.jieqi,
684
- lunarMonth: validated.lunarMonth,
685
- dayGanZhi: validated.dayGanZhi,
686
- hourGanZhi: validated.hourGanZhi,
687
- guirenMethod: validated.guirenMethod,
688
- });
689
- const text = (0, daliurenTextRenderer_1.renderDaliurenText)(result);
690
- return {
691
- content: [
692
- {
693
- type: "text",
694
- text,
695
- },
696
- ],
697
- };
698
- }
699
- // === BaZi List Tool Handlers ===
700
- if (name === "bazi_dayun") {
701
- const validated = BaziDaYunListSchema.parse(args);
702
- const normalized = normalizeBirthInfo(validated);
703
- // Calculate BaZi chart first
704
- const result = await baziService.calculate({
705
- year: normalized.year,
706
- month: normalized.month,
707
- day: normalized.day,
708
- hour: normalized.hour,
709
- minute: normalized.minute,
710
- gender: normalized.gender,
711
- longitude: normalized.longitude,
712
- });
713
- if (!result.chart || !result.birthInfo) {
714
- throw new Error("Failed to calculate BaZi chart");
715
- }
716
- // Calculate DaYun
717
- const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, normalized.gender, { startYear: normalized.year, endYear: normalized.year + 100 });
718
- // Get direction and start info
719
- const direction = LuckCycleCalculator_1.LuckCycleCalculator.calLuckySequence(normalized.gender, result.chart.year.stem) === 'forward' ? '顺行' : '逆行';
720
- const startAge = daYunList.length > 0 ? daYunList[0].startAge : 1;
721
- const startYear = normalized.year + startAge - 1;
722
- const options = {
723
- name: normalized.name,
724
- birthYear: normalized.year,
725
- birthMonth: normalized.month,
726
- birthDay: normalized.day,
727
- birthHour: normalized.hour,
728
- birthMinute: normalized.minute,
729
- gender: normalized.gender,
730
- dayMaster: result.chart.day.stem,
731
- yearPillar: { stem: result.chart.year.stem, branch: result.chart.year.branch },
732
- monthPillar: { stem: result.chart.month.stem, branch: result.chart.month.branch },
733
- dayPillar: { stem: result.chart.day.stem, branch: result.chart.day.branch },
734
- hourPillar: { stem: result.chart.hour.stem, branch: result.chart.hour.branch },
735
- direction,
736
- startAge,
737
- startYear,
738
- };
739
- const text = (0, listTextRenderer_1.renderBaziDaYunList)(daYunList.slice(0, validated.count), options);
740
- return { content: [{ type: "text", text }] };
741
- }
742
- if (name === "bazi_liunian") {
743
- const validated = BaziLiuNianListSchema.parse(args);
744
- const normalized = normalizeBirthInfo(validated);
745
- // Calculate BaZi chart first
746
- const result = await baziService.calculate({
747
- year: normalized.year,
748
- month: normalized.month,
749
- day: normalized.day,
750
- hour: normalized.hour,
751
- minute: normalized.minute,
752
- gender: normalized.gender,
753
- longitude: normalized.longitude,
754
- });
755
- if (!result.chart || !result.birthInfo) {
756
- throw new Error("Failed to calculate BaZi chart");
757
- }
758
- // Calculate DaYun list to match each LiuNian to its DaYun
759
- const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, normalized.gender, { startYear: normalized.year, endYear: normalized.year + 100 });
760
- // Calculate LiuNian for the range
761
- const liuNianList = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, normalized.year, validated.startYear, validated.endYear);
762
- const options = {
763
- name: normalized.name,
764
- birthYear: normalized.year,
765
- birthMonth: normalized.month,
766
- birthDay: normalized.day,
767
- birthHour: normalized.hour,
768
- birthMinute: normalized.minute,
769
- gender: normalized.gender,
770
- dayMaster: result.chart.day.stem,
771
- yearPillar: { stem: result.chart.year.stem, branch: result.chart.year.branch },
772
- monthPillar: { stem: result.chart.month.stem, branch: result.chart.month.branch },
773
- dayPillar: { stem: result.chart.day.stem, branch: result.chart.day.branch },
774
- hourPillar: { stem: result.chart.hour.stem, branch: result.chart.hour.branch },
775
- startYear: validated.startYear,
776
- endYear: validated.endYear,
777
- daYunList,
778
- };
779
- const text = (0, listTextRenderer_1.renderBaziLiuNianList)(liuNianList, options);
780
- return { content: [{ type: "text", text }] };
781
- }
782
- if (name === "bazi_liuyue") {
783
- const validated = BaziLiuYueListSchema.parse(args);
784
- const normalized = normalizeBirthInfo(validated);
785
- const { year: gregorianYear, ganzhi: ganzhiYear } = parseGanzhiYear(validated.ganzhiYear);
786
- // Calculate BaZi chart first
787
- const result = await baziService.calculate({
788
- year: normalized.year,
789
- month: normalized.month,
790
- day: normalized.day,
791
- hour: normalized.hour,
792
- minute: normalized.minute,
793
- gender: normalized.gender,
794
- longitude: normalized.longitude,
795
- });
796
- if (!result.chart || !result.birthInfo) {
797
- throw new Error("Failed to calculate BaZi chart");
798
- }
799
- // Get year stem and branch
800
- const { stem: yearStem, branch: yearBranch } = getYearStemBranch(gregorianYear);
801
- // Calculate DaYun list to find current DaYun
802
- const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, normalized.gender, { startYear: normalized.year, endYear: normalized.year + 100 });
803
- // Calculate age for the target year (虛歲)
804
- const targetAge = gregorianYear - normalized.year + 1;
805
- // Find current DaYun
806
- let currentDaYun;
807
- const matchedDaYun = daYunList.find(dy => targetAge >= dy.startAge && targetAge <= dy.endAge);
808
- if (matchedDaYun) {
809
- currentDaYun = {
810
- stem: matchedDaYun.stem,
811
- branch: matchedDaYun.branch,
812
- startAge: matchedDaYun.startAge,
813
- endAge: matchedDaYun.endAge,
814
- };
815
- }
816
- // Calculate current LiuNian
817
- const liuNianList = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, normalized.year, gregorianYear, gregorianYear);
818
- let currentLiuNian;
819
- if (liuNianList.length > 0) {
820
- const ln = liuNianList[0];
821
- currentLiuNian = {
822
- stem: ln.stem,
823
- branch: ln.branch,
824
- age: ln.age,
825
- };
826
- }
827
- // Calculate LiuYue
828
- const calculator = new LiuYueCalculator_1.LiuYueCalculator();
829
- const liuYueList = calculator.calculateLiuYue(yearStem, yearBranch, (result.basic?.dayMasterElement || '木'), (result.traditional?.yongShen?.yongShen || []), {
830
- year: normalized.year,
831
- month: normalized.month,
832
- day: normalized.day,
833
- hour: normalized.hour,
834
- minute: normalized.minute,
835
- }, gregorianYear);
836
- const options = {
837
- name: normalized.name,
838
- birthYear: normalized.year,
839
- birthMonth: normalized.month,
840
- birthDay: normalized.day,
841
- birthHour: normalized.hour,
842
- birthMinute: normalized.minute,
843
- gender: normalized.gender,
844
- dayMaster: result.chart.day.stem,
845
- yearPillar: { stem: result.chart.year.stem, branch: result.chart.year.branch },
846
- monthPillar: { stem: result.chart.month.stem, branch: result.chart.month.branch },
847
- dayPillar: { stem: result.chart.day.stem, branch: result.chart.day.branch },
848
- hourPillar: { stem: result.chart.hour.stem, branch: result.chart.hour.branch },
849
- ganzhiYear,
850
- gregorianYear,
851
- currentDaYun,
852
- currentLiuNian,
853
- };
854
- const text = (0, listTextRenderer_1.renderBaziLiuYueList)(liuYueList, options);
855
- return { content: [{ type: "text", text }] };
856
- }
857
- if (name === "bazi_liuri") {
858
- const validated = BaziLiuRiListSchema.parse(args);
859
- const normalized = normalizeBirthInfo(validated);
860
- const { year: gregorianYear, ganzhi: ganzhiYear } = parseGanzhiYear(validated.ganzhiYear);
861
- const monthNum = parseGanzhiMonth(validated.ganzhiMonth);
862
- // Calculate BaZi chart first
863
- const result = await baziService.calculate({
864
- year: normalized.year,
865
- month: normalized.month,
866
- day: normalized.day,
867
- hour: normalized.hour,
868
- minute: normalized.minute,
869
- gender: normalized.gender,
870
- longitude: normalized.longitude,
871
- });
872
- if (!result.chart || !result.birthInfo) {
873
- throw new Error("Failed to calculate BaZi chart");
874
- }
875
- // Get year and month stem/branch
876
- const { stem: yearStem, branch: yearBranch } = getYearStemBranch(gregorianYear);
877
- const { stem: monthStem, branch: monthBranch } = getMonthStemBranch(gregorianYear, monthNum);
878
- // Calculate DaYun list to find current DaYun
879
- const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, normalized.gender, { startYear: normalized.year, endYear: normalized.year + 100 });
880
- // Calculate age for the target year (虛歲)
881
- const targetAge = gregorianYear - normalized.year + 1;
882
- // Find current DaYun
883
- let currentDaYun;
884
- const matchedDaYun = daYunList.find(dy => targetAge >= dy.startAge && targetAge <= dy.endAge);
885
- if (matchedDaYun) {
886
- currentDaYun = {
887
- stem: matchedDaYun.stem,
888
- branch: matchedDaYun.branch,
889
- startAge: matchedDaYun.startAge,
890
- endAge: matchedDaYun.endAge,
891
- };
892
- }
893
- // Calculate current LiuNian
894
- const liuNianList = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, normalized.year, gregorianYear, gregorianYear);
895
- let currentLiuNian;
896
- if (liuNianList.length > 0) {
897
- const ln = liuNianList[0];
898
- currentLiuNian = {
899
- stem: ln.stem,
900
- branch: ln.branch,
901
- age: ln.age,
902
- };
903
- }
904
- // Current LiuYue info
905
- const currentLiuYue = {
906
- stem: monthStem,
907
- branch: monthBranch,
908
- month: monthNum,
909
- };
910
- // Calculate LiuRi
911
- const calculator = new LiuRiCalculator_1.LiuRiCalculator();
912
- const liuRiList = calculator.calculateLiuRi(monthStem, monthBranch, yearStem, yearBranch, (result.basic?.dayMasterElement || '木'), (result.traditional?.yongShen?.yongShen || []), gregorianYear, monthNum);
913
- // Get the first and last date from the calculated list
914
- const startDate = liuRiList.length > 0 ? liuRiList[0].date : new Date();
915
- const endDate = liuRiList.length > 0 ? liuRiList[liuRiList.length - 1].date : new Date();
916
- const options = {
917
- name: normalized.name,
918
- birthYear: normalized.year,
919
- birthMonth: normalized.month,
920
- birthDay: normalized.day,
921
- birthHour: normalized.hour,
922
- birthMinute: normalized.minute,
923
- gender: normalized.gender,
924
- dayMaster: result.chart.day.stem,
925
- yearPillar: { stem: result.chart.year.stem, branch: result.chart.year.branch },
926
- monthPillar: { stem: result.chart.month.stem, branch: result.chart.month.branch },
927
- dayPillar: { stem: result.chart.day.stem, branch: result.chart.day.branch },
928
- hourPillar: { stem: result.chart.hour.stem, branch: result.chart.hour.branch },
929
- ganzhiMonth: monthStem + monthBranch,
930
- ganzhiYear,
931
- gregorianYear,
932
- startDate,
933
- endDate,
934
- currentDaYun,
935
- currentLiuNian,
936
- currentLiuYue,
937
- };
938
- const text = (0, listTextRenderer_1.renderBaziLiuRiList)(liuRiList, options);
939
- return { content: [{ type: "text", text }] };
940
- }
941
- // === ZiWei List Tool Handlers ===
942
- if (name === "ziwei_daxian") {
943
- const validated = ZiweiDaXianListSchema.parse(args);
944
- const normalized = normalizeBirthInfo(validated);
945
- // Calculate ZiWei chart
946
- const result = ziweiService.calculate({
947
- year: normalized.year,
948
- month: normalized.month,
949
- day: normalized.day,
950
- hour: normalized.hour,
951
- gender: normalized.gender,
952
- });
953
- if (!result.decades || result.decades.length === 0) {
954
- throw new Error("Failed to calculate ZiWei decades");
955
- }
956
- // Determine direction
957
- const yangStems = ['甲', '丙', '戊', '庚', '壬'];
958
- const yearStem = result.basicInfo?.fourPillars?.year?.stem || '';
959
- const isYang = yangStems.includes(yearStem);
960
- const isMale = validated.gender === 'male';
961
- const direction = ((isYang && isMale) || (!isYang && !isMale)) ? '顺行' : '逆行';
962
- // Find Ming Gong stars
963
- const mingGongPalace = result.palaces?.find(p => p.name === '命宮' || p.name === '命宫' || p.name === 'Life');
964
- const mingGongStars = mingGongPalace?.majorStars?.map(s => typeof s === 'string' ? s : s.name) || [];
965
- // Find Shen Gong
966
- const shenGongPalace = result.palaces?.find(p => p.isBodyPalace);
967
- const shenGongStars = shenGongPalace?.majorStars?.map(s => typeof s === 'string' ? s : s.name) || [];
968
- const options = {
969
- name: normalized.name,
970
- birthYear: normalized.year,
971
- birthMonth: normalized.month,
972
- birthDay: normalized.day,
973
- birthHour: normalized.hour,
974
- birthMinute: normalized.minute,
975
- gender: normalized.gender,
976
- mingGong: mingGongPalace?.name || '命宮',
977
- mingGongStars,
978
- shenGong: shenGongPalace?.name,
979
- shenGongStars,
980
- palaces: result.palaces, // 传入完整宫位数据
981
- mutagenInfo: result.mutagenInfo, // 传入四化信息
982
- direction,
983
- };
984
- const text = (0, listTextRenderer_1.renderZiweiDaXianList)(result.decades.slice(0, validated.count), options);
985
- return { content: [{ type: "text", text }] };
986
- }
987
- if (name === "ziwei_xiaoxian") {
988
- const validated = ZiweiXiaoXianListSchema.parse(args);
989
- const normalized = normalizeBirthInfo(validated);
990
- const result = ziweiService.calculate({
991
- year: normalized.year,
992
- month: normalized.month,
993
- day: normalized.day,
994
- hour: normalized.hour,
995
- gender: normalized.gender,
996
- });
997
- if (!result.palaces) {
998
- throw new Error("Failed to calculate ZiWei chart");
999
- }
1000
- const minorLimitList = ziweiService.getMinorLimitRange(normalized.year, validated.startAge, validated.endAge);
1001
- const mingGongPalace = result.palaces?.find(p => p.name === '命宮' || p.name === '命宫' || p.name === 'Life');
1002
- const mingGongStars = mingGongPalace?.majorStars?.map(s => typeof s === 'string' ? s : s.name) || [];
1003
- const currentYear = new Date().getFullYear();
1004
- const currentAge = currentYear - normalized.year + 1;
1005
- let currentDecade;
1006
- if (result.decades && result.decades.length > 0) {
1007
- const matchedDecade = result.decades.find(d => currentAge >= d.startAge && currentAge <= d.endAge);
1008
- if (matchedDecade) {
1009
- currentDecade = {
1010
- palaceName: matchedDecade.palaceName || result.palaces?.[matchedDecade.palaceIndex]?.name || '未知',
1011
- startAge: matchedDecade.startAge,
1012
- endAge: matchedDecade.endAge,
1013
- };
1014
- }
1015
- }
1016
- const options = {
1017
- name: normalized.name,
1018
- birthYear: normalized.year,
1019
- birthMonth: normalized.month,
1020
- birthDay: normalized.day,
1021
- birthHour: normalized.hour,
1022
- birthMinute: normalized.minute,
1023
- gender: normalized.gender,
1024
- mingGong: mingGongPalace?.name || '命宮',
1025
- mingGongStars,
1026
- palaces: result.palaces,
1027
- mutagenInfo: result.mutagenInfo,
1028
- startAge: validated.startAge,
1029
- endAge: validated.endAge,
1030
- currentDecade,
1031
- decades: result.decades,
1032
- };
1033
- const text = (0, listTextRenderer_1.renderZiweiXiaoXianList)(minorLimitList, options);
1034
- return { content: [{ type: "text", text }] };
1035
- }
1036
- if (name === "ziwei_liunian") {
1037
- const validated = ZiweiLiuNianListSchema.parse(args);
1038
- const normalized = normalizeBirthInfo(validated);
1039
- // Calculate ZiWei chart
1040
- const result = ziweiService.calculate({
1041
- year: normalized.year,
1042
- month: normalized.month,
1043
- day: normalized.day,
1044
- hour: normalized.hour,
1045
- gender: normalized.gender,
1046
- });
1047
- if (!result.palaces) {
1048
- throw new Error("Failed to calculate ZiWei chart");
1049
- }
1050
- // Calculate yearly info for each year in the range
1051
- const yearlyList = [];
1052
- for (let year = validated.startYear; year <= validated.endYear; year++) {
1053
- const yearly = YearlyCalculator_1.YearlyCalculator.calculate(year, normalized.year, result.palaces);
1054
- if (yearly) {
1055
- yearlyList.push(yearly);
1056
- }
1057
- }
1058
- // Find Ming Gong
1059
- const mingGongPalace = result.palaces?.find(p => p.name === '命宮' || p.name === '命宫' || p.name === 'Life');
1060
- const mingGongStars = mingGongPalace?.majorStars?.map(s => typeof s === 'string' ? s : s.name) || [];
1061
- const options = {
1062
- name: normalized.name,
1063
- birthYear: normalized.year,
1064
- birthMonth: normalized.month,
1065
- birthDay: normalized.day,
1066
- birthHour: normalized.hour,
1067
- birthMinute: normalized.minute,
1068
- gender: normalized.gender,
1069
- mingGong: mingGongPalace?.name || '命宮',
1070
- mingGongStars,
1071
- palaces: result.palaces, // 传入完整宫位数据
1072
- mutagenInfo: result.mutagenInfo, // 传入四化信息
1073
- startYear: validated.startYear,
1074
- endYear: validated.endYear,
1075
- decades: result.decades, // 传入大限列表用于匹配所属大限
1076
- };
1077
- const text = (0, listTextRenderer_1.renderZiweiLiuNianList)(yearlyList, options);
1078
- return { content: [{ type: "text", text }] };
1079
- }
1080
- if (name === "ziwei_liuyue") {
1081
- const validated = ZiweiLiuYueListSchema.parse(args);
1082
- const normalized = normalizeBirthInfo(validated);
1083
- // Calculate ZiWei chart
1084
- const result = ziweiService.calculate({
1085
- year: normalized.year,
1086
- month: normalized.month,
1087
- day: normalized.day,
1088
- hour: normalized.hour,
1089
- gender: normalized.gender,
1090
- });
1091
- // Get yearly months (农历月)
1092
- const monthlyList = ziweiService.getYearlyMonths(validated.lunarYear);
1093
- // Find Ming Gong
1094
- const mingGongPalace = result.palaces?.find(p => p.name === '命宮' || p.name === '命宫' || p.name === 'Life');
1095
- const mingGongStars = mingGongPalace?.majorStars?.map(s => typeof s === 'string' ? s : s.name) || [];
1096
- // Check for leap month in this lunar year
1097
- const lunar = lunar_javascript_1.Lunar.fromYmd(validated.lunarYear, 1, 1);
1098
- const leapMonth = lunar.getYear() === validated.lunarYear ?
1099
- lunar_javascript_1.Lunar.fromYmd(validated.lunarYear, 6, 1).getLeapMonth?.() : undefined;
1100
- // Calculate age for the target year (虛歲)
1101
- const targetAge = validated.lunarYear - normalized.year + 1;
1102
- // Find current decade (大限)
1103
- let currentDecade;
1104
- if (result.decades && result.decades.length > 0) {
1105
- const matchedDecade = result.decades.find(d => targetAge >= d.startAge && targetAge <= d.endAge);
1106
- if (matchedDecade) {
1107
- currentDecade = {
1108
- palaceName: matchedDecade.palaceName || result.palaces?.[matchedDecade.palaceIndex]?.name || '未知',
1109
- startAge: matchedDecade.startAge,
1110
- endAge: matchedDecade.endAge,
1111
- };
1112
- }
1113
- }
1114
- // Calculate current yearly (流年)
1115
- const yearlyInfo = YearlyCalculator_1.YearlyCalculator.calculate(validated.lunarYear, normalized.year, result.palaces);
1116
- let currentYearly;
1117
- if (yearlyInfo) {
1118
- const { stem: yearStem, branch: yearBranch } = getYearStemBranch(validated.lunarYear);
1119
- currentYearly = {
1120
- year: validated.lunarYear,
1121
- age: targetAge,
1122
- palaceName: result.palaces?.[yearlyInfo.palaceIndex]?.name || '未知',
1123
- heavenlyStem: yearStem,
1124
- earthlyBranch: yearBranch,
1125
- };
1126
- }
1127
- // Calculate current minor limit (小限)
1128
- const minorLimitInfo = ziweiService.getMinorLimitInfo(normalized.year, validated.lunarYear);
1129
- let currentMinorLimit;
1130
- if (minorLimitInfo) {
1131
- currentMinorLimit = {
1132
- age: minorLimitInfo.age,
1133
- palaceName: result.palaces?.[minorLimitInfo.palaceIndex]?.name || '未知',
1134
- heavenlyStem: minorLimitInfo.heavenlyStem,
1135
- earthlyBranch: minorLimitInfo.earthlyBranch,
1136
- };
1137
- }
1138
- // 添加小限四化到 mutagenInfo
1139
- const enhancedMutagenInfo = { ...result.mutagenInfo };
1140
- if (minorLimitInfo?.heavenlyStem) {
1141
- enhancedMutagenInfo.minorLimit = MutagenCore_1.MutagenCore.getMutagen(minorLimitInfo.heavenlyStem) || undefined;
1142
- }
1143
- const options = {
1144
- name: normalized.name,
1145
- birthYear: normalized.year,
1146
- birthMonth: normalized.month,
1147
- birthDay: normalized.day,
1148
- birthHour: normalized.hour,
1149
- birthMinute: normalized.minute,
1150
- gender: normalized.gender,
1151
- mingGong: mingGongPalace?.name || '命宮',
1152
- mingGongStars,
1153
- palaces: result.palaces,
1154
- mutagenInfo: enhancedMutagenInfo,
1155
- lunarYear: validated.lunarYear,
1156
- gregorianYear: validated.lunarYear,
1157
- leapMonth: typeof leapMonth === 'number' ? leapMonth : undefined,
1158
- currentDecade,
1159
- currentMinorLimit,
1160
- currentYearly,
1161
- };
1162
- const text = (0, listTextRenderer_1.renderZiweiLiuYueList)(monthlyList, options);
1163
- return { content: [{ type: "text", text }] };
1164
- }
1165
- if (name === "ziwei_liuri") {
1166
- const validated = ZiweiLiuRiListSchema.parse(args);
1167
- const normalized = normalizeBirthInfo(validated);
1168
- // Calculate ZiWei chart
1169
- const result = ziweiService.calculate({
1170
- year: normalized.year,
1171
- month: normalized.month,
1172
- day: normalized.day,
1173
- hour: normalized.hour,
1174
- gender: normalized.gender,
1175
- });
1176
- // Handle leap month (negative number)
1177
- const isLeapMonth = validated.lunarMonth < 0;
1178
- const actualMonth = Math.abs(validated.lunarMonth);
1179
- // Get lunar month boundaries
1180
- const monthParam = isLeapMonth ? -actualMonth : actualMonth;
1181
- const lunarFirstDay = lunar_javascript_1.Lunar.fromYmd(validated.lunarYear, monthParam, 1);
1182
- // Find last day of the month
1183
- let lastDayNum = 29;
1184
- try {
1185
- lunar_javascript_1.Lunar.fromYmd(validated.lunarYear, monthParam, 30);
1186
- lastDayNum = 30;
1187
- }
1188
- catch {
1189
- // Month only has 29 days
1190
- }
1191
- const lunarLastDay = lunar_javascript_1.Lunar.fromYmd(validated.lunarYear, monthParam, lastDayNum);
1192
- // Convert to solar dates
1193
- const firstSolar = lunarFirstDay.getSolar();
1194
- const lastSolar = lunarLastDay.getSolar();
1195
- const startDate = new Date(firstSolar.getYear(), firstSolar.getMonth() - 1, firstSolar.getDay());
1196
- const endDate = new Date(lastSolar.getYear(), lastSolar.getMonth() - 1, lastSolar.getDay());
1197
- // Build daily list
1198
- const dailyList = [];
1199
- for (let day = 1; day <= lastDayNum; day++) {
1200
- try {
1201
- const lunarDay = lunar_javascript_1.Lunar.fromYmd(validated.lunarYear, monthParam, day);
1202
- const solarDay = lunarDay.getSolar();
1203
- const solarDate = new Date(solarDay.getYear(), solarDay.getMonth() - 1, solarDay.getDay());
1204
- // Get daily info from calculator
1205
- const dailyInfo = ziweiService.getDailyInfo(solarDay.getYear(), solarDay.getMonth(), solarDay.getDay());
1206
- dailyList.push({
1207
- lunarMonth: actualMonth,
1208
- lunarDay: day,
1209
- isLeapMonth,
1210
- gregorianDate: solarDate,
1211
- ganzhi: dailyInfo ? `${dailyInfo.heavenlyStem}${dailyInfo.earthlyBranch}` : '',
1212
- palaceIndex: dailyInfo?.palaceIndex || 0,
1213
- });
1214
- }
1215
- catch (e) {
1216
- // Skip invalid dates
1217
- }
1218
- }
1219
- // Find Ming Gong
1220
- const mingGongPalace = result.palaces?.find(p => p.name === '命宮' || p.name === '命宫' || p.name === 'Life');
1221
- const mingGongStars = mingGongPalace?.majorStars?.map(s => typeof s === 'string' ? s : s.name) || [];
1222
- // Get monthly palace
1223
- const monthlyInfo = ziweiService.getMonthlyInfo(validated.lunarYear, actualMonth - 1, actualMonth, isLeapMonth);
1224
- const monthlyPalace = monthlyInfo ? result.palaces?.[monthlyInfo.palaceIndex]?.name : undefined;
1225
- // Calculate age for the target year (虛歲)
1226
- const targetAge = validated.lunarYear - normalized.year + 1;
1227
- // Find current decade (大限)
1228
- let currentDecade;
1229
- if (result.decades && result.decades.length > 0) {
1230
- const matchedDecade = result.decades.find(d => targetAge >= d.startAge && targetAge <= d.endAge);
1231
- if (matchedDecade) {
1232
- currentDecade = {
1233
- palaceName: matchedDecade.palaceName || result.palaces?.[matchedDecade.palaceIndex]?.name || '未知',
1234
- startAge: matchedDecade.startAge,
1235
- endAge: matchedDecade.endAge,
1236
- };
1237
- }
1238
- }
1239
- // Calculate current yearly (流年)
1240
- const yearlyInfo = YearlyCalculator_1.YearlyCalculator.calculate(validated.lunarYear, normalized.year, result.palaces);
1241
- let currentYearly;
1242
- if (yearlyInfo) {
1243
- const { stem: yearStem, branch: yearBranch } = getYearStemBranch(validated.lunarYear);
1244
- currentYearly = {
1245
- year: validated.lunarYear,
1246
- age: targetAge,
1247
- palaceName: result.palaces?.[yearlyInfo.palaceIndex]?.name || '未知',
1248
- heavenlyStem: yearStem,
1249
- earthlyBranch: yearBranch,
1250
- };
1251
- }
1252
- // Current monthly info (流月)
1253
- let currentMonthly;
1254
- if (monthlyInfo) {
1255
- currentMonthly = {
1256
- month: actualMonth,
1257
- palaceName: result.palaces?.[monthlyInfo.palaceIndex]?.name || '未知',
1258
- heavenlyStem: monthlyInfo.heavenlyStem,
1259
- earthlyBranch: monthlyInfo.earthlyBranch,
1260
- };
1261
- }
1262
- // Calculate current minor limit (小限)
1263
- const minorLimitInfo = ziweiService.getMinorLimitInfo(normalized.year, validated.lunarYear);
1264
- let currentMinorLimit;
1265
- if (minorLimitInfo) {
1266
- currentMinorLimit = {
1267
- age: minorLimitInfo.age,
1268
- palaceName: result.palaces?.[minorLimitInfo.palaceIndex]?.name || '未知',
1269
- heavenlyStem: minorLimitInfo.heavenlyStem,
1270
- earthlyBranch: minorLimitInfo.earthlyBranch,
1271
- };
1272
- }
1273
- // 计算小限四化和流月四化
1274
- const enhancedMutagenInfo = { ...result.mutagenInfo };
1275
- if (minorLimitInfo?.heavenlyStem) {
1276
- enhancedMutagenInfo.minorLimit = MutagenCore_1.MutagenCore.getMutagen(minorLimitInfo.heavenlyStem) || undefined;
1277
- }
1278
- if (monthlyInfo?.heavenlyStem) {
1279
- enhancedMutagenInfo.monthly = MutagenCore_1.MutagenCore.getMutagen(monthlyInfo.heavenlyStem) || undefined;
1280
- }
1281
- const options = {
1282
- name: normalized.name,
1283
- birthYear: normalized.year,
1284
- birthMonth: normalized.month,
1285
- birthDay: normalized.day,
1286
- birthHour: normalized.hour,
1287
- birthMinute: normalized.minute,
1288
- gender: normalized.gender,
1289
- mingGong: mingGongPalace?.name || '命宮',
1290
- mingGongStars,
1291
- palaces: result.palaces,
1292
- mutagenInfo: enhancedMutagenInfo,
1293
- lunarYear: validated.lunarYear,
1294
- lunarMonth: actualMonth,
1295
- isLeapMonth,
1296
- gregorianStartDate: startDate,
1297
- gregorianEndDate: endDate,
1298
- monthlyPalace,
1299
- currentDecade,
1300
- currentMinorLimit,
1301
- currentYearly,
1302
- currentMonthly,
1303
- };
1304
- const text = (0, listTextRenderer_1.renderZiweiLiuRiList)(dailyList, options);
1305
- return { content: [{ type: "text", text }] };
1306
- }
1307
- throw new Error(`Unknown tool: ${name}`);
1308
- }
1309
- catch (error) {
1310
- logger.error(`Tool ${name} failed`, error);
1311
- const errorMessage = error instanceof Error ? error.message : String(error);
1312
- return {
1313
- content: [
1314
- {
1315
- type: "text",
1316
- text: `Error: ${errorMessage}`,
1317
- },
1318
- ],
1319
- isError: true,
1320
- };
1321
- }
1322
- });
1323
- // ============================================
1324
- // Start Server
1325
- // ============================================
1326
28
  async function main() {
29
+ const server = (0, server_1.createMingpanServer)();
1327
30
  const transport = new stdio_js_1.StdioServerTransport();
1328
31
  await server.connect(transport);
1329
- logger.info("Mingpan MCP server started (v0.1.2)");
32
+ logger.info(`Mingpan MCP server started (v${server_1.SERVER_VERSION})`);
1330
33
  }
1331
34
  main().catch((error) => {
1332
35
  logger.error("Server failed to start", error);