destiny-telling
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
destiny-telling
給 AI agent 與本機程式使用的北派紫微、八字、疊宮及雙向交叉計算。只提供數值與結構資料,以及本機 stdio MCP;不提供模型 API 呼叫、HTTP 服務、外部 KB 存取、預測解讀文章或資料持久化。計算期間不需 API key,也不會把輸入送往遠端。
結果為傾向非定論、不構成醫療法律投資建議
解讀知識庫是另一個私有服務(destinytelling.life),不在本 repo
上面兩句是範圍與免責聲明,不是解讀知識庫。本專案不產生吉凶評分、投資指令或醫療法律判斷。
安裝與執行範圍
預定 GitHub 來源是 cph0512/destiny-telling。以下安裝指令適用於該 repository 已建立、且呼叫者有讀取權限時;本文件不宣稱遠端已建立、已公開或已發布至 npm。
git clone https://github.com/cph0512/destiny-telling.git
cd destiny-telling
npm ci --ignore-scriptspackage.json要求 Node>=25.9.0;目前實測的 runtime 是 Nodev25.9.0,沒有第二個 Node 版本或其他作業系統的相容性測試結論。專案是 ESM,root entry 為
index.js;不需 build。private: true刻意防止npm publish,與 GitHub repository 的 PRIVATE/PUBLIC 可見性無關。不要把套件名稱當作 npm 已發布的證據。MCP 已實測直接執行
node /absolute/path/destiny-telling/mcp/server.js,以及測試擁有的destiny-telling-mcpsymlink(透過 Node 與可執行 shebang 兩種啟動)。這是入口回歸測試,尚未驗證真正 npm 安裝後的 bin。stdio server 由 client 啟動為子程序;stdout 保留給 JSON-RPC,不能在該程序插入一般 log。它不是 HTTP endpoint,不監聽網路 port。
Related MCP server: 命盘 Mingpan
Claude / Cursor 的本機 stdio 設定
下列各是一份 mcpServers JSON 設定片段,不是已替你安裝到 client 的設定,也不宣稱任何特定 client 版本已實測。將 /absolute/path/destiny-telling 換成自己的 checkout 絕對路徑;若 client 的 PATH 找不到 node,將 command 換成自己的 Node 執行檔絕對路徑。不要把兩者當成同一個路徑。
Claude:
{
"mcpServers": {
"destiny-telling": {
"command": "node",
"args": ["/absolute/path/destiny-telling/mcp/server.js"]
}
}
}Cursor:
{
"mcpServers": {
"destiny-telling": {
"command": "node",
"args": ["/absolute/path/destiny-telling/mcp/server.js"]
}
}
}將片段合併進自己 client 的 MCP 設定後,由該 client 啟動。server 不需要登入、金鑰或環境變數。MCP 只有下面五個工具,沒有 KB、儲存或模型工具。
輸入共通規則
所有 MCP 工具都接受一個 JSON object。root object 與 cross_sihua.a/b 均拒絕未知欄位(additionalProperties: false)。不要傳 id、姓名、時區或其他未列欄位。字串不會被轉成數字;不自動修正日期、取整數或轉換性別。省略與 null 不同;下表的 optional 欄位不能以 null 代替。
scope 與 levels 的跨欄位依存由 server refinement 執行,並寫在 descriptions 與下列表格;不要假設 tools/list 的 JSON Schema 已把所有條件編碼為 if/then。欄位出現在 properties 中不表示任何 scope 都能傳。
共用 Birth:
欄位 | 型別 / 驗證範圍 | 必填 | 省略時 |
| string,補零 | 是 | 無預設 |
| integer,0..23,出生當地民用小時 | 是 | 無預設 |
| integer,0..59,出生分鐘 | 否 | 0 |
| string,只接受 | 是 | 無預設 |
所有日期欄位均使用同一驗證:四位年份 0001..9999、月份 01..12、日數符合公曆閏年與該月天數,不接受時間尾碼或未補零日期。這是輸入驗證範圍,不是上游曆法在所有年份皆可計算的保證;上游不支援的計算可能被拒絕,或在原先允許的分支以 null 標明時間層缺失,不補造結果。實測覆蓋以後面的測試段落為準。
日期與小時不做時區、夏令時間或真太陽時校正。呼叫者須先決定要送入的民用日期與時間。hour/minute 是出生時分;targetHour/targetMinute 才是目標流時,不可互換。
出生分鐘會保留在正規化的 input,但上游紫微(含 overlay/cross)與 finance 不套用分鐘;八字將出生分鐘傳給 lunar-javascript。targetMinute 保留但上游流時不套用,不代表分鐘級精度。root daily 計算使用出生分鐘 0,並明列限制。
共通輸出 envelope
以下所有型別區塊都是 schema/shape 說明,不是執行結果,也不是可直接解析的 JSON。未提供任何臆造的數值輸出;後面的 JSON 範例均為合成輸入。
成功的 MCP tools/call result:
{
structuredContent: Envelope,
content: [{ type: "text", text: JSON.stringify(Envelope) }]
}structuredContent 與唯一 text 解碼後的 object 完全相等。成功不另加 isError: false。所有計算的 JSON companion 都回傳 envelope object,不是已序列化的字串。
Envelope = {
schema: "destiny-telling.calc/v1",
kind: string, // 見各工具 / root API 對照
input: object, // 正規化輸入,見各工具
referenceDate: DateString | null, // 不放在 input 裡冒充出生欄位
config: {
school: "north",
gengMutagens: ["太陽", "武曲", "天同", "天相"]
},
data: object, // 各工具專屬 schema
omitted: string[], // 明列未輸出的欄位路徑
limitations: string[] // 機器可讀限制碼
}DateString 是上述日期字串,S 是 string,N 是有限 number,I 是有限 integer;T[] 為陣列、Record<S,T> 為以字串作 key 的 object、? 表示該欄位可能不存在。這些符號只是文件型別記法,沒有隱藏欄位。
無效輸入回 isError: true 與 text content,不回 structuredContent。handler 計算例外的固定訊息是 Calculation rejected: invalid or unsupported input.;SDK 前置 schema 驗證的文字可能不同。不要依賴錯誤文字作 schema,亦不要把錯誤當作空盤。測試檢查錯誤不回顯整份輸入或合成出生日期,不代表已窮盡任意惡意字串。
共用資料型別(shape,非結果)
LocatedHua = { star: S, hua: S, zhi: S | null, gongName: S }
Effect = { star: S, hua: S, source: S }
ChartPeriod = {
ganZhi: S, sihua: S[], mingGongZhi: S,
dieBenGong: S, palaceNames: S[]
}
FinancePalace = { gan: S, zhi: S, stars: S[], minor: S[] }
FinanceTemporalPalace = FinancePalace & { dieBen: S }星名、宮名、干支、四化名稱及 detail/sourceLabel 等字串是計算標籤或事實列舉,不是解讀文章。原本本命四化的短標籤與各層標籤保留原行為,agent 不應自行把它們正規化後宣稱與原演算法相同。
五個 MCP 工具
1. ziwei_chart
輸入:Birth 全部欄位,加上:
欄位 | 型別 | 必填 | 省略時 |
| DateString | 否 | 執行時程序的實際本地日期 |
以該日期建立時間層;明確給定日期才能避免「今天」造成結果隨執行日變動。不是只替輸出加日期標籤。
合成輸入(fixture S1;fixture 的 id 不送入工具):
{"birthDate":"2001-03-07","hour":6,"minute":10,"gender":"女","referenceDate":"2026-10-24"}輸出:kind = "ziwei.chart",input = Birth(含補上的 minute),referenceDate 是實際使用日期,data = ZiweiChart:
ZiweiChart = {
basic: {
solarDate: S, lunarDate: S, yearGanZhi: S, shiChen: S,
gender: "男" | "女", yinYang: S, mingGong: S, mingGongZhi: S,
shenGong: S, commandStar: S, bodyStar: S, wuXingJu: S,
lunarMonth: I, shiChenIdx: I
},
gongs: Record<S, {
name: S, stars: S[], minor: S[], sihua: S[], changSheng: S
}>,
gongGan: Record<S,S>,
daXian: { zhi: S, startAge: N, endAge: N }[],
siHua: Record<S,S>,
feiHua: Record<S, { gan: S, sihua: S[] }>,
horoscope: null | {
decadal: ChartPeriod,
yearly: ChartPeriod,
age: { nominalAge: N, ganZhi: S, sihua: S[], dieBenGong: S }
}
}宮位 maps 以地支作 key,siHua 以星名作 key。上游無法取得時間層時 horoscope 為 null,不代表有可用流年資料。omitted = [];limitations = ["UPSTREAM_ZIWEI_BIRTH_MINUTE_NOT_APPLIED"]。
2. ziwei_overlay
輸入:Birth 全部欄位,加上:
欄位 | 型別 / 範圍 | 必填 / 可用條件 | 省略時 |
|
| 是 | 無預設 |
| DateString | 是,所有 scope 都需要 | 無預設 |
| integer,1..12,明確斗君月序 | 僅 | 其他 scope 不得傳 |
| integer,0..23 | 僅 | 不計算流時, |
| integer,0..59 | 僅 | 不送入目標分鐘;不影響上游結果 |
targetDate 會用來重建盤及決定參考年。year 算全部 1..12 斗君月;month 只選明確指定的斗君月。這個 month 不是 targetDate 的公曆月,也不會自動從公曆或農曆日期換算。year/month 不接受目標時分;day 不接受 month;此工具不接受額外 referenceDate。
三個 scope 的合成輸入(S2):
{"birthDate":"1990-11-02","hour":21,"minute":40,"gender":"男","scope":"year","targetDate":"2026-10-24"}{"birthDate":"1990-11-02","hour":21,"minute":40,"gender":"男","scope":"month","targetDate":"2026-10-24","month":6}{"birthDate":"1990-11-02","hour":21,"minute":40,"gender":"男","scope":"day","targetDate":"2026-10-24","targetHour":23,"targetMinute":59}year/month 輸出:kind = "ziwei.transit",input = {...Birth, months: I[]},分別是全部斗君序或單一選定序;envelope 不保留 scope,referenceDate = targetDate。
TransitData = {
decadal: OverlayPeriod,
yearly: OverlayPeriod,
monthly: Record<S, {
mingGongZhi: S, dieBenGong: S, gan: S | null,
effects: (Effect & { zhi: S, gongName: S })[]
}>,
palaceEffects: Record<S, {
gongName: S, stars: S[], natal: Effect[], decadal: Effect[],
yearly: Effect[], monthly: Record<S,Effect[]>
}>,
highlights: TransitHighlight[]
} | { result: null }
OverlayPeriod = {
ganZhi: S, mingGongZhi: S, dieBenGong: S, sihua: LocatedHua[]
}
TransitHighlight =
{ type: "雙祿" | "雙忌" | "祿忌同宮", zhi: S, gongName: S, detail: S }
| { type: "雙權", zhi: S, gongName: S }
| { type: "化忌沖", zhi: S, gongName: S, targetGong: S, detail: S }
| { type: "三祿疊" | "三忌疊", zhi: S, gongName: S, month: I, detail: S }monthly 的 keys 是所選斗君序的十進位字串,不是日期;palaceEffects 以地支作 key。{result:null} 表示原 overlay 無資料,不是已算出空白的全年。
highlights 是原條件的命中紀錄,不是新評分:雙類各為同類至少 2 筆、祿忌同宮各至少 1 筆;三類包含該斗君月後同類至少 3 筆;沖的對宮結構亦保留。原本本命短標籤的判斷行為未改,不能把紀錄數當作另外定義的機率或風險分數。
omitted = ["summary", "_lookup", "highlights[].impact", "highlights[type=雙權].detail"]limitations = ["UPSTREAM_ZIWEI_BIRTH_MINUTE_NOT_APPLIED", "MONTHS_ARE_DOUJUN_ORDER_NOT_CALENDAR_CONVERSION", "RAW_TARGET_YEAR_IS_LABEL_ONLY"]
day 輸出:kind = "ziwei.dayhour",input = {...Birth, targetDate, targetHour?, targetMinute?},只保留實際提供的目標時分,referenceDate = targetDate。
DayHourData = {
daily: { gan: S, zhi: S, ganZhi: S, sihua: LocatedHua[] },
hourly: null | {
gan: S | null, zhi: S, shichenIdx: I,
ganZhi: S | null, sihua: LocatedHua[]
},
highlights: {
type: "多祿疊" | "多忌疊" | "祿忌同宮", gongName: S, detail: S
}[]
} | { result: null }找不到星時保留 zhi: null 與事實標記 gongName: "(本命無此星)",不補造宮位。shichenIdx 為時辰索引,不是分鐘。
omitted = ["summary", "highlights[].impact"]limitations = ["UPSTREAM_ZIWEI_BIRTH_MINUTE_NOT_APPLIED", "UPSTREAM_TARGET_MINUTE_NOT_APPLIED"]
3. bazi_chart
輸入恰為 Birth:必填 birthDate/hour/gender,minute 可省略而為 0;不接受 referenceDate 或目標日期。
合成輸入(S1):
{"birthDate":"2001-03-07","hour":6,"minute":10,"gender":"女"}輸出:kind = "bazi.chart",input = Birth,referenceDate = null,omitted = [],limitations = []。
BaziData = {
solarDate: S, lunarDate: S, gender: "男" | "女", shiChen: S,
pillars: { year: Pillar, month: Pillar, day: Pillar, time: Pillar },
dayMaster: S, dayWuXing: S,
wuXing: { 金: I, 木: I, 水: I, 火: I, 土: I },
daYun: { ganZhi: S, startAge: N, startYear: N }[],
startAge: N, shengXiao: S
}
Pillar = {
ganZhi: S, naYin: S, shiShenGan: S, shiShenZhi: S[], hideGan: S[]
}空的 limitations 不是對曆法或命理有效性的全面保證,只表示這個 wrapper 沒有附加限制碼。
4. cross_sihua
欄位 | 型別 / 範圍 | 必填 / 可用條件 | 省略時 |
| strict | 是 | 無預設;內層 minute 仍預設 0 |
| strict | 是 | 無預設;內層 minute 仍預設 0 |
| DateString | 是 | 無預設;用同一天建立雙盤 |
| 下列 enum 的非空、無重複陣列,1..8 個 | 否 |
|
| integer,1..12,明確斗君月序 | 選 | 無自動換算 |
| DateString | 選 | 無預設 |
levels 的合法值及輸出 layer:natal → L1、palace → L2、decadal → L3、yearly → L4、pastDecadal → L3b、pastDecadal2 → L3c、monthly → L5、daily → L6。
referenceDate 選雙盤時間層及相對歷史大限;targetDate 只供選中的流日計算,不把雙盤參考日偷偷換成該日。month 同樣是斗君序,與 targetDate 月份無自動對應。pastDecadal/pastDecadal2 依原 daXian 陣列索引取得前一與前兩個位置,不重新排序;不存在的歷史大限不產生該層 flights,不報成計算錯誤,也不補造星曜。
合成輸入(S3/S4,八層包含 monthly/daily/前兩大限):
{
"a":{"birthDate":"1975-07-19","hour":0,"minute":20,"gender":"女"},
"b":{"birthDate":"1963-12-30","hour":23,"minute":30,"gender":"男"},
"referenceDate":"2026-10-24",
"levels":["natal","palace","decadal","yearly","pastDecadal","pastDecadal2","monthly","daily"],
"month":6,
"targetDate":"2026-10-25"
}輸出:kind = "cross.sihua",input = {a: Birth, b: Birth, levels: S[], month?, targetDate?},條件欄位只在所選層存在。referenceDate 為雙盤參考日。
CrossData = {
flights: { aToB: Flight[], bToA: Flight[] },
meta: { levels: S[], nameA: "甲方", nameB: "乙方" }
}
Flight = {
layer: "L1" | "L2" | "L3" | "L4" | "L3b" | "L3c" | "L5" | "L6",
layerLabel: S, sourceLabel: S,
fromPalace: S | null,
fromPalaceZhi?: S, fromGan?: S,
star: S, hua: S, toPalace: S, toPalaceZhi: S,
starKind: "major" | "minor"
}fromPalaceZhi/fromGan 只在 L2,且 L2 的 fromPalace 為字串;其他層 fromPalace 為 null。同一方向的執行順序固定為 L1、L2、L3、L4、L3b、L3c、L5、L6,與呼叫者排列 levels 的次序不同;meta.levels 保留選擇次序。JSON/MCP 不接受 nameA/nameB 或人物身分,固定使用甲方/乙方。
omitted = ["summary"]limitations = ["UPSTREAM_ZIWEI_BIRTH_MINUTE_NOT_APPLIED", "MONTHS_ARE_DOUJUN_ORDER_NOT_CALENDAR_CONVERSION", "MISSING_HISTORICAL_DECADES_PRODUCE_NO_FLIGHTS"]
5. finance_chart
輸入:Birth 全部欄位,加上 optional referenceDate: DateString;省略時取程序實際本地日期。沒有其他欄位或預設。出生分鐘只保留,不參與上游計算。
合成輸入(S2):
{"birthDate":"1990-11-02","hour":21,"minute":40,"gender":"男","referenceDate":"2026-10-24"}輸出:kind = "finance.chart",input = Birth,referenceDate 為實際使用日期:
FinanceData = {
basic: {
solarDate: S, lunarDate: S, chineseDate: S, gender: "男" | "女",
mingGong: S, shenGong: S, juName: S, yearSihua: Record<S,S>
},
benMing: Record<S,FinancePalace | null>,
keyFeiHua: Record<S,{ gan: S, sihua: S[] }>,
decadal: FinancePeriod,
yearly: FinancePeriod,
months: { month: I, ganZhi: S, sihua: S[], caiBo?: FinanceTemporalPalace }[],
age: { nominalAge: N, ganZhi: S, sihua: S[] }
}
FinancePeriod = {
ganZhi: S, sihua: S[], palaces: Record<S,FinanceTemporalPalace>
}本命/時間宮位 maps 以宮名作 key;yearSihua 以星名作 key。benMing 選取命宮、財帛、官祿、遷移、福德、田宅、子女、交友等原始宮位資料,不輸出投資建議。
注意:finance.data.months[].month 是原實作在參考年每個公曆月 15 日取樣的 1..12 索引,與 ziwei_overlay/cross_sihua 的輸入斗君序不是同一個介面。此工具沒有供呼叫者指定的 month 欄位;不要把取樣結果誤當全年每一天或自動換算後的斗君月。
omitted = [];limitations = ["UPSTREAM_FINANCE_HOUR_PRECISION_MINUTE_NOT_APPLIED"]。
Root ESM API
在 checkout 根目錄旁的 ESM 程式使用相對 import,或自行換成實際 module URL:
import {
calculateChartJson, calculateCrossSihuaJson,
calculateBaziJson, calculateFinanceJson, calculateDailyJson,
getMonthlySihuaStarsJson
} from './index.js';
const birth = { birthDate: '2001-03-07', hour: 6, minute: 10, gender: '女' };
const chart = calculateChartJson({ ...birth, referenceDate: '2026-10-24' });
const monthly = getMonthlySihuaStarsJson(chart.data, 6);
// chart 與 monthly 都是 envelope object;此範例沒有宣稱任何計算數值。以下列全計算函式與 JSON companions。y/m/d 是整數公曆日期組件;birth 指上述 strict Birth。建議跨程序傳輸都用 Json 版本;原 raw 簽章彼此時分/性別的參數次序不同,不能任意交換。
Raw / helper 簽章 | JSON companion 與輸入 | kind / data |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Raw 與 JSON 的差別
chart/finance 的 raw
options只接受referenceDate;省略取實際本地日期。JSON chart/finance 同義,其他 JSON 函式的必要日期不可省略。raw transit 的
targetYear只改 legacy 年份標籤,不重建盤、不重算流年。要換參考年必須重建 chart,或用要求referenceDate的 JSON companion。rawtargetMonths為斗君序選擇;JSONmonths預設全部 1..12,明傳須為非空、無重複的整數 1..12 陣列。raw transit 含
_lookup函式,不能當純 JSON 傳輸;JSON 版明列省略_lookup/summary等欄位。不要用JSON.stringify(raw)靜默吞函式後冒充完整資料。raw day/hour 的目標 minute 不參與上游計算。JSON 版另驗證日期及目標時分依存,不接受只有
targetMinute。raw cross 的 opts 可帶
levels、nameA/nameB(預設甲方/乙方),以及pastDecadalSihua/pastDecadal2Sihua/monthlySihua/dailySihua(各為{a,b}星名陣列或缺資料)及相對應的pastDecadalLabel/pastDecadal2Label/monthlyLabel/dailyLabel。raw 不會替這些 extras 計算時間層;JSON 版改從雙盤及日期呼叫原 helpers,且不接受 caller labels 或姓名。raw helpers 保留原邊界/null 行為;JSON companions 才驗證 month 整數 1..12、日期及 offset 整數。offset 不保證有對應大限,超出資料範圍為
null。三個 helper 的input分別為{chart,month}、{chart,targetDate}、{chart,offset};都不知道 chart 建立時的參考日,因此 envelopereferenceDate: null,limitations含CHART_REFERENCE_DATE_UNKNOWN。每日 helper 的目標日不冒充 chart 參考日。monthly helper 另有
MONTHS_ARE_DOUJUN_ORDER_NOT_CALENDAR_CONVERSION;decadal helper 另有MISSING_DECADAL_GAN_NORMALIZED_TO_NULL,僅將缺失的gan: undefined明確改成null。它們omitted均為空陣列。helpers 的原始陣列/null 放在
data.stars或data.result內;不直接以陣列/null 冒充 envelope。DecadalResult = {stars: S[] | null, gan: S | null, zhi: S, startAge: N, endAge: N}。所有 JSON 輸出先做 lossless JSON 驗證,不以序列化刪除 unsupported values 作為修正。
TianGan 參考盤
calculateChartByTianGanJson 只接受必填 birthDate/gender,不接受 hour/minute。使用上游 index 0 的參考盤,不是未知時辰的推定結果,也不是「已知出生時間」盤;不能據此宣稱主星/宮位不受時辰影響。
kind = "ziwei.tiangan"
input = { birthDate: DateString, gender: "男" | "女" }
referenceDate = null
data = {
solarDate: S, lunarDate: S, yearGanZhi: S, yearGan: S,
gender: "男" | "女", referenceShiChenIdx: 0, yearSiHua: S[],
starMap: Record<S,{gan: S, stars: S[]}>,
feiHua: Record<S,{gan: S, sihua: S[]}>
}
omitted = []
limitations = ["INDEX0_REFERENCE_CHART_NOT_KNOWN_BIRTHTIME"]Root daily(不是第六個 MCP 工具)
calculateDailyJson 接受 strict Birth 加必填 targetDate;出生時分仍依 Birth 規則驗證,但實際 daily 上游使用分鐘 0。raw daily 使用 snake_case,上游保留的介面可接受未補零日期;JSON companion 僅接受補零日期,且要求明確 hour/gender,不能套用 raw 的省略預設。
kind = "daily.chart"
input = { ...Birth, targetDate: DateString }
referenceDate = targetDate
data = {
ziwei: {
natal: { mingGong: S, mingGongStars: S[] },
decadal: DailyPeriodWithOverlay,
yearly: DailyPeriodWithOverlay,
monthly: DailyPeriod,
daily: DailyPeriodWithOverlay
},
bazi: {
natal: { year: S, month: S, day: S, hour: S, dayMaster: S },
daily: {
dayPillar: S, monthPillar: S, yearPillar: S, dayNayin: S, lunarDate: S
},
interaction: {
relationCode: S, relationTerm: S,
natalDayStem?: S, natalElement?: S, dailyStem?: S, dailyElement?: S
}
},
target_date: S, birth_date: S
}
DailyPeriod = { ganZhi: S, mutagen: S[], palaceNames: S[] }
DailyPeriodWithOverlay = DailyPeriod & { dieBenGong: S }
omitted = ["bazi.daily.dayYi", "bazi.daily.dayJi", "bazi.interaction.relation"]
limitations = ["UPSTREAM_DAILY_BIRTH_MINUTE_ZERO"]relationCode 為 SAME、NATAL_GENERATES_DAILY、DAILY_GENERATES_NATAL、NATAL_CONTROLS_DAILY、DAILY_CONTROLS_NATAL 或 UNKNOWN;只是五行關係代碼。UNKNOWN 分支沒有四個 stem/element 欄位,不輸出解讀句子。
Formatters、常數及共用 exports
以下函式只回傳事實表格/字串,不回傳 envelope:formatChart(chart)、formatChartCompact(chart)、formatChartByTianGan(y,m,d,gender)、formatBazi(chart)、formatBaziCompact(chart)、formatFinance(chart)。若要 transport 請選對應 JSON calculator,而不是把格式化字串當作可解析資料。
root 亦匯出 SHI_CHEN_RANGE、DI_ZHI、TIAN_GAN 以及底層 __internals(cross 的定位/分層 helpers 與表)。它們不是額外 MCP tools。
共用函式 | 行為 |
| 驗證 strict Birth,補 minute 0,回傳新 object |
| 驗證公曆日期並回傳補零字串;JSON calculators 不啟用未補零選項 |
| 驗證整數日期組件及 Birth,回傳正規化 Birth;注意 gender 在 minute 前 |
| 要求 plain object,不接受 array/null/其他 prototype |
| 拒絕未知 key、symbol、非 enumerable 或 accessor 欄位 |
| 驗證有限數字、dense array、plain object 等可無損 JSON 值;拒絕 undefined/函式/循環/-0 等 |
| 建立上面完整 envelope、驗證後回傳 JSON object;沒有替 caller 解讀資料 |
保留的北派設定與精度界線
庚干固定為「太陽祿、武曲權、天同科、天相忌」,共享設定的星序是 ['太陽','武曲','天同','天相']。此設定及流月斗君、流日/流時算術、交叉層級邏輯均保留既有計算;不因包裝成 MCP 而更換門派表或修補上游特殊行為。
固定 referenceDate 可重現時間層;沒有明確日期的 chart/finance 呼叫不應只憑 MCP 的 idempotent hint 當成永久固定結果。helper 不知道傳入 raw chart 的日期時會明列未知,不從內容猜測。沒有完整曆年、所有出生組合或分鐘級準確度的驗證承諾。
測試:區分完整 gate 與無原檔的 smoke
完整 gate:
npm test這不只是一般 unit tests:它直接 import 授權且未變更的原始計算檔,做數值/結構 parity、SHA256 before/after 檢查及從原檔於記憶體取得禁止片段的中性掃描。五個原始計算檔的 hashes 與 tests/fixtures/source-manifest.json 比對;另外兩個上游測試檔的 hashes 在 parity suite 比對。不是複製一份計算輸出 baseline 作為「原檔」。
公開 checkout 不包含那些原始來源,因此單靠本 repo 不保證 npm test 可過;缺少原檔會 fail,不會自動 skip。請只在有授權原檔的環境跑完整 gate,並由呼叫者設定 DT_SRC_MIRROR 與 DT_SRC_API 為各自來源根目錄,或保留 helper 的預設相對布局(repo 的上兩層下有 src-mirror/ 與 src-api/):
mirror 根下需有
src/ziwei-calc.js、src/crosssihua.js、src/bazi-calc.js、src/finance-calc.js,及test-crosssihua.mjs、test-heban-modes.mjs。API 根下需有
calc-daily.mjs。resolve hook 只替指定原始計算檔的依賴解析指向本 repo 已裝套件;不改寫原始演算法。
不要為了變綠而複製私有原檔到公開 repo、替換 hash、建立輸出快照、放寬 parity 或宣稱缺原檔可跳過。
沒有原檔時,可在 checkout 根目錄跑這組自含 smoke/integration:
node --test tests/index-exports.test.mjs tests/integration.test.mjs tests/mcp-smoke.test.mjs已檢查這三檔及其本地匯入:只用產品、已安裝 dependencies、合成 fixture 與 fixed-clock.mjs,不使用 source hooks/integrity/neutral-scan helper、不讀外部原檔。包含真實 stdio 子程序與五工具呼叫,不是 mock;但它不是 direct-original parity,也不能替代完整發布 gate。test:sol 腳本仍包含需要原檔的掃描,不可把它誤作無原檔替代方案。
實測覆蓋使用七組合成 births 與四個固定日期 2024-02-10、2025-12-31、2026-10-24、2027-01-01。紫微 parity 含每例 12 斗君月、無流時及 24 小時、TianGan index0;cross 以每個 fixture 與下一個環狀配對,檢查雙向八層及歷史缺失,不宣稱測過所有兩兩配對或所有曆日。MCP smoke 檢查 initialization、恰好五工具、三種 overlay scope、cross temporal 層、非法欄位/日期/時分拒絕、stdout JSON-RPC 與子程序清理;另以測試擁有的臨時 symlink 驗證 Node/shebang 啟動的真實 initialization、list、tool call,並清理子程序及臨時目錄。中性掃描是已知片段檢查,不是完整 PII、secret 或語意審查。
測試輸出才是當次通過數的依據;本文件不以舊測試數或單一子集代表最終驗收。直接 Node entry 與測試擁有的 symlink 回歸,也不等於 Claude/Cursor 已在使用者應用程式完成安裝,或 npm-installed bin 已驗證。
授權與依賴致謝
本專案附 MIT LICENSE:Copyright 2026 cph0512 / destinytelling.life。
以下名稱、版本、MIT 授權與 repository URL 已依本地安裝 metadata 及隨附 LICENSE 核對;不是對遠端最新版本或可用性的網路驗證:
直接依賴 | 已安裝版本 | 授權 | Repository |
iztro | 2.6.3 | MIT | |
lunar-javascript | 1.7.7 | MIT | |
@modelcontextprotocol/sdk | 1.32.2 | MIT | |
zod | 4.6.7 | MIT |
感謝 iztro 與 lunar-javascript 提供底層排盤/曆法計算、MCP SDK 提供本機協議傳輸、zod 提供輸入驗證。第三方 copyright 與 MIT 文本見 NOTICE 及各套件隨附 LICENSE;直接依賴清單不冒充完整傳遞依賴授權稽核。
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
Related MCP Connectors
Deterministic BaZi and Chinese metaphysics tools for AI agents: charts, divination, almanac.
Zi Wei Dou Shu for AI agents: free natal charts, six transit levels, and optional readings.
BaZi four pillars, Chinese zodiac, lunisolar calendar and almanac days for AI agents.
BaZi MCP gateway: 14 tools (6 fortune / 5 forum / 3 meta). API key required. Entertainment only.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables traditional Chinese metaphysics tools like Bazi, Ziwei, and Qimen via MCP, integrating AI analysis for divination and fortune-telling.762AGPL 3.0
- AlicenseAqualityBmaintenanceProvides traditional Chinese astrology (Bazi, Ziwei) and divination (Liuyao, Meihua, Qimen, etc.) calculations as MCP tools for AI assistants.18266 npm131Apache 2.0
- AlicenseNot gradedqualityCmaintenanceProvides free hosted Zi Wei Dou Shu (Purple Star Astrology) natal charts and six-level transits as MCP tools, enabling AI agents to compute charts and transits through natural language.MIT
- AlicenseBqualityFmaintenanceWindows-local stdio MCP server for Chinese calendar and Four Pillars (BaZi) calculations, providing deterministic tools for day pillars, four pillars, calendar context, and natural calendar context.4MIT