개발자 가이드 (API & MCP)

고전위키의 분석 엔진을 외부에서 활용하기 위한 개발자 문서입니다. AI 에이전트를 위한 MCP(Model Context Protocol)와 일반적인 REST API를 모두 지원합니다.

1. 활용 방식 비교

프로젝트 내의 엔진들을 호출하는 방식은 목적에 따라 세 가지로 나뉩니다. AI 에이전트 연동 시에는 MCP 방식을 강력히 권장합니다.

MCP (AI 전용)

외부 연동용. AI 모델이 도구를 직접 호출하여 실시간으로 데이터를 분석합니다.

API (HTTP)

타 서버나 웹 앱에서 한 번의 요청으로 결과를 받아올 때 사용합니다.

Internal (Module)

고전위키 백엔드 로직에서 직접 엔진을 호출하는 방식입니다.

2. 한자 독음 (Oneman Show)

한문 텍스트를 입력받아 정밀한 한글 독음으로 변환하는 서비스입니다. AI가 문맥에 맞는 독음을 선택하도록 도울 수 있습니다.

연동 가이드 (MCP 설정)

Claude, Cursor 등 MCP 호환 앱의 설정 파일에 아래 내용을 추가하면 AI가 직접 독음을 변환할 수 있습니다.

hanja-mcp.json
{
  "mcpServers": {
    "hanja-reader": {
      "serverUrl": "https://port-0-gojeonwiki-m96pevok5f31061b.sel4.cloudtype.app/api/mcp/oneman-show"
    }
  }
}

MCP 제공 도구 설명

hanja_to_reading

한자 독음 변환

한문 원문에 대해 한글 독음 및 각 글자별 훈음 후보군을 반환합니다.

Actual Output (JSON)
{
  "converted": "배",
  "tokens": [
    { 
      "text": "北", 
      "reading": "배", 
      "candidates": ["배", "북"], 
      "type": "hanja" 
    }
  ]
}

API 사용법 (REST)

MCP 설정 없이 일반적인 HTTP 요청으로도 한자 변환 기능을 사용할 수 있습니다.

POST /api/mcp/hanja/convert

한자 → 한글 변환

단일 문자열을 입력받아 한글 독음과 후보군을 반환합니다.

Request (Bash)
curl -X POST "https://port-0-gojeonwiki-m96pevok5f31061b.sel4.cloudtype.app/api/mcp/hanja/convert" \
-H "Content-Type: application/json" \
-d '{
  "text": "北",
  "useAI": false
}'
Response (JSON)
{
  "converted": "배",
  "tokens": [
    { "text": "北", "reading": "배", "candidates": ["배", "북"], "type": "hanja" }
  ]
}

3. 처방 추출기 (Extractor)

고전 처방 데이터베이스를 검색하고, 복잡한 처방 본문에서 약재와 주치증 등을 AI가 자동으로 분류하여 추출합니다.

MCP 제공 도구 설명

suggest_prescription

처방명 추천

키워드 및 서적명 필터를 통해 유사한 처방명을 추천받습니다.

Actual Output (JSON)
{
  "suggestions": [
    { "chinese_name": "平胃散", "hangul_name": "평위산", "similarity": 1.0 }
  ],
  "total": 1
}
suggest_books

서지명 추천

데이터베이스 내 고전 문헌(서지명) 목록을 검색 및 추천합니다.

Actual Output (JSON)
[
  { "traditional": "東醫寶鑑", "hangul": "동의보감" },
  { "traditional": "方藥合編", "hangul": "방약합편" }
]
search_prescription

처방 내용 검색

처방명/서지명 기준으로 후보 목록을 검색합니다. 경량 목록만 반환되며, 본문 전문은 get_prescription_detail로 별도 조회합니다.

Actual Output (JSON)
{
  "prescriptions": [
    {
      "id": 123,
      "classic_title": "東醫寶鑑",
      "preview": "治脾胃不和, 飲食不進...",
      "csv_info": { "hangul_name": "평위산", "composition": "..." },
      "analysis_score": null
    }
  ],
  "total": 1
}
get_prescription_detail

