MCP도 Tool Use를 사용합니다.

자손킴 @jasonkim@hackers.pub

지난 글에서는 Subagent가 Tool Use 위에서 어떻게 동작하는지 알아보았다. 이번 글에서는 MCP(Model Context Protocol)가 Tool Use와 어떻게 연결되는지 내장 도구인 Subagent를 예시로 비교하며 설명할 것이다. 또한 내장 도구가 있음에도 불구하고 MCP가 필요한 이유에 대해서도 알아본다.

내장 도구 vs MCP 도구

Subagent 글에서 살펴본 Task 도구는 에이전트에 내장된 도구였다. MCP 도구는 어떻게 다를까? 결론부터 말하면 LLM 입장에서는 둘 다 그냥 도구다. 차이는 실행이 어디서 일어나는가뿐이다.

내장 도구든 MCP 도구든 API 요청의 tools 배열에 동일한 형태로 들어간다:

{
  "tools": [
    {
      "name": "Read",
      "description": "Reads a file from the local filesystem...",
      "input_schema": { ... }
    },
    {
      "name": "Task",
      "description": "Launch a new agent to handle complex tasks...",
      "input_schema": { ... }
    },
    {
      "name": "mcp__claude-in-chrome__navigate",
      "description": "Navigate to a URL in the browser...",
      "input_schema": { ... }
    }
  ]
}

LLM은 도구 이름과 description, input_schema만 보고 어떤 도구를 호출할지 결정한다. 이 도구가 내장인지 MCP인지는 알 수 없고 알 필요도 없다.

핵심 차이는 도구가 어디서 실행되는가다.

내장 도구 (예: Task) MCP 도구
실행 위치 Host 내부 Host 외부 (별도 프로세스)
통신 방식 함수 호출 프로토콜 (STDIO/HTTP)
실행 주체 Host (또는 LLM) 외부 시스템
결과 Host가 생성한 데이터 외부 시스템이 반환한 데이터

다이어그램으로 보면 더 명확하다:

                        Host 프로세스
    ─────────────────────────────────────────────────
    
                         Agent

              ┌────────────┴────────────┐
              ▼                         ▼
            Task                   mcp__xxx 도구
          (내장 도구)                     │
              │                         │
              ▼                         │ STDIO / HTTP
         새 메시지 루프                    │
           (LLM)                       │

    ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─

                        외부 프로세스     ▼
                                   MCP Server
                               (Chrome, DB...)
  • 내장 도구 흐름: Agent → Task → 새 메시지 루프 (모두 Host 프로세스 내부)
  • MCP 도구 흐름: Agent → mcp__xxx 도구 → [프로세스 경계] → MCP Server (Host 외부)

실제 예시로 보는 차이

지난 글에서 본 Explorer subagent 호출과 MCP 도구 호출을 비교해보자.

내장 도구 (Task) 호출:

{
  "type": "tool_use",
  "id": "toolu_01ABC123",
  "name": "Task",
  "input": {
    "subagent_type": "Explore",
    "prompt": "entity 구조를 탐색해주세요",
    "description": "Entity 구조 탐색"
  }
}

Task 도구가 호출되면 Host 내부에서 새로운 메시지 루프가 생성되고, Haiku 모델이 Glob, Read 등 다른 내장 도구로 탐색을 수행한다. 결과는 LLM이 생성한 분석 텍스트다.

MCP 도구 호출:

{
  "type": "tool_use",
  "id": "toolu_01DEF456",
  "name": "mcp__claude-in-chrome__navigate",
  "input": {
    "tabId": 12345,
    "url": "http://localhost:3000"
  }
}

MCP 도구가 호출되면 Host는 외부의 MCP Server(Chrome 브라우저 프로세스)에 명령을 전달한다. 결과는 브라우저가 반환한 데이터(스크린샷, 콘솔 로그 등)다.

Agent 입장에서는 둘 다 tool_use 요청을 받아 실행하고 tool_result를 반환하는 동일한 패턴이다.

MCP 도구가 tools 배열에 포함되는 방식

MCP 서버가 제공하는 도구들은 어떻게 tools 배열에 들어갈까? MCP 도구는 mcp__server-name__tool-name 형태의 이름을 가진다.

