다들 붙이는 MCP가 뭐길래, AI에게 도구를 연결하는 표준 입문
Tools18분 읽기

다들 붙이는 MCP가 뭐길래, AI에게 도구를 연결하는 표준 입문

MCP를 호스트·클라이언트·서버 세 부품과 전송·데이터 층으로 뜯어 봅니다. 호출 메시지, 2026-07-28 개정, 로컬·원격 연결, 도구 정의 비용, 권한 점검까지 정리했습니다.

Claude Desktop에 폴더 하나를 연결하고 “다운로드 폴더에 뭐가 있어?“라고 물으면 목록이 돌아옵니다. 그런데 그 폴더를 실제로 읽은 프로그램은 누구 것이고, 어디서 돌고, 누구의 권한으로 움직였을까요? 이 질문에 답하려면 MCP(Model Context Protocol)를 “AI 앱과 도구를 잇는 표준”이라는 한 줄로 두지 말고 층별로 뜯어 봐야 합니다. 이 글은 바깥에서 안쪽으로 내려갑니다. 부품의 배치, 메시지가 오가는 길, 서버가 내놓는 부품, 호출 한 번의 속, 2026-07-28 개정이 걷어낸 것, 붙일 때 따라오는 권한, 규모가 커질 때의 비용 순서입니다. 기준은 공식 문서의 최신 개정(2026-07-28)이고 확인일은 2026-10-27(UTC)입니다.

폴더를 읽는 프로그램은 어디서 돌고 있나

공식 아키텍처 문서는 MCP를 호스트, 클라이언트, 서버 셋으로 나눕니다. 호스트는 Claude Code나 Claude Desktop, Visual Studio Code 같은 AI 앱입니다. 호스트는 연결할 서버마다 클라이언트를 하나씩 만들고, 클라이언트는 자기 서버와 전용 연결을 유지합니다. 문서의 예로, Visual Studio Code가 Sentry 서버에 붙으면 클라이언트 객체가 하나 생기고, 로컬 파일 시스템 서버에 또 붙으면 하나 더 생깁니다.

아래 그림은 내 컴퓨터에서 도는 AI 앱을 기준으로 그렸습니다. 볼 것은 경계선입니다. 클라이언트는 호스트 안에 있고, 서버는 내 컴퓨터 안과 바깥 어느 쪽에도 놓일 수 있습니다.

호스트 안의 클라이언트 셋이 로컬 서버 둘과 원격 서버 하나에 각각 연결된 구조 그림 1. 호스트 한 개, 클라이언트는 서버 수만큼, 길은 두 종류

그림에서 “로컬”과 “원격”을 가르는 것은 서버가 놓인 장소가 아니라 쓰는 길입니다. 문서는 같은 컴퓨터에서 표준 입출력(stdio)으로 연결되는 서버를 흔히 로컬 서버, Sentry가 자기 플랫폼에서 운영하며 Streamable HTTP로 연결되는 서버를 원격 서버라고 부른다고 설명합니다. stdio 서버는 보통 클라이언트 하나를 상대하고, HTTP 서버는 여러 클라이언트를 받습니다.

처음 질문의 답도 여기서 나옵니다. 폴더를 읽은 것은 Claude Desktop이 자식 프로세스로 띄운 파일 시스템 서버이고, 내 컴퓨터에서 내 사용자 계정 권한으로 돌며, 설정에 적어 준 폴더만 열 수 있습니다.

쉽게 말하면

식당 홀 직원(호스트)이 주방 스테이션마다 전용 주문 창구(클라이언트)를 하나씩 두고 일한다고 생각해 보세요. 어느 창구로 주문을 넣을지는 홀 직원이 손님 말을 듣고 정하고, 각 스테이션은 자기 방식대로 요리합니다. 모든 창구가 같은 주문서 양식을 쓰기 때문에 스테이션이 늘어도 홀 직원은 새 양식을 배울 필요가 없습니다. MCP가 정하는 것은 이 주문서 양식까지이고, 요리가 안전한지는 주방마다 따로 봐야 합니다.

