# AI 에이전트

MCP 도구가 주문 2만 건을 돌려주면 Claude는 어떻게 할까?

@Hong2026-10-14

이 글에 담긴 코드와 결과는 직접 실행해 측정한 값을 바탕으로 작성했습니다. 실측은 Hong과 팀원들이 진행했고, 그 결과를 바탕으로 AI가 글을 쓰고 Hong이 검토합니다.

실습 코드 내려받기

질문
MCP 도구가 수천에서 수만 건을 돌려주면 Claude Code는 그 결과를 어떻게 처리할까?
답
Claude Code 2.1.295는 5만 자를 넘는 MCP 결과를 자르지 않고 파일로 빼며 2만 건은 한도를 올려도 들어가지 않았고, 서버에서 거르면 건수와 상관없이 약 1만 5천 토큰으로 12문항을 모두 맞혔다.
조건
2026-10-12~13(한국 시간), Claude Code 2.1.295 claude -p, Opus 5.5(claude-opus-5-5) effort high, 질문 12개 × 1~3회

환경

측정일
2026년 10월 12~13일(한국 시간)
Claude Code
2.1.295, claude -p, --model opus(결과 JSON modelUsage의 키로 claude-opus-5-5 확인), --effort high
반복
조건마다 질문 12개, 서버 거르기·SQL·기본 한도 조건은 3회, 원본 조건은 200·1,000건 2회와 3,000건 1회
호스트
macOS 15.7.4, Node v25.5.0, sqlite3 3.43.2
비용
결과 JSON total_cost_usd, 구독 로그인으로 부른 호출을 API 단가로 환산한 추정치(실제 청구액 아님)
목차
  1. 실습 준비
  2. 실습 1: 결과가 크면 Claude Code는 무엇을 하나
  3. 실습 2: 네 가지 도구 설계
  4. 정리

이번 시간에는 MCP 도구가 수천에서 수만 건의 결과를 돌려줄 때 Claude Code가 그 결과를 어떻게 다루는지, 그리고 도구를 어떻게 설계하면 모델이 덜 읽고도 잘 맞히는지를 claude -p로 측정하며 배워가는 시간입니다. 큰 결과를 받았을 때의 동작을 먼저 보고, 같은 질문 12개를 도구 설계만 바꿔 풀게 했을 때의 입력 토큰과 정답 수를 비교할게요.

도구 설계를 비교하는 실습에서 서버에서 거르는 조건, SQL 조건, 기본 한도 조건은 세 번씩 돌렸습니다. 원본을 그대로 넣는 조건은 구독 사용량이 많이 들었고, 측정 중에 Mac이 잠자기에 들어가 긴 호출이 계속 끊겼어요. 그래서 200·1,000건은 두 번, 3,000건은 한 번만 돌렸습니다.

모델 출력은 비결정적이라 같은 명령을 다시 돌리면 숫자가 달라질 수 있어요. --model opus가 가리키는 모델도 시간이 지나면 달라질 수 있습니다.

실습 준비

이 글의 명령은 모두 실습 코드의 claude-mcp-large-results/ 디렉터리에서 실행합니다.

  • make_data.mjs, paths.mjs: 주문 데이터 생성 스크립트와 데이터·실행 디렉터리 경로 모듈
  • make_db.sh: 주문 TSV를 읽기 전용 SQLite 파일로 만드는 스크립트
  • mcpgen/: 설정 파일 하나로 도구와 결과를 정하는 stdio MCP 서버 생성기(파일 2개)
  • handlers/: 주문 도구 넷(orders.mjs)과 길이를 정해 메모를 돌려주는 get_memo(blob.mjs) 결과를 만드는 모듈(파일 2개)
  • make_catalog.mjs, catalog_orders.json: 도구 다섯 개의 카탈로그를 만드는 스크립트와 그 결과
  • make_configs.mjs: 조건마다 생성기 설정과 mcp.json을 만드는 스크립트
  • make_questions.mjs, questions.jsonl: 질문 12개를 쓰는 스크립트와 그 결과
  • answers.mjs, answers.sql: 정답을 Node와 SQL 두 가지로 계산해 gold-N.json에 쓰는 스크립트와 SQL
  • q.sh, install_q.sh: SQL 조회 래퍼와 그 설치 스크립트
  • run.mjs: 실습별 호출을 차례로 돌리는 스크립트
  • parse.mjs, grade.mjs, summary.mjs: 호출 기록 파싱, 채점, 집계 스크립트
  • mask.mjs, show.mjs: 홈 경로 가림 모듈과 호출 하나의 필드를 골라 찍는 스크립트

