UNPKG

k-mfds-fooddb-mcp-server

Version:

식품의약품안전처 식품영양성분DB를 MCP 도구로 제공합니다.

90 lines (82 loc) 4.18 kB
import { z } from "zod"; import { searchFoodNutritionInfo } from "../external/mfds/service"; import { SearchFoodNutritionRequest } from "../external/mfds/dtos/SearchFoodNutritionRequest"; export const foodSearchTool = { name: 'searchFoodNutrition', description: '식품의약품안전처 식품영양성분DB에서 식품 정보를 검색합니다. 식품명, 제조사, 카테고리 등을 기준으로 검색할 수 있습니다.', inputSchema: { foodNameKr: z.string().optional().describe('검색할 식품명 (예: "사과", "김치")'), makerName: z.string().optional().describe('제조사명 (예: "농심", "롯데")'), foodCategory1Name: z.string().optional().describe('식품 대분류명 (예: "곡류", "채소류", "육류")'), itemReportNo: z.string().optional().describe('품목제조보고번호'), researchYearMonthDate: z.string().optional().describe('데이터 생성일자 (YYYYMMDD 형식)'), pageNo: z.number().optional().describe('페이지 번호 (기본값: 1)'), numOfRows: z.number().optional().describe('한 페이지 결과수 (기본값: 10, 최대: 100)'), updateDate: z.string().optional().describe('데이터 수정일자 (YYYYMMDD 형식)'), dbClassName: z.string().optional().describe('품목대표/상용제품 구분') }, handler: async (params: any) => { try { console.error('[foodSearchTool.handler()] called with params:', params); // 최소한 하나의 검색 조건이 있는지 확인 const hasSearchCriteria = params.foodNameKr || params.makerName || params.foodCategory1Name || params.itemReportNo; if (!hasSearchCriteria) { return { content: [{ type: 'text' as const, text: '검색 조건이 필요합니다. 식품명(foodNameKr), 제조사명(makerName), 식품대분류명(foodCategory1Name), 또는 품목제조보고번호(itemReportNo) 중 하나 이상을 입력해주세요.' }] }; } const request = new SearchFoodNutritionRequest({ foodNameKr: params.foodNameKr || '', makerName: params.makerName || '', foodCategory1Name: params.foodCategory1Name || '', itemReportNo: params.itemReportNo || '', researchYearMonthDate: params.researchYearMonthDate || '', pageNo: params.pageNo || 1, numOfRows: params.numOfRows || 10, type: params.type || 'json', updateDate: params.updateDate || '', dbClassName: params.dbClassName || '' }); const response = await searchFoodNutritionInfo(request); if (response.data.length === 0) { return { content: [{ type: 'text' as const, text: '검색 결과가 없습니다. 검색 조건을 변경해보세요.' }] }; } // 검색 결과를 구조화된 형태로 반환 const resultText = response.data.map((food, index) => { const nutritionInfo = food.nutritionComponents.map(comp => `${comp.name}: ${comp.value}${comp.unit}` ).join(', '); return `${index + 1}. ${food.foodNameKr} - 제조사: ${food.makerName} - 카테고리: ${food.foodCategory1Name} > ${food.foodCategory2Name} > ${food.foodCategory3Name} - 1회 섭취량: ${food.servingSize} - 영양성분: ${nutritionInfo} - 품목제조보고번호: ${food.itemReportNum} - 데이터생성일: ${food.researchDate}`; }).join('\n\n'); const pagingInfo = response.paging; const summary = `\n\n총 ${pagingInfo.totalCount}개 중 ${response.data.length}개 결과 (페이지 ${pagingInfo.pageNo}/${Math.ceil(parseInt(pagingInfo.totalCount) / pagingInfo.numOfRows)})`; return { content: [{ type: 'text' as const, text: resultText + summary }] }; } catch (error) { return { content: [{ type: 'text' as const, text: `검색 중 오류가 발생했습니다: ${error instanceof Error ? error.message : '알 수 없는 오류'}` }] }; } } };