표준이 필요했던 이유는 곱셈과 덧셈의 차이로 보입니다. 앱 3곳이 서비스 4곳과 각자 이으면 연동이 12개(편집부 계산)지만, 서버를 한 번 만들어 두면 앱 쪽 3개와 서비스 쪽 4개, 7개로 끝납니다. 2024-11-25 Anthropic이 오픈 소스로 공개했고, 2025-12-09 Linux Foundation이 Agentic AI Foundation(AAIF)을 만들며 MCP를 창립 기여 프로젝트로 받았습니다. 같은 보도자료는 공개 MCP 서버가 1만 개를 넘었고 Claude, Cursor, Microsoft Copilot, Gemini, Visual Studio Code, ChatGPT가 채택했다고 적었습니다. 그리고 MCP는 맥락을 주고받는 방법만 정합니다. AI 앱이 모델을 어떻게 쓰고 받은 맥락을 어떻게 다룰지는 규격 밖입니다.

바깥 껍질은 길, 안쪽 껍질은 말

공식 문서는 MCP를 두 겹으로 설명합니다. 안쪽이 무슨 말을 주고받는지 정한 데이터 층, 바깥쪽이 그 말을 어떤 길에 싣는지 정한 전송 층입니다.

  • 데이터 층: JSON-RPC 2.0 메시지서버 발견(server/discover), 도구·리소스·프롬프트, 사용자에게 되묻기, 변경 알림. 규격 분량의 대부분이 여기에 있음
  • 전송 층: stdio 또는 Streamable HTTPstdio는 같은 컴퓨터의 자식 프로세스와 표준 입출력으로 대화하고 네트워크가 필요 없음. Streamable HTTP는 클라이언트가 HTTP POST로 보내고 필요하면 서버가 SSE로 스트리밍
  • 인증: HTTP 전송 쪽 일원격 서버는 OAuth로 토큰을 받는 것을 권장. stdio 서버는 환경 변수에서 자격 증명을 읽도록 규격이 안내

두 전송은 같은 JSON-RPC 메시지를 나르기 때문에 서버 코드를 크게 바꾸지 않고 로컬에서 원격으로 옮길 수 있습니다. 반대로 말하면 길이 달라도 말은 같아야 하고, 이 지점에서 stdio 서버의 유명한 함정이 생깁니다. stdio에서는 표준 출력이 곧 말이 오가는 길입니다. 서버가 디버깅용으로 print()를 한 줄 찍으면 JSON-RPC 응답 사이에 일반 글자가 섞여 연결이 깨집니다. 확인용 출력은 표준 오류(stderr)로 보내야 하고, 이 규칙은 HTTP 서버에는 해당하지 않습니다.

서버가 내놓는 부품 세 개와 쥐고 있는 사람

서버가 클라이언트에게 줄 수 있는 기능은 세 종류입니다. 종류보다 중요한 것은 누가 언제 고르느냐입니다.

부품 고르는 쪽 하는 일 예
도구(Tools) 모델 실행하는 함수. 바깥 세계에 무언가를 함 파일 쓰기, API 호출, 데이터베이스 조회
리소스(Resources) 앱 읽기 전용 맥락 자료. URI와 MIME 형식이 붙음 파일 내용, 데이터베이스 스키마, API 문서
프롬프트(Prompts) 사용자 재사용하는 질문 틀 슬래시 명령으로 부르는 “출장 계획” 틀

문서가 드는 데이터베이스 서버 예가 세 부품의 역할을 잘 갈라 줍니다. 질의를 실행하는 도구, 스키마를 담은 리소스, 도구 쓰는 법의 예시를 담은 프롬프트가 한 서버에 같이 있을 수 있습니다. 읽기만 하는 리소스와 세상을 바꾸는 도구가 나뉘어 있어서, 확인이 필요한 지점이 어디인지도 분명해집니다.