그 밖의 파일은 데이터·보조 스크립트입니다.

MCP 서버는 claude가 직접 띄우는 stdio 자식 프로세스예요. 데이터 생성과 채점, 집계는 표준 모듈만 쓰는 Node 스크립트이고, SQL은 macOS 기본 /usr/bin/sqlite3를 씁니다.

claude --version
/usr/bin/sqlite3 --version | cut -d' ' -f1
2.1.295 (Claude Code)
3.43.2

make_data.mjs가 주문 N건을 만들어요. 주문일은 2026년 1월 1일부터 181일 사이, 상태는 paid 80%·refunded 12%·cancelled 8%, 금액은 1,000~299,900원(100원 단위), 수량은 1~5개입니다. orders-N.json은 JSON.stringify를 그대로 쓴 JSON 배열 한 줄이고, 같은 주문을 orders-N.tsv로도 써서 SQLite에 넣어요. 파일은 /tmp/claude-<uid>/cmcpbig/data/에 둡니다(paths.mjs).

node make_data.mjs
orders-200.json  28269 chars  29869 bytes  141.3 chars/row  customers 40  sha256 019d4196d1c088f0
orders-1000.json  141543 chars  149543 bytes  141.5 chars/row  customers 199  sha256 e67f77ab43248586
orders-3000.json  424666 chars  448666 bytes  141.6 chars/row  customers 597  sha256 bb9621082a6f2286
orders-20000.json  2830127 chars  2990127 bytes  141.5 chars/row  customers 3978  sha256 9c3ca931bbef42bd

출력을 보면 주문 한 건이 약 141.5자예요. Claude Code의 기본 문자 한도 5만 자는 약 353건에 해당하니까, 1,000건부터는 기본 설정에서 그대로 들어가지 않습니다.

make_db.sh는 건수마다 TSV를 orders 표(컬럼 8개, amount·qty는 INTEGER)에 넣어 orders-N.db를 만들고, 파일을 읽기 전용(444)으로 바꿔요. 출력은 발췌예요.

sh make_db.sh
orders-200.db  200 rows, amount integer, qty integer
orders-1000.db  1000 rows, amount integer, qty integer
orders-3000.db  3000 rows, amount integer, qty integer
orders-20000.db  20000 rows, amount integer, qty integer

도구 서버는 표준 모듈만 쓰는 작은 stdio MCP 서버예요. 서버 생성기 mcpgen/은 설정 파일 하나로 실을 도구와, 결과를 만드는 handler 모듈을 정합니다. 도구별 _meta(tool_meta)도 설정으로 넣을 수 있고, 원본을 그대로 넘기는 조건 하나만 여기에 {"anthropic/maxResultSizeChars": 500000}을 넣습니다.

handler handlers/orders.mjs는 도구 넷을 처리해요. list_orders는 orders-N.json 문자열을 그대로 돌려줍니다. export_orders는 데이터 대신 래퍼 명령 q.sh N "<SQL>"과 표 이름, 컬럼 목록, 건수만 돌려주고요. 나머지 둘은 다음과 같아요.

  • aggregate_orders: where(기간, 지역, 카테고리, 상태, 고객 ID 목록)로 거른 뒤 metric(count, sum_amount, avg_amount, sum_qty, max_amount, min_amount, count_distinct_customers)으로 집계합니다. group_by를 주면 그룹별 값을 정렬해 limit(최대 100)개까지 돌려줍니다.
  • find_orders: 같은 where로 거른 주문을 정렬해 limit·offset 단위로 돌려주고, 조건에 맞는 전체 건수(total_matched)를 함께 줍니다.

make_catalog.mjs가 도구 다섯 개(메모 도구 get_memo 포함)를 catalog_orders.json에 써요. 그리고 make_configs.mjs가 조건마다 생성기 설정과 --mcp-config에 줄 mcp.json을 만듭니다. 원본 조건의 설정을 모델 호출 없이 펼쳐 보면 _meta가 붙은 걸 확인할 수 있어요(발췌).