{
  "name": "mcp__claude-in-chrome__navigate",
  "description": "Navigate to a URL, or go forward/back in browser history...",
  "input_schema": {
    "type": "object",
    "properties": {
      "tabId": {
        "description": "Tab ID to navigate",
        "type": "number"
      },
      "url": {
        "description": "The URL to navigate to",
        "type": "string"
      }
    },
    "required": ["tabId", "url"]
  }
}

이 네이밍 규칙이 필요한 이유는 여러 MCP 서버가 동시에 연결될 수 있기 때문이다. 예를 들어 filesystem 서버와 github 서버가 둘 다 read라는 도구를 제공한다면 충돌이 발생한다. mcp__filesystem__readmcp__github__read로 구분하면 이 문제가 해결된다.

Claude Code에서 /mcp를 입력하면 연결된 MCP 서버 목록을 볼 수 있다. Claude in Chrome이 제공하는 도구들을 살펴보자:

도구 이름 설명
mcp__claude-in-chrome__navigate URL로 이동하거나 브라우저 히스토리 앞/뒤로 이동
mcp__claude-in-chrome__computer 마우스/키보드로 브라우저와 상호작용, 스크린샷 촬영
mcp__claude-in-chrome__read_page 페이지의 접근성 트리 표현을 가져옴
mcp__claude-in-chrome__find 자연어로 페이지 요소 찾기
mcp__claude-in-chrome__form_input 폼 요소에 값 입력
mcp__claude-in-chrome__javascript_tool 페이지 컨텍스트에서 JavaScript 실행

이 도구들은 에이전트가 MCP 서버에 연결할 때 서버로부터 목록을 받아와 tools 배열에 추가된다. 에이전트가 시작될 때 대략 다음과 같은 과정이 일어난다:

  1. 에이전트가 설정된 MCP 서버들에 연결
  2. 각 서버에 tools/list 요청을 보내 제공하는 도구 목록 수신
  3. 받은 도구들에 mcp__server-name__ prefix를 붙여 tools 배열에 추가
  4. API 요청 시 내장 도구와 함께 전송

MCP 도구 호출 흐름

Claude가 MCP 도구를 호출하면 에이전트는 다음 단계를 수행한다:

Claude                    Agent                    MCP Server
   │                        │                          │
   │  tool_use              │                          │
   │  (mcp__claude-in-      │                          │
   │   chrome__navigate)    │                          │
   │ ─────────────────────► │                          │
   │                        │                          │
   │                      prefix 파싱                   │
   │                      server: claude-in-chrome     │
   │                      tool: navigate               │
   │                        │                          │
   │                        │  tools/call              │
   │                        │ ───────────────────────► │
   │                        │                          │
   │                        │  실행 결과                 │
   │                        │ ◄─────────────────────── │
   │                        │                          │
   │  tool_result           │                          │
   │ ◄───────────────────── │                          │
   │                        │                          │

결국 MCP 도구 호출도 일반 Tool Use와 동일한 패턴을 따른다. 차이점은 에이전트가 도구를 직접 실행하는 대신 외부 MCP 서버에 위임한다는 것뿐이다.

MCP는 왜 도구를 외부로 분리하는가

지금까지 MCP 도구가 어떻게 동작하는지 살펴보았다. 그런데 왜 이런 구조가 필요할까?

모든 도구를 내장할 수 없다

에이전트에 도구를 추가하는 가장 단순한 방법은 에이전트 내부에 직접 구현하는 것이다. 하지만 이 방식에는 한계가 있다:

  • 모든 도구를 미리 구현할 수 없다: 파일 시스템, 데이터베이스, 브라우저, Slack, GitHub, Jira... 세상에는 수많은 시스템이 있고 에이전트 개발자가 이 모든 연동을 직접 구현하기는 불가능하다.
  • 사용자마다 필요한 도구가 다르다: 어떤 사용자는 PostgreSQL을, 다른 사용자는 MongoDB를 사용한다. 모든 조합을 에이전트에 내장할 수 없다.
  • 도구 업데이트가 어렵다: 외부 API가 변경되면 에이전트 전체를 다시 배포해야 한다.

