본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 22. 23:00

당신의 MCP 서버에 40개의 도구가 필요하지 않은 이유

요약

MCP(Model Context Protocol) 서버 설계 시 모든 API 엔드포인트를 도구로 노출하는 대신, 에이전트의 사용성을 고려하여 도구의 수를 최적화해야 합니다. 너무 많은 유사 도구는 모델의 혼란과 오류를 유발하므로, 목적 중심의 추상화된 도구 설계가 필요합니다.

핵심 포인트

  • API 엔드포인트를 그대로 미러링하는 방식은 에이전트에게 오류 가능성을 높임
  • 모델은 맥락 이해보다 패턴 매칭에 의존하므로 도구 이름과 스키마가 명확해야 함
  • 도구의 개수를 줄이고 목적별로 그룹화하여 에이전트의 판단력을 높여야 함
  • 프로덕션 환경에서는 포괄적인 노출보다 정제된 인터페이스가 더 효과적임

MCP 데모들을 보면 모든 것을 노출하는 것이 승리라고 생각하게 만듭니다.

"여기 제 모든 엔드포인트(endpoints)가 있습니다. 여기 제 모든 데이터베이스 테이블(database tables)이 있습니다. 여기 제 모든 내부 액션(internal actions)이 있습니다. 이제 에이전트(agent)는 무엇이든 호출할 수 있습니다."

이것은 약 10분 동안은 강력하게 느껴집니다.

하지만 곧 모델(model)이 잘못된 도구(tool)를 호출하거나, 올바른 인자(argument)를 잘못된 형태(shape)로 전달하거나, 검색 엔드포인트(search endpoint)에 차트를 요청하거나, 파괴적인 액션(destructive action)을 재시도하거나, 도구 이름이 세 가지 다른 의미로 해석될 만큼 모호하여 확신에 찬 듯한 답변을 내놓게 됩니다.

문제는 MCP가 아닙니다. 문제는 MCP를 백엔드(backend)를 위한 마법 같은 어댑터(adapter)로 취급하는 것입니다.

MCP 서버는 단순히 "내 API를 에이전트가 접근할 수 있게 만든 것"이 아닙니다. 그것은 매우 문자 그대로 받아들이고, 매우 주의가 산만한 사용자를 위한 제품 접점(product surface)입니다.

그리고 그 사용자는 다름 아닌 언어 모델(language model)입니다.

함정: 하나의 엔드포인트, 하나의 도구

첫 번째 본능은 명확합니다:

GET /users/:id        -> get_user
GET /users            -> list_users
GET /invoices/:id     -> get_invoice
...

이것은 API를 그대로 반영하기 때문에 깔끔해 보입니다.

하지만 에이전트에게는 종종 나쁜 방식입니다.

인간은 문서를 읽고, 제품의 맥락(context)을 이해하며, 유사한 경로(route) 사이에서 선택할 수 있습니다. 모델은 당신의 제품을 진정으로 "이해"하지 못합니다. 그들은 이름, 설명, 스키마(schema), 이전 메시지, 그리고 컨텍스트 윈도우(context window)에 들어가는 모든 정보에 대해 패턴 매칭(pattern-match)을 수행할 뿐입니다.

만약 모델에게 40개의 유사한 도구를 준다면, 당신은 모델에게 힘을 준 것이 아닙니다. 거의 맞을 법한 40가지의 오류 가능성을 준 것입니다.

프로덕션 환경에서 바뀐 점

FXMacroData를 위한 MCP 레이어(layer)를 구축하면서 교훈은 명확해졌습니다.

백엔드에는 캘린더 이벤트(calendar events), FX 페어(FX pairs), 환율(rates), COT 포지셔닝(COT positioning), 원자재(commodities), 채권 수익률(bond yields), 메타데이터(metadata), 그리고 문서(docs)를 위한 일반적인 API 경로(routes)가 있습니다. 모든 경로를 MCP로 미러링(mirroring)하는 것은 포괄적으로 보일 수 있지만, 에이전트가 너무 많은 유사한 선택지 사이에서 고민하게 만들 것입니다.

유용한 MCP 경계(boundary)는 더 작았습니다:

  • 시장 요약(market summary)을 위한 도구 하나;
  • 발표 일정(release calendar)을 위한 도구 하나;
  • FX 페어 스냅샷(FX pair snapshot)을 위한 도구 하나;
  • 차트화 가능한 지표 이력(chartable indicator history)을 위한 도구 하나;
  • COT 포지셔닝(COT positioning)을 위한 도구 하나;
  • 원자재(commodities)를 위한 도구 하나;
  • 채권 수익률(bond yields)을 위한 도구 하나;
  • 데이터 범위 및 메타데이터(data coverage and metadata)를 위한 도구 하나.

이는 데모에서는 덜 인상적일 수 있습니다.

하지만 실제 채팅에서는 더 유용합니다.

에이전트는 이제 질문이 엔드포인트(endpoint), 캐시된 대시보드 페이로드(cached dashboard payload), 또는 정규화된 데이터 테이블(normalized data table) 중 어디에 매핑되는지 알 필요가 없습니다. 오직 사용자의 의도(user intent)만 파악하면 됩니다.

