본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 15. 15:23

60초 만에 MCP 서버의 토큰 세금(Token Tax) 측정하기

요약

MCP 서버의 도구 정의가 컨텍스트 예산을 소모하는 '토큰 세금(Token Tax)' 개념을 설명하고 이를 측정하는 방법을 안내합니다. 실제 파일 시스템 서버를 통해 도구 정의가 차지하는 토큰 비중을 계산하고, 여러 서버 사용 시 발생하는 컨텍스트 팽창 문제를 경고합니다.

핵심 포인트

  • 토큰 세금은 에이전트 작업 전 도구 정의가 소모하는 컨텍스트 비용임
  • MCP 서버의 tools/list를 tiktoken으로 토큰화하여 직접 측정 가능
  • 도구 검색(Tool Search)은 로딩을 지연시킬 뿐 토큰 소모를 줄이지 못함
  • 여러 MCP 서버를 사용할 경우 토큰 소모가 복리로 증가하여 컨텍스트 팽창 유발

**MCP 서버 토큰 세금 (MCP server token tax)**은 에이전트가 유용한 일을 단 하나라도 수행하기 _전_에 모든 도구 정의(tool definition)가 소모하는 컨텍스트 예산(context budget)을 의미합니다. 이를 측정하려면 서버의 tools/list JSON을 가져와 각 정의를 토큰화(tokenize)하면 됩니다. Claude Code의 도구 검색(Tool Search)은 로딩을 지연시킬 뿐, 세금을 줄여주지는 않습니다. 아래의 60초 감사(audit)를 실행하면 다른 사람의 수치를 반복하는 대신, 도구당 실제 비용을 확인할 수 있습니다.

요약하자면: MCP 서버 토큰 세금은 에이전트가 무엇인가를 하기 전에 모든 도구 정의가 소모하는 컨텍스트 예산입니다. 이를 측정하려면 서버의 tools/list를 가져와 tiktoken으로 각 정의를 토큰화하십시오. 실제 파일 시스템(filesystem) 서버를 실행한 결과: 14개의 도구, 2,638 토큰, 200K 컨텍스트 창의 약 1.3%를 차지했습니다.

AI 공개 (AI disclosure): 저는 AI의 도움을 받아 mcp_token_tax.py를 작성했으며, 게시하기 전에 직접 실행했습니다. 아래의 모든 수치는 해당 스크립트를 실제로 실행하여 복사했거나, 날짜가 명시된 링크가 포함된 외부 수치입니다. 각각을 구분하여 표시했습니다.

저는 단순히 숫자를 반복하고 싶지 않았습니다. 직접 측정하고 싶었습니다. 그래서 실제로 공개된 파일 시스템 MCP 서버를 구동하여 실제 tools/list를 캡처하고 계산했습니다. 그 결과는 저를 놀라게 했으며, 이것이 이 포스트가 존재하는 이유입니다.

요약 (TL;DR)

  • 토큰 세금 (Token Tax)이란 실제 작업이 수행되기 전, (거의) 매 턴마다 컨텍스트 (Context) 내에 자리 잡고 있는 도구 정의 (Tool definitions)의 비용을 의미합니다.
  • 실제 @modelcontextprotocol/server-filesystem 서버를 측정해 보았습니다: 14개의 도구, 2,638 토큰, 200K 컨텍스트 창의 약 1.3%. 서버 하나는 작습니다. 이것이 대부분의 "컨텍스트 팽창 (Context bloat)" 포스트들이 생략하는 솔직한 부분입니다.
  • 이는 복리로 쌓입니다. Anthropic의 자체 수치에 따르면, 5개의 서버를 설정할 경우 약 55K 토큰이 소모되며, 내부적으로 "최적화 전"에는 134K 토큰이 소모됩니다 (Anthropic, 2025년 11월). 세금은 실재합니다. 다만 단일 서버가 아닌 그 "합계" 속에 존재할 뿐입니다.
  • 도구 검색 (Tool Search)은 지연 로딩 (Lazy loading)을 통해 세금을 숨길 뿐, 삭제하지는 않습니다. 도구가 실제로 실행될 때, 그 정의는 여전히 컨텍스트에 진입합니다. 따라서 어떤 도구가 비용이 많이 드는지 여전히 파악하고 있어야 합니다.
  • 이 스크립트는 키가 필요 없고 (Keyless), 읽기 전용이며 (Read-only), 저장된 픽스처 (Fixture)에 대해 결정론적 (Deterministic)입니다. 표준 라이브러리 (Stdlib)와 tiktoken만 사용합니다. 복사해서 실행하고, 여러분의 스택을 감사 (Audit)해 보세요.

