UNPKG

mcp-tung-shing

Version:

A Model Context Protocol plugin for Chinese Tung Shing (黄历/通勝/通胜) almanac calculations

263 lines (262 loc) 12.3 kB
#!/usr/bin/env node import * as __WEBPACK_EXTERNAL_MODULE_dayjs__ from "dayjs"; import * as __WEBPACK_EXTERNAL_MODULE_dayjs_plugin_lunar_779f8ffa__ from "dayjs-plugin-lunar"; import * as __WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_server_stdio_js_4f861174__ from "@modelcontextprotocol/sdk/server/stdio.js"; import * as __WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_server_mcp_js_2c42c5d0__ from "@modelcontextprotocol/sdk/server/mcp.js"; import * as __WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_types_js_fc45a208__ from "@modelcontextprotocol/sdk/types.js"; import * as __WEBPACK_EXTERNAL_MODULE_zod_to_json_schema_a1d75503__ from "zod-to-json-schema"; import * as __WEBPACK_EXTERNAL_MODULE_zod__ from "zod"; import * as __WEBPACK_EXTERNAL_MODULE_tyme4ts__ from "tyme4ts"; import "dayjs/locale/zh-cn.js"; function handleDirection(direction) { const directions = { 东: '正东', 南: '正南', 西: '正西', 北: '正北' }; return directions[direction] || direction; } const IGNORE_DAY_TABOO_NAMES = [ '齐醮', '酬神', '祀灶', '焚香', '订婚', '挽面', '开容', '开井开池', '作陂放水', '伐木做梁', '穿屏扇架', '盖屋合脊', '作厕', '造屋', '求财', '买车', '酝酿', '作染', '鼓铸', '见贵', '渡水', '剃头', '起基动土', '破屋坏垣', '造仓库', '立券交易', '安机', '会友', '求医疗病' ]; const getDayTabooNames = ()=>__WEBPACK_EXTERNAL_MODULE_tyme4ts__.Taboo.NAMES.filter((item)=>!IGNORE_DAY_TABOO_NAMES.includes(item)); var types_ContentType = /*#__PURE__*/ function(ContentType) { ContentType["宜"] = "宜"; ContentType["忌"] = "忌"; ContentType["吉凶"] = "吉凶"; ContentType["五行"] = "五行"; ContentType["冲煞"] = "冲煞"; ContentType["值神"] = "值神"; ContentType["建除十二神"] = "建除十二神"; ContentType["二十八星宿"] = "二十八星宿"; ContentType["吉神宜趋"] = "吉神宜趋"; ContentType["凶煞宜忌"] = "凶煞宜忌"; ContentType["彭祖百忌"] = "彭祖百忌"; ContentType["方位"] = "方位"; return ContentType; }({}); var types_TabooType = /*#__PURE__*/ function(TabooType) { TabooType[TabooType["宜"] = 1] = "宜"; TabooType[TabooType["忌"] = 2] = "忌"; return TabooType; }({}); const tabooFilterSchema = __WEBPACK_EXTERNAL_MODULE_zod__.z.object({ type: __WEBPACK_EXTERNAL_MODULE_zod__.z.nativeEnum(types_TabooType).describe('过滤类型:宜(1)、忌(2)'), value: __WEBPACK_EXTERNAL_MODULE_zod__.z["enum"](getDayTabooNames()).describe('要筛选的宜忌事项') }); const getTungShingParamsSchema = __WEBPACK_EXTERNAL_MODULE_zod__.z.object({ startDate: __WEBPACK_EXTERNAL_MODULE_zod__.z.string().optional().default(new Date().toISOString().split('T')[0]).describe('开始日期,格式为"YYYY-MM-DD"的字符串'), days: __WEBPACK_EXTERNAL_MODULE_zod__.z.union([ __WEBPACK_EXTERNAL_MODULE_zod__.z.number().int().min(1), __WEBPACK_EXTERNAL_MODULE_zod__.z.string().regex(/^\d+$/).transform((val)=>Number.parseInt(val)) ]).optional().default(1).describe('要获取的连续天数'), includeHours: __WEBPACK_EXTERNAL_MODULE_zod__.z.boolean().optional().default(false).describe('是否包含时辰信息'), tabooFilters: __WEBPACK_EXTERNAL_MODULE_zod__.z.array(tabooFilterSchema).optional().describe('多个筛选宜忌事项,条件之间为或关系') }); __WEBPACK_EXTERNAL_MODULE_dayjs__["default"].extend(__WEBPACK_EXTERNAL_MODULE_dayjs_plugin_lunar_779f8ffa__.PluginLunar); function getHourlyAlmanac(date) { const lunarHour = date.toLunarHour(); const sixtyCycle = lunarHour.getSixtyCycle(); const heavenStem = sixtyCycle.getHeavenStem(); const earthBranch = sixtyCycle.getEarthBranch(); return { [types_ContentType["宜"]]: lunarHour.getRecommends().map((item)=>item.getName()), [types_ContentType["忌"]]: lunarHour.getAvoids().map((item)=>item.getName()), [types_ContentType["吉凶"]]: lunarHour.getTwelveStar().getEcliptic().getLuck().toString(), [types_ContentType["值神"]]: lunarHour.getTwelveStar().toString(), [types_ContentType["五行"]]: sixtyCycle.getSound().toString(), [types_ContentType["冲煞"]]: `冲${earthBranch.getOpposite().getZodiac()}${earthBranch.getOminous()}`, [types_ContentType["方位"]]: [ `喜神${handleDirection(heavenStem.getJoyDirection().toString())}`, `财神${handleDirection(heavenStem.getWealthDirection().toString())}`, `福神${handleDirection(heavenStem.getMascotDirection().toString())}` ] }; } function getDailyAlmanac(date, includeHours = false) { var _lunarDay_getFestival; const parsedDate = (0, __WEBPACK_EXTERNAL_MODULE_dayjs__["default"])(date); if (!parsedDate.isValid()) throw new Error('Invalid date'); const lunarDay = parsedDate.toLunarDay(); const solarDay = lunarDay.getSolarDay(); const sixtyCycle = lunarDay.getSixtyCycle(); const earthBranch = sixtyCycle.getEarthBranch(); const twentyEightStar = lunarDay.getTwentyEightStar(); const gods = lunarDay.getGods().reduce((acc, god)=>{ const category = '吉' === god.getLuck().getName() ? 'auspicious' : 'inauspicious'; acc[category].push(god.getName()); return acc; }, { auspicious: [], inauspicious: [] }); const result = { 公历: parsedDate.locale('zh-cn').format('YYYY 年 M 月 D日(ddd)'), 农历: parsedDate.format('LY年LMLD'), 节日: null === (_lunarDay_getFestival = lunarDay.getFestival()) || void 0 === _lunarDay_getFestival ? void 0 : _lunarDay_getFestival.getName(), 节气: solarDay.getTermDay().toString(), 七十二候: solarDay.getPhenologyDay().toString(), 当日: { [types_ContentType["宜"]]: lunarDay.getRecommends().map((item)=>item.getName()), [types_ContentType["忌"]]: lunarDay.getAvoids().map((item)=>item.getName()), [types_ContentType["吉凶"]]: lunarDay.getTwelveStar().getEcliptic().getLuck().toString(), [types_ContentType["五行"]]: sixtyCycle.getSound().toString(), [types_ContentType["冲煞"]]: `冲${earthBranch.getOpposite().getZodiac()}${earthBranch.getOminous()}`, [types_ContentType["值神"]]: lunarDay.getTwelveStar().toString(), [types_ContentType["建除十二神"]]: lunarDay.getDuty().toString(), [types_ContentType["二十八星宿"]]: `${twentyEightStar}${twentyEightStar.getSevenStar()}${twentyEightStar.getAnimal()}${twentyEightStar.getLuck()})`, [types_ContentType["吉神宜趋"]]: gods.auspicious, [types_ContentType["凶煞宜忌"]]: gods.inauspicious, [types_ContentType["彭祖百忌"]]: `${sixtyCycle.getHeavenStem().getPengZuHeavenStem()} ${earthBranch.getPengZuEarthBranch()}` } }; if (includeHours) { result.分时 = {}; for(let i = 0; i < 12; i++){ const hour = parsedDate.addLunar(i, 'dual-hour'); result.分时[hour.format('LH')] = getHourlyAlmanac(hour); } } return result; } function createServer() { const mcpServer = new __WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_server_mcp_js_2c42c5d0__.McpServer({ name: 'Tung Shing', version: "1.7.1" }, { capabilities: { tools: {}, prompts: {} } }); mcpServer.server.setRequestHandler(__WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_types_js_fc45a208__.ListToolsRequestSchema, ()=>({ tools: [ { name: 'get-tung-shing', description: '获取通胜黄历,包括公历、农历、宜忌、吉凶、冲煞等信息', inputSchema: (0, __WEBPACK_EXTERNAL_MODULE_zod_to_json_schema_a1d75503__.zodToJsonSchema)(getTungShingParamsSchema) } ] })); mcpServer.server.setRequestHandler(__WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_types_js_fc45a208__.CallToolRequestSchema, async (request)=>{ switch(request.params.name){ case 'get-tung-shing': { const { startDate, days, includeHours, tabooFilters = [] } = getTungShingParamsSchema.parse(request.params.arguments); const start = (0, __WEBPACK_EXTERNAL_MODULE_dayjs__["default"])(startDate); if (!start.isValid()) return { content: [ { type: 'text', text: 'Invalid date' } ], isError: true }; return { content: Array.from({ length: days }, (_, i)=>{ const almanac = getDailyAlmanac(start.add(i, 'day'), includeHours); if (!tabooFilters.length) return { type: 'text', text: JSON.stringify(almanac) }; const recommends = almanac.当日[types_ContentType["宜"]] || []; const avoids = almanac.当日[types_ContentType["忌"]] || []; const hasMatch = tabooFilters.some((filter)=>{ if (filter.type === types_TabooType["宜"]) return recommends.includes(filter.value); if (filter.type === types_TabooType["忌"]) return avoids.includes(filter.value); return false; }); if (hasMatch) return { type: 'text', text: JSON.stringify(almanac) }; return null; }).filter(Boolean) }; } default: return { content: [ { type: 'text', text: `Unknown tool: ${request.params.name}` } ], isError: true }; } }); mcpServer.server.setRequestHandler(__WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_types_js_fc45a208__.ListPromptsRequestSchema, ()=>({ prompts: [ { name: 'get-taboo', description: '获取宜忌事项类型' } ] })); mcpServer.server.setRequestHandler(__WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_types_js_fc45a208__.GetPromptRequestSchema, (request)=>{ switch(request.params.name){ case 'get-taboo': return { messages: [ { role: 'assistant', content: { type: 'text', text: `宜忌事项类型清单\n${getDayTabooNames().map((name)=>`- ${name}`).join('\n')}` } } ] }; default: return { messages: [] }; } }); return mcpServer; } __WEBPACK_EXTERNAL_MODULE_dayjs__["default"].extend(__WEBPACK_EXTERNAL_MODULE_dayjs_plugin_lunar_779f8ffa__.PluginLunar); (async ()=>{ try { const server = createServer(); const transport = new __WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_server_stdio_js_4f861174__.StdioServerTransport(); await server.connect(transport); console.error('Tung Shing MCP server started'); } catch (error) { console.error('Failed to start Tung Shing MCP server:', error); process.exit(1); } })();