처방 본문 상세 조회

contentId 기반으로 본문 전문(원문/번역)과 메타데이터를 조회합니다.

Actual Output (JSON)
{
  "id": 123,
  "classic_id": 5,
  "classic_title": "東醫寶鑑",
  "classic_author": "허준",
  "volume": "1",
  "original": "治脾胃不和, 飲食不進...",
  "translation": "비위가 화합하지 못하고..."
}
extract_details

본문 상세 분석

특정 처방(contentId) 본문에서 구성/적응증/사용법 영역을 정밀 추출합니다. 일반적으로 get_prescription_detail 조회 후 호출합니다.

Actual Output (JSON)
{
  "composition": { "text": "창출 2돈...", "similarity": 0.9, "start_index": 10 },
  "indication": { "text": "습부하계...", "similarity": 0.85 },
  "use_method": { "text": "강삼조이...", "similarity": 0.95 }
}

API 사용법 (REST)

웹 프론트엔드나 타 서비스에서 처방 데이터베이스를 검색할 때 사용합니다.

GET /api/extractor/prescriptions/suggest

처방명 자동완성(검색)

Request
curl "https://port-0-gojeonwiki-m96pevok5f31061b.sel4.cloudtype.app/api/extractor/prescriptions/suggest?keyword=평위산"
Response (JSON)
{
  "suggestions": [
    { "chinese_name": "平胃散", "hangul_name": "평위산", "similarity": 1.0 }
  ],
  "total": 1
}
GET /api/extractor/prescriptions/search

처방 상세 조회

Request
curl "https://port-0-gojeonwiki-m96pevok5f31061b.sel4.cloudtype.app/api/extractor/prescriptions/search?prescriptionName=평위산"
Response (JSON)
{
  "prescriptions": [
    {
      "classic_title": "동의보감",
      "original": "치비위불화...",
      "csv_info": { "hangul_name": "평위산", "composition": "창출, 후박..." }
    }
  ],
  "total": 1
}
POST /api/extractor/extract

처방 상세 추출

Request
curl -X POST "https://port-0-gojeonwiki-m96pevok5f31061b.sel4.cloudtype.app/api/extractor/extract" \
-H "Content-Type: application/json" \
-d '{ "contentId": 123 }'
Response (JSON)
{
  "composition": { "text": "창출 2돈...", "similarity": 0.9 },
  "indication": { "text": "습부하계...", "similarity": 0.85 }
}
POST /api/extractor/extract-direct

직접 전달 기반 처방 추출

처방명, composition, indication, useMethod, 서적명을 직접 전달하여 여러 DB 결과를 검색하고 각각에 대해 추출을 수행합니다.

Request
curl -X POST "https://port-0-gojeonwiki-m96pevok5f31061b.sel4.cloudtype.app/api/extractor/extract-direct" \
-H "Content-Type: application/json" \
-d '{
  "prescriptionName": "평위산",
  "composition": "창출 2돈, 후박 1돈, 진피 1돈, 감초 5푼",
  "indication": "습부하계, 비위불화",
  "useMethod": "강삼조이, 생강 3편, 대조 2개로 수전",
  "dbBookTitle": "東醫寶鑑",
  "limit": 20
}'
Response (JSON)
{
  "prescriptions": [
    {
      "id": 123,
      "classic_id": 5,
      "classic_title": "東醫寶鑑",
      "classic_author": "허준",
      "classic_year": "1613",
      "volume": "1",
      "original": "治脾胃不和, 飲食不進...",
      "translation": "비위가 화합하지 못하고...",
      "regions": {
        "composition": {
          "text": "창출 2돈...",
          "similarity": 0.9,
          "start_index": 10,
          "end_index": 50
        },
        "indication": {
          "text": "습부하계...",
          "similarity": 0.85,
          "start_index": 60,
          "end_index": 120
        },
        "use_method": {
          "text": "강삼조이...",
          "similarity": 0.95,
          "start_index": 130,
          "end_index": 180
        }
      },
      "analysis_score": 0.9,
      "f1_score": 0.92
    }
  ],
  "total": 1
}
파라미터 설명:
  • prescriptionName (필수): 처방명 (한자/한글)
  • composition (필수): 구성 약재 텍스트
  • indication (필수): 적응증 텍스트
  • useMethod (필수): 사용법 텍스트
  • bookTitle (선택): CSV 기준 서적명 필터 (bookTitle 또는 dbBookTitle 중 하나는 필수)
  • dbBookTitle (선택): DB 기준 서적명 필터 (bookTitle 또는 dbBookTitle 중 하나는 필수)
  • limit (선택): 최대 결과 수 (기본값: 20)

