Skip to main content
Glama

Saju Fortune-Telling MCP Server

by hjsh200219
CLAUDE.md16.8 kB
# CLAUDE.md 이 파일은 이 저장소에서 작업할 때 Claude Code (claude.ai/code)에게 제공되는 가이드입니다. **⚠️ 중요: 이 프로젝트에서는 모든 응답을 한국어로 작성해야 합니다.** ## 프로젝트 개요 한국 전통 사주팔자를 계산하고 운세를 분석하는 MCP(Model Context Protocol) 서버입니다. **기술 스택**: TypeScript (ES2022), Node.js 18+, MCP SDK, 엄격한 타입 체크 ## 개발 명령어 ```bash # TypeScript → JavaScript 빌드 npm run build # 핫 리로드 개발 모드 npm run watch # 빌드된 서버 실행 npm start # 테스트 실행 npm test # TypeScript 린트 npm run lint # 코드 포맷팅 npm run format ``` ## MCP 서버 아키텍처 ### 진입점 [src/index.ts](src/index.ts) - `@modelcontextprotocol/sdk`로 7개 통합 도구가 등록된 MCP 서버 ### 도구 등록 패턴 1. `src/tools/*.ts`에서 핸들러 import 2. `core/tool-definitions.ts`에 도구 스키마 등록 3. `CallToolRequestSchema` switch문에서 도구 호출 라우팅 4. `{ content: [{ type: 'text', text: result }] }` 형태로 반환 ### 7개 통합 MCP 도구 1. **analyze_saju** - 사주 분석 통합 (basic/fortune/yongsin/school_compare/yongsin_method) 2. **check_compatibility** - 두 사람의 궁합 분석 3. **convert_calendar** - 양력 ↔ 음력 변환 (로컬 테이블 1900-2200) 4. **get_daily_fortune** - 특정 날짜의 일일 운세 5. **get_dae_un** - 10년 단위 대운(大運) 조회 6. **get_fortune_by_period** - 시간대별 운세 (year/month/hour/multi-year) 7. **manage_settings** - 해석 설정 관리 (get/set) ## 핵심 아키텍처 패턴 ### 한국 진태양시 보정 **중요**: [src/lib/saju.ts](src/lib/saju.ts)의 모든 사주 계산은 한국 진태양시(眞太陽時) 보정을 위해 -30분 조정을 적용합니다: ```typescript const adjustedDate = new Date(date.getTime() - 30 * 60 * 1000); ``` 이 조정은 정확한 사주팔자 계산을 위해 **필수**입니다. 모든 기둥(년/월/일/시)은 `adjustedDate`를 사용해야 합니다. ### 사주 계산 파이프라인 [src/lib/saju.ts](src/lib/saju.ts)가 전체 계산을 조율합니다: ``` 1. 달력 변환 (음력 → 양력, 필요시) 2. 한국 시간 조정 (-30분) 3. 4기둥 계산 (년 → 월 → 일 → 시) 4. 절기별 지장간 세력 계산 5. 오행(五行) 개수 세기 6. 십성(十星) 분석 7. 신살(神殺) 탐지 8. 일간 강약 평가 9. 격국(格局) 결정 10. 용신(用神) 선정 ``` 각 단계는 이전 결과에 의존합니다. **단계를 건너뛰거나 실행 순서를 변경하면 안 됩니다**. ### 지장간 세력 시스템 [src/data/earthly_branches.ts](src/data/earthly_branches.ts) - `calculateJiJangGanStrength()` 함수가 절기 관계에 따라 장간 세력을 계산합니다: - **당령(當令)** - 완벽한 일치: 정기 90%, 중기 7%, 여기 3% - **퇴기(退氣)** - 이전 달: 정기 50%, 중기 30%, 여기 20% - **진기(進氣)** - 다음 달: 정기 60%, 중기 30%, 여기 10% - **먼 시기**: 정기 40%, 중기 10%, 여기 5% 이 시스템은 정확한 일간 강약 평가와 용신 선정에 필수적입니다. ## 데이터 레이어 아키텍처 ### 정적 데이터 모듈 (`src/data/`) - [heavenly_stems.ts](src/data/heavenly_stems.ts) - 10개 천간(天干)과 오행, 음양 - [earthly_branches.ts](src/data/earthly_branches.ts) - 12개 지지(地支)와 지장간 매핑 - [wuxing.ts](src/data/wuxing.ts) - 오행(五行) 관계(상생/상극/설기) - [solar_terms.ts](src/data/solar_terms.ts) - 24절기(節氣) 통합 (1900-2200, 4개 테이블 자동 분기) - [lunar_table.ts](src/data/lunar_table.ts) - 음력 테이블 통합 (1900-2200, 4개 테이블 자동 분기) - [longitude_table.ts](src/data/longitude_table.ts) - 전국 162개 시군구 경도 데이터 - [modern_careers.ts](src/data/modern_careers.ts) - 500+ 현대 직업 데이터베이스 (십성/오행 매핑, 원격근무/글로벌 기회 포함) **연도별 데이터 테이블**: - [lunar_table_1900_2019.ts](src/data/lunar_table_1900_2019.ts) - 음력 데이터 (1900-2019) - [lunar_table_extended.ts](src/data/lunar_table_extended.ts) - 음력 데이터 (2020-2030) - [lunar_table_2031_2100.ts](src/data/lunar_table_2031_2100.ts) - 음력 데이터 (2031-2100) - [lunar_table_2101_2200.ts](src/data/lunar_table_2101_2200.ts) - 음력 데이터 (2101-2200) - [solar_terms_1900_2019.ts](src/data/solar_terms_1900_2019.ts) - 절기 데이터 (1900-2019) - [solar_terms_complete.ts](src/data/solar_terms_complete.ts) - 절기 데이터 (2020-2030) - [solar_terms_2031_2100.ts](src/data/solar_terms_2031_2100.ts) - 절기 데이터 (2031-2100) - [solar_terms_2101_2200.ts](src/data/solar_terms_2101_2200.ts) - 절기 데이터 (2101-2200) ### 분석 라이브러리 (`src/lib/`) #### 핵심 계산 엔진 - [saju.ts](src/lib/saju.ts) - **메인 조율자** - 사주팔자 계산 - [calendar.ts](src/lib/calendar.ts) - 양력 ↔ 음력 변환 및 윤달 처리 - [ten_gods.ts](src/lib/ten_gods.ts) - 간 관계 기반 십성(十星) 계산 - [sin_sal.ts](src/lib/sin_sal.ts) - 15개 신살(神殺) 탐지 및 길흉 분류 - [day_master_strength.ts](src/lib/day_master_strength.ts) - 일간(日干) 강약 평가 - [gyeok_guk.ts](src/lib/gyeok_guk.ts) - 격국(格局) 결정 - [yong_sin.ts](src/lib/yong_sin.ts) - 균형을 위한 용신(用神) 선정 - [dae_un.ts](src/lib/dae_un.ts) - 성별 기반 10년 대운 계산 - [fortune.ts](src/lib/fortune.ts) - 운세 해석 및 조언 - [compatibility.ts](src/lib/compatibility.ts) - 궁합 점수 계산 #### 용신(用神) 알고리즘 시스템 (`src/lib/yongsin/`) - [strength_algorithm.ts](src/lib/yongsin/strength_algorithm.ts) - 강약용신 (일간 강약 기준) - [seasonal_algorithm.ts](src/lib/yongsin/seasonal_algorithm.ts) - 조후용신 (계절 한난조습 조절) - [mediation_algorithm.ts](src/lib/yongsin/mediation_algorithm.ts) - 통관용신 (충돌 오행 중재) - [disease_algorithm.ts](src/lib/yongsin/disease_algorithm.ts) - 병약용신 (사주 불균형 진단 및 치료) - [selector.ts](src/lib/yongsin/selector.ts) - 통합 선택기 (자동/수동 용신 선택) #### 해석 유파 시스템 (`src/lib/interpreters/`) - [ziping_interpreter.ts](src/lib/interpreters/ziping_interpreter.ts) - 자평명리 해석기 (정통 격국 체계) - [modern_interpreter.ts](src/lib/interpreters/modern_interpreter.ts) - 현대명리 해석기 (실용적 현대 직업 중심) - [index.ts](src/lib/interpreters/index.ts) - 적천수, 궁통보감, 신살중심 해석기 포함 #### 기타 분석 도구 - [career_matcher.ts](src/lib/career_matcher.ts) - 직업 매칭 엔진 (십성 35%, 오행 25%, 용신 20%, 현대성 20%) - [school_comparator.ts](src/lib/school_comparator.ts) - 유파 비교 분석 엔진 - [interpretation_settings.ts](src/lib/interpretation_settings.ts) - 해석 설정 관리 (싱글톤) ## 타입 시스템 [src/types/index.ts](src/types/index.ts)에 모든 핵심 타입이 정의되어 있습니다: ### 주요 타입 - `SajuData` - 모든 분석 결과를 포함한 완전한 사주팔자 데이터 - `Pillar` - 단일 기둥 (간 + 지 + 오행 + 음양) - `HeavenlyStem` - 10개 천간 리터럴 타입 - `EarthlyBranch` - 12개 지지 리터럴 타입 - `WuXing` - 5개 오행 리터럴 타입 - `TenGod` - 10개 십성 리터럴 타입 - `SinSal` - 15개 신살 리터럴 타입 (원진살, 귀문관살 포함) ### SajuData의 중요 필드 - `jiJangGan` - 4기둥 모두의 지장간 세력 (정기/중기/여기 값 포함) - `branchRelations` - 삼합/삼형/육해 관계 - `dayMasterStrength` - 일간 강약 평가 (매우 약함 → 매우 강함) - `gyeokGuk` - 격국 분류 - `yongSin` - 희신/기신/수신을 포함한 용신 정보 ## MCP 서버 테스트 ### Claude Desktop 연동 `~/Library/Application Support/Claude/claude_desktop_config.json`에 추가: ```json { "mcpServers": { "saju": { "command": "npx", "args": ["-y", "tsx", "/Users/hoshin/workspace/fortuneteller/src/index.ts"] } } } ``` ### 빌드 후 테스트 `npm run build` 실행 후: ```json { "mcpServers": { "saju": { "command": "node", "args": ["/Users/hoshin/workspace/fortuneteller/dist/index.js"] } } } ``` ### 지연 로딩 모드 활성화 도구 스키마를 Tool Discovery 요청 시에만 로드하려면 환경 변수를 설정: ```json { "mcpServers": { "saju": { "command": "node", "args": ["/Users/hoshin/workspace/fortuneteller/dist/index.js"], "env": { "SAJU_LAZY_LOAD_SCHEMAS": "true" } } } } ``` **지연 로딩 모드**: - `false` (기본값): 서버 시작 시 모든 도구 스키마 로드 - `true`: Tool Discovery 요청 시에만 스키마 생성 (메모리 효율적) ## 일반적인 구현 패턴 ### 새 MCP 도구 추가하기 1. `src/tools/new_tool.ts`에 타입 인터페이스와 함께 핸들러 생성 2. [src/core/tool-definitions.ts](src/core/tool-definitions.ts)의 `TOOL_DEFINITIONS` 배열에 도구 스키마 추가 3. [src/core/tool-handler.ts](src/core/tool-handler.ts)의 `handleToolCall()` switch문에 case 추가 4. [src/tools/index.ts](src/tools/index.ts)에서 핸들러 export 5. 재빌드 및 테스트 **예시**: ```typescript // 1. src/tools/new_tool.ts export interface NewToolArgs { param1: string; param2?: number; } export function handleNewTool(args: NewToolArgs): string { const { param1, param2 = 10 } = args; // 로직 구현 return JSON.stringify({ result: '...' }, null, 2); } // 2. src/core/tool-definitions.ts export const TOOL_DEFINITIONS: Tool[] = [ // ... 기존 도구들 { name: 'new_tool', description: '새로운 도구 설명', inputSchema: { type: 'object', properties: { param1: { type: 'string', description: '파라미터 1' }, param2: { type: 'number', default: 10 }, }, required: ['param1'], }, }, ]; // 3. src/core/tool-handler.ts import { handleNewTool } from '../tools/index.js'; export async function handleToolCall(name: string, args: unknown): Promise<string> { switch (name) { // ... 기존 case들 case 'new_tool': return handleNewTool(args as Parameters<typeof handleNewTool>[0]); // ... } } // 4. src/tools/index.ts export { handleNewTool } from './new_tool.js'; ``` ### MCP 도구 개발 시 주의사항 #### 스키마-핸들러 일관성 (Schema-Handler Consistency) **중요**: MCP 도구의 스키마 정의와 핸들러 인터페이스는 반드시 일치해야 합니다. **올바른 패턴**: ```typescript // ✅ 스키마에서 개별 필드를 정의한 경우 { name: 'example_tool', inputSchema: { type: 'object', properties: { birthDate: { type: 'string' }, birthTime: { type: 'string' }, calendar: { type: 'string', enum: ['solar', 'lunar'], default: 'solar' }, isLeapMonth: { type: 'boolean', default: false } }, required: ['birthDate', 'birthTime'] } } // ✅ 핸들러 인터페이스도 개별 필드로 정의 export interface ExampleToolArgs { birthDate: string; birthTime: string; calendar?: CalendarType; // optional, 스키마의 default 값 활용 isLeapMonth?: boolean; // optional, 스키마의 default 값 활용 } // ✅ 핸들러에서 기본값 적용 export function handleExampleTool(args: ExampleToolArgs): string { const { birthDate, birthTime, calendar = 'solar', // 기본값 명시 isLeapMonth = false, // 기본값 명시 } = args; // 내부에서 필요시 calculateSaju() 호출 const sajuData = calculateSaju(birthDate, birthTime, calendar, isLeapMonth, gender); // ... } ``` **잘못된 패턴** (❌): ```typescript // ❌ 스키마는 개별 필드인데 핸들러는 객체를 받는 경우 export interface WrongArgs { sajuData: SajuData; // 스키마와 불일치! } ``` #### 기본값(Default) 처리 규칙 스키마에 `default` 값이 있는 필드는: 1. 핸들러 인터페이스에서 **optional**(`?`)로 선언 2. 핸들러 함수에서 **destructuring 시 기본값 명시** ```typescript // 스키마: default: 'solar' calendar?: CalendarType; // optional // 핸들러: 기본값 적용 const { calendar = 'solar' } = args; ``` #### 날짜/시간 문자열 파싱 시 검증 필수 문자열 형식의 날짜/시간을 파싱할 때는 반드시 검증 로직을 추가해야 합니다: **YYYY-MM 형식 파싱**: ```typescript if (targetMonth) { const parts = targetMonth.split('-'); if (parts.length !== 2) { throw new Error(`잘못된 월 형식입니다: ${targetMonth}. YYYY-MM 형식을 사용하세요.`); } const year = parseInt(parts[0]!, 10); const month = parseInt(parts[1]!, 10); if (isNaN(year) || isNaN(month) || month < 1 || month > 12) { throw new Error(`유효하지 않은 월입니다: ${targetMonth}`); } } ``` **YYYY-MM-DD HH:mm 형식 파싱**: ```typescript if (targetDateTime) { const parts = targetDateTime.split(' '); if (parts.length !== 2) { throw new Error( `잘못된 일시 형식입니다: ${targetDateTime}. YYYY-MM-DD HH:mm 형식을 사용하세요.` ); } const [datePart, timePart] = parts; const hour = parseInt(timePart!.split(':')[0]!, 10); if (isNaN(hour) || hour < 0 || hour > 23) { throw new Error(`유효하지 않은 시간입니다: ${hour} (0-23 사이여야 합니다)`); } } ``` #### 에러 메시지 작성 규칙 - 모든 에러 메시지는 **한국어**로 작성 - 구체적인 오류 내용과 올바른 형식을 함께 안내 - 예: `throw new Error(\`잘못된 월 형식입니다: ${targetMonth}. YYYY-MM 형식을 사용하세요.\`);` ### 오행 관계 다루기 [src/data/wuxing.ts](src/data/wuxing.ts) 유틸리티 사용: - `getGeneratingElement()` - 이 오행을 생(生)하는 오행 - `getGeneratedElement()` - 이 오행이 생(生)하는 오행 - `getControllingElement()` - 이 오행을 극(克)하는 오행 - `getControlledElement()` - 이 오행이 극(克)하는 오행 - `getWeakeningElement()` - 이 오행을 설(洩)하는 오행 ### 달력 변환 [src/lib/calendar.ts](src/lib/calendar.ts)가 윤달을 포함한 음양력 변환을 처리합니다 (로컬 테이블 기반, 1900-2200): ```typescript // 동기 함수로 변경됨 (KASI API 제거) const result = convertCalendar('2025-01-01', 'solar', 'lunar'); // 반환값: { // originalDate: string, // originalCalendar: CalendarType, // convertedDate: string, // convertedCalendar: CalendarType, // isLeapMonth?: boolean, // solarTerm: SolarTerm // } ``` **로컬 테이블 직접 사용**: ```typescript import { solarToLunarLocal, lunarToSolarLocal } from '../data/lunar_table.js'; // 양력 → 음력 const lunar = solarToLunarLocal(2025, 1, 1); // 반환값: { year, month, day, isLeapMonth } | null // 음력 → 양력 const solar = lunarToSolarLocal(2025, 1, 1, false); // 반환값: { year, month, day } | null ``` ## 사주 용어 핵심 용어 (한글 → 한자 → 영문): - **사주팔자** (四柱八字) - Four Pillars of Destiny - **천간** (天干) - Heavenly Stems (10개) - **지지** (地支) - Earthly Branches (12개) - **오행** (五行) - Five Elements - **십성** (十星) - Ten Gods (관계 유형) - **신살** (神殺) - Special stars (길흉 지표) - **지장간** (支藏干) - Hidden stems within branches - **일간** (日干) - Day master (가장 중요한 간) - **용신** (用神) - Beneficial element for balance - **격국** (格局) - Life pattern classification - **대운** (大運) - 10-year major fortune cycles - **진태양시** (眞太陽時) - True solar time ## 빌드 출력 TypeScript는 다음과 함께 `dist/`로 컴파일됩니다: - 디버깅용 소스맵 - 타입 체크용 선언 파일 (.d.ts) - .js 확장자를 가진 ES2022 모듈 ## 코드 품질 절대 규칙 - **🚫 ESLint Disable 절대 금지**: - `eslint-disable`, `eslint-disable-line`, `eslint-disable-next-line` 절대 사용 금지 - `// @ts-ignore`, `// @ts-nocheck` 등 TypeScript 체크 비활성화 금지 - **모든 린트 에러는 반드시 코드 수정으로만 해결** - 코드 수정 후에는 반드시 `npm run lint` 실행하여 에러 확인 및 수정 - 린트 에러가 있는 상태로 작업 완료 금지 ## 응답 언어 규칙 **⚠️ 필수**: 이 프로젝트에서 Claude Code는 **모든 응답을 한국어로 작성**해야 합니다. - 코드 설명, 에러 메시지, 작업 완료 알림 등 모든 텍스트를 한국어로 작성 - 기술 용어는 한국어 표기를 우선하되, 필요시 영문을 괄호 안에 병기 - 예: "사주팔자(Four Pillars)", "오행(五行, Five Elements)"

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hjsh200219/fortuneteller'

If you have feedback or need assistance with the MCP directory API, please join our Discord server