mingpan 0.1.1 → 0.1.2

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 (135) hide show
  1. package/README.md +53 -7
  2. package/dist/core/bazi/types.d.ts +0 -1
  3. package/dist/core/bazi/types.d.ts.map +1 -1
  4. package/dist/index.js +398 -164
  5. package/dist/index.js.map +1 -1
  6. package/dist/output/daliurenTextRenderer.d.ts +23 -0
  7. package/dist/output/daliurenTextRenderer.d.ts.map +1 -0
  8. package/dist/output/daliurenTextRenderer.js +109 -0
  9. package/dist/output/daliurenTextRenderer.js.map +1 -0
  10. package/dist/output/liuyaoTextRenderer.d.ts +12 -0
  11. package/dist/output/liuyaoTextRenderer.d.ts.map +1 -0
  12. package/dist/output/liuyaoTextRenderer.js +148 -0
  13. package/dist/output/liuyaoTextRenderer.js.map +1 -0
  14. package/dist/output/meihuaTextRenderer.d.ts +12 -0
  15. package/dist/output/meihuaTextRenderer.d.ts.map +1 -0
  16. package/dist/output/meihuaTextRenderer.js +53 -0
  17. package/dist/output/meihuaTextRenderer.js.map +1 -0
  18. package/dist/services/bazi/types.d.ts +0 -2
  19. package/dist/services/bazi/types.d.ts.map +1 -1
  20. package/dist/services/bazi/types.js.map +1 -1
  21. package/dist/services/daliuren/DaliurenService.d.ts +24 -0
  22. package/dist/services/daliuren/DaliurenService.d.ts.map +1 -0
  23. package/dist/services/daliuren/DaliurenService.js +67 -0
  24. package/dist/services/daliuren/DaliurenService.js.map +1 -0
  25. package/dist/services/daliuren/calculators/SanChuanCalculator.d.ts +87 -0
  26. package/dist/services/daliuren/calculators/SanChuanCalculator.d.ts.map +1 -0
  27. package/dist/services/daliuren/calculators/SanChuanCalculator.js +443 -0
  28. package/dist/services/daliuren/calculators/SanChuanCalculator.js.map +1 -0
  29. package/dist/services/daliuren/calculators/ShenShaCalculator.d.ts +33 -0
  30. package/dist/services/daliuren/calculators/ShenShaCalculator.d.ts.map +1 -0
  31. package/dist/services/daliuren/calculators/ShenShaCalculator.js +92 -0
  32. package/dist/services/daliuren/calculators/ShenShaCalculator.js.map +1 -0
  33. package/dist/services/daliuren/calculators/SiKeCalculator.d.ts +35 -0
  34. package/dist/services/daliuren/calculators/SiKeCalculator.d.ts.map +1 -0
  35. package/dist/services/daliuren/calculators/SiKeCalculator.js +121 -0
  36. package/dist/services/daliuren/calculators/SiKeCalculator.js.map +1 -0
  37. package/dist/services/daliuren/calculators/TianDiPanCalculator.d.ts +41 -0
  38. package/dist/services/daliuren/calculators/TianDiPanCalculator.d.ts.map +1 -0
  39. package/dist/services/daliuren/calculators/TianDiPanCalculator.js +138 -0
  40. package/dist/services/daliuren/calculators/TianDiPanCalculator.js.map +1 -0
  41. package/dist/services/daliuren/data/constants.d.ts +62 -0
  42. package/dist/services/daliuren/data/constants.d.ts.map +1 -0
  43. package/dist/services/daliuren/data/constants.js +240 -0
  44. package/dist/services/daliuren/data/constants.js.map +1 -0
  45. package/dist/services/daliuren/index.d.ts +11 -0
  46. package/dist/services/daliuren/index.d.ts.map +1 -0
  47. package/dist/services/daliuren/index.js +33 -0
  48. package/dist/services/daliuren/index.js.map +1 -0
  49. package/dist/services/daliuren/types.d.ts +152 -0
  50. package/dist/services/daliuren/types.d.ts.map +1 -0
  51. package/dist/services/daliuren/types.js +17 -0
  52. package/dist/services/daliuren/types.js.map +1 -0
  53. package/dist/services/liuyao/LiuyaoService.d.ts +37 -0
  54. package/dist/services/liuyao/LiuyaoService.d.ts.map +1 -0
  55. package/dist/services/liuyao/LiuyaoService.js +214 -0
  56. package/dist/services/liuyao/LiuyaoService.js.map +1 -0
  57. package/dist/services/liuyao/calculators/FushenCalculator.d.ts +40 -0
  58. package/dist/services/liuyao/calculators/FushenCalculator.d.ts.map +1 -0
  59. package/dist/services/liuyao/calculators/FushenCalculator.js +124 -0
  60. package/dist/services/liuyao/calculators/FushenCalculator.js.map +1 -0
  61. package/dist/services/liuyao/calculators/JintuishenCalculator.d.ts +37 -0
  62. package/dist/services/liuyao/calculators/JintuishenCalculator.d.ts.map +1 -0
  63. package/dist/services/liuyao/calculators/JintuishenCalculator.js +86 -0
  64. package/dist/services/liuyao/calculators/JintuishenCalculator.js.map +1 -0
  65. package/dist/services/liuyao/calculators/LiuqinCalculator.d.ts +24 -0
  66. package/dist/services/liuyao/calculators/LiuqinCalculator.d.ts.map +1 -0
  67. package/dist/services/liuyao/calculators/LiuqinCalculator.js +75 -0
  68. package/dist/services/liuyao/calculators/LiuqinCalculator.js.map +1 -0
  69. package/dist/services/liuyao/calculators/LiushenCalculator.d.ts +29 -0
  70. package/dist/services/liuyao/calculators/LiushenCalculator.d.ts.map +1 -0
  71. package/dist/services/liuyao/calculators/LiushenCalculator.js +58 -0
  72. package/dist/services/liuyao/calculators/LiushenCalculator.js.map +1 -0
  73. package/dist/services/liuyao/calculators/NajiaCalculator.d.ts +55 -0
  74. package/dist/services/liuyao/calculators/NajiaCalculator.d.ts.map +1 -0
  75. package/dist/services/liuyao/calculators/NajiaCalculator.js +87 -0
  76. package/dist/services/liuyao/calculators/NajiaCalculator.js.map +1 -0
  77. package/dist/services/liuyao/calculators/WangshuaiCalculator.d.ts +43 -0
  78. package/dist/services/liuyao/calculators/WangshuaiCalculator.d.ts.map +1 -0
  79. package/dist/services/liuyao/calculators/WangshuaiCalculator.js +100 -0
  80. package/dist/services/liuyao/calculators/WangshuaiCalculator.js.map +1 -0
  81. package/dist/services/liuyao/calculators/XunkongCalculator.d.ts +30 -0
  82. package/dist/services/liuyao/calculators/XunkongCalculator.d.ts.map +1 -0
  83. package/dist/services/liuyao/calculators/XunkongCalculator.js +58 -0
  84. package/dist/services/liuyao/calculators/XunkongCalculator.js.map +1 -0
  85. package/dist/services/liuyao/data/guagong.d.ts +94 -0
  86. package/dist/services/liuyao/data/guagong.d.ts.map +1 -0
  87. package/dist/services/liuyao/data/guagong.js +317 -0
  88. package/dist/services/liuyao/data/guagong.js.map +1 -0
  89. package/dist/services/liuyao/index.d.ts +13 -0
  90. package/dist/services/liuyao/index.d.ts.map +1 -0
  91. package/dist/services/liuyao/index.js +29 -0
  92. package/dist/services/liuyao/index.js.map +1 -0
  93. package/dist/services/liuyao/types.d.ts +154 -0
  94. package/dist/services/liuyao/types.d.ts.map +1 -0
  95. package/dist/services/liuyao/types.js +11 -0
  96. package/dist/services/liuyao/types.js.map +1 -0
  97. package/dist/services/meihua/MeihuaService.d.ts +32 -0
  98. package/dist/services/meihua/MeihuaService.d.ts.map +1 -0
  99. package/dist/services/meihua/MeihuaService.js +176 -0
  100. package/dist/services/meihua/MeihuaService.js.map +1 -0
  101. package/dist/services/meihua/calculators/BianguaCalculator.d.ts +21 -0
  102. package/dist/services/meihua/calculators/BianguaCalculator.d.ts.map +1 -0
  103. package/dist/services/meihua/calculators/BianguaCalculator.js +46 -0
  104. package/dist/services/meihua/calculators/BianguaCalculator.js.map +1 -0
  105. package/dist/services/meihua/calculators/HuguaCalculator.d.ts +22 -0
  106. package/dist/services/meihua/calculators/HuguaCalculator.d.ts.map +1 -0
  107. package/dist/services/meihua/calculators/HuguaCalculator.js +46 -0
  108. package/dist/services/meihua/calculators/HuguaCalculator.js.map +1 -0
  109. package/dist/services/meihua/calculators/QiguaCalculator.d.ts +40 -0
  110. package/dist/services/meihua/calculators/QiguaCalculator.d.ts.map +1 -0
  111. package/dist/services/meihua/calculators/QiguaCalculator.js +105 -0
  112. package/dist/services/meihua/calculators/QiguaCalculator.js.map +1 -0
  113. package/dist/services/meihua/calculators/TiyongCalculator.d.ts +34 -0
  114. package/dist/services/meihua/calculators/TiyongCalculator.d.ts.map +1 -0
  115. package/dist/services/meihua/calculators/TiyongCalculator.js +105 -0
  116. package/dist/services/meihua/calculators/TiyongCalculator.js.map +1 -0
  117. package/dist/services/meihua/data/bagua.d.ts +19 -0
  118. package/dist/services/meihua/data/bagua.d.ts.map +1 -0
  119. package/dist/services/meihua/data/bagua.js +81 -0
  120. package/dist/services/meihua/data/bagua.js.map +1 -0
  121. package/dist/services/meihua/index.d.ts +11 -0
  122. package/dist/services/meihua/index.d.ts.map +1 -0
  123. package/dist/services/meihua/index.js +27 -0
  124. package/dist/services/meihua/index.js.map +1 -0
  125. package/dist/services/meihua/types.d.ts +95 -0
  126. package/dist/services/meihua/types.d.ts.map +1 -0
  127. package/dist/services/meihua/types.js +6 -0
  128. package/dist/services/meihua/types.js.map +1 -0
  129. package/dist/shared/types.d.ts +0 -1
  130. package/dist/shared/types.d.ts.map +1 -1
  131. package/dist/utils/timeNormalization.d.ts +48 -0
  132. package/dist/utils/timeNormalization.d.ts.map +1 -0
  133. package/dist/utils/timeNormalization.js +69 -0
  134. package/dist/utils/timeNormalization.js.map +1 -0
  135. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -17,8 +17,15 @@ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
