MCP 도구 스키마, 에이전트가 덜 헷갈리게 쓰려면
MCP 도구 스키마는 에이전트가 “언제·무엇을·어떻게” 호출할지 읽는 계약입니다. description으로 선택 기준을 주고, required에는 진짜 필수만 넣으며, 실행 실패는 모델이 고칠 수 있는 문구로 isError: true 결과에 담습니다.
이 글은 도구 스키마 설계만 다룹니다. 서버가 목록에 안 뜨거나 연결이 끊기는 문제는 별도 연결 실패 가이드를 참고하시기 바랍니다. 가격·플랜 비교는 없습니다.
description에 뭘 넣나?
한 줄 답: 도구가 하는 일, 쓰지 말아야 할 경우, 인자 의미를 한 문단 안에 구체적으로 적습니다. 이름만 반복하는 설명은 피합니다.
모델은 name보다 description으로 도구를 고릅니다. 공식 Tools 안내에서도 명확한 이름·설명, 상세한 JSON Schema, 설명 속 예시가 권장됩니다.
넣으면 좋은 내용:
- 무엇을 하는지 — “도시 날씨를 조회한다”처럼 동작 단위로 씁니다.
- 무엇을 거절하는지 — “미국 도시만 지원”, “삭제하지 않음”처럼 한계를 밝힙니다.
- 언제 쓰지 말지 — 비슷한 도구가 있으면 구분 기준을 한 줄 추가합니다.
- 부작용 — 쓰기·삭제·전송이 있으면 그 사실을 description에 드러냅니다.
피하면 좋은 내용:
- “유틸리티 도구”, “헬퍼”처럼 의미 없는 라벨
- 스키마와 다른 약속(설명에는 optional인데
required에만 있는 필드) - 내부 구현 스택·파일 경로 나열(모델 선택에 도움이 안 됨)
속성마다 description을 달아 포맷·범위·예시를 적습니다. "limit"만 두면 부족하고, "반환할 최대 개수, 1–20"처럼 쓰면 호출 품질이 올라갑니다.
{
"name": "create_ticket",
"description": "트래커에 이슈를 생성합니다. 담당자 배정·삭제는 하지 않습니다. 제목과 priority만 필수입니다.",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"required": ["title", "priority"],
"properties": {
"title": {
"type": "string",
"minLength": 3,
"maxLength": 120,
"description": "이슈 제목. 3–120자."
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high"],
"description": "우선순위. low | medium | high."
},
"labels": {
"type": "array",
"items": { "type": "string", "maxLength": 32 },
"maxItems": 8,
"description": "선택. 라벨 최대 8개."
}
}
}
}
additionalProperties: false를 쓰면 include_archive처럼 오타 키를 초기에 거를 수 있습니다.
required는?
한 줄 답: 연산의 최소 입력만 required에 넣고, 예제 JSON에 있던 편의 필드를 전부 필수로 올리지 않습니다.
흔한 실수는 샘플 객체의 모든 키를 required에 복사하는 것입니다. 그러면 모델이 없는 값을 지어내거나, 호출 전에 불필요한 질문을 반복합니다.
실무 기준:
- 없으면 실행 자체가 불가능한 필드만 필수 — ID, 경로, 쿼리 문자열 등.
- 기본값이 의미 있는 필드는 optional —
limit,dry_run, 정렬 방향. - 의미 있는 기본값을 서버가 채우면 안 되는 필드는 필수 유지 — 금액, 대상 경로, 권한 수준.
enum,minimum/maximum,minLength로 범위를 스키마에 고정합니다.
핸들러에서도 스키마와 같은 규칙으로 한 번 더 검증합니다. 스키마만 믿고 런타임 검증을 생략하면, 클라이언트가 스키마를 느슨하게 해석할 때 바로 깨집니다.
| 넣기 | 빼기 |
|---|---|
| 대상 리소스 ID | UI에서만 쓰는 표시용 필드 |
| 쓰기 대상 경로 | 기본 페이지 크기 |
| 검색 쿼리 본문 | 디버그 플래그 |
도구를 너무 크게 만들지 않습니다. “제품 전체를 조작”하는 단일 도구보다, 생성·조회·갱신을 나눈 좁은 도구가 스키마와 required를 단순하게 유지합니다.
실패 메시지를 어떻게?
한 줄 답: 프로토콜 오류와 도구 실행 오류를 나누고, 모델이 고칠 수 있는 실패는 isError: true 결과 본문에 행동 가능한 문장으로 반환합니다.
MCP 스펙 기준으로 구분은 다음과 같습니다.
- Protocol errors — 알 수 없는 도구명, 요청 형식 자체 오류. JSON-RPC
error로 돌아갑니다. 모델이 고치기 어렵습니다. - Tool execution errors — 잘못된 날짜, 범위 밖 값, API 실패, 비즈니스 규칙 위반. 결과의
content에 넣고isError: true를 켭니다. 클라이언트가 모델에 넘겨 재시도하게 합니다.
좋은 실행 오류 예:
Invalid departure date: must be in the future. Current date is 2026-09-24.
나쁜 실행 오류 예:
Error: ECONNRESET at Object.<anonymous> (/app/src/handler.js:214:11)
작성 규칙:
- 무엇을 고치면 되는지 한 문장으로 씁니다.
- 허용 포맷·허용 범위·다음 행동 후보를 포함합니다.
- 스택 트레이스·내부 시크릿·파일 시스템 절대 경로는 넣지 않습니다.
- “조용히 기본값으로 채우기”로 필수 필드를 숨기지 않습니다. 특히 priority·금액·삭제 대상은 추측하지 않습니다.
타임아웃·권한·레이트리밋도 같은 패턴입니다. 모델이 재시도·축소·다른 도구 전환을 고를 수 있게 원인을 짧게 남깁니다.
마무리
MCP 도구 스키마를 에이전트 친화적으로 쓰려면 description에 동작·한계·부작용을 쓰고, required는 최소 입력만 유지하며, 실패는 isError 결과로 고칠 수 있게 돌려줍니다. 연결·프로세스 문제는 스키마 문제가 아니므로 각 클라이언트의 연결 로그를 먼저 보시기 바랍니다.