node make_catalog.mjs && node make_configs.mjs > /dev/null
node mcpgen/mkconfig.mjs --config configs/s2/A-N3000.json --dry-run
  _meta list_orders {"anthropic/maxResultSizeChars":500000}

질문은 make_questions.mjs가 questions.jsonl로 써요. 모든 질문 끝에는 주문 데이터는 lab 서버 도구로 볼 수 있다. 마지막 줄에 'ANSWER: <값>' 형식으로 답하고, 값에는 쉼표와 단위를 쓰지 마.를 붙이고, 채점은 마지막 ANSWER: 줄만 봅니다. 질문은 단순 필터(Q02 2026년 3월 refunded 주문의 amount 합계 등), 그룹(Q06 refunded 주문이 있는 고객 수 등), 주문 찾기(Q07 제주 지역에서 amount가 가장 큰 주문의 order_id), 계산 조합(Q12 3월 paid 주문 amount의 중앙값 등) 네 묶음이에요.

정답은 answers.mjs가 JSON 데이터를 Node로 계산한 값과 answers.sql을 sqlite3 -readonly로 돌린 값을 비교해서, 하나라도 다르면 멈춰요. 출력은 발췌예요.

node make_questions.mjs && node answers.mjs
questions.jsonl: 12 questions
N=1000 node == sql: yes  Q01=133 Q02=3486300 Q03=145581 Q04=식품 Q05=C0076 1746200 Q06=100 Q07=O000409 Q08=190 Q09=5.9 Q10=111 Q11=16 Q12=131300.0
       ties: Q04 false, Q05 false, Q07 false, Q11 10th/11th false; Q02 rows 24, Q12 rows 135

모델이 SQL로 푸는 조건에서 허용 규칙으로 열어 준 명령은 래퍼 q.sh 하나예요. 래퍼는 건수와 SQL 두 인자만 받고, DB 경로를 스스로 정하고, 점(.)으로 시작하는 sqlite3 명령 줄을 거부하고, SQL을 표준 입력으로 sqlite3 -readonly -safe에 넘겨요. -readonly는 쓰기를, -safe는 .shell, ATTACH, writefile() 같은 위험한 기능을 막는 sqlite3 옵션이에요. install_q.sh는 래퍼를 /tmp/claude-<uid>/cmcpbig/bin/q.sh로 복사하고 권한을 555로 바꿉니다. macOS의 /tmp는 /private/tmp를 가리키는 링크라서, 허용 규칙과 도구가 돌려주는 명령은 모두 실제 경로(pwd -P)로 씁니다.

sh install_q.sh
/private/tmp/claude-501/cmcpbig/bin/q.sh 3000 "SELECT status, COUNT(*) FROM orders GROUP BY status;"
/private/tmp/claude-501/cmcpbig/bin/q.sh
cancelled|242
paid|2370
refunded|388

claude -p를 그냥 부르면 사용자 CLAUDE.md, 권한 허용 목록, 계정에 연결한 MCP 커넥터가 함께 실려요. 그래서 run.mjs는 모든 호출을 빈 실행 디렉터리 /tmp/claude-<uid>/cmcpbig/run에서 claude -p --model opus --output-format stream-json에 다음 옵션을 붙여 하나씩 부릅니다.

  • 빈 실행 디렉터리 + --setting-sources project: 사용자 설정(~/.claude/settings.json의 권한 허용 목록 등)과 CLAUDE.md를 읽지 않습니다.
  • --strict-mcp-config --mcp-config: 준 서버 하나만 붙입니다. 이것이 없으면 계정에 연결한 claude.ai 커넥터가 따라 붙어요.
  • --allowedTools "mcp__lab": 서버 lab의 도구는 묻지 않고 부르고, 조건에 따라 Bash 규칙만 더 허용합니다.
  • --effort high, --max-turns 20: 한도에 걸리면 결과가 error_max_turns입니다.
  • --no-session-persistence: 대화 기록 파일을 남기지 않습니다.