4. Saram 차트 (MCP)

임상 진료 기록을 구조화된 차트 데이터(Saram v0.3 스키마)로 관리하는 MCP 도구 모음입니다. 세션 기반으로 동작하며, 총 7개의 도구를 제공합니다.

개요 및 아키텍처

AI(DeepSeek)가 MCP tool들을 직접 호출하여 차트를 구성하는 Agent Loop 패턴으로 동작합니다. 모든 tool은 순수 비즈니스 로직만 포함하며, tool 내부에 LLM 호출이 없습니다.

Architecture
사용자 입력 (자연어 진료 기록)
    |
    v
DeepSeek (Agent Loop) --- function-calling ---> MCP Tools
    |                                              |
    |  <--- tool results ---                       |
    v                                              v
텍스트 응답 (완료 메시지)                   State 업데이트 (차트 JSON)
도구 목록 (7개):
  • 차트 도구 — saram_session, saram_read, saram_patch, saram_export
  • 코드셋 도구 — list_codelists, search_codes, get_code_info

차트 도구 (4개)

saram_session

세션 관리

차트 세션을 생성, 조회, 삭제합니다. 모든 차트 작업은 세션 안에서 이루어집니다.

파라미터:
  • action (필수): create | list | get | delete
  • sessionId: 세션 ID (get, delete 시 필요)
  • metadata: 세션 메타데이터 (create 시 선택)
Actual Output (JSON)
// saram_session({ action: "create" })
{
  "sessionId": "ses_a1b2c3",
  "created": "2026-02-11T10:00:00Z",
  "state": { "schema_version": "0.3.0", "patient": {}, "chief_complaints": [], "encounters": [], "memos": [] }
}
saram_read

차트 데이터 읽기

환자 정보, 주소(CC), 방문(encounter), 통계, 이력 등을 조회합니다.

파라미터:
  • sessionId (필수): 세션 ID
  • target (필수): state | patient | cc | encounters | encounter | stats | history | context
  • id: 특정 항목 ID (target=encounter 시 필요)
  • options: 추가 옵션 (state: {summary:true}, encounters: {dateFrom, dateTo})
Actual Output (JSON)
// saram_read({ sessionId: "ses_a1b2c3", target: "patient" })
{
  "patient_id": "김동현_580312",
  "sex": "M",
  "birth_date": "1958-03-12",
  "history": { "conditions": [...], "family_history": null },
  "baseline": { "items": [...] }
}
saram_patch

Patch 적용/검증 (canonical 기본)

Patch ops를 직접 적용하거나 사전 검증합니다. canonical 포맷만 지원합니다.

파라미터:
  • sessionId (필수): 세션 ID
  • action (필수): apply | validate
  • format (선택): canonical (기본)
  • patch (필수): Patch 객체 { ops: [{ op, path, value, ... }] }
Actual Output (JSON)
// saram_patch({ sessionId: "ses_a1b2c3", action: "validate", format: "canonical",
//   patch: { ops: [{ op: "set", path: ["patient","sex"], value: "M" }] } })
{
  "ok": true,
  "valid": true,
  "ops_count": 1
}
saram_export