리소스 주소는 두 방식입니다. 고정 주소(calendar://events/2024)와, 값을 채우는 템플릿(travel://activities/{city}/{category})이고, 템플릿은 일부만 쳐도 후보를 제안하는 자동 완성을 지원합니다. 도구는 모델이 대화 맥락에서 스스로 골라 부르도록 설계됐지만, 규격은 사람이 거부할 수 있어야 한다고(SHOULD) 권고합니다. 모델에 노출되는 도구를 화면에 보이고, 실행될 때 표시하고, 작업 전에 확인을 받으라는 내용입니다.

서버 쪽 부품만 있는 것은 아닙니다. 클라이언트가 내놓는 부품으로 사용자에게 되묻기(elicitation)가 있습니다. 서버가 작업 중에 날짜나 확인 같은 입력을 사용자에게 요청하는 기능이고, 입력창을 띄우는 form 모드와 외부 주소로 보내는 URL 모드가 있습니다. 비밀번호·API 키·토큰·결제 정보는 form 모드로 요청하면 안 되고 URL 모드를 써야 합니다. 샘플링(서버가 앱의 모델에게 답변을 부탁하는 기능)과 로깅은 2026-07-28에 폐기 예정이 됐고, 뒤의 개정 절에서 다룹니다.

tools/call 한 번을 단계별로 열어 보기

서버를 붙이면 내부에서는 이 순서가 흐릅니다.

  1. (선택) 클라이언트가 server/discover로 서버가 지원하는 규격 버전, 기능, 정체를 묻습니다. 서버는 이 요청을 반드시 구현해야 하지만 클라이언트가 먼저 부를지는 선택입니다. 응답은 캐시할 수 있어서 문서 예시는 ttlMs를 3,600,000(1시간)으로 둡니다.
  2. 도구 목록을 요청하면(tools/list) 도구마다 이름, 설명, 입력 형식(JSON 스키마)이 옵니다. 목록에도 ttlMs(예시 300,000, 5분)와 cacheScope가 붙습니다.
  3. 모델이 목록을 보고 쓸 도구와 인자를 고릅니다. 사용자 승인을 거쳐 클라이언트가 tools/call을 보내고, 결과는 content 배열로 돌아옵니다.

실제 메시지는 이렇게 생겼습니다. 공식 문서의 계산기 도구 예시를 줄였고, 요청마다 규격 버전과 클라이언트 기능이 _meta에 실립니다.

// 목록 응답의 도구 하나: 이름, 설명, 입력 형식
{
  "name": "calculator_arithmetic",
  "title": "Calculator",
  "description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
  "inputSchema": {
    "type": "object",
    "properties": { "expression": { "type": "string" } },
    "required": ["expression"]
  }
}

// 호출 요청
{
  "jsonrpc": "2.0", "id": 3, "method": "tools/call",
  "params": {
    "name": "calculator_arithmetic",
    "arguments": { "expression": "2 + 3 * 4" },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": { "elicitation": {} }
    }
  }
}

// 응답: 결과는 content 배열, 실패는 isError로 표시
{
  "jsonrpc": "2.0", "id": 3,
  "result": { "resultType": "complete", "content": [{ "type": "text", "text": "14" }], "isError": false }
}

모델이 도구를 쓸지 말지 판단하는 거의 유일한 단서가 description과 inputSchema입니다. 도구 이름은 1~128자의 영문·숫자·밑줄·하이픈·점으로 짓고 서버 안에서 유일해야 한다고 규격이 권고합니다. 목록은 연결마다 달라지면 안 되고, 결정적인 순서로 돌려주면 클라이언트 캐시와 모델 업체의 프롬프트 캐시 적중에 유리합니다.

오류는 두 갈래로 나뉘고, 이 구분이 서버의 품질을 가릅니다.

종류 언제 돌아오는 모습 누가 고치나
프로토콜 오류 알 수 없는 도구, 규격에 어긋난 요청, 서버 내부 오류 JSON-RPC 오류(예: -32602) 사람이나 앱
도구 실행 오류 API 실패, 날짜 형식 같은 입력 검증 실패, 업무 규칙 위반 정상 응답 안의 isError: true와 설명 문장 모델이 읽고 인자를 고쳐 재시도

그래서 도구를 만드는 쪽은 “날짜는 미래여야 합니다”처럼 모델이 읽고 고칠 수 있는 문장으로 실패를 돌려주는 편이 낫습니다. 규격은 서버에게 입력 검증, 접근 제어, 호출 횟수 제한, 출력 정화를 요구하고(MUST), 클라이언트에게는 민감한 작업의 사용자 확인, 도구 입력을 서버로 보내기 전에 보여 주기, 시간 제한, 사용 기록을 권고합니다.

세션을 걷어낸 2026-07-28 개정

최신 개정의 핵심은 상태를 없앤 것입니다. 이전에는 연결을 열면 initialize로 인사를 나누고, 이후 요청이 그 세션(Mcp-Session-Id 헤더)에 기대어 처리됐습니다. 지금은 모든 요청이 규격 버전과 클라이언트 기능을 직접 싣고 가므로 서버는 요청 하나만 보고 처리합니다. 왼쪽이 2025-11-25까지, 오른쪽이 2026-07-28입니다. 같은 도구 호출이 앞쪽에서는 사전 절차를 거치고 뒤쪽에서는 한 번에 시작되는 것을 보면 됩니다.