호출마다 600초가 넘으면 자식 프로세스를 PID로 끝내요. stream-json 전체는 out/<실습>/<조건>/<질문>-r<회차>.jsonl로 남깁니다.

총 입력 토큰은 결과 이벤트 usage의 input_tokens + cache_creation_input_tokens + cache_read_input_tokens로, 호출 하나에서 모든 요청이 읽은 입력의 합이에요. grade.mjs의 판정은 다섯 가지예요. 정답, 오답, 답 없음(파일을 못 읽었다며 숫자를 내지 않음), 끝내지 못함(error_max_turns, 타임아웃), 권한 거부 뒤 실패(거부가 있었고 정답이 아님)입니다. summary.mjs가 호출 기록과 채점 결과로 글의 숫자를 내고, show.mjs는 stream-json 한 호출에서 필요한 필드만 남겨 JSON으로 찍습니다(긴 문자열은 잘라 ...(N chars)를 붙이고, 홈 경로는 mask.mjs가 ~로 바꿔요).

실습 1: 결과가 크면 Claude Code는 무엇을 하나

도구 get_memo 하나만 실은 서버로, 본문 종류와 길이만 바꿔 가며 한 번씩 불러 볼게요. handler handlers/blob.mjs가 같은 문장을 되풀이한 본문을 정확히 원하는 글자 수(JavaScript 문자열 길이)로 만들고, 끝에 "끝 표식: 이 메모의 문서 번호는 MEMO-7731-K 입니다."를 붙입니다.

  • en: 영어 문장 "This memo describes the order processing rules, and refunds and cancellations are counted by the date they were received. " 되풀이
  • ko: 한국어 문장 "이 메모는 주문 처리 기준을 적은 운영 문서이며 환불과 취소는 접수한 날짜를 기준으로 집계합니다. " 되풀이

질문은 get_memo 도구를 한 번 불러 메모를 읽어 줘. 그다음 (1) 도구 결과로 메모 본문을 받았는지, 파일 저장 위치 안내를 받았는지, 중간이 생략됐다는 표시가 있는지 한 문장으로 말해. (2) 메모 끝 표식에 적힌 문서 번호를 마지막 줄에 'ANSWER: <문서 번호>' 형식으로 적어.입니다. --tools ""라서 모델에게는 MCP 도구 말고 아무 도구도 없어요.

summary.mjs s1은 서버 기록의 글자 수, tool_result(도구 결과로 모델에게 실제로 들어간 블록)가 무엇이었는지, 도구 결과 몫 토큰, 모델 답을 한 줄로 찍어요.

도구 결과 몫은 도구를 부른 요청 다음 요청의 입력 토큰에서, 그 요청의 입력 토큰을 뺀 값입니다.

node summary.mjs s1 a-
a-en-45000 MAX_MCP=unset: server 45,000 chars -> inline, tool_result 45,000 chars, result tokens 11,525, answer MEMO-7731-K
a-en-49999 MAX_MCP=unset: server 49,999 chars -> inline, tool_result 49,999 chars, result tokens 12,795, answer MEMO-7731-K
a-en-50001 MAX_MCP=unset: server 50,001 chars -> file (persisted, 48.9KB + 2KB preview), tool_result 2,268 chars, result tokens 725, answer 확인 불가 (끝 표식이 생략된 부분에 있음)
a-en-50001 MAX_MCP=200000: server 50,001 chars -> file (persisted, 48.9KB + 2KB preview), tool_result 2,268 chars, result tokens 723, answer 확인 불가 (메모 끝부분이 도구 결과에 포함되지 않음)
a-en-70000 MAX_MCP=unset: server 70,000 chars -> file (persisted, 68.4KB + 2KB preview), tool_result 2,268 chars, result tokens 727, answer 확인 불가 (메모 끝부분이 생략되어 문서 번호를 볼 수 없음)
a-en-70000 MAX_MCP=200000: server 70,000 chars -> file (persisted, 68.4KB + 2KB preview), tool_result 2,268 chars, result tokens 725, answer 확인 불가 (메모 끝부분이 생략됨)

출력을 보면 49,999자까지는 그대로 들어갔어요. 50,001자부터는 MAX_MCP_OUTPUT_TOKENS=200000으로 토큰 한도를 충분히 올려도 파일로 빠졌습니다.