이 글은 **MCP FinOps: 삭감하기 전에 측정하라 (Measure before you cut)**라는 작은 스레드의 첫 번째 포스트입니다. 이 글은 제 작업의 제어 측면인 폭주하는 에이전트 루프를 중단시키는 엄격한 지출 한도 설정 (Hard spend-cap that stops a runaway agent loop)잘못된 에이전트 동작이 실행되기 전 거부하는 실행 전 게이트 (Pre-execution gate that refuses a bad agent action before it runs)와 나란히 위치합니다. 그것들은 잘못된 동작을 막아줍니다. 이 글은 단지 여러분에게 수치를 제공할 뿐입니다. 왜냐하면 측정하지 않은 것은 삭감할 수 없기 때문입니다.

토큰 세금 (Token Tax)이란 정확히 무엇인가?

도구 정의 (Tool definition)는 텍스트입니다. 이름, 제목, 사람이 읽을 수 있는 설명, 입력값에 대한 JSON 스키마 (JSON Schema) (그리고 이제는 종종 출력 스키마와 어노테이션 (Annotations)까지 포함됩니다)로 구성됩니다. MCP 서버를 연결하면, 호스트는 이 모든 것을 직렬화 (Serialize)하여 모델의 컨텍스트에 주입합니다. 그래야 모델이 해당 도구가 존재한다는 것과 어떻게 호출해야 하는지를 알 수 있기 때문입니다.

그 텍스트는 단 한 번만 비용이 청구되는 것이 아닙니다. 모델이 도구를 사용하기 위해서는 해당 도구들을 계속해서 "보고" 있어야 하므로, 턴(turn)이 반복될 때마다 계속 따라붙습니다. 한 번도 호출하지 않은 10개의 도구가 있다면, 그것들은 모든 요청마다 컨텍스트 윈도우(context window) 안에 조용히 자리 잡고 있습니다. 이것이 바로 세금(tax)입니다. 즉, 선언은 했지만 실제로는 사용하지 않을 수도 있는 기능에 대해 지불하는 임대료인 셈입니다.

여기서 두 가지 비용이 발생합니다. 명백한 것은 비용(dollars)입니다. 즉, 반복적으로 지불해야 하는 입력 토큰(input tokens)입니다. 더 교묘한 비용은 바로 "공간(room)"입니다. 정의(definition)에 사용되는 모든 토큰은 실제 대화, 검색된 문서, 혹은 붙여넣은 파일에 사용할 수 없는 토큰이 됩니다. MCP 명세(spec)는 2026-07-28 릴리스 후보(release candidate)를 통해 상태가 없는(stateless) 핵심 구조로 나아가고 있으며, 이는 많은 것을 재편하겠지만 이곳의 기본적인 물리 법칙을 바꾸지는 않습니다. 정의는 여전히 어떤 방식으로든 모델에 전달되어야 하기 때문입니다.