차트 내보내기

세션의 차트 데이터를 JSON, CSV, 또는 요약 테이블 형식으로 내보냅니다.

파라미터:
  • sessionId (필수): 세션 ID
  • format (필수): json | csv | table

코드셋 도구 (3개)

경혈, 변증, 처방, 본초 등 의료 코드 리스트를 검색합니다. 현재 약 74,000건의 코드가 등록되어 있으며, registry.json에 리스트를 추가하는 것만으로 KCD, ICD 등 새 코드 체계를 확장할 수 있습니다.

현재 등록된 리스트:
  • jein_acupoint — 경혈 (1,104건)
  • jein_pattern — 변증 (57,942건)
  • jein_prescription — 처방 (2,636건)
  • jein_herb — 본초 (12,662건)
list_codelists

코드 리스트 목록 조회

사용 가능한 코드 리스트의 이름, 설명, 코드 수를 반환합니다.

Actual Output (JSON)
{
  "ok": true,
  "codelists": [
    { "name": "jein_acupoint", "display": "경혈 (제인)", "count": 1104 },
    { "name": "jein_pattern", "display": "변증 (제인)", "count": 57942 },
    { "name": "jein_prescription", "display": "처방 (제인)", "count": 2636 },
    { "name": "jein_herb", "display": "본초 (제인)", "count": 12662 }
  ]
}
search_codes

코드 검색

지정한 리스트에서 한글 또는 한자로 코드를 검색합니다. 각 결과에 confidence(0~1)와 matchLevel(exact/strong/weak)이 포함됩니다.

파라미터:
  • query (필수): 검색어 (예: "요통", "足三里")
  • listName (필수): 리스트 이름 (예: "jein_pattern")
  • limit (선택): 최대 결과 수 (기본값: 10)
Actual Output (JSON)
// search_codes({ query: "요통", listName: "jein_pattern", limit: 3 })
{
  "ok": true,
  "query": "요통",
  "listName": "jein_pattern",
  "count": 3,
  "results": [
    { "code": "SB005862", "korean": "요통", "hanja": "腰痛", "confidence": 0.95, "matchLevel": "strong" },
    { "code": "SB005882", "korean": "요통 장성구루", "hanja": "腰痛 將成傴僂", "confidence": 0.95, "matchLevel": "strong" },
    { "code": "SB085847", "korean": "요통 NOS, 경부", "hanja": "...", "confidence": 0.95, "matchLevel": "strong" }
  ]
}
get_code_info

코드 상세 조회

코드를 직접 지정하여 상세 정보(이름, 소속 리스트, 승인 여부, 메모)를 조회합니다.

Actual Output (JSON)
// get_code_info({ code: "KH000590" })
{
  "ok": true,
  "code": "KH000590",
  "listName": "jein_acupoint",
  "korean": "족삼리",
  "hanja": "足三里",
  "approved": true,
  "memo": "혈위; 앉은 자세..."
}

코드 검색 알고리즘

검색은 4단계 매칭으로 동작하며, 앞 단계에서 충분한 결과를 찾으면 뒷 단계는 건너뜁니다. 이를 통해 57,000건 이상의 변증 리스트에서도 빠른 검색이 가능합니다.

매칭 단계:
  1. 정확 일치 — confidence 1.0 (matchLevel: exact)
  2. startsWith — confidence 0.93~0.95 (matchLevel: strong)
  3. includes — confidence 0.83~0.85 (matchLevel: strong)
  4. 하이브리드 유사도 — LCS + Jaccard + 부분일치 가중합 (matchLevel: strong/weak)
confidence 기반 저장 규칙 (Agent Loop):
  • strong 이상 (confidence ≥ 0.8): codes 배열에 코드 저장
  • weak (confidence < 0.8): 코드 저장하지 않고 memo에 원문 저장, 후보 안내