50,001자 영어 본문의 실제 토큰은 약 1만 2천 8백(49,999자 줄 값)으로, 기본 토큰 한도 25,000보다 작아요. 그러니 토큰과 상관없는 문자 한도가 따로 있다는 뜻이고, MCP 문서의 문장("saves a successful result with no image content to a file once it's longer than 50,000 characters, whatever its token count")과도 맞습니다. 이때 모델이 받은 tool_result는 이렇습니다(뒤를 자른 발췌).

node show.mjs out/s1/a-en-50001/default-r1.jsonl tools 400
{"type":"assistant","message":{"content":[{"type":"tool_use","name":"mcp__lab__get_memo","input":{}}]}}
{"type":"user","message":{"content":[{"type":"tool_result","content":"<persisted-output>\nOutput too large (48.9KB). Full output saved to: ~/.claude/projects/-private-tmp-claude-501-cmcpbig-run/741d8b7c-373b-42e9-b64d-e797f641034b/tool-results/toolu_01NZ841NnMf7Q3PTmGbVSUf4.json\n\nPreview (first 2KB):\n[\n  {\n    \"type\": \"text\",\n    \"text\": \"This memo describes the order processing rules, and refunds and cancellations are counted by the date they were recei...(2268 chars)"}]}}

데이터 대신 <persisted-output>으로 감싼 저장 경로와 앞 2KB 미리보기가 왔어요. 미리보기는 Claude Code가 결과 블록 배열을 JSON으로 다시 쓴 파일의 앞부분이라 표식이 있는 끝부분은 보이지 않고, 모델은 네 번 모두 문서 번호를 "확인 불가"로 답했어요.

도구가 tools/list의 _meta에 "anthropic/maxResultSizeChars": 500000을 적으면, 그 도구의 문자 한도가 그 값으로 올라가요. 그리고 텍스트 결과에는 MAX_MCP_OUTPUT_TOKENS도 적용되지 않습니다.

node summary.mjs s1 c
c-en-70000-meta MAX_MCP=unset: server 70,000 chars -> inline, tool_result 70,000 chars, result tokens 17,876, answer MEMO-7731-K
c-ko-44990-meta MAX_MCP=10000: server 44,990 chars -> inline, tool_result 44,990 chars, result tokens 45,868, answer MEMO-7731-K

70,000자 영어 본문이 그대로 들어갔어요. 한국어 44,990자도 MAX_MCP_OUTPUT_TOKENS=10000인데 45,868토큰이 그대로 들어갔습니다. 한도를 올리는 방법은 두 가지입니다.

  • 사용자 쪽: MAX_MCP_OUTPUT_TOKENS. 토큰 판정만 바꾸고 5만 자 문자 한도는 그대로입니다.
  • 서버 쪽: anthropic/maxResultSizeChars. 도구별로, 최대 500,000자까지 문자 한도를 올리고 토큰 판정을 건너뜁니다.

실습 2: 네 가지 도구 설계

이번에는 같은 주문 데이터와 같은 질문 12개를, 도구 설계만 바꿔 풀게 해 볼게요. 건수는 200, 1,000, 3,000, 20,000입니다.

  • A(원본, 한도 올림): list_orders 하나. anthropic/maxResultSizeChars: 500000을 달아 3,000건(424,666자)까지 원본이 그대로 들어갑니다. --tools ""라 모델은 받은 JSON을 생각(thinking) 안에서 집계합니다. 20,000건은 500,000자를 넘어 파일로 빠지므로 Q01, Q02 두 번만 불러 그 동작만 확인했어요.
  • A0(원본, 기본 한도): 같은 list_orders에 표시가 없습니다. 1,000건부터 파일로 빠지고, 모델에게는 Read와 Bash를 주되 Bash 허용 규칙은 주지 않았어요. 1,000건과 20,000건 두 단계만 돌렸어요.
  • B(서버에서 거르기): aggregate_orders와 find_orders. 모델은 거를 조건과 집계 종류를 인자로 보내고 작은 JSON만 받습니다.
  • C(SQLite 파일 + SQL): export_orders가 조회 명령 형식과 스키마만 돌려주고, 모델은 Bash로 q.sh <행 수> "<SQL>"을 돌립니다. 허용 규칙은 Bash(/private/tmp/claude-501/cmcpbig/bin/q.sh <행 수> *) 하나예요.