Ken Alger는 그의 2026년 3월 멀티 에이전트 MCP에 관한 글에서 그로 인해 발생하는 하류 증상(downstream symptom)을 명확하게 짚었습니다. "너무 많은 도구를 다루는 단일 에이전트는 종종... 도구 혼동(Tool Confusion): 여러 도구가 사용 가능할 때 잘못된 함수를 선택하는 문제"와 더불어 "지연 시간(Latency) 및 비용(Cost)" 문제를 겪습니다." 토큰은 그 문제의 한 단면일 뿐입니다. 정확도(Accuracy)가 또 다른 단면입니다. Anthropic의 동일한 11월 포스트에 담긴 자체 테스트 결과에 따르면, 모든 정의를 한꺼번에 전달하는 것을 "중단"했을 때 모델의 도구 선택 정확도가 49%에서 74%로 상승했습니다. 컨텍스트 내의 도구가 적을수록 더 나은 선택을 하게 됩니다. 세금은 비단 금전적인 것만이 아닙니다.

도구: 지금 바로 여러분의 서버에서 실행해 보세요

전체 코드는 다음과 같습니다. 이 도구는 단 한 가지 작업만 수행합니다. tools/list를 읽고, tiktokeno200k_base 인코딩(gpt-4o 제품군 인코딩 — 이전 모델의 경우 cl100k_base로 교체 가능)을 사용하여 각 도구를 토큰화한 뒤, 컨텍스트 윈도우 점유율과 라운드당 예상 비용을 포함한 도구별 테이블을 출력합니다.

도구를 입력하는 방법은 두 가지입니다. 게시된 stdio 서버를 지정하면 JSON-RPC 핸드셰이크 (handshake)를 수행하고 실제 tools/list를 실시간으로 캡처합니다. 이 방식은 키(key)가 필요 없는 읽기 전용 방식이며, tools/call을 절대 호출하지 않으므로 아무것도 실행되지 않습니다. 또는 이전에 저장해둔 JSON 픽스처 (fixture)를 전달하여, 바이트 단위까지 동일하게 재현되는 결정론적 (deterministic) 실행을 수행할 수 있습니다.

#!/usr/bin/env python3
"""mcp_token_tax.py - MCP 서버의 도구 정의에 대한 토큰 세금(token tax)을 측정합니다."""
import argparse, json, subprocess, sys, threading
...

실행 방법은 두 가지입니다. 실제 npm 패키지를 대상으로 실시간 실행:

pip install tiktoken
python3 mcp_token_tax.py \
  --server "npx -y @modelcontextprotocol/server-filesystem@latest /tmp"

또는 이미 저장된 tools/list를 대상으로 실행 (결정론적):

python3 mcp_token_tax.py --fixture filesystem_toolslist.json --price 3.00

저는 실시간 방식과 픽스처 방식을 나란히 실행해 보았습니다. 동일하게 캡처된 버전의 경우 토큰 수가 일치했으며, 이것이 바로 이 방식의 핵심입니다. 픽스처는 추측값이 아니라 실제로 캡처된 출력값입니다. 한 가지 주의할 점은 @latest는 계속 변하는 대상이라는 것입니다. 패키지에 새로운 설명이나 스키마 (schema) 필드가 추가되면, 실시간 측정값이 픽스처와 달라질 수 있습니다. 다음 달에도 비교 가능한 수치가 필요하다면 버전을 고정(@2025...)하십시오.

수치가 실제로 의미하는 것

다음은 실제 @modelcontextprotocol/server-filesystem (서버 자체 보고 버전: secure-filesystem-server v0.2.0)을 대상으로 오늘 캡처한 실행 결과 그대로의 내용입니다:

MCP token tax  -  secure-filesystem-server v0.2.0
encoding: o200k_base (gpt-4o family)  |  14 tools

...