17
17
  const zod_1 = require("zod");
18
18
  const zod_to_json_schema_1 = require("zod-to-json-schema");
19
19
  const lunar_javascript_1 = require("lunar-javascript");
20
+ const timeNormalization_1 = require("./utils/timeNormalization");
20
21
  const BaziService_1 = require("./services/bazi/BaziService");
21
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");
22
29
  const LiuNianCalculator_1 = require("./services/bazi/calculators/LiuNianCalculator");
23
30
  const DaYunCalculator_1 = require("./services/bazi/calculators/DaYunCalculator");
24
31
  const LuckCycleCalculator_1 = require("./services/bazi/calculators/LuckCycleCalculator");
@@ -30,6 +37,14 @@ const listTextRenderer_1 = require("./output/listTextRenderer");
30
37
  const logger_1 = require("./shared/logger");
31
38
  const MutagenCore_1 = require("./core/ziwei/MutagenCore");
32
39
  const logger = new logger_1.Logger("mingpan");
40
+ // ============================================
41
+ // Timezone Configuration
42
+ // ============================================
43
+ // Force deterministic timezone behavior (Beijing Time) across environments.
44
+ // This ensures lunar-javascript and Date operations behave consistently
45
+ // regardless of the host machine's timezone setting.
46
+ // TODO: Remove when multi-timezone support is implemented (M4 milestone)
47
+ process.env.TZ = timeNormalization_1.BEIJING_TZ;
33
48
  // Helper to avoid TypeScript's excessively deep type instantiation error