첫 요청 토큰은 질문을 받은 첫 요청의 입력이고, 도구 결과 몫은 원본 조건(A)에서만 셉니다.

node summary.mjs tokens
A  N=200   calls 24  total input median 19,769 (19,712~36,222), first request 3,330, tool result 13,110 (13,110~13,110), per row 65.5
A  N=1000  calls 24  total input median 72,009 (71,952~72,056), first request 3,330, tool result 65,350 (65,350~65,350), per row 65.3
A  N=3000  calls 12  total input median 202,597 (202,539~401,792), first request 3,330, tool result 195,937 (195,937~195,937), per row 65.3
A  N=20000 calls 2  total input median 7,986 (7,982~7,989), first request 3,304
A0 N=1000  calls 36  total input median 78,556 (24,886~267,454), first request 5,339
A0 N=20000 calls 36  total input median 44,045 (31,552~245,190), first request 5,339
B  N=200   calls 36  total input median 15,277 (9,834~21,772), first request 4,877
B  N=1000  calls 36  total input median 15,292 (9,834~27,897), first request 4,877
B  N=3000  calls 36  total input median 15,328 (9,834~21,957), first request 4,877
B  N=20000 calls 36  total input median 15,193 (9,835~19,214), first request 4,877
C  N=200   calls 36  total input median 20,554 (14,763~28,024), first request 4,696
C  N=1000  calls 36  total input median 20,446 (14,744~27,143), first request 4,696
C  N=3000  calls 36  total input median 20,504 (14,751~26,928), first request 4,696
C  N=20000 calls 36  total input median 20,531 (14,764~27,133), first request 4,696
  • 원본(A)의 도구 결과 몫은 200건 13,110, 1,000건 65,350, 3,000건 195,937토큰으로 주문 한 건에 65.3~65.5토큰이었어요. 총 입력 중앙값은 19,769에서 202,597로 건수에 거의 비례해 늘었습니다.
  • 서버 거르기(B)는 15,193~15,328, SQL(C)은 20,446~20,554로, 건수가 100배가 돼도 1% 안쪽에서 움직였어요.
  • 기본 한도(A0)의 1,000건은 78,556으로, 원본을 그대로 넣은 A(72,009)보다도 컸어요. 거부된 명령, Read로 다시 읽은 파일 조각, grep 출력이 대화에 쌓였기 때문입니다.
  • 20,000건의 A는 7,986토큰만 읽고 끝났습니다.

정답 수와 시간도 볼게요. 출력은 원본(A) 200~3,000건과 SQL(C) 3,000건만 둘째 줄을 남긴 발췌예요.

node summary.mjs acc
A  N=200   correct per rep 12,12 (of 12)  correct 24
         단순 필터 8/8, 그룹 8/8, 행 찾기 2/2, 계산 조합 6/6; turns median 2 (2~2), duration median 15.3s (6.2~40.8), output tokens median 1,561, cost $3.53, spilled 0, denials 0, fallback 0
A  N=1000  correct per rep 12,12 (of 12)  correct 24
         단순 필터 8/8, 그룹 8/8, 행 찾기 2/2, 계산 조합 6/6; turns median 2 (2~2), duration median 40.4s (8.3~283.6), output tokens median 5,221, cost $17.32, spilled 0, denials 0, fallback 0
A  N=3000  correct per rep 10 (of 12)  correct 10, wrong 1, unfinished 1
         단순 필터 4/4, 그룹 2/4, 행 찾기 1/1, 계산 조합 3/3; turns median 2 (2~2), duration median 140.2s (22.6~377.0), output tokens median 18,867, cost $21.67, spilled 0, denials 0, fallback 0
