# 아키텍처와 입력 계약 ## 책임 경계 | 구성요소 | 책임 | DB 접근 | |---|---|---| | `search_carrier_performance` | Bearer 기반 사용자 식별 및 VPD 적용 선사 조회 | 허용 | | AI 웹 콘솔 | 도구 계약을 판별해 조회 결과를 정규화하고 렌더러를 후속 호출 | 없음 | | `render_hmm_carrier_report` | DB CLOB 템플릿에 허용된 JSON을 매핑 | 템플릿만 읽음 | | 브라우저 | 반환 HTML 표시·다운로드 | 없음 | ```text HMM portal ──► /mcp (Bearer) ──► Backoffice MCP facade ──► DB Agent Tool │ VPD applied rows │ Console │ report MCP tool call │ HMM_REPORT_TEMPLATES │ HTML 응답 ``` 리포트 MCP도 같은 Bearer 인증을 통과해야 하지만, 권한 판단은 조회 MCP에서 끝난다. 리포트 입력의 임의 사용자 ID를 신뢰하거나 DB를 재조회하지 않는다. ## 포털의 범용 순차 호출 규칙 포털은 `render_hmm_carrier_report`라는 이름을 조건문에 넣지 않는다. 발견한 MCP 도구가 아래 계약을 동시에 보이면 **이전 결과 입력형 렌더러**로 분류한다. - 입력 스키마에 `reportJson`·`report_payload`처럼 리포트 JSON/payload를 받는 문자열이 있다. - 설명에 HTML/리포트/렌더링 의도와 `조회 결과`, `후속 처리`, `already-authorized`처럼 선행 결과를 사용한다는 의도가 있다. 사용자가 리포트·보고서·대시보드·차트·HTML을 요청하고 이 렌더러가 발견되면, 기존 LLM 라우터는 렌더러를 제외한 데이터 도구 중 하나를 먼저 선택한다. 첫 응답의 `items` 또는 `results`만 camelCase JSON으로 정규화해 두 번째 도구에 전달한다. 포털은 렌더러의 `html` 응답을 iframe으로 표시한다. 이 규칙은 동일 계약을 선언하는 다른 업무 리포트 도구에도 적용된다. ## `reportJson` 계약 최상위에는 `report` 객체와 `rows` 배열만 허용한다. `report`에는 `id`, `category`, `title`, `generatedAt`, `requestedBy`, `question`, `answer`, `execution`, `evidence`, `limitation`을 넣는다. 행에는 담당자·선사 식별자와 최신 KPI만 넣는다. 서버는 JSON 크기, 행 수, 문자열 길이, 숫자 형식을 제한하고, 템플릿에 주입할 JSON에서 ``를 이스케이프한다. payload는 저장하지 않는다. ## 배포 도구 계약 `BACKOFFICE_MCP_TOOLS`에 다음과 같이 등록한다. 실제 환경 변수에는 비밀값을 넣지 않는다. ```json { "name": "render_hmm_carrier_report", "label": "HMM 선사 실적 HTML 리포트", "description": "VPD 적용 선사 실적 조회 결과를 HMM HTML 리포트로 표현합니다.", "argumentName": "reportJson", "argumentDescription": "정규화된 선사 실적 리포트 JSON입니다.", "executionType": "AGENT_TOOL", "targetName": "HMM_CARRIER_REPORT_RENDERER", "targetParameterName": "P_REPORT_JSON" } ``` `targetName`은 DBMS_CLOUD_AI_AGENT custom tool `HMM_CARRIER_REPORT_RENDERER`다. 템플릿에는 `const reportData = __REPORT_DATA__;` 자리만 둔다. DB 함수는 호출 시 전달받은 JSON을 이 자리에 삽입하고, 조회 Tool을 호출하거나 기본 업무 행을 보충하지 않는다.