이전 개정의 initialize와 세션 ID 절차, 그리고 2026-07-28의 요청마다 정보를 싣는 호출을 나란히 놓은 시퀀스 그림 2. 세션을 열고 호출하던 방식과, 요청마다 정보를 싣는 방식

그림 아래쪽 두 줄도 달라졌습니다. 스트림이 끊기면 예전에는 Last-Event-ID로 이어받았지만 이제 그 재개 기능이 없고, 진행 중이던 요청은 사라지므로 새 요청 ID로 다시 보냅니다. 목록(tools/list 등)은 연결마다 달라지지 않습니다. 장바구니나 열린 브라우저처럼 상태가 필요한 서버는 create_basket처럼 핸들을 돌려주는 도구를 만들고, 모델이 그 핸들을 다음 호출의 인자로 넘기는 방식을 규격이 권합니다.

변경 알림도 신청제가 됐습니다. 클라이언트가 subscriptions/listen으로 받을 알림 종류(도구 목록 변경, 리소스 변경 등)를 정해 열고, 서버가 확인 응답을 한 뒤 그 알림만 보냅니다. 다만 알림은 최선 노력(best effort)이라 재연결 중에는 빠질 수 있어서, 규격은 신선도를 위해 폴링을 병행하라고 합니다. 서버가 먼저 묻던 요청(roots/list, sampling/createMessage, elicitation/create)은 다중 왕복 요청(MRTR)으로 바뀌었습니다. 서버가 resultType: "input_required" 결과에 필요한 입력을 담아 돌려주면, 클라이언트가 inputResponses를 붙여 원래 요청을 다시 보내는 방식입니다.

이번 개정에는 폐기 예정 목록도 생겼습니다. 규격은 폐기 예정 기능을 최소 12개월 유예한 뒤 철거한다는 수명 정책을 같이 채택했고, 새로 만드는 구현은 아래 기능을 채택하지 말라고 합니다.

폐기 예정 대신 쓸 것
루트(Roots) 폴더·파일을 도구 인자, 리소스 URI, 서버 설정으로 넘김
샘플링(Sampling) 모델 업체 API를 서버가 직접 호출
로깅(Logging) stdio 서버는 stderr, 그 외는 OpenTelemetry
HTTP+SSE 전송 Streamable HTTP
동적 클라이언트 등록(RFC 7591) 클라이언트 ID 메타데이터 문서

오래 걸리는 작업을 다루는 태스크도 핵심 규격에서 빠져 공식 확장(io.modelcontextprotocol/tasks)으로 옮겨 갔습니다. 서버가 작업 핸들을 돌려주면 클라이언트가 tasks/get으로 폴링해 결과를 받는 구조입니다. 이 흐름이 날짜로 어떻게 쌓였는지 한 줄로 보면 다음과 같습니다.

2024-11-25 공개부터 2026-07-28 개정과 SDK 2.x 라인까지의 타임라인 그림 3. 개정 이름은 곧 날짜이고, 지금은 SDK도 2.x 라인이 현역

GitHub 릴리스 기준으로 Python SDK는 v2.3.0(2026-10-02), TypeScript SDK 서버 패키지는 2.4.0(2026-10-23)이 최신이고 TypeScript 쪽 1.x 라인도 1.32.2로 같이 갱신됩니다. 직접 서버를 만들 때는 SDK가 어느 개정을 따르는지부터 보는 것이 안전합니다.

내 컴퓨터에 붙이는 설정과 스코프

공식 로컬 연결 안내는 Claude Desktop에 파일 시스템 서버를 붙이는 과정입니다. 준비물은 Claude Desktop과 Node.js(LTS 권장)입니다.

  1. Claude 메뉴(창 안의 계정 설정이 아닙니다)에서 Settings를 열고 Developer 탭의 Edit Config를 누릅니다.
  2. 설정 파일(macOS는 ~/Library/Application Support/Claude/claude_desktop_config.json, Windows는 %APPDATA%\Claude\claude_desktop_config.json)에 아래 내용을 넣습니다.
  3. 창만 닫지 말고 앱을 완전히 종료한 뒤 다시 켭니다.
  4. 입력창 아래 “Add files, connectors, and more”의 Connectors에서 filesystem 서버의 도구 목록을 확인합니다.
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/username/Desktop", "/Users/username/Downloads"]
    }
  }
}