도구는 약속입니다

API 라우트(route)는 다음과 같이 말합니다:

이 요청을 보내면, 서버가 응답할 것입니다.

MCP 도구는 다음과 같이 말해야 합니다:

정확히 이 작업을 위해, 이러한 정확한 입력값과 함께 나를 사용하세요. 그러면 이런 종류의 결과를 기대할 수 있습니다.

이는 좋은 도구 설명(tool description)이 마케팅 문구가 아니라는 것을 의미합니다. 그것은 모델을 위한 라우팅 로직(routing logic)입니다.

나쁨:

{
  "name": "get_data",
  "description": "API에서 데이터를 가져옵니다."
...

좋음:

{
  "name": "lookup_release_calendar",
  "description": "하나의 통화 및 날짜 범위에 대해 예정된 경제 발표 이벤트를 반환합니다. 향후 거시 경제 이벤트에 관한 질문에 답하기 전에 이 도구를 사용하세요."
...

금융에 관심이 없더라도, 이 패턴은 중요합니다. 두 번째 도구는 모델에게 언제 이 도구를 사용해야 하는지, 무엇을 반환하는지, 그리고 어떤 종류의 사용자 질문을 지원하는지를 알려줍니다.

이것이 기준입니다.

더 적은 도구, 더 날카로운 경계

저는 에이전트에게 영리한 도구 45개를 주는 것보다 지루한 도구 8개를 주는 편을 택하겠습니다.

지루한 도구는 여러분의 내부 라우트 구조(internal route structure)가 아니라 사용자의 의도(user intent)에 매핑되어야 합니다.

사용자 의도더 나은 도구 형태
"앞으로 무엇이 예정되어 있나요?"lookup_calendar
...

중요한 부분은 모델이 유용한 호출을 하기 전에 머릿속으로 여러분의 백엔드 아키텍처(backend architecture)를 조립할 필요가 없어야 한다는 점입니다.

그것은 여러분의 역할입니다.

Diagram comparing endpoint-shaped MCP tools with a smaller intent-shaped MCP tool layer

이름은 생각보다 더 중요합니다

개발자들은 간결한 이름을 좋아합니다.

하지만 모델에게는 지루한 이름이 필요합니다.

저는 예전에 다음과 같은 이름들을 좋아했습니다:

query
fetch
resolve
...

이러한 이름들은 우리에게는 편리하지만, 모델에게는 모호합니다. 모델이 설명(description)으로부터 너무 많은 것을 추론하도록 강요하기 때문입니다.

제품의 의도(product intent)를 담은 이름을 선호하세요:

search_docs
lookup_account_status
get_time_series
...

길어도 괜찮습니다. 모호한 것이 더 큰 비용을 초래합니다.

데이터베이스 행(row) 전체를 반환하지 마세요

응답 형태(response shape)는 입력 스키마(input schema)만큼이나 중요합니다.

만약 도구가 거대한 중첩 객체(nested object)를 반환한다면, 모델은 기꺼이 잘못된 필드를 사용할 것입니다. 내부 메모를 인용하거나, created_atupdated_at과 혼동하거나, 사용자에게 보여줄 의도가 없었던 구현 세부 사항을 요약해 버릴 수도 있습니다.

해당 작업을 지원하는 데 필요한 가장 작은 형태를 반환하세요.

Diagram showing an oversized database-row response becoming a smaller MCP response contract with status, items, and next_action

{
  "status": "ok",
  "items": [
...

next_action 필드는 모델이 이를 통해 더 나은 동작을 보이는 것을 보기 전까지는 우스꽝스러워 보일 수 있습니다.

당신은 단순히 데이터를 반환하는 것이 아닙니다. 당신은 행동 유도성(affordances)을 반환하는 것입니다.

해피 패스(happy path)가 아닌 실패를 위해 구축하세요

대부분의 도구 데모는 성공적인 호출만을 보여줍니다.

프로덕션 품질은 지루한 실패 상태(failure states)에서 나옵니다.

다음과 같은 상황에서 도구는 무엇을 반환해야 할까요?

  • 일치하는 레코드가 없을 때;
  • 사용자가 권한 밖의 것을 요청했을 때;
  • 입력값은 유효하지만 범위가 너무 넓을 때;
  • 상위 데이터(upstream data)가 오래되었을(stale) 때;
  • 작업이 위험하여 확인이 필요할 때;
  • 모델이 잘못된 도구를 선택했을 때?

모델이 500 에러나 빈 배열(empty array)만 보고 이 모든 것을 추론하게 만들지 마세요.

예를 들어:

{
  "status": "no_results",
  "message": "해당 날짜 범위에 일치하는 행을 찾을 수 없습니다.",
...

이것은 단순히 더 나은 UX를 제공하는 것만이 아닙니다. 환각(hallucination) 압박을 줄여줍니다. 모델은 침묵을 메우는 대신 정확하게 말할 수 있는 무언가를 갖게 됩니다.

당신의 OpenAPI 스키마(schema)는 여전히 중요합니다

MCP가 API 설계를 대체하는 것은 아닙니다.

오히려 MCP는 허술한 API 설계의 문제를 더 명확하게 드러냅니다.

깔끔한 OpenAPI 스키마는 타입(type), 설명(description), 인증 요구사항(auth requirements), 그리고 예시(examples)에 대한 신뢰할 수 있는 단일 출처(source of truth)를 제공합니다. 그러면 MCP 레이어는 그 위에 에이전트 친화적인(agent-friendly) 더 작은 도구 세트를 노출할 수 있습니다.

제가 선호하는 스택은 다음과 같습니다:

Backend API
  -> 문서화된 OpenAPI 스키마 (OpenAPI schema)
  -> 작은 MCP 도구 레이어 (small MCP tool layer)
...

MCP 서버가 문서화되지 않은 두 번째 API가 되어서는 안 됩니다. 그것은 디버깅해야 할 접점(surface)을 두 개로 늘릴 뿐입니다.

도구 목록을 UI처럼 테스트하세요

버튼에 "초안 삭제"라고 적혀 있다면, 당신은 그 라벨을 검토할 것입니다.

MCP 도구 이름이 run_action이라고 되어 있다면, 당신 역시 그 라벨을 검토해야 합니다.

저는 도구 목록을 출력하고 인간에게 다음과 같은 질문을 던지는 간단한 테스트 방식을 선호합니다:

  • 각 도구가 언제 사용되어야 하는지 알 수 있는가?
  • 두 개의 도구가 같은 일을 하는 것처럼 들리지는 않는가?
  • 너무 일반적인(generic) 도구 이름은 없는가?
  • 파괴적인(destructive) 도구들이 명확하게 표시되어 있는가?
  • 필수 인자(required arguments)가 명확한가?
  • 각 도구가 모델이 안전하게 요약할 수 있는 형태(shape)를 반환하는가?

그다음, 지루할 정도로 평범한 프롬프트(prompt)로 실제 도구 호출을 실행해 봅니다:

이번 주에 무엇이 바뀌었나요?
최근 에러를 보여주세요.
API 키에 관한 문서를 찾아주세요.
...

만약 모델이 계속해서 잘못된 도구를 선택한다면, 단순히 "프롬프트를 개선"하려고 하지 마세요. 도구의 경계(tool boundary)를 수정해야 합니다.

이 아이디어의 배경

저는 FXMacroData와 관련된 공개 API, OpenAPI, 문서, 그리고 MCP 접점들을 작업하면서 이 문제에 대해 고민해 왔습니다.

도메인이 핵심이 아닙니다. 교훈이 핵심입니다.

제품 데이터를 에이전트에게 노출하는 순간, 당신의 API는 더 이상 결정론적인 호출자(deterministic callers)만을 위한 것이 아닙니다. 강력한 이름, 엄격한 스키마(schema), 명확한 실패(failure) 처리, 그리고 인간 개발자보다 더 적은 선택지가 필요한 모델을 위한 것이기도 합니다.

경계가 더 나을수록, 필요한 "에이전트적(agentic)" 마법은 줄어듭니다.

제가 현재 사용하는 체크리스트

새로운 MCP 도구를 추가하기 전에, 저는 스스로에게 묻습니다:

  • 이것이 실제 사용자의 의도인가, 아니면 단순히 내가 가지고 있는 엔드포인트(endpoint)인가?
  • 기존 도구가 동일한 질문에 답할 수 있는가?
  • 이름이 지루할 정도로 구체적인가?
  • 설명(description)에 언제 사용해야 하는지가 명시되어 있는가?
  • 인자(arguments)가 충분히 좁은 범위로 정의되어 있는가?
  • 응답 형태(response shape)가 내부 객체보다 작은가?
  • 결과 없음(no-results)이나 권한 실패(permission failures)를 명확하게 처리하는가?
  • 모델이 응답을 직접 인용하더라도 괜찮을 정도인가?
  • 이 도구를 호출해야 하는 최소 하나 이상의 스모크 프롬프트(smoke prompt)가 있는가?

만약 답변이 모호하다면, 저는 아마 아직 새로운 도구가 필요하지 않은 상태일 것입니다.

결론 (Closing)

MCP는 에이전트(agent)에게 외부 시스템을 사용할 수 있는 표준화된 방법을 제공하기 때문에 유용합니다.

하지만 표준이 잘못된 경계(boundaries)를 구원해주지는 않습니다.

여러분의 MCP 서버가 백엔드(backend)가 할 수 있는 모든 것을 노출할 필요는 없습니다. 에이전트가 수행해야 할 몇 가지 작업만을 노출해야 하며, 올바른 호출이 명확해지도록 이름과 스키마(schema)를 설계해야 합니다.

최고의 에이전트 도구는 가장 강력한 도구가 아닙니다.

모델이 쉽게 오해할 수 없는 도구입니다.

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0