MCP 도구가 API를 정확히 감싸더라도 모델이 언제 어떤 인자로 호출해야 하는지 이해하지 못하면 실제 사용성은 낮습니다. 처음에는 함수 이름과 JSON schema만 정확하면 모델이 알맞은 도구를 고를 것으로 기대했습니다. 하지만 기능이 비슷한 도구가 늘자 설명의 작은 차이가 선택과 인자 생성에 영향을 줬고, 단순 성공률만으로는 원인을 찾기 어려웠습니다.
그래서 도구 이름과 설명, 필수 parameter, 응답 크기를 함께 조정하고 실제 호출 trace로 품질을 비교했습니다.
도구가 늘수록 이름만으로는 구분되지 않았다
서로 비슷한 도구 이름과 짧은 설명 때문에 모델이 목록 조회와 상세 조회를 혼동했습니다. 기본값이 있는 파라미터까지 required로 노출되거나 반대의 경우가 생겨 불필요한 재질문과 실패가 발생했습니다. 운영용 AI 챗봇의 도구 계층에서 백엔드 JSON을 그대로 반환하면 큰 배열과 중첩 필드가 모델 컨텍스트를 소모해 정작 필요한 판단 정보가 뒤로 밀렸습니다.
사용 조건과 금지 조건을 담은 설명
좋은 설명은 기능을 길게 소개하는 문장이 아니라 선택 경계를 알려 주는 인터페이스였습니다. 비슷한 두 도구에는 각각 언제 쓰는지와 언제 쓰지 않는지를 함께 적고, 필수 인자의 의미를 실제 사용자 표현과 맞췄습니다. 모델명이나 구현 세부사항을 설명에 늘어놓는 것은 선택 정확도에 거의 도움이 되지 않았습니다.
- 도구 설명에는 사용 시점과 사용하지 말아야 할 시점을 함께 적습니다.
- 스키마의 required와 default는 실제 서버 검증 규칙과 일치시킵니다.
- 응답은 후속 판단에 필요한 필드를 우선하고 크기 제한을 명시합니다.
Schema와 응답 크기를 함께 조정하기
도메인 동작이 겹치는 도구를 그룹별로 정리하고 동사와 대상이 드러나는 이름으로 바꿨습니다. 설명에는 선행 식별자, 페이징 방식, 대표적인 실패 조건을 포함했습니다.
Spring AI가 생성하는 JSON Schema를 실제 호출 로그와 비교해 optional과 default 노출을 수정했습니다. 파라미터 이름은 내부 DB 컬럼보다 사용자가 표현하는 용어에 맞췄습니다.
큰 응답은 항목 수와 문자열 길이에 상한을 두고 truncated 여부와 다음 조회 방법을 함께 반환했습니다. 상세가 필요하면 별도의 도구를 호출하도록 경계를 나눴습니다.
{"name":"get_project","description":"정확한 projectId로 단일 프로젝트 상태를 조회한다. 이름 검색에는 search_projects를 사용한다.","inputSchema":{"type":"object","required":["projectId"],"properties":{"projectId":{"type":"string","format":"uuid"}},"additionalProperties":false}}
const limited = rows.slice(0, 50);
return { items: limited, truncated: rows.length > limited.length,
nextCursor: limited.at(-1)?.id ?? null };
{"error":{"code":"PROJECT_NOT_FOUND","message":"projectId에 해당하는 프로젝트가 없습니다.","retryable":false,"suggestion":"search_projects로 후보를 찾으세요."}}
세 설명 방식이 만든 차이
| 설명 방식 | 모델에 제공되는 정보 | 주된 실패 |
|---|---|---|
| 모호한 한 줄 | 기능 이름 정도만 전달 | 비슷한 도구 혼동과 잘못된 인자 |
| 긴 문서 전체 복사 | 배경 정보까지 모두 전달 | 토큰 낭비와 핵심 조건 희석 |
| 선택 조건 + 엄격한 schema | 사용 시점과 허용 인자를 명시 | 설명과 schema의 지속적인 평가 필요 |
정답률 대신 비교하는 호출 Trace
평가 결과는 최종 답변의 성공 여부만 집계하지 않았습니다. 어떤 후보를 비교했고 어느 도구를 골랐으며 인자를 몇 번 수정했는지 trace로 남겼습니다. 덕분에 설명 변경이 선택 오류를 줄였는지, 아니면 잘못된 인자를 늘렸는지를 따로 판단할 수 있었습니다.
- 비슷한 search/get/list 도구가 구분되지 않아 불필요한 호출이 늘어나는 문제.
- additionalProperties 허용으로 모델의 오타 필드가 조용히 무시되는 문제.
- 수천 행 결과가 context를 채워 이후 추론 품질을 떨어뜨리는 문제.
운영 지표가 된 평가 세트
- 같은 사용자 질문 세트로 변경 전후 도구 선택률과 재시도 횟수를 비교합니다.
- 스키마 변경은 MCP 클라이언트 캐시와 호환성을 확인합니다.
- 잘린 응답이 정상 완료처럼 오해되지 않도록 메타데이터를 포함합니다.
- 대표 질문과 기대 tool·arguments를 eval dataset으로 관리합니다.
- invalid argument와 truncation 비율을 tool별로 측정합니다.
- description 변경도 코드처럼 회귀 eval을 통과한 뒤 배포합니다.
호출 오류가 줄어든 만큼 필요한 회귀 평가
모델이 잘못된 도구를 먼저 호출하거나 필수 인자를 빠뜨리는 비율이 줄었습니다. 응답 크기를 통제하면서 긴 도구 결과 때문에 최종 답변이 불안정해지는 문제도 완화됐습니다.
설명을 길게 만드는 것만으로 정확도가 오르지는 않았습니다. 비슷한 도구 사이의 선택 조건, 필수 인자와 결과의 한계를 짧게 드러내고 실제 호출 trace로 효과를 비교해야 했습니다.
도구 설명을 제품 인터페이스로 다루기
도구 설명을 바꾼 뒤에는 최종 답변의 인상보다 어느 도구를 어떤 인자로 골랐는지를 먼저 봤습니다. 이름이 비슷한 도구를 섞은 평가 세트를 고정하자 모델 변경과 설명 변경의 영향을 분리할 수 있었습니다.
도구 스키마는 모델에게 건네는 제품 인터페이스입니다. 백엔드 함수 목록을 그대로 노출하는 대신 모델이 결정하는 데 필요한 구분과 실패 조건을 제공해야 합니다. 이 품질은 한 번 작성한 문서가 아니라 평가 결과에 맞춰 계속 관리할 대상입니다.
답글 남기기