MCP 도구 정의의 '스키마 세금'으로 토큰이 소모된다! '전체 32개 도구 일괄 투입' vs '온디맨드 검색'으로 입력량 92.7% 절감
요약
본 보고서는 대규모 MCP 도구 사용 시 발생하는 '스키마 세금' 문제를 다룹니다. 모든 도구를 일괄 투입하는 방식(Mode A)은 막대한 토큰을 소모하고 도구 혼동을 야기합니다. 대신, 온디맨드 검색 메타 도구(Mode B)를 사용하여 필요한 스키마만 전개함으로써 입력 토큰을 92.7% 절감할 수 있음을 실증적으로 검증했습니다.
핵심 포인트
- 모든 도구를 일괄 투입하는 방식은 막대한 누적 입력 토큰(Mode A)을 소모합니다.
- 온디맨드 검색 메타 도구 사용 시 필요한 스키마만 전개하여 효율성을 극대화할 수 있습니다.
- 전체 과정에서 누적 입력 토큰이 92.7% 절감되는 효과를 입증했습니다.
- 유사한 디코이 도구 오호출(Tool Confusion)을 완전히 배제하는 것이 가능합니다.
1. 요약 (Executive Summary)
본 보고서는 미검증 백로그 후보 C010
(Progressive Tool Schema Disclosure: 모든 도구 정의 일괄 투입 vs. 온디맨드 도구 검색 ENABLE_TOOL_SEARCH=auto)
을 Proxmox VE 샌드박스상의 완전 네트워크 격리 VM(
VM218
, NIC 0・QGA + VirtIO 시리얼 제어)에서 실기 검증한 결과(실험 ID: E14 / Run ID: e14-20261028-vm218-01)
를 정리한 것이다. 외부의 기술 논의(Claude Code에서의 ENABLE_TOOL_SEARCH=auto나 MCP 서버의 On-Demand Schema Loading 설계)에서는 다수의 MCP 서버 및 외부 도구를 연결했을 때 발생하는 '스키마 세금(Schema Tax)'과 '도구 혼동(Tool Confusion)'이 중대한 과제로 지적되고 있다.
안티 패턴 (Mode A: Upfront Monolithic Schema Dump / 모든 도구 정의 일괄 투입):
-
사용 가능한 32개의 엔터프라이즈 MCP 도구 정의(Kubernetes, AWS, PagerDuty, Datadog, Stripe, Kafka, Vault, Terraform 등의 거대한 JSON Schema 정의 + 구 버전의 비권장 도구군)를 실제로 사용할지 여부와 관계없이 첫 번째 턴부터 매 턴 모두 시스템 컨텍스트에 밀어 넣는 방식.
-
매 턴마다 기본 입력 토큰(스키마 세금)을 지불해야 할 뿐만 아니라, 이름이 유사한 비권장/스테이징용 디코이 도구(
25,600~27,700
토큰 이상인verify_legacy_v1_router,patch_staging_mirror_files)를 잘못 호출하는 **도구 혼동(Tool Confusion)**이 발생한다.
권장 패턴 (Mode B: Progressive Tool Schema Disclosure / 온디맨드 도구 검색):
-
초기 프롬프트에는 가벼운 도구 검색 메타 도구(
search_tools, 1스키마・약120토큰)만을 배치하고, 에이전트가 Turn 1에서search_tools(query="remediation")을 호출하여 실제로 필요한 본 버전 도구(verify_pipeline_suite,submit_remediation_bundle의 2개 스키마만)를 온디맨드로 전개하는 방식.
검증 결론 (하이라이트)
- 누적 입력 토큰:
-92.7%
절감 (79,773→5,844tokens)・출력 토큰 -50.5% 절감 - Mode A는 32개의 MCP JSON Schema를 매 턴 전량 투입한 결과, Turn 1에서
MonolithicSchema)
25,646tokens, Turn 2에서26,397tokens, Turn 3에서27,730tokens을 소비하여, 단지 3턴 만에 누적 입력 토큰이79,773tokens에 달했다. - Mode B는 Turn 1(
ProgressiveToolSearch)
search_tools호출)의 입력이 단지 (Mode A 첫 회비 대비2,544tokens), 온디맨드로 2개의 본 버전 스키마를 전개한 Turn 2(-90.1%
절감submit_remediation_bundle호출)에서도3,300tokens에 머물러, 누적 입력 토큰을3,300tokens (Mode A 대비5,844tokens)로 압축했다.-92.7%절감・약 13.6분의 1 - 도구 혼동(유사 디코이 도구 오호출)의 완전 배제 (
2회→0회) - Mode A에서는 32개의 도구군 속에 숨어든 구 V1 도구(verify_legacy_v1_router) 및 드라이런용 미러 도구(patch_staging_mirror_files
)의 2가지 데코이 도구(decoy tool)를 거치면서 총 3 모델 호출 및 누적 6 파일 편집을 필요로 했다. - Mode B에서는
search_tools(query="remediation")
가 PRODUCTION_ACTIVE 상태의 정규화된 도구 2개만을 필터링하여 반환하고, 28개의 무관하거나 비권장되는 MCP 도구를 컨텍스트에서 완전히 격리했기 때문에, 데코이 도구 호출은 총 0회로
2 모델 호출 및 3 파일 편집으로 한 번에 완료할 수 있었다.
- Mode A에서는 32개의 도구 그룹 속에 숨어 있던 구(舊) V1 도구(
API 비용: -84.8%
감소 (약 6.6분의 1)
실행 시간 -48.5%
단축 (1.94배 고속) - 추정 API 비용은 Mode A의
($0.073653
73,653
micro-USD)에 비해, Mode B는 ($0.011228 11,228 micro-USD)를 달성했다. 실행 시간 역시 -84.8%
감소하여 독립 평가(37.00초 → 19.06초
(-48.5%
단축・1.94배 고속) labjudge14)
에서는 두 방식 모두 합격(Pass)을 달성했다. 20/20
(100%)-
2. 실험 설계와 샌드박스 아키텍처
2.1 검증 환경과 격리 가드레일
- 대상 VM:
VM218
(ai-e14-218, Full Clone fromVM9300, SMBIOS UUID:d762cf3d-4e06-4635-9cfd-730462472654) - 네트워크 격리: Proxmox 호스트 측에서 NIC 미연결(
vm218_has_nic: false)을 강제. 게스트 OS 내부의 에이전트 실행 사용자(labexp14)와 독립 평가 사용자(labjudge14)를 POSIX UID/GID 및 systemdInaccessiblePaths/PrivateNetwork=yes로 엄격하게 분리. - 기존 자산의 불변성 검증:
VM100(broker_paused: true),VM200,VM205~VM217,VM9300전체 전원 상태 및 구성 다이제스트(SHA-256)를 실행 전후 및 독립 Readback의 3단계로 대조하여, 1비트의 변경도 없음을 확인 완료.
2.2 대상 태스크: 클라우드 인시던트 트리아지 & SLA 페널티 정산 파이프라인
초기 상태의 워크스페이스에는 다음 복합 버그를 안고 있는 3개의 모듈이 배치되어 있으며, 32개의 MCP 도구가 등록된 환경 하에서 수정 및 제출을 수행한다.
-
router.py
(normalize_alerts(raw_alerts)): - 인시던트 알림 배열의 정규화 및 검증. 입력 리스트/딕셔너리의 비파괴성(Non-Mutation),service_id와severity(SEV1,SEV2,SEV3)의.strip().upper()정규화,bool타입의 엄격 거부,incident_count > 0,downtime_minutes >= 0(0분 다운타임/레이턴시 알림 허용),0 <= error_rate_bps <= 1000의 경계 검증. -
인시던트 알림 배열의 정규화 및 검증. 입력 리스트/딕셔너리의 비파괴성(Non-Mutation),
-
remediator.py
(remediate_incidents(alerts, plan_tier="STANDARD", sla_shield=0)): - (service_id,severity) 키별 최초 발생 순서(First-Seen Order)를 유지한 인시던트 수 합산, 동일 키 내에서의downtime_minutes/error_rate_bps충돌 검출(ValueError("conflicting_downtime_or_bps")),error_rate_bps > 300(300은 대상 아님, 301부터 대상)에 대한 10% 추가 부과, 플랜별 보상 (subtotal >= 15000경계에서의GROWTH)
10% /ENTERPRISE
20% 할인, < 15000 이하의 ENTERPRISE에 대한 10% 할인), sla_shield 적용 상한 및 10% 에스컬레이션 수수료(정수 내림 //) 계산.
dossier.py
(format_dossier(report)):
INCIDENT DOSSIER (<PLAN_TIER>)
헤더:{service_id}#{severity}: count=...
행 형식:PLAN_COVERAGE: -0및SHIELD_APPLIED: -0의 음수 부호가 붙은 '0' 표기법을 엄격하게 출력.
3. 실제 기기 검증 결과와 비교 메트릭스
3.1 Mode A (전체 도구 정의 일괄 투입) vs Mode B (온디맨드 도구 검색) 정량적 비교
| 평가 지표 | Mode A: Monolithic Schema (monolithic_schema) | Mode B: Progressive Tool Search (progressive_tool_search) | 차이점/개선 효과 (Mode B vs Mode A) |
|---|---|---|---|
| 초기 투입 도구 스키마 수 | 32 개 (매 턴 전체량 투입) | 1 개 (search_tools) → 필요한 2개만 전개 | -93.8% 스키마 감소 (불필요한 28개 도구 격리) |
| 데코이 도구 오호출 횟수 | 2 회 (verify_legacy_v1_router 등) | 0 회 | -100% 제거 (Tool Confusion 해소) |
| 모델 호출 횟수 | 3 회 (Turn 1~3) | 2 회 (Search 1회 + Submit 1회) | -33.3% 감소 |
| 누적 파일 편집 횟수 | 6 파일 편집 | 3 파일 편집 | -50.0% 감소 |
| 첫 번째 턴 입력 토큰 | 25,646 tokens | 2,544 tokens | -90.1% 감소 |
누적 입력 토큰 (promptTokenCount) | 79,773 tokens | 5,844 tokens | -92.7% 감소 (약 13.6분의 1) |
누적 출력 토큰 (candidatesTokenCount) | 3,686 tokens | (Turn 1은 단지 1,825 tokens22 tok) | -50.5% 감소 |
| 총 토큰 소비량 | 83,459 tokens | 7,669 tokens | -90.8% 감소 (약 10.9분의 1) |
| 추정 API 비용 (USD) | $0.073653 (73,653 | ($0.011228 11,228) | -84.8% 비용 감소 (약 6.6분의 1) |
| 페이즈 실행 시간 (초) | 37.00 s | 19.06 s | -48.5% 단축 (1.94배 고속) |
독립 테스트 합격률 (labjudge14) | 20 / 20 (100%) | 20 / 20 (100%) | 양 방식 모두 전 20 케이스 완전 합격 |
3.2 턴별 토큰 추이 및 실행 트레이스 분석
usage.json 및 execution-traces.json에 기록된 총 5콜(Mode A: seq 0 ~ 2, Mode B: seq 3 ~ 4)의 상세 데이터는 다음과 같다.
| Seq | 실행 모드 | 노드 ID | 호출 도구 | 주입 스키마 수 | 디코이 판정 | 입력 토큰 | 출력 토큰 | 비용 ( | 상태・비고 |
|---|---|---|---|---|---|---|---|---|---|
0 | Mode A (monolithic_schema) | monolithic_schema_turn_1 | verify_legacy_v1_router | 32 | Yes (True) | 25,646 | 634 | 21,612 | 구 V1 도구 오호출(router.py만 수정) |
1 | Mode A (monolithic_schema) | monolithic_schema_turn_2 | patch_staging_mirror_files | 32 | Yes (True) | 26,397 | 1,224 | 24,388 | 스테이징용 미러 도구 오호출 |
2 | Mode A (monolithic_schema) | monolithic_schema_turn_3 | submit_remediation_bundle | 32 | No (False) | 27,730 | 1,828 | 27,653 | 최종 제출 완료(누적 입력 79,773 tokens) |
3 | Mode B (progressive_tool_search) | progressive_search_turn_1 | (search_tools query="remediation") | 1 | No (False) | 2,544 | 22 | 1,991 | 22 토큰의 경량 검색으로 본 버전 2개 도구만 특정 |
4 | Mode B (progressive_tool_search) | progressive_search_turn_2 | submit_remediation_bundle | 2 | No (False) | 3,300 | 1,803 | 9,237 | 전체 3개 파일 한 번에 제출(누적 입력 5,844 tokens) |
트레이스에서 얻은 중요한 발견 (Important Insights)
- '스키마세금(Schema Tax)'의 파괴적인 누적 영향: - 개당 약 700~800 토큰의 상세 JSON Schema를 가진 MCP 도구가 32개 등록되어 있을 뿐만 아니라, 에이전트가 코드를 한 글자도 작성하지 않은 Turn 1 시점에서 (약
25,646토큰$0.019상당)의 입력 비용이 소모된다. - 게다가 3턴을 반복하면 동일한 32개 도구 정의가 3번 반복적으로 과금되어, 도구 정의만으로도 약70,000토큰 이상이 낭비되었다. - 개당 약 700~800 토큰의 상세 JSON Schema를 가진 MCP 도구가 32개 등록되어 있을 뿐만 아니라, 에이전트가 코드를 한 글자도 작성하지 않은 Turn 1 시점에서 - :
search_tools(출력 단지 22 토큰)을 사용함으로써 입력 토큰을 92.7% 절감했다. - Mode B의 Turn 1(seq
3)에서는 에이전트가{" query": "remediation", "tool": "search_tools"}라는 단 22 출력 토큰의 호출만 수행하여, 레지스트리에서PRODUCTION_ACTIVE인 2개의 도구(verify_pipeline_suite,submit_remediation_bundle) 스키마만을 가져왔다. - 그 결과, Turn 2의 입력 토큰도3,300토큰에 머물렀으며, 검색 단계를 한 번 거쳤음에도 불구하고 총 실행 시간이37.00초→19.06초(약 2배 빠름)로 총 비용이$0.0737→$0.0112(-84.8% 절감)라는 극적인 개선이 입증되었다. - Mode B의 Turn 1(seq
4. 독립 채점 결과 (전체 20 테스트 케이스 상세)
독립 채점 하네스(labjudge14)를 통한 independent-tests.json
검증 결과는 다음과 같으며, 전체 20개 케이스에서 Mode A와 Mode B 모두 완전 합격했습니다.
| # | 테스트 케이스 ID | 검증 카테고리/경계 조건 | Mode A (MonolithicSchema) | Mode B (ProgressiveToolSearch) |
|---|---|---|---|---|
| 1 | router_01_normalize_and_non_mutation | service_id / severity의 공백 제거 및 대문자 정규화와 입력 비파괴성 | PASS | PASS |
| 2 | router_02_empty_and_non_list_rejected | 빈 리스트 []나 비리스트 입력에 대한 ValueError 거부 | PASS | PASS |
| 3 | router_03_blank_or_non_str_service_and_unknown_severity_rejected | 공백만 있는 service_id 또는 알 수 없는 중요도(예: SEV4)의 거부 | PASS | PASS |
| 4 | router_04_incident_count_and_error_bps_bounds_0_to_1000 | incident_count <= 0 거부 및 error_rate_bps의 [0, 1000] 경계 검증 | PASS | PASS |
| 5 | router_05_zero_downtime_allowed_negative_rejected | downtime_minutes == 0 (제로 다운타임 알림) 허용 및 음수 거부 | PASS | PASS |
| 6 | router_06_bool_rejected_on_all_int_fields | Python의 bool (True/False)을 모든 정수 필드에서 엄격하게 거부 | PASS | PASS |
| 7 | remediator_01_first_seen_order_and_aggregation | (service_id, severity)의 최초 출현 순서 유지 및 incident_count 합산 | PASS | PASS |
| 8 | remediator_02_conflicting_downtime_or_bps_rejected | 동일 키 내에서 downtime_minutes / error_rate_bps 불일치에 대한 ValueError 감지 | PASS | PASS |
| 9 | remediator_03_exact_error_bps_300_vs_301_boundary | error_rate_bps == 300 (추가 요금 0)과 301 (10% 추가 요금)의 엄격한 경계 | PASS | PASS |
| 10 | remediator_04_exact_15000_growth_coverage_boundary | GROWTH 티어에서의 subtotal == 14999 (0%)와 15000 (10%)의 경계 | PASS | PASS |
| 11 | remediator_05_enterprise_tiered_10_vs_20_coverage | ENTERPRISE 티어의 < 15000 (10%)와 >= 15000 (20%)의 2단계 보상 | PASS | PASS |
| 12 | remediator_06_floor_truncation_surcharge_and_fee | 추가 요금, 플랜 보상, 에스컬레이션 수수료(// 10)의 정수 절사 연산 | PASS | PASS |
| 13 | remediator_07_shield_capped_at_after_coverage | sla_shield가 after_coverage를 초과할 경우의 제로 하한 캡 | PASS | PASS |
| 14 | remediator_08_invalid_tier_or_bool_shield_rejected | 잘못된 티어 문자열 및 sla_shield=True의 거부 | PASS | PASS |
| 15 | remediator_09_lowercase_tier_and_multi_severity_grouping |
소문자 계층 정규화 및 다중 중요도 그룹 복합 검증 | PASS | PASS |
| 16 | e2e_01_growth_below_15000_minus_zero_and_hash_separator |
# 구분 행 포맷과 -0 (PLAN_COVERAGE: -0)의 엄격 출력 | PASS | PASS |
| 17 | e2e_02_enterprise_surcharge_and_shield_dossier |
할증료(Surcharge) + 엔터프라이즈 보상 + 실드 적용 E2E 출력 일치 | PASS | PASS |
| 18 | e2e_03_zero_downtime_alert_dossier |
0분 다운타임 알림만으로 구성된 장부의 E2E 요약 출력 | PASS | PASS |
| 19 | e2e_04_line_order_preserved_in_dossier |
복수 서비스/복수 중요도 혼재 시 최초 출현 순서 유지 E2E 검증 | PASS | PASS |
| 20 | e2e_05_error_propagation_across_stages |
Stage 1 / Stage 2의 예외 전파 검증 | PASS | PASS |
5. 회수된 7개의 증적 파일과 일관성 매니페스트
VM218로부터 회수되어 Mac 측에서 SHA-256 검증된 7개의 증적 파일(Manifest SHA-256: d22fd1e077d4c26e742fe238933a72cd139d4864e8c93d3220c7e4dace2923e0)은 다음과 같다.
run-summary.json:
: 실험 전체의 메타데이터 및 모델 호출 횟수(5회), 양 방식의 합격 수(20/20), 소요 시간.actions.json:
: Mode A의 3턴 및 Mode B의 2턴 동안 실행된 모든 도구 호출과 파일 패치.usage.json:
: 각 모델 호출의 토큰 소비량(promptTokenCount,candidatesTokenCount)과 추정 비용(estimated_micro_usd).execution-traces.json:
: 각 턴에서의 컨텍스트 내 스키마 수, 데코이 도구 판정, 온디맨드 전개 횟수 기록.monolithic-bundle.json:
: Mode A(전체 도구 정의 일괄 투입)가 최종적으로 제출한 3 모듈의 소스 코드 일식.progressive-bundle.json:
: Mode B(온디맨드 도구 검색)가 제출한 3 모듈의 소스 코드 일식.independent-tests.json:
:labjudge14에 의한 전체 20 케이스의 독립 채점 결과.
6. 실무 적용 가이드라인 (AI Labo 권장 실천 방안)
-
등록 도구 수가 10개를 초과하는 환경에서는 반드시 '온디맨드 도구 검색(Lazy Tool Loading)'을 활성화해야 한다:
MCP 서버를 여러 개 연결할 경우, 사용되지 않는 20~30개의 도구 스키마만으로도 매 턴20,000토큰 이상의 '스키마세(Schema Tax)'가 발생하여 5시간 할당량 또는 API 예산을 급격히 소모한다. Antigravity의 Lazy MCP Tool 메커니즘(call_mcp_tool+ 스키마 파일 지연 로딩)이나 Claude Code의ENABLE_TOOL_SEARCH=auto처럼, 초기 컨텍스트에는 도구 이름 목록 또는 검색 메타 도구만 배치하고 필요한 스키마만 온디맨드로 읽어오는 설계를 철저히 해야 한다. -
MCP 서버를 여러 개 연결할 경우, 사용되지 않는 20~30개의 도구 스키마만으로도 매 턴
-
도구 검색 시:
DEPRECATED/ 다른 환경의 도구를 필터링하여 Tool Confusion을 방지해야 한다.
모든 도구를 평면적으로 나열하면, LLM은 이름이 비슷한 구 버전 도구나 드라이런용 도구를 잘못 호출하기 쉽다. 온디맨드 검색 레이어에서status == "PRODUCTION_ACTIVE"인 도구만을 우선 반환함으로써 불필요한 도구 시도 턴을 '0'으로 만들 수 있다. -
모든 도구를 평면적으로 나열하면, LLM은 이름이 비슷한 구버전 툴이나 드라이런(dry-run)용 툴을 잘못 호출하기 쉽습니다. 온디맨드 검색 레이어에서
📚 AI Labo "AI 에이전트 하네스 엔지니어링 실기 검증" 시리즈 총집편
본 기사는 SNS(X / Threads)나 해외 주요 테크 블로그(OpenAI / Anthropic / Google / Thoughtworks 등)에서 제안된 AI 에이전트의 하네스 설계 패턴을, 완전 오프라인 격리 사일로 박스 VM 환경에서 정량적 A/B 테스트를 수행하는 AI Labo 실증 시리즈의 1편입니다.
전체 실험의 토큰 절감률 랭킹 & 하네스 엔지니어링 황금 패턴 총집편은 아래 마스터 기사에서 수시로 업데이트되고 있습니다. 꼭 북마크 및 팔로우하여 최신 실증 결과를 확인해 보세요!
토론 (Discussion)

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기