A  N=20000 correct per rep 0 (of 2)  no_answer 2
A0 N=1000  correct per rep 7,11,12 (of 12)  correct 30, denied_fail 6
A0 N=20000 correct per rep 9,10,10 (of 12)  correct 29, denied_fail 6, unfinished 1
B  N=200   correct per rep 12,12,12 (of 12)  correct 36
B  N=1000  correct per rep 12,12,12 (of 12)  correct 36
B  N=3000  correct per rep 12,12,12 (of 12)  correct 36
B  N=20000 correct per rep 12,12,12 (of 12)  correct 36
C  N=200   correct per rep 12,12,12 (of 12)  correct 36
C  N=1000  correct per rep 12,12,12 (of 12)  correct 36
C  N=3000  correct per rep 12,12,12 (of 12)  correct 36
         단순 필터 12/12, 그룹 12/12, 행 찾기 3/3, 계산 조합 9/9; turns median 4 (3~5), duration median 12.6s (8.0~17.6), output tokens median 739, cost $0.94, spilled 0, denials 0, fallback 0
C  N=20000 correct per rep 12,12,12 (of 12)  correct 36

출력을 보면 서버 거르기(B)와 SQL(C)은 네 단계 모두 세 번 다 12개를 맞혔어요.

원본(A)은 200건과 1,000건에서 두 번 다 12개를 맞혔지만, 시간과 출력이 건수를 따라 늘었습니다. 시간 중앙값은 15.3초, 40.4초, 140.2초, 출력 토큰 중앙값은 1,561, 5,221, 18,867이에요. 3,000건은 한 번만 돌렸고, Q06(refunded 주문이 있는 고객 수)은 293명을 292명으로 하나 빠뜨렸고, Q10(주문 5건 이상인 고객 수)은 600초 제한 안에 끝내지 못했어요.

비용은 A 3,000건 12호출이 21.67달러(호출당 약 1.8달러), C 3,000건 36호출이 0.94달러였어요. 원본 조건은 질문이 도구 결과보다 앞에 와서, 같은 결과라도 질문마다 프롬프트 캐시에 새로 써야 하고 캐시 쓰기는 읽기보다 비쌉니다.

기본 한도(A0)는 정답 수가 3회 사이에 7~12개(1,000건)로 크게 흔들렸어요. 파일로 빠진 결과를 안내문이 권하는 python3 -c로 읽으려 했지만, 이 환경에서 python3는 읽기 전용 명령이 아니어서 모두 거부됐습니다. 명령 종류를 센 이 집계는 출력을 싣지 않은 기록이에요.

정리

범위: Claude Code 2.1.295 claude -p, Opus 5.5(claude-opus-5-5) effort high, 합성 주문 200~20,000건, 질문 12개를 조건마다 1~3회(첫 단락). 같은 명령을 다시 돌리면 숫자가 다를 수 있어요.

  • Claude Code 2.1.295는 5만 자를 넘는 MCP 성공 결과를 자르지 않고 통째로 파일로 빼 모델에게 앞 2KB 미리보기만 줬고, MAX_MCP_OUTPUT_TOKENS=200000으로 올려도 이 문자 한도는 그대로였어요. 읽을 도구가 없으면 모델은 끝부분의 표식을 보지 못했습니다.
  • 도구가 _meta에 anthropic/maxResultSizeChars를 적으면 70,000자 영어 본문이 그대로 들어갔고, 한국어 44,990자는 MAX_MCP_OUTPUT_TOKENS=10000에서도 45,868토큰이 그대로 들어갔어요. 큰 결과를 꼭 넘겨야 하는 도구라면 사용자 쪽 토큰 한도보다 이 서버 쪽 표시를 먼저 보세요.
  • 원본을 그대로 넣으면 주문 한 건에 약 65토큰씩 입력이 늘었고, 50만 자 상한을 넘는 20,000건은 한도를 올려도 들어가지 않았어요. 서버에서 거르는 도구(B)와 SQLite 파일 + SQL(C)은 200건부터 20,000건까지 입력이 약 1만 5천, 약 2만 토큰으로 거의 같았고 세 번 모두 12개를 맞혔습니다. 합성 주문 한 가지와 질문 12개로 잰 결과라서, 실제 데이터에서는 건당 토큰과 정답률이 다를 수 있습니다.
  • 기본 한도에 Bash와 Read만 열어 둔 조건(A0)은 1,000건에서 정답 수가 3회 사이 7~12개로 흔들렸고, 안내문이 권하는 python3 -c는 모두 거부됐어요. 이 조건의 결과는 사용자 허용 규칙에 달려 있어요.
내 링크 만들기