MCP는 이 문제를 도구 제공자와 도구 사용자의 분리로 해결한다.

MCP의 핵심 구조

MCP는 클라이언트-서버 아키텍처를 따른다.

참여자 (Participants):

  • MCP Host: MCP 클라이언트를 관리하는 AI 애플리케이션 (예: Claude Desktop, VS Code, Claude Code)
  • MCP Client: MCP 서버와 연결을 유지하고 컨텍스트를 얻어오는 컴포넌트
  • MCP Server: MCP 클라이언트에게 컨텍스트를 제공하는 프로그램 (도구 제공자)

Host와 Client의 관계:

  • Host는 MCP 서버 연결마다 별도의 MCP Client를 생성한다
  • 예를 들어 Claude Code(Host)가 Chrome 서버와 filesystem 서버에 연결하면 두 개의 MCP Client 객체가 생성된다
  • 각 MCP Client는 하나의 MCP Server와 전용 연결을 유지한다

이 분리 덕분에:

  • 도구 제공자는 MCP 서버만 만들면 됨 (에이전트 코드 수정 불필요)
  • 에이전트 개발자는 MCP 클라이언트만 구현하면 모든 MCP 서버의 도구 사용 가능
  • 사용자는 필요한 MCP 서버만 설치하여 에이전트 기능 확장 가능

MCP와 인증

원격 MCP 서버를 사용할 때는 인증이 필요한 상황이 발생한다. MCP 서버가 사용자의 GitHub 저장소에 접근하거나 Slack 워크스페이스에 메시지를 보내야 할 때, "이 요청이 정말 이 사용자로부터 온 것인가?"를 확인해야 한다.

MCP는 프로토콜 수준에서 OAuth 2.1 인증 체계를 표준화했다. 덕분에 어떤 MCP 클라이언트든 동일한 방식으로 MCP 서버에 인증할 수 있고, MCP 서버 개발자는 인증 로직을 한 번만 구현하면 모든 클라이언트와 호환된다.

Tool Use를 넘어서

지금까지 MCP를 Tool Use의 확장으로 설명했다. 실제로 MCP 도구는 가장 많이 사용되는 기능이고, LLM이 외부 시스템과 상호작용하는 핵심 방식이다.

하지만 MCP가 제공하는 것이 도구만은 아니다. MCP 명세를 보면 Tool Use와 무관하게 동작하는 기능들이 있다. 이 기능들은 tool_use -> tool_result 사이클을 거치지 않고 다른 방식으로 LLM에게 컨텍스트를 제공하거나 LLM의 능력을 활용한다.

MCP의 확장 기능

MCP는 도구(Tools) 외에도 몇가지 핵심 기능들이 있다. Resources, Prompts, 그리고 Sampling이다.

Resources

Resources는 Tool Use를 거치지 않는 데이터 제공 기능이다. 도구는 LLM이 "행동"을 요청할 때 호출되지만 Resource는 LLM이 응답을 생성하기 전에 컨텍스트로 미리 주입된다.

예를 들어 PostgreSQL MCP 서버가 데이터베이스 스키마를 Resource로 노출한다고 하자. 사용자가 "users 테이블에 email 컬럼 추가해줘"라고 요청하면 LLM은 별도의 도구 호출 없이도 현재 스키마 구조를 이미 알고 있다. SELECT * FROM information_schema.columns를 먼저 실행할 필요가 없는 것이다. Resource가 컨텍스트에 미리 주입되어 있기 때문이다.

Prompts

Prompts도 Tool Use와 무관하다. MCP 서버가 미리 정의한 재사용 가능한 프롬프트 템플릿으로 클라이언트가 직접 요청해서 가져온다.

예를 들어 코드 리뷰 MCP 서버가 "보안 취약점 분석" 프롬프트 템플릿을 제공하면 클라이언트는 이 템플릿을 불러와 LLM에게 전달할 수 있다. LLM이 도구를 호출하는 것이 아니라 클라이언트가 MCP 서버로부터 프롬프트를 받아오는 것이다.

Sampling (역방향 LLM 호출)