34
49
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
50
  function schemaToJson(schema) {
@@ -38,6 +53,8 @@ function schemaToJson(schema) {
38
53
  // ============================================
39
54
  // Zod Schemas for Tool Inputs
40
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.");
41
58
  // Base birth info schema
42
59
  const BaseBirthInfoSchema = zod_1.z.object({
43
60
  year: zod_1.z.number().int().min(1900).max(2100).describe("Birth year (e.g., 1990)"),
@@ -47,8 +64,33 @@ const BaseBirthInfoSchema = zod_1.z.object({
47
64
  minute: zod_1.z.number().int().min(0).max(59).optional().default(0).describe("Birth minute (0-59)"),
48
65
  gender: zod_1.z.enum(["male", "female"]).describe("Gender for fortune direction calculation"),
49
66
  longitude: zod_1.z.number().min(-180).max(180).optional().describe("Birth location longitude for true solar time adjustment"),
67
+ isLunar: isLunarField,
50
68
  name: zod_1.z.string().optional().describe("Subject name (optional)"),
51
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
+ }
52
94
  const BaziCalculateSchema = zod_1.z.object({
53
95
  year: zod_1.z.number().int().min(1900).max(2100).describe("Birth year (e.g., 1990)"),
54
96
  month: zod_1.z.number().int().min(1).max(12).describe("Birth month (1-12)"),
@@ -57,7 +99,7 @@ const BaziCalculateSchema = zod_1.z.object({
57
99
  minute: zod_1.z.number().int().min(0).max(59).optional().default(0).describe("Birth minute (0-59)"),
58
100
  gender: zod_1.z.enum(["male", "female"]).optional().default("male").describe("Gender for DaYun calculation direction"),
59
101
  longitude: zod_1.z.number().min(-180).max(180).optional().describe("Birth location longitude for true solar time adjustment"),
60
- isLunar: zod_1.z.boolean().optional().default(false).describe("Whether the birth date is in lunar calendar"),
102
+ isLunar: isLunarField,
61
103
  detail: zod_1.z.enum(["simple", "standard", "detailed"]).optional().default("standard").describe("Output detail level"),
62
104
  includeAnalysis: zod_1.z.boolean().optional().default(true).describe("Include strength and pattern analysis"),
63
105
  includeDaYun: zod_1.z.boolean().optional().default(true).describe("Include decade fortune (大運)"),
@@ -70,7 +112,7 @@ const ZiweiCalculateSchema = zod_1.z.object({
70
112
  hour: zod_1.z.number().int().min(0).max(23).describe("Birth hour in 24-hour format (0-23)"),
71
113
  minute: zod_1.z.number().int().min(0).max(59).optional().default(0).describe("Birth minute (0-59)"),
72
114
  gender: zod_1.z.enum(["male", "female"]).describe("Gender (required for ZiWei calculation)"),
73
- isLunar: zod_1.z.boolean().optional().default(false).describe("Whether the birth date is in lunar calendar"),
115
+ isLunar: isLunarField,
74
116
  detail: zod_1.z.enum(["simple", "standard", "detailed"]).optional().default("standard").describe("Output detail level"),
75
117
  targetYear: zod_1.z.number().int().optional().describe("Calculate yearly fortune for this specific year"),
76
118
  includeDecades: zod_1.z.boolean().optional().default(true).describe("Include decade fortune (大限)"),
@@ -84,12 +126,56 @@ const CombinedCalculateSchema = zod_1.z.object({
84
126
  minute: zod_1.z.number().int().min(0).max(59).optional().default(0).describe("Birth minute (0-59)"),
85
127
  gender: zod_1.z.enum(["male", "female"]).describe("Gender (required for both calculations)"),
86
128
  longitude: zod_1.z.number().min(-180).max(180).optional().describe("Birth location longitude for true solar time adjustment"),
87
- isLunar: zod_1.z.boolean().optional().default(false).describe("Whether the birth date is in lunar calendar"),
129
+ isLunar: isLunarField,
88
130
  detail: zod_1.z.enum(["simple", "standard", "detailed"]).optional().default("standard").describe("Output detail level"),
89
131
  targetYear: zod_1.z.number().int().optional().describe("Calculate yearly fortune for this specific year"),
90
132
  systems: zod_1.z.array(zod_1.z.enum(["bazi", "ziwei"])).optional().default(["bazi", "ziwei"]).describe("Which systems to calculate"),
91
133
  });
92
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
+ // ============================================
93
179
  // List Tool Schemas
94
180
  // ============================================
95
181
  // 八字大运列表
@@ -147,7 +233,7 @@ const ZiweiLiuRiListSchema = BaseBirthInfoSchema.extend({
147
233
  // ============================================
148
234
  const server = new index_js_1.Server({
149
235
  name: "mingpan",
150
- version: "0.1.1",
236
+ version: "0.1.2",
151
237
  }, {
152
238
  capabilities: {
153
239
  tools: {},
@@ -327,6 +413,75 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
327
413
  用于精细的日期选择。`,
328
414
  inputSchema: schemaToJson(ZiweiLiuRiListSchema),
329
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
+ },
330
485
  ],
331
486
  };
332
487
  });
@@ -335,6 +490,8 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
335
490
  // ============================================
336
491
  const baziService = new BaziService_1.BaziService({ debug: false });
337
492
  const ziweiService = new ZiweiService_1.ZiweiService();
493
+ const liuyaoService = new LiuyaoService_1.LiuyaoService();
494
+ const meihuaService = new MeihuaService_1.MeihuaService();
338
495
  // Helper: Calculate year stem and branch
339
496
  function getYearStemBranch(year) {
340
497
  const STEMS = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
@@ -407,20 +564,21 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
407
564
  // === Existing Chart Calculation Handlers ===
408
565
  if (name === "bazi_basic") {
409
566
  const validated = BaziCalculateSchema.parse(args);
567
+ const normalized = normalizeBirthInfo(validated);
410
568
  const result = await baziService.calculate({
411
- year: validated.year,
412
- month: validated.month,
413
- day: validated.day,
414
- hour: validated.hour,
415
- minute: validated.minute,
416
- gender: validated.gender,
417
- longitude: validated.longitude,
418
- useLunar: validated.isLunar,
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
419
577
  });
420
578
  // If targetYear is specified, calculate LiuNian
421
579
  let liuNianInfo = "";
422
580
  if (validated.targetYear && result.chart) {
423
- const liuNians = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, validated.year, validated.targetYear, validated.targetYear);
581
+ const liuNians = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, normalized.year, validated.targetYear, validated.targetYear);
424
582
  if (liuNians.length > 0) {
425
583
  const liunian = liuNians[0];
426
584
  liuNianInfo = `\n\n=== 流年 ${validated.targetYear} ===\n干支:${liunian.stem}${liunian.branch}`;
@@ -431,8 +589,8 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
431
589
  includePersonal: false,
432
590
  includeLocation: !!validated.longitude,
433
591
  };
434
- const birthDate = new Date(validated.year, validated.month - 1, validated.day, validated.hour, validated.minute);
435
- const text = (0, fortuneTextRenderer_1.renderBaziText)({ bazi: result, gender: validated.gender, birthDate }, options);
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);
436
594
  return {
437
595
  content: [
438
596
  {
@@ -444,21 +602,22 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
444
602
  }
445
603
  if (name === "ziwei_basic") {
446
604
  const validated = ZiweiCalculateSchema.parse(args);
605
+ const normalized = normalizeBirthInfo(validated);
447
606
  const result = await ziweiService.calculate({
448
- year: validated.year,
449
- month: validated.month,
450
- day: validated.day,
451
- hour: validated.hour,
452
- gender: validated.gender,
607
+ year: normalized.year,
608
+ month: normalized.month,
609
+ day: normalized.day,
610
+ hour: normalized.hour,
611
+ gender: normalized.gender,
453
612
  });
454
613
  const options = {
455
614
  detail: validated.detail,
456
615
  includePersonal: false,
457
616
  };
458
- const birthDate = new Date(validated.year, validated.month - 1, validated.day, validated.hour, validated.minute);
617
+ const birthDate = new Date(normalized.year, normalized.month - 1, normalized.day, normalized.hour, normalized.minute);
459
618
  const text = (0, fortuneTextRenderer_1.renderZiweiText)({
460
619
  ziwei: result,
461
- gender: validated.gender,
620
+ gender: normalized.gender,
462
621
  birthDate,
463
622
  mutagen: result.mutagenInfo // 傳入四化信息
464
623
  }, options);
@@ -471,36 +630,103 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
471
630
  ],
472
631
  };
473
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
+ }
474
699
  // === BaZi List Tool Handlers ===
475
700
  if (name === "bazi_dayun") {
476
701
  const validated = BaziDaYunListSchema.parse(args);
702
+ const normalized = normalizeBirthInfo(validated);
477
703
  // Calculate BaZi chart first
478
704
  const result = await baziService.calculate({
479
- year: validated.year,
480
- month: validated.month,
481
- day: validated.day,
482
- hour: validated.hour,
483
- minute: validated.minute,
484
- gender: validated.gender,
485
- longitude: validated.longitude,
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,
486
712
  });
487
713
  if (!result.chart || !result.birthInfo) {
488
714
  throw new Error("Failed to calculate BaZi chart");
489
715
  }
490
716
  // Calculate DaYun
491
- const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, validated.gender, { startYear: validated.year, endYear: validated.year + 100 });
717
+ const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, normalized.gender, { startYear: normalized.year, endYear: normalized.year + 100 });
492
718
  // Get direction and start info
493
- const direction = LuckCycleCalculator_1.LuckCycleCalculator.calLuckySequence(validated.gender, result.chart.year.stem) === 'forward' ? '顺行' : '逆行';
719
+ const direction = LuckCycleCalculator_1.LuckCycleCalculator.calLuckySequence(normalized.gender, result.chart.year.stem) === 'forward' ? '顺行' : '逆行';
494
720
  const startAge = daYunList.length > 0 ? daYunList[0].startAge : 1;
495
- const startYear = validated.year + startAge - 1;
721
+ const startYear = normalized.year + startAge - 1;
496
722
  const options = {
497
- name: validated.name,
498
- birthYear: validated.year,
499
- birthMonth: validated.month,
500
- birthDay: validated.day,
501
- birthHour: validated.hour,
502
- birthMinute: validated.minute,
503
- gender: validated.gender,
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,
504
730
  dayMaster: result.chart.day.stem,
505
731
  yearPillar: { stem: result.chart.year.stem, branch: result.chart.year.branch },
506
732
  monthPillar: { stem: result.chart.month.stem, branch: result.chart.month.branch },
@@ -515,31 +741,32 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
515
741
  }
516
742
  if (name === "bazi_liunian") {
517
743
  const validated = BaziLiuNianListSchema.parse(args);
744
+ const normalized = normalizeBirthInfo(validated);
518
745
  // Calculate BaZi chart first
519
746
  const result = await baziService.calculate({
520
- year: validated.year,
521
- month: validated.month,
522
- day: validated.day,
523
- hour: validated.hour,
524
- minute: validated.minute,
525
- gender: validated.gender,
526
- longitude: validated.longitude,
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,
527
754
  });
528
755
  if (!result.chart || !result.birthInfo) {
529
756
  throw new Error("Failed to calculate BaZi chart");
530
757
  }
531
758
  // Calculate DaYun list to match each LiuNian to its DaYun
532
- const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, validated.gender, { startYear: validated.year, endYear: validated.year + 100 });
759
+ const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, normalized.gender, { startYear: normalized.year, endYear: normalized.year + 100 });
533
760
  // Calculate LiuNian for the range
534
- const liuNianList = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, validated.year, validated.startYear, validated.endYear);
761
+ const liuNianList = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, normalized.year, validated.startYear, validated.endYear);
535
762
  const options = {
536
- name: validated.name,
537
- birthYear: validated.year,
538
- birthMonth: validated.month,
539
- birthDay: validated.day,
540
- birthHour: validated.hour,
541
- birthMinute: validated.minute,
542
- gender: validated.gender,
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,
543
770
  dayMaster: result.chart.day.stem,
544
771
  yearPillar: { stem: result.chart.year.stem, branch: result.chart.year.branch },
545
772
  monthPillar: { stem: result.chart.month.stem, branch: result.chart.month.branch },
@@ -554,16 +781,17 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
554
781
  }
555
782
  if (name === "bazi_liuyue") {
556
783
  const validated = BaziLiuYueListSchema.parse(args);
784
+ const normalized = normalizeBirthInfo(validated);
557
785
  const { year: gregorianYear, ganzhi: ganzhiYear } = parseGanzhiYear(validated.ganzhiYear);
558
786
  // Calculate BaZi chart first
559
787
  const result = await baziService.calculate({
560
- year: validated.year,
561
- month: validated.month,
562
- day: validated.day,
563
- hour: validated.hour,
564
- minute: validated.minute,
565
- gender: validated.gender,
566
- longitude: validated.longitude,
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,
567
795
  });
568
796
  if (!result.chart || !result.birthInfo) {
569
797
  throw new Error("Failed to calculate BaZi chart");
@@ -571,9 +799,9 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
571
799
  // Get year stem and branch
572
800
  const { stem: yearStem, branch: yearBranch } = getYearStemBranch(gregorianYear);
573
801
  // Calculate DaYun list to find current DaYun
574
- const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, validated.gender, { startYear: validated.year, endYear: validated.year + 100 });
802
+ const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, normalized.gender, { startYear: normalized.year, endYear: normalized.year + 100 });
575
803
  // Calculate age for the target year (虛歲)
576
- const targetAge = gregorianYear - validated.year + 1;
804
+ const targetAge = gregorianYear - normalized.year + 1;
577
805
  // Find current DaYun
578
806
  let currentDaYun;
579
807
  const matchedDaYun = daYunList.find(dy => targetAge >= dy.startAge && targetAge <= dy.endAge);
@@ -586,7 +814,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
586
814
  };
587
815
  }
588
816
  // Calculate current LiuNian
589
- const liuNianList = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, validated.year, gregorianYear, gregorianYear);
817
+ const liuNianList = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, normalized.year, gregorianYear, gregorianYear);
590
818
  let currentLiuNian;
591
819
  if (liuNianList.length > 0) {
592
820
  const ln = liuNianList[0];
@@ -599,20 +827,20 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
599
827
  // Calculate LiuYue
600
828
  const calculator = new LiuYueCalculator_1.LiuYueCalculator();
601
829
  const liuYueList = calculator.calculateLiuYue(yearStem, yearBranch, (result.basic?.dayMasterElement || '木'), (result.traditional?.yongShen?.yongShen || []), {
602
- year: validated.year,
603
- month: validated.month,
604
- day: validated.day,
605
- hour: validated.hour,
606
- minute: validated.minute,
830
+ year: normalized.year,
831
+ month: normalized.month,
832
+ day: normalized.day,
833
+ hour: normalized.hour,
834
+ minute: normalized.minute,
607
835
  }, gregorianYear);
608
836
  const options = {
609
- name: validated.name,
610
- birthYear: validated.year,
611
- birthMonth: validated.month,
612
- birthDay: validated.day,
613
- birthHour: validated.hour,
614
- birthMinute: validated.minute,
615
- gender: validated.gender,
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,
616
844
  dayMaster: result.chart.day.stem,
617
845
  yearPillar: { stem: result.chart.year.stem, branch: result.chart.year.branch },
618
846
  monthPillar: { stem: result.chart.month.stem, branch: result.chart.month.branch },
@@ -628,17 +856,18 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
628
856
  }
629
857
  if (name === "bazi_liuri") {
630
858
  const validated = BaziLiuRiListSchema.parse(args);
859
+ const normalized = normalizeBirthInfo(validated);
631
860
  const { year: gregorianYear, ganzhi: ganzhiYear } = parseGanzhiYear(validated.ganzhiYear);
632
861
  const monthNum = parseGanzhiMonth(validated.ganzhiMonth);
633
862
  // Calculate BaZi chart first
634
863
  const result = await baziService.calculate({
635
- year: validated.year,
636
- month: validated.month,
637
- day: validated.day,
638
- hour: validated.hour,
639
- minute: validated.minute,
640
- gender: validated.gender,
641
- longitude: validated.longitude,
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,
642
871
  });
643
872
  if (!result.chart || !result.birthInfo) {
644
873
  throw new Error("Failed to calculate BaZi chart");
@@ -647,9 +876,9 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
647
876
  const { stem: yearStem, branch: yearBranch } = getYearStemBranch(gregorianYear);
648
877
  const { stem: monthStem, branch: monthBranch } = getMonthStemBranch(gregorianYear, monthNum);
649
878
  // Calculate DaYun list to find current DaYun
650
- const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, validated.gender, { startYear: validated.year, endYear: validated.year + 100 });
879
+ const daYunList = DaYunCalculator_1.DaYunCalculator.calculate(result.chart, result.birthInfo, normalized.gender, { startYear: normalized.year, endYear: normalized.year + 100 });
651
880
  // Calculate age for the target year (虛歲)
652
- const targetAge = gregorianYear - validated.year + 1;
881
+ const targetAge = gregorianYear - normalized.year + 1;
653
882
  // Find current DaYun
654
883
  let currentDaYun;
655
884
  const matchedDaYun = daYunList.find(dy => targetAge >= dy.startAge && targetAge <= dy.endAge);
@@ -662,7 +891,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
662
891
  };
663
892
  }
664
893
  // Calculate current LiuNian
665
- const liuNianList = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, validated.year, gregorianYear, gregorianYear);
894
+ const liuNianList = LiuNianCalculator_1.LiuNianCalculator.calculate(result.chart, normalized.year, gregorianYear, gregorianYear);
666
895
  let currentLiuNian;
667
896
  if (liuNianList.length > 0) {
668
897
  const ln = liuNianList[0];
@@ -685,13 +914,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
685
914
  const startDate = liuRiList.length > 0 ? liuRiList[0].date : new Date();
686
915
  const endDate = liuRiList.length > 0 ? liuRiList[liuRiList.length - 1].date : new Date();
687
916
  const options = {
688
- name: validated.name,
689
- birthYear: validated.year,
690
- birthMonth: validated.month,
691
- birthDay: validated.day,
692
- birthHour: validated.hour,
693
- birthMinute: validated.minute,
694
- gender: validated.gender,
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,
695
924
  dayMaster: result.chart.day.stem,
696
925
  yearPillar: { stem: result.chart.year.stem, branch: result.chart.year.branch },
697
926
  monthPillar: { stem: result.chart.month.stem, branch: result.chart.month.branch },
@@ -712,13 +941,14 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
712
941
  // === ZiWei List Tool Handlers ===
713
942
  if (name === "ziwei_daxian") {
714
943
  const validated = ZiweiDaXianListSchema.parse(args);
944
+ const normalized = normalizeBirthInfo(validated);
715
945
  // Calculate ZiWei chart
716
946
  const result = ziweiService.calculate({
717
- year: validated.year,
718
- month: validated.month,
719
- day: validated.day,
720
- hour: validated.hour,
721
- gender: validated.gender,
947
+ year: normalized.year,
948
+ month: normalized.month,
949
+ day: normalized.day,
950
+ hour: normalized.hour,
951
+ gender: normalized.gender,
722
952
  });
723
953
  if (!result.decades || result.decades.length === 0) {
724
954
  throw new Error("Failed to calculate ZiWei decades");
@@ -736,13 +966,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
736
966
  const shenGongPalace = result.palaces?.find(p => p.isBodyPalace);
737
967
  const shenGongStars = shenGongPalace?.majorStars?.map(s => typeof s === 'string' ? s : s.name) || [];
738
968
  const options = {
739
- name: validated.name,
740
- birthYear: validated.year,
741
- birthMonth: validated.month,
742
- birthDay: validated.day,
743
- birthHour: validated.hour,
744
- birthMinute: validated.minute,
745
- gender: validated.gender,
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,
746
976
  mingGong: mingGongPalace?.name || '命宮',
747
977
  mingGongStars,
748
978
  shenGong: shenGongPalace?.name,
@@ -756,21 +986,22 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
756
986
  }
757
987
  if (name === "ziwei_xiaoxian") {
758
988
  const validated = ZiweiXiaoXianListSchema.parse(args);
989
+ const normalized = normalizeBirthInfo(validated);
759
990
  const result = ziweiService.calculate({
760
- year: validated.year,
761
- month: validated.month,
762
- day: validated.day,
763
- hour: validated.hour,
764
- gender: validated.gender,
991
+ year: normalized.year,
992
+ month: normalized.month,
993
+ day: normalized.day,
994
+ hour: normalized.hour,
995
+ gender: normalized.gender,
765
996
  });
766
997
  if (!result.palaces) {
767
998
  throw new Error("Failed to calculate ZiWei chart");
768
999
  }
769
- const minorLimitList = ziweiService.getMinorLimitRange(validated.year, validated.startAge, validated.endAge);
1000
+ const minorLimitList = ziweiService.getMinorLimitRange(normalized.year, validated.startAge, validated.endAge);
770
1001
  const mingGongPalace = result.palaces?.find(p => p.name === '命宮' || p.name === '命宫' || p.name === 'Life');
771
1002
  const mingGongStars = mingGongPalace?.majorStars?.map(s => typeof s === 'string' ? s : s.name) || [];
772
1003
  const currentYear = new Date().getFullYear();
773
- const currentAge = currentYear - validated.year + 1;
1004
+ const currentAge = currentYear - normalized.year + 1;
774
1005
  let currentDecade;
775
1006
  if (result.decades && result.decades.length > 0) {
776
1007
  const matchedDecade = result.decades.find(d => currentAge >= d.startAge && currentAge <= d.endAge);
@@ -783,13 +1014,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
783
1014
  }
784
1015
  }
785
1016
  const options = {
786
- name: validated.name,
787
- birthYear: validated.year,
788
- birthMonth: validated.month,
789
- birthDay: validated.day,
790
- birthHour: validated.hour,
791
- birthMinute: validated.minute,
792
- gender: validated.gender,
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,
793
1024
  mingGong: mingGongPalace?.name || '命宮',
794
1025
  mingGongStars,
795
1026
  palaces: result.palaces,
@@ -804,13 +1035,14 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
804
1035
  }
805
1036
  if (name === "ziwei_liunian") {
806
1037
  const validated = ZiweiLiuNianListSchema.parse(args);
1038
+ const normalized = normalizeBirthInfo(validated);
807
1039
  // Calculate ZiWei chart
808
1040
  const result = ziweiService.calculate({
809
- year: validated.year,
810
- month: validated.month,
811
- day: validated.day,
812
- hour: validated.hour,
813
- gender: validated.gender,
1041
+ year: normalized.year,
1042
+ month: normalized.month,
1043
+ day: normalized.day,
1044
+ hour: normalized.hour,
1045
+ gender: normalized.gender,
814
1046
  });
815
1047
  if (!result.palaces) {
816
1048
  throw new Error("Failed to calculate ZiWei chart");
@@ -818,7 +1050,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
818
1050
  // Calculate yearly info for each year in the range
819
1051
  const yearlyList = [];
820
1052
  for (let year = validated.startYear; year <= validated.endYear; year++) {
821
- const yearly = YearlyCalculator_1.YearlyCalculator.calculate(year, validated.year, result.palaces);
1053
+ const yearly = YearlyCalculator_1.YearlyCalculator.calculate(year, normalized.year, result.palaces);
822
1054
  if (yearly) {
823
1055
  yearlyList.push(yearly);
824
1056
  }
@@ -827,13 +1059,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
827
1059
  const mingGongPalace = result.palaces?.find(p => p.name === '命宮' || p.name === '命宫' || p.name === 'Life');
828
1060
  const mingGongStars = mingGongPalace?.majorStars?.map(s => typeof s === 'string' ? s : s.name) || [];
829
1061
  const options = {
830
- name: validated.name,
831
- birthYear: validated.year,
832
- birthMonth: validated.month,
833
- birthDay: validated.day,
834
- birthHour: validated.hour,
835
- birthMinute: validated.minute,
836
- gender: validated.gender,
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,
837
1069
  mingGong: mingGongPalace?.name || '命宮',
838
1070
  mingGongStars,
839
1071
  palaces: result.palaces, // 传入完整宫位数据
@@ -847,13 +1079,14 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
847
1079
  }
848
1080
  if (name === "ziwei_liuyue") {
849
1081
  const validated = ZiweiLiuYueListSchema.parse(args);
1082
+ const normalized = normalizeBirthInfo(validated);
850
1083
  // Calculate ZiWei chart
851
1084
  const result = ziweiService.calculate({
852
- year: validated.year,
853
- month: validated.month,
854
- day: validated.day,
855
- hour: validated.hour,
856
- gender: validated.gender,
1085
+ year: normalized.year,
1086
+ month: normalized.month,
1087
+ day: normalized.day,
1088
+ hour: normalized.hour,
1089
+ gender: normalized.gender,
857
1090
  });
858
1091
  // Get yearly months (农历月)
859
1092
  const monthlyList = ziweiService.getYearlyMonths(validated.lunarYear);
@@ -865,7 +1098,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
865
1098
  const leapMonth = lunar.getYear() === validated.lunarYear ?
866
1099
  lunar_javascript_1.Lunar.fromYmd(validated.lunarYear, 6, 1).getLeapMonth?.() : undefined;
867
1100
  // Calculate age for the target year (虛歲)
868
- const targetAge = validated.lunarYear - validated.year + 1;
1101
+ const targetAge = validated.lunarYear - normalized.year + 1;
869
1102
  // Find current decade (大限)
870
1103
  let currentDecade;
871
1104
  if (result.decades && result.decades.length > 0) {
@@ -879,7 +1112,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
879
1112
  }
880
1113
  }
881
1114
  // Calculate current yearly (流年)
882
- const yearlyInfo = YearlyCalculator_1.YearlyCalculator.calculate(validated.lunarYear, validated.year, result.palaces);
1115
+ const yearlyInfo = YearlyCalculator_1.YearlyCalculator.calculate(validated.lunarYear, normalized.year, result.palaces);
883
1116
  let currentYearly;
884
1117
  if (yearlyInfo) {
885
1118
  const { stem: yearStem, branch: yearBranch } = getYearStemBranch(validated.lunarYear);
@@ -892,7 +1125,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
892
1125
  };
893
1126
  }
894
1127
  // Calculate current minor limit (小限)
895
- const minorLimitInfo = ziweiService.getMinorLimitInfo(validated.year, validated.lunarYear);
1128
+ const minorLimitInfo = ziweiService.getMinorLimitInfo(normalized.year, validated.lunarYear);
896
1129
  let currentMinorLimit;
897
1130
  if (minorLimitInfo) {
898
1131
  currentMinorLimit = {
@@ -908,13 +1141,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
908
1141
  enhancedMutagenInfo.minorLimit = MutagenCore_1.MutagenCore.getMutagen(minorLimitInfo.heavenlyStem) || undefined;
909
1142
  }
910
1143
  const options = {
911
- name: validated.name,
912
- birthYear: validated.year,
913
- birthMonth: validated.month,
914
- birthDay: validated.day,
915
- birthHour: validated.hour,
916
- birthMinute: validated.minute,
917
- gender: validated.gender,
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,
918
1151
  mingGong: mingGongPalace?.name || '命宮',
919
1152
  mingGongStars,
920
1153
  palaces: result.palaces,
@@ -931,13 +1164,14 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
931
1164
  }
932
1165
  if (name === "ziwei_liuri") {
933
1166
  const validated = ZiweiLiuRiListSchema.parse(args);
1167
+ const normalized = normalizeBirthInfo(validated);
934
1168
  // Calculate ZiWei chart
935
1169
  const result = ziweiService.calculate({
936
- year: validated.year,
937
- month: validated.month,
938
- day: validated.day,
939
- hour: validated.hour,
940
- gender: validated.gender,
1170
+ year: normalized.year,
1171
+ month: normalized.month,
1172
+ day: normalized.day,
1173
+ hour: normalized.hour,
1174
+ gender: normalized.gender,
941
1175
  });
942
1176
  // Handle leap month (negative number)
943
1177
  const isLeapMonth = validated.lunarMonth < 0;
@@ -989,7 +1223,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
989
1223
  const monthlyInfo = ziweiService.getMonthlyInfo(validated.lunarYear, actualMonth - 1, actualMonth, isLeapMonth);
990
1224
  const monthlyPalace = monthlyInfo ? result.palaces?.[monthlyInfo.palaceIndex]?.name : undefined;
991
1225
  // Calculate age for the target year (虛歲)
992
- const targetAge = validated.lunarYear - validated.year + 1;
1226
+ const targetAge = validated.lunarYear - normalized.year + 1;
993
1227
  // Find current decade (大限)
994
1228
  let currentDecade;
995
1229
  if (result.decades && result.decades.length > 0) {
@@ -1003,7 +1237,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1003
1237
  }
1004
1238
  }
1005
1239
  // Calculate current yearly (流年)
1006
- const yearlyInfo = YearlyCalculator_1.YearlyCalculator.calculate(validated.lunarYear, validated.year, result.palaces);
1240
+ const yearlyInfo = YearlyCalculator_1.YearlyCalculator.calculate(validated.lunarYear, normalized.year, result.palaces);
1007
1241
  let currentYearly;
1008
1242
  if (yearlyInfo) {
1009
1243
  const { stem: yearStem, branch: yearBranch } = getYearStemBranch(validated.lunarYear);
@@ -1026,7 +1260,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1026
1260
  };
1027
1261
  }
1028
1262
  // Calculate current minor limit (小限)
1029
- const minorLimitInfo = ziweiService.getMinorLimitInfo(validated.year, validated.lunarYear);
1263
+ const minorLimitInfo = ziweiService.getMinorLimitInfo(normalized.year, validated.lunarYear);
1030
1264
  let currentMinorLimit;
1031
1265
  if (minorLimitInfo) {
1032
1266
  currentMinorLimit = {
@@ -1045,13 +1279,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1045
1279
  enhancedMutagenInfo.monthly = MutagenCore_1.MutagenCore.getMutagen(monthlyInfo.heavenlyStem) || undefined;
1046
1280
  }
1047
1281
  const options = {
1048
- name: validated.name,
1049
- birthYear: validated.year,
1050
- birthMonth: validated.month,
1051
- birthDay: validated.day,
1052
- birthHour: validated.hour,
1053
- birthMinute: validated.minute,
1054
- gender: validated.gender,
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,
1055
1289
  mingGong: mingGongPalace?.name || '命宮',
1056
1290
  mingGongStars,
1057
1291
  palaces: result.palaces,
@@ -1092,7 +1326,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1092
1326
  async function main() {
1093
1327
  const transport = new stdio_js_1.StdioServerTransport();
1094
1328
  await server.connect(transport);
1095
- logger.info("Mingpan MCP server started (v0.1.1)");
1329
+ logger.info("Mingpan MCP server started (v0.1.2)");
1096
1330
  }
1097
1331
  main().catch((error) => {
1098
1332
  logger.error("Server failed to start", error);