npx가 패키지를 받아 서버를 띄우고, args 끝의 경로들이 서버가 열 수 있는 폴더입니다. 필요한 폴더만 적는 것이 이 설정의 핵심이고, Windows에서는 역슬래시를 C:\\Users\\username\\Desktop처럼 두 번 씁니다. 서버가 목록에 안 나타나면 공식 문서의 순서대로 앱 완전 재시작, JSON 문법, 상대 경로가 아닌 절대 경로를 보고, 그다음 설정에 적은 명령을 터미널에서 직접 실행해 봅니다. 로그는 macOS의 ~/Library/Logs/Claude, Windows의 %APPDATA%\Claude\logs에 있고 mcp.log에 연결 정보가, mcp-server-서버이름.log에 서버의 stderr가 쌓입니다.

터미널 코딩 도구 Claude Code는 설정 파일 대신 명령으로 붙입니다.

# 원격 서버(HTTP). 이름과 주소를 지정
claude mcp add --transport http notion https://mcp.notion.com/mcp

# 로컬 서버(stdio). -- 뒤가 서버를 띄우는 명령
claude mcp add --env AIRTABLE_API_KEY=내키 --transport stdio airtable -- npx -y airtable-mcp-server

claude mcp list      # 설정된 서버와 연결 상태

Claude Code 문서는 SSE 전송을 폐기 예정으로 안내하고, v2.1.265 이후 버전은 HTTP를 먼저 시도한 뒤 서버가 받아 주지 않을 때 SSE로 넘어간다고 적습니다. 저장 범위는 세 가지입니다.

범위 쓰이는 곳 팀과 공유 저장 위치
local(기본) 현재 프로젝트만 아니오 ~/.claude.json의 프로젝트 항목
project 현재 프로젝트만 예, 저장소로 프로젝트 루트의 .mcp.json
user 내 모든 프로젝트 아니오 ~/.claude.json

같은 이름의 서버가 여러 곳에 있으면 local, project, user, 플러그인, claude.ai 커넥터 순으로 이기고 필드를 합치지 않습니다. 저장소에서 받은 .mcp.json의 서버는 대화형 세션에서는 승인 창이 뜨고 승인 전까지 “Pending approval”로 멈춥니다. 다만 claude -p, Agent SDK, 클라우드 세션에서는 묻지 않고 프로젝트 서버를 불러옵니다. 이런 환경에서 막으려면 disabledMcpjsonServers에 넣거나 --strict-mcp-config로 지정한 서버만 쓰게 해야 합니다.

원격 서버의 로그인 길

원격 서버는 프로그램이 서비스 운영사 쪽에서 돌고, 내 계정의 토큰을 쥡니다. Claude에서는 Settings의 Connectors에서 Add custom connector로 서버 주소를 넣고 인증을 마친 뒤, 같은 화면에서 도구별 허용·차단을 정합니다. 규격이 정한 인증은 OAuth 2.1을 바탕으로 하고, 클라이언트가 토큰을 얻는 길은 이렇습니다.

  1. 토큰 없이 서버에 요청합니다.
  2. 서버가 401과 함께 “내 인증 정보는 여기”라는 주소(resource_metadata)를 돌려줍니다.
  3. 클라이언트가 그 주소의 보호 리소스 메타데이터에서 인증 서버를 찾고, 인증 서버 메타데이터를 읽습니다.
  4. 클라이언트를 등록합니다. 클라이언트 ID 메타데이터 문서가 권장 방식이고 동적 클라이언트 등록은 폐기 예정입니다.
  5. 브라우저에서 사용자가 로그인·동의합니다. PKCE와 resource 파라미터를 쓰고, 응답에 iss가 있으면 클라이언트가 기록해 둔 발급자와 맞는지 검증합니다.
  6. 받은 코드를 토큰으로 바꿔 이후 모든 요청에 Authorization: Bearer 헤더로 싣습니다.

토큰을 주소 뒤 쿼리에 넣는 것은 금지이고, 서버는 자기에게 발급된 토큰만 받아야 합니다. 필요한 권한이 모자라면 403과 insufficient_scope로 필요한 범위를 알려 주어 클라이언트가 그 범위만 추가로 동의받게 되어 있습니다. 처음에는 읽기 같은 낮은 권한만 요청하고 필요할 때 올리는 방식이 권장됩니다.

직접 서버를 만들어 인스펙터로 열어 보기