저에게 그 1.3%라는 수치를 인용하기 전에 두 가지 사실을 정직하게 밝히겠습니다. 저는 o200k_base인 gpt-4o 토크나이저 (tokenizer)를 사용하여 계산했습니다. Claude는 공개된 토크나이저를 제공하지 않으므로, Claude의 200K 컨텍스트 윈도우 (context window) 기준으로는 이것이 하나의 _대리 지표 (proxy)_이며, 실제 Claude 토큰 수치는 약간 다를 수 있습니다. 또한 저는 전체 도구 (tool) 객체를 압축된 JSON 형식으로 계산했습니다. name/description/inputSchema만 주입하는 호스트 (host)라면 여기서 약 1,640 토큰에 더 가까운 수치가 나올 것이고, 동일한 객체를 프리티 (pretty-printed) 형식으로 출력하면 약 4,036 토큰이 소모됩니다. 따라서 "모델에 도달하는 실제 양"에 대한 정직한 범위는 대략 1.6K~4K이며, 2,638 토큰은 모든 도구에 대해 동일하게 계산된, 그 범위 내에서 제가 방어할 수 있는 단일 지점입니다. 아래의 순위와 점유율은 매우 확실합니다. 절대적인 총합은 정밀한 측정값이 아닌, 규모(order-of-magnitude)를 나타내는 수치로 취급하십시오.

이제 솔직한 이야기를 해보겠습니다. 2,638 토큰. 200K 윈도우의 1.3%. 서버 하나를 기준으로 볼 때, 이는 무서운 수준이 아닙. 만약 단일 MCP 서버가 비상사태(five-alarm fire)라는 것을 확인받으러 오셨다면, 저는 그렇게 말씀드릴 수 없습니다. 적어도 이 서버는 그렇지 않습니다. 파일 시스템 (filesystem) 서버는 매우 가볍습니다. 14개의 도구, 간결한 설명, 단순한 스키마 (schema)로 구성되어 있습니다. 가장 비용이 많이 드는 단일 도구인 read_text_file은 250 토큰이 소모되는데, 이는 주로 해당 도구의 설명이 head/tail 동작을 산문 형태로 상세히 기술하고 있기 때문입니다.

그렇다면 공포는 어디에서 오는 걸까요? 두 가지 이유가 있으며, 둘 다 실재하는 문제입니다.

첫째, 장황한 텍스트가 비용을 유발합니다. 즉, 단순한 파라미터 개수가 아니라 산문(prose)과 스키마(schema) 모두가 원인입니다. read_text_file(250 토큰, 긴 head/tail 설명 포함)과 list_allowed_directories(143 토큰, 산문이 거의 없고 파라미터가 0개)를 비교해 보십시오. 하지만 설명(description)에만 과도한 공을 돌려서는 안 됩니다. 이 14개 도구 전체를 살펴보면, 토큰 수는 설명의 길이(~0.36의 상관관계)보다 입력 스키마(input schema)의 크기(~0.80의 상관관계)와 더 밀접하게 연관되어 있습니다. edit_file이 이를 증명합니다. 설명은 짧지만 비대한 중첩 edits 스키마 때문에 이 도구는 239 토큰을 기록하며 표에서 두 번째로 무거운 도구가 되었습니다. 따라서 규칙은 "산문을 주의하라"가 아니라 "전체 표면적(total surface area)을 주의하라"입니다. 단락 형태의 설명과 거대한 enum 리스트를 포함한 방대한 스키마 모두 비용을 발생시킵니다. 이 두 가지를 모두 제공하는 서버는 이 가벼운 참조 서버(reference server)가 내지 않는 세금을 지불하게 됩니다. 이것이 바로 실제 환경에서 사용되는 GitHub나 Slack 같은 무거운 서버들이 한 자릿수(order of magnitude) 더 높은 수치를 기록하는 이유입니다.

둘째, 이것은 복리로 작용합니다. 1.3%의 비용을 발생시키는 서버 하나는 아무것도 아닙니다. 하지만 실제 서버들을 쌓아 올리면 이야기가 달라집니다. Anthropic은 2025년 11월에 실제 측정값을 발표했습니다: GitHub는 약 26K 토큰, Slack은 약 21K 토큰이었으며, 58개의 도구를 가진 5개 서버 설정은 "대화가 시작되기도 전에 약 55K 토큰"에 도달했습니다. 그들의 내부 배포 환경에서는 "최적화 전"에 134K 토큰에 달했습니다 (Anthropic engineering, 2025-11-24). 이것은 그들이 직접 측정한 그들의 수치이며, 저는 인용하는 것이지 주장하는 것이 아닙니다. 하지만 그 형태는 제 실험 결과가 축소판으로 예측한 것과 정확히 일치합니다. 가벼운 서버 하나는 저렴하지만, 수다스러운 서버 열 개는 하나의 세금 구간(tax bracket)이 됩니다.