Sampling은 가장 독특한 기능이다. 일반적인 MCP 흐름은 LLM → Agent → MCP Server지만 Sampling은 이 방향을 뒤집는다:

일반 흐름:     LLM → Agent → MCP Server
Sampling:     MCP Server → Agent → LLM

MCP 서버가 복잡한 판단이 필요할 때 역으로 LLM에게 질문할 수 있다. 예를 들어 코드 분석 MCP 서버가 특정 패턴을 발견했을 때 "이 코드가 보안 취약점인지 판단해달라"고 LLM에게 요청하는 식이다. MCP 서버는 LLM의 답변을 기반으로 최종 결과를 만들거나 다른 도구나 함수를 사용하는 등의 판단을 할 수 있게 된다.

Sampling은 Tool Use의 tool_use -> tool_result 패턴이 아니라 MCP 프로토콜 자체의 sampling/createMessage 요청을 통해 동작한다.

마무리

지금까지 MCP가 Tool Use 위에서 어떻게 동작하고 또 Tool Use를 넘어 어떤 기능들을 제공하는지 살펴보았다.

MCP 도구는 Tool Use다. 내장 도구와 동일하게 tools 배열에 포함되고 tool_use로 호출되며 tool_result로 결과가 반환된다. LLM 입장에서는 구분이 없다. 차이점은 실행 위치뿐이다. 내장 도구는 Host 프로세스 내부에서, MCP 도구는 외부 MCP Server에서 실행된다.

하지만 MCP는 도구만 제공하지 않는다. Resources와 Prompts는 Tool Use 없이 컨텍스트를 제공하고 Sampling은 MCP 서버가 역으로 LLM을 활용할 수 있게 한다. MCP는 Tool Use를 확장하면서도 Tool Use만으로는 해결할 수 없는 영역까지 커버하는 프로토콜이다.

모든 도구를 에이전트에 내장할 수 없기 때문에 에이전트와 도구를 분리할 필요가 생겼고 MCP는 도구 제공자와 사용자를 분리하여 생태계 확장을 가능하게 한다.

이 글에서는 Tool Use의 기본 구조를, 이어지는 글에서는 Subagent가 Tool Use 위에서 동작함을 살펴보았고 이번 글에서 MCP가 Tool Use를 확장하면서도 그 이상의 기능을 제공함을 살펴보았다. Claude Code의 핵심 확장 기능들은 Tool Use라는 메커니즘 위에서 동작하지만 MCP 생태계는 그보다 더 넓은 가능성을 열어두고 있다.

Read more →
4

Neovim Super villain. 풀스택 엔지니어 내지는 프로덕트 엔지니어라고 스스로를 소개하지만 사실상 잡부를 담당하는 사람. CLI 도구를 만드는 것에 관심이 많습니다.

Hackers' Pub에서는 자발적으로 바이럴을 담당하고 있는 사람. Hackers' Pub의 무궁무진한 발전 가능성을 믿습니다.

그 외에도 개발자 커뮤니티 생태계에 다양한 시도들을 합니다. 지금은 https://vim.kr / https://fedidev.kr 디스코드 운영 중

Hi, I'm who's behind Fedify, Hollo, BotKit, and this website, Hackers' Pub! My main account is at @hongminhee洪 民憙 (Hong Minhee) :nonbinary:.

Fedify, Hollo, BotKit, 그리고 보고 계신 이 사이트 Hackers' Pub을 만들고 있습니다. 제 메인 계정은: @hongminhee洪 民憙 (Hong Minhee) :nonbinary:.

FedifyHolloBotKit、そしてこのサイト、Hackers' Pubを作っています。私のメインアカウントは「@hongminhee洪 民憙 (Hong Minhee) :nonbinary:」に。

Welcome to the Newsmast AI Channel. A curated feed of posts from the Fediverse, handmade by @newsmast@newmast.social, and broadcasting to Bluesky (if you've opted-in via @bsky.brid.gy)!

To post to the community just add to your post. You can create a list to follow this account, and exclude the posts from your home timeline.

Wondering why you’ve been boosted by this account? Check out this thread: newsmast.social/@newsmast/1119