공식 서버 만들기 튜토리얼은 Python(3.10 이상, SDK 2.0.0 이상)과 TypeScript 등으로 제공됩니다. Python은 타입 힌트와 설명 문자열(docstring)에서 도구 정의가 만들어집니다.

from mcp.server import MCPServer

mcp = MCPServer("notes")

@mcp.tool()
async def count_words(text: str) -> str:
    """주어진 글의 단어 수를 센다.

    Args:
        text: 단어 수를 셀 글
    """
    return f"{len(text.split())} words"

if __name__ == "__main__":
    mcp.run(transport="stdio")

함수 하나가 도구 하나가 되고, docstring이 곧 모델이 읽는 description이 됩니다. 앞서 본 tools/list 응답의 한 줄이 이 함수에서 나온 것입니다. 설명을 대충 쓰면 모델이 도구를 엉뚱한 때 고르거나 아예 찾지 못합니다.

앱에 붙이기 전에 공식 인스펙터로 먼저 열면 서버 문제인지 앱 설정 문제인지 갈립니다. 설치 없이 npx @modelcontextprotocol/inspector node path/to/server/index.js로 실행하고, 기본은 웹 화면이며 --cli(스크립트·CI용)와 --tui(터미널 화면) 모드도 있습니다. Node 22.19.0 이상이 필요하고 실행할 때마다 토큰이 든 주소를 출력합니다. 원격 서버는 --server-url 주소 --transport http로 점검합니다. OAuth 토큰과 환경 변수 값은 키체인에 저장되고, 키체인이 없는 환경에서는 ~/.mcp-inspector/secrets.json에 저장되며 암호화 키를 주지 않으면 평문입니다.

도구 정의가 컨텍스트를 잡아먹는 규모

서버를 많이 붙일수록 모델에게 보여 줄 도구 설명도 늘어납니다. 공식 클라이언트 모범 사례 문서는 모든 도구 정의를 대화 시작에 통째로 넣으면, 서버 수십 개와 도구 수백 개 환경에서는 사용자 메시지를 읽기도 전에 컨텍스트 창 대부분이 정의로 채워질 수 있다고 경고합니다. 문서 그림의 예시 값을 같은 축에 놓았습니다. 빨강이 기본 방식이고 초록이 줄이는 방식입니다.

도구 정의 15만 토큰 대 2천 토큰, 도구 결과 10만 토큰 대 215토큰을 견준 막대 차트 그림 4. 문서가 든 예시 값(측정값이 아님). 코드 모드의 215는 스크립트 약 200과 요약 약 15를 더한 편집부 계산

위의 두 줄은 도구 정의가 차지하는 양이고, 아래 두 줄은 도구를 연달아 부를 때 중간 결과가 지나가는 양입니다. 해법도 둘로 갈립니다. 정의 쪽은 진행적 도구 탐색입니다. 앱이 정의를 받아 두되 모델에게는 도구를 검색하는 작은 도구만 먼저 주고, 모델이 고른 것의 정의만 불러옵니다. 문서는 컨텍스트 창의 1~5% 같은 임계값을 넘으면 이 방식으로 바꾸라고 예를 듭니다. 검색 방식은 키워드(BM25, 정규식), 임베딩, 작은 모델이 고르는 서브 에이전트, 혼합이 있고, Claude와 OpenAI는 도구 검색을 자체 기능으로 제공합니다. Claude Code 문서는 도구 검색이 기본으로 켜져 있고 ENABLE_TOOL_SEARCH=false로 끌 수 있다고 적습니다.

결과 쪽은 코드 모드입니다. 모델이 코드를 쓰고 샌드박스 안에서 도구 호출을 묶어 실행하면 중간 결과는 모델을 거치지 않고 요약만 돌아옵니다. 다만 샌드박스는 앱이 구현해야 하고, 스크립트를 승인했다고 그 안의 모든 호출이 승인된 것은 아니므로 호출마다 같은 확인 정책을 적용해야 합니다. 한편 도구를 중간에 넣고 빼면 프롬프트 캐시가 깨져, 그 손실이 줄인 정의보다 클 수 있다고 문서가 덧붙입니다.

일반 사용자에게는 이 문제가 이렇게 보입니다. 서버를 많이 붙인 뒤 답이 느려지거나 엉뚱한 도구를 고른다면 쓰지 않는 서버부터 꺼 보세요. 출력 쪽에는 별도 한도가 있어서, Claude Code는 도구 출력이 10,000 토큰을 넘으면 경고(이 기준은 고정)하고 기본 한도는 25,000 토큰이며 MAX_MCP_OUTPUT_TOKENS로 조정합니다. 텍스트 결과가 50,000자를 넘으면 서버가 한도를 올리지 않은 한 파일로 저장됩니다.