FinOps(재무 운영) 관점에서 보자면, 달러 단위의 수치는 ROI(투자 대비 수익)를 결정짓는 핵심 요소입니다. 입력 토큰 100만 개당 3달러라고 가정할 때, 파일 시스템 서버 하나는 한 라운드에 0.0079달러가 듭니다. 사소한 수준입니다. 하지만 55K 토큰 규모의 멀티 서버 스택에서 에이전트 루프(agent loop)의 턴(turn) 빈도로 이를 실행한다면, 모델이 해당 도구들을 사용하든 안 하든 매 호출마다 55K 토큰의 오버헤드(overhead) 비용을 영원히 지불하게 됩니다. 이것이 여러분의 청구서와 대조해 볼 만한 계산법입니다. 실제 --price--ctx 값을 대입하여 최종 결론을 확인해 보십시오.

왜 도구 검색(Tool Search)은 세금을 제거하는 대신 숨기는가

Claude Code는 도구 검색(Tool Search) 기능을 출시했으며, 이는 진정으로 훌륭합니다. 도구 정의(tool definitions)가 컨텍스트 창(context window)의 약 10%를 초과할 때, 시스템은 모든 도구를 사전에 로드하는 것을 중단합니다. 대신 가벼운 인덱스(index)를 유지하다가, 모델이 특정 도구가 필요하다고 결정할 때만 해당 도구의 전체 정의를 가져옵니다. Anthropic은 전체 라이브러리에 여전히 접근할 수 있으면서도 전달되는 토큰이 약 85% 감소했다고 보고했습니다. 진정한 승리입니다. 사용해 보십시오.

하지만 동사에 주목하십시오. 그것은 로딩을 *연기(defers)*하는 것입니다. 정의를 삭제하는 것이 아닙니다. 모델이 실제로 create_or_update_file을 호출하려고 할 때, 그 도구의 전체 스키마(schema)가 그 시점에 컨텍스트(context)에 진입합니다. 즉, 여러분은 그 시점에 세금을 지불하며, 여기에 해당 도구를 찾아낸 검색 단계의 비용까지 추가됩니다. 사용하는 도구에 대한 총 청구 금액은 대략 동일합니다. 변하는 점은 이번 턴에 사용하지 않는 50개의 도구에 대해서는 비용을 지불하지 않게 된다는 것입니다.

이것이 바로 "도구 검색을 활성화했으니 끝났다"라는 생각이 함정인 이유입니다. 지연 로딩(Lazy loading)은 훌륭한 기본 설정입니다. 하지만 그것은 측정(measurement)이 아니며, 의사 결정(decision)도 아닙니다. 그것은 여러분이 결코 들여다보지 않았던 비용을 조용히 분할 상환(amortizes)할 뿐입니다. 저의 반대 의견은 다음과 같으며, 댓글에서 기꺼이 틀렸음을 인정하겠습니다: 세금을 추적하여 없애는 것은 그것을 제어하는 것이 아닙니다. 제어하는 방법은 위의 표를 열어 여러분의 read_text_file을 찾는 것입니다. 즉, 설명을 절반으로 줄일 수 있는 비대한 도구 하나를 찾거나, 하나로 합칠 수 있는 거의 중복된 네 개의 읽기 도구를 찾아내어 삭감하는 것입니다. 도구 검색은 비대함(bloat)을 보이지 않게 만듭니다. 감사는 그것을 수정 가능하게(editable) 만듭니다. 먼저 측정하고, 그다음 삭감한 뒤, 남은 부분은 지연 로딩이 처리하도록 두십시오.

이것이 아닌 것

저는 과장해서 홍보하기보다는, 작더라도 정직한 수치를 여러분이 신뢰하기를 바랍니다.

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0