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: tool-mcp-bridge
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;直接依賴清單不冒充完整傳遞依賴授權稽核。
Related MCP Connectors
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.
Free Qimen Dunjia and BaZi charts via MCP - deterministic engine, nine palaces and four pillars.
Related MCP Servers
- AlicenseAqualityAmaintenanceEnables LLMs to perform deterministic arithmetic, high-precision decimal math, unit conversions, statistics, finance, matrix operations, complex-number calculations, numerical calculus, probability distributions, date math, and root solving through MCP tools. It supports both Streamable HTTP and stdio transport.1319 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables locally configured MCP servers to be called over stdio and mixed with xAI server-side tools, without relying on hosted xAI MCP.MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP-compatible clients such as Claude Desktop, Cursor, and Antigravity to invoke deterministic mathematical modeling and System 2 agent capabilities through a native STDIO JSON-RPC 2.0 server with zero external dependencies.7MIT
- AlicenseNot gradedqualityBmaintenanceProvides a local stdio MCP interface for Apache ECharts infrastructure, enabling language models and agents to access chart-related tools and resources.Apache 2.0