붙인 서버가 내 권한으로 할 수 있는 일

서버는 AI 앱이 시키는 대로 움직이는 프로그램입니다. 로컬 서버는 내 계정 권한으로 도는 별도 프로그램이고, 원격 서버는 내 계정의 토큰을 쥡니다. 그래서 별 수나 설치 편의가 아니라 출처와 권한 범위를 먼저 봐야 합니다. 공식 보안 모범 사례 문서가 꼽는 위험을 “누가 막아야 하나”와 함께 정리했습니다.

위험 벌어지는 일 막아야 하는 쪽
로컬 서버 시작 명령 설정에 적힌 한 줄이 내 권한으로 실행됨. 악성 명령이 섞여도 눈치채기 어려움 사용자는 명령 전체를 읽고, 앱은 실행할 명령을 생략 없이 보여 주고 동의를 받음
토큰 패스스루 서버가 자기에게 발급되지 않은 토큰을 받아 다른 API로 넘김 서버 운영자: 자기에게 발급된 토큰만 받기
혼동된 대리인 중계 서버의 고정 ID와 예전 동의 기록 때문에, 공격자의 앱이 동의 없이 인증 코드를 받아 감 서버 운영자: 클라이언트별로 동의 화면 두기
SSRF 서버가 알려 준 주소를 앱이 따라가다 내부망·클라우드 메타데이터를 건드림 앱 개발자: 사설 대역(169.254.0.0/16 포함) 차단, HTTPS 강제
상태 핸들 탈취 추측한 핸들 값으로 남의 장바구니·작업에 접근 서버 운영자: 핸들을 인증된 사용자에 묶고 무작위 값 사용
과도한 권한 범위 처음부터 모든 권한을 받아 토큰이 새면 피해가 큼 모두: 읽기 같은 최소 범위로 시작

사용자 몫으로 바로 할 수 있는 일은 다섯 가지입니다.

  • 파일 서버에는 필요한 폴더만, 데이터베이스 서버에는 읽기 전용 계정을 연결합니다.
  • 도구 승인 창을 습관적으로 넘기지 않습니다. 쓰기·삭제·발송 도구는 입력값을 읽고 승인합니다.
  • 출처가 불분명한 서버나, 설정에 적힌 명령을 이해하지 못한 서버는 붙이지 않습니다.
  • API 키는 환경 변수로 넘기고, 쓰지 않는 서버는 설정에서 지웁니다.
  • 웹 페이지나 문서를 읽어 오는 서버는 그 안의 문구에 모델이 끌려갈 수 있음을 기억합니다.

마지막 항목은 Claude Code 문서도 경고합니다. 외부 콘텐츠를 가져오는 서버는 프롬프트 인젝션(읽어 온 글 속 지시를 모델이 따르는 현상)에 노출될 수 있으니 신뢰하는 서버만 연결하라는 것입니다. 한쪽 서버에서 읽은 내용이 다른 쪽 서버의 도구 입력으로 흘러갈 수 있다는 점은 서버를 여럿 붙일수록 커지는 문제이고, 규격이 도구 호출 입력을 서버로 보내기 전에 사용자에게 보여 주라고 권고하는 이유와 같습니다.

막혔을 때 먼저 묻는 것들

설정은 맞는데 stdio 서버가 바로 끊긴다면?

서버가 표준 출력으로 일반 글자를 찍고 있는지부터 의심하세요. 표준 출력은 메시지가 오가는 길이라 print 한 줄이 연결을 깨뜨립니다. 서버의 stderr는 Claude Desktop의 mcp-server-이름.log에 기록되니 거기서 오류 문장을 읽을 수 있습니다. 같은 명령을 인스펙터로 띄워 도구 목록이 나오는지 보면, 서버 쪽 문제인지 앱 설정 쪽 문제인지 갈립니다.

서버를 업데이트했는데 새 도구가 안 보이면?

앱이 목록을 캐시하고 있을 가능성이 큽니다. 클라이언트는 목록 응답의 ttlMs만큼 목록을 재사용하고, 변경 알림은 subscriptions/listen으로 신청해야 오며 서버가 listChanged 기능을 선언해야 합니다. 그마저 최선 노력이라 재연결 중에는 빠질 수 있습니다. 가장 빠른 확인은 앱에서 서버를 다시 연결하는 것(Claude Code는 /mcp)이나 앱 재시작입니다.

MCP 밖의 길과 이어서 볼 서버

MCP가 모든 연결의 정답은 아닙니다. 같은 도구를 세 가지 방식으로 줄 수 있고, 작업의 모양이 선택을 정합니다.

방식 도구를 정하는 곳 실행하는 곳 잘 맞는 경우
API 도구 사용(함수 호출) 요청마다 tools 값으로 직접 정의 내 앱 코드(서버 도구는 Anthropic 인프라) 한 앱 안에서 쓰는 전용 도구
MCP 서버 서버가 목록으로 공개 서버 프로세스(로컬 또는 원격) 여러 앱이 같은 도구를 재사용할 때
CLI + 스킬 명령줄 도구와 지침 파일 에이전트가 쓰는 셸 도구 정의로 컨텍스트를 아끼고 싶을 때

Playwright MCP의 README는 코딩 에이전트에게는 CLI와 스킬 조합이 토큰 면에서 더 효율적이라고 밝히고, 브라우저 상태가 이어지거나 화면 구조를 계속 들여다봐야 하는 탐색형 자동화에는 MCP가 맞는다고 구분합니다. Claude API에는 원격 MCP 서버를 별도 클라이언트 없이 연결하는 MCP 커넥터도 있어 두 방식이 배타적이지도 않습니다.

붙일 서버를 찾는 길은 두 갈래입니다. 규격을 관리하는 modelcontextprotocol 조직의 servers 저장소는 별이 가장 많지만 교육용 참조 구현 모음이라고 README가 밝힙니다. 지금 남은 서버는 Everything, Fetch, Filesystem, Git, Memory, Sequential Thinking, Time 7개이고, GitHub·PostgreSQL·Slack·SQLite·Puppeteer 등 13개는 보관용 저장소로 옮겨졌습니다. README는 서버 목록을 보려면 공식 레지스트리(registry.modelcontextprotocol.io)를 보라고 안내합니다. 레지스트리는 여전히 미리보기(preview) 상태이고 코드를 호스팅하지 않으며 server.json 메타데이터만 저장합니다. 이름은 io.github.user/server처럼 역방향 도메인 형식이라 GitHub 계정이나 도메인을 증명한 사람만 그 이름 아래 올릴 수 있고, 코드 검사는 npm·PyPI 같은 패키지 저장소와 마켓플레이스 몫입니다. 올라 있다는 것은 찾을 수 있다는 뜻이고 검증됐다는 뜻이 아닙니다.

저장소 역할 GitHub 별(2026-10-27 UTC)
servers 교육용 참조 서버 모음 91,582
python-sdk Python SDK(MIT) 24,675
typescript-sdk TypeScript SDK 13,655
inspector 서버 점검 도구 11,154
modelcontextprotocol 규격과 문서 9,535
registry 공식 레지스트리 7,408

별 수는 관심도일 뿐 품질이나 안전의 증거가 아닙니다. 확장 쪽도 따로 크고 있습니다. MCP Apps는 서버가 대화 안에 샌드박스 iframe 화면(차트·폼·뷰어)을 그리게 하는 확장이고 Claude, Claude Desktop, Visual Studio Code의 GitHub Copilot, Microsoft 365 Copilot, Goose, Postman 등이 지원한다고 문서가 밝히며, 클라이언트와 서버가 함께 지원해야 쓸 수 있습니다.

실제 서버를 하나씩 뜯어 본 글도 이 사이트에 있습니다. 어떤 서버가 보관 처리됐고 무엇으로 갈아탈지는 추천 목록의 단골 MCP 서버 10개 중 5개는 이미 보관 처리됐다, 브라우저를 직접 여는 서버는 Chrome DevTools MCP, 최신 문서를 끌어오는 서버는 Context7에서 다뤘습니다. 데이터베이스에 연결할 때 권한과 안전 장치는 Supabase MCP와 Neon MCP, 읽기 전용 원격 서버의 실제 모습은 Microsoft Learn MCP와 Fabric IQ MCP, 코드 구조를 기억하는 로컬 서버는 codebase-memory-mcp 글에서 볼 수 있습니다.

#MCP#Model Context Protocol#AI 에이전트#Claude Desktop#개발 도구