Ch6. MCP 서버 연동
Claude Code에서 Model Context Protocol 서버와 도구·리소스를 운영하는 방법
핵심 요약
- Claude Code는 MCP 클라이언트로 동작하며
claude mcp add는 HTTP(권장)·stdio·SSE(deprecated) 전송을 지원합니다. - 서버 범위는 local(기본)·project(
.mcp.json, 팀 공유)·user 세 가지이며, 같은 이름이면 local > project > user > 플러그인 > claude.ai 순으로 하나만 적용됩니다. - 원격 서버 OAuth는
/mcp또는claude mcp login/logout으로 처리하고, 비DCR 서버는--client-id·--callback-port·headersHelper로 인증을 구성합니다. - Tool Search는 기본 활성화되어 도구를 지연 로드하며
ENABLE_TOOL_SEARCH(auto·auto:N등)로 제어합니다. - 도구 출력은 기본 25,000 토큰 제한이며
MAX_MCP_OUTPUT_TOKENS나_meta어노테이션으로 한도를 조정합니다. 장시간 호출은CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT을 별도 운영값으로 둡니다.
MCP(Model Context Protocol)는 Claude Code를 외부 도구·데이터베이스·API에 연결하는 표준 프로토콜입니다. GitHub, DB, 사내 도구를 Claude Code에서 그대로 쓸 수 있습니다.
MCP 개념
Claude Code는 MCP 클라이언트로서 여러 MCP 서버에 동시에 연결합니다. 각 서버는 도구(tools), 리소스(resources), 프롬프트(prompts)를 제공합니다.
MCP 서버 추가
claude mcp add는 세 가지 전송 방식(transport)을 지원합니다. 공식 문서는 원격
서버에는 HTTP를 권장하며, SSE 전송은 deprecated되었으니 가능하면 HTTP로
연결하세요.
# HTTP 원격 서버 (권장)
claude mcp add --transport http notion https://mcp.notion.com/mcp
# Bearer 토큰 헤더 포함
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer YOUR_GITHUB_PAT"
# 로컬 stdio 서버
claude mcp add --transport stdio --env AIRTABLE_API_KEY=KEY airtable \
-- npx -y airtable-mcp-server옵션 순서
모든 옵션(--transport, --env, --scope, --header)은 서버 이름 앞에 와야
하며, --(이중 대시) 뒤에 서버에 전달할 실제 실행 명령과 인자를 둡니다.
설정 파일 직접 편집과 범위(scope)
MCP 서버는 세 가지 범위(scope)로 저장됩니다. --scope 플래그로 지정합니다.
| 범위 | 로드 위치 | 팀 공유 | 저장 위치 |
|---|---|---|---|
| local(기본값) | 현재 프로젝트만 | 아니오 | ~/.claude.json(프로젝트 경로별) |
| project | 현재 프로젝트만 | 예(버전 관리) | 프로젝트 루트 .mcp.json |
| user | 모든 프로젝트 | 아니오 | ~/.claude.json |
범위 이름 변경
구버전의 project 범위는 현재 local로, global 범위는 user로 이름이
바뀌었습니다. 기본값은 local입니다. local 범위 서버는 ~/.claude.json의 해당
프로젝트 항목 아래에 저장되며, 팀 공유용 .mcp.json(project 범위)과는 다른
위치입니다.
.mcp.json(project 범위)과 add-json에서 사용하는 JSON 스키마 예시입니다. type은
stdio, http, sse를 받으며, JSON에서는 streamable-http를 http의 별칭으로
인식합니다.
{
"mcpServers": {
"github": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "ghp_..."
}
}
}
}project 범위 서버는 보안상 처음 사용할 때 승인 프롬프트가 표시됩니다. 승인 기록을
초기화하려면 claude mcp reset-project-choices를 실행합니다.
환경 변수 확장
.mcp.json에서는 ${VAR}(값 치환)과 ${VAR:-default}(기본값) 구문으로 환경 변수를
확장할 수 있습니다. 확장 가능한 위치는 command, args, env, url, headers이며,
값이 없고 기본값도 없으면 설정 파싱에 실패합니다.
stdio 서버에는 Claude Code가 프로젝트 루트를 CLAUDE_PROJECT_DIR 환경 변수로
주입하므로, 서버 내부에서 프로젝트 상대 경로를 안정적으로 해석할 수 있습니다.
JSON으로 직접 추가 / Claude Desktop 가져오기
# JSON 문자열로 추가
claude mcp add-json weather '{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer token"}}'
# Claude Desktop 설정 가져오기 (macOS, WSL)
claude mcp add-from-claude-desktopOAuth 인증
많은 원격 서버가 OAuth 2.0을 요구합니다. 서버가 401 Unauthorized 또는 403 Forbidden을 반환하면 Claude Code가 인증 필요 상태로 표시하고, /mcp에서 브라우저
로그인 흐름을 진행합니다. 토큰은 안전하게 저장되고 자동 갱신됩니다.
최신 CLI는 대화형 /mcp 메뉴 외에도 claude mcp login <server>와 claude mcp logout <server>로
원격 서버 인증을 명시적으로 시작하거나 해제할 수 있습니다. 팀 bootstrap script에는 list/get 검증과
login/logout 안내를 분리해 두면 운영자가 브라우저 인증 단계를 놓치지 않습니다.
고정 콜백 포트와 사전 등록 자격증명 (비DCR 서버)
일부 MCP 서버는 Dynamic Client Registration(DCR)을 지원하지 않습니다("does not
support dynamic client registration" 오류). 이럴 때는 사전 등록한 OAuth 자격증명을
넘깁니다. --client-secret 플래그는 값을 인자로 받지 않고 마스킹된 입력
프롬프트를 띄우며, CI에서는 MCP_CLIENT_SECRET 환경 변수로 대신합니다.
# 고정 콜백 포트 + 사전 등록 client-id (secret은 마스킹 입력)
claude mcp add --transport http \
--client-id your-client-id --client-secret --callback-port 8080 \
my-server https://mcp.example.com/mcp
# CI에서 환경 변수로 secret 주입
MCP_CLIENT_SECRET=your-secret claude mcp add --transport http \
--client-id your-client-id --client-secret --callback-port 8080 \
my-server https://mcp.example.com/mcp--callback-port는 사전 등록된 http://localhost:PORT/callback 형식의 리다이렉트
URI에 맞춰 콜백 포트를 고정합니다(DCR과 함께 단독 사용 가능). 이 플래그들은 HTTP/SSE
전송에만 적용되며 stdio 서버에는 영향이 없습니다.
OAuth 메타데이터 디스커버리 override
oauth.authServerMetadataUrl을 .mcp.json의 oauth 객체에 설정하면 기본 디스커버리
체인을 우회해 특정 인증 서버 메타데이터 URL을 직접 지정할 수 있습니다(v2.1.64 이상).
기본 디스커버리는 먼저 RFC 9728 Protected Resource Metadata(/.well-known/oauth-protected-resource)를
확인한 뒤, RFC 8414 Authorization Server Metadata(/.well-known/oauth-authorization-server)로
폴백합니다.
{
"mcpServers": {
"my-server": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"oauth": {
"authServerMetadataUrl": "https://auth.example.com/.well-known/openid-configuration"
}
}
}
}또한 CIMD(Client ID Metadata Document)를 사용하는 서버는 별도 클라이언트 등록 없이도 자동으로 디스커버리됩니다.
OAuth scope 제한
oauth.scopes에 공백으로 구분한 단일 문자열을 지정하면 인증 흐름에서 요청할 scope를
고정합니다. 보안팀이 승인한 범위로 제한할 때 쓰며, 이 값은
authServerMetadataUrl이나 서버가 디스커버리한 scope보다 우선합니다.
{
"mcpServers": {
"slack": {
"type": "http",
"url": "https://mcp.slack.com/mcp",
"oauth": { "scopes": "channels:read chat:write search:read" }
}
}
}동적 인증 헤더 (headersHelper)
OAuth 외 인증 방식(Kerberos, 단기 토큰, 사내 SSO 등)을 쓰는 서버는 headersHelper로
연결 시점에 헤더를 만듭니다. 명령은 stdout에 JSON 객체(문자열 키-값)를
출력해야 하며, 셸에서 10초 타임아웃으로 실행됩니다. 연결마다 새로 실행하고 캐싱은
없습니다.
{
"mcpServers": {
"internal-api": {
"type": "http",
"url": "https://mcp.internal.example.com",
"headersHelper": "/opt/bin/get-mcp-auth-headers.sh"
}
}
}headersHelper 실행 시 다음 환경 변수를 사용할 수 있습니다:
CLAUDE_CODE_MCP_SERVER_NAME— 서버 이름CLAUDE_CODE_MCP_SERVER_URL— 서버 URL
서버마다 다른 인증 헤더를 헬퍼 스크립트 하나로 동적으로 만들 때 쓰면 좋습니다.
신뢰 확인
headersHelper는 임의의 셸 명령을 실행합니다. project/local 범위에 정의된 경우
워크스페이스 신뢰 다이얼로그를 수락한 뒤에만 실행됩니다.
관리 명령어
claude mcp list
claude mcp get github
claude mcp remove github
claude mcp serveclaude mcp list/get은 승인 대기 중인 project 범위 서버를 ⏸ Pending approval,
거부된 서버를 ✗ Rejected로 표시합니다. claude mcp serve는 Claude Code 자체를 stdio
MCP 서버로 띄워 다른 애플리케이션(예: Claude Desktop)이 Claude의 도구에 접근하게
합니다.
예약된 서버 이름
workspace는 내부용으로 예약된 서버 이름입니다. 이 이름의 서버를 정의하면 로드 시
건너뛰며 이름을 바꾸라는 경고가 표시됩니다.
/mcp로 상태 확인
/mcp/mcp 패널은 연결된 서버마다 도구 개수를 보여주고, tools capability를 광고하면서도
도구가 0개인 서버를 따로 표시합니다. OAuth 인증이 필요한 원격 서버 인증도 /mcp에서
합니다. 인증 해제는 /mcp 메뉴의 "Clear authentication"으로 합니다.
v2.1.181~v2.1.190 릴리스에서는 MCP 상태가 실제보다 나쁘게 보이는 표시 문제가 일부 수정되었습니다. 그래도 장애 대응에서는 /mcp 표시만 보지 말고 claude mcp get <server>, 서버 로그, HTTP 상태, OAuth 토큰 상태를 함께 확인하세요.
자동 재연결과 동적 도구 갱신
HTTP/SSE 서버가 세션 도중 끊기면 지수 백오프로 자동 재연결합니다(최대 5회, 1초에서 시작해 2배씩 증가). 초기 연결도 5xx·연결 거부·타임아웃 같은 일시적 오류에 한해 최대 3회 재시도합니다(v2.1.121). 인증·not-found 오류는 설정 변경이 필요하므로 재시도하지 않습니다. stdio 서버는 로컬 프로세스라 자동 재연결되지 않습니다.
MCP list_changed 알림을 지원하므로, 서버가 도구·프롬프트·리소스 목록을 바꾸면
재연결 없이 자동으로 갱신됩니다.
플러그인 제공 MCP 서버
플러그인은 MCP 서버를 번들로 포함할 수
있습니다. 플러그인 루트의 .mcp.json 또는 plugin.json 인라인으로 정의하며, 플러그인
활성화 시 자동 시작됩니다. ${CLAUDE_PLUGIN_ROOT}(번들 파일),
${CLAUDE_PLUGIN_DATA}(영속 상태), ${CLAUDE_PROJECT_DIR}(프로젝트 루트) 변수를
사용할 수 있습니다.
claude.ai MCP 커넥터
claude.ai 계정으로 로그인한 경우 claude.ai에서 추가한 MCP 서버를 Claude Code에서
자동으로 사용할 수 있습니다. 단, 활성 인증 방식이 claude.ai 구독일 때만 로드되며
ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, apiKeyHelper, Bedrock/Vertex 등이
활성화되면 로드되지 않습니다. 비활성화하려면 환경 변수
ENABLE_CLAUDEAI_MCP_SERVERS=false를 설정합니다.
범위 우선순위와 중복 제거
같은 서버가 여러 곳에 정의되면 Claude Code는 가장 높은 우선순위 정의 하나만 사용하며, 필드는 병합하지 않습니다. 우선순위는 다음과 같습니다.
- local 범위
- project 범위
- user 범위
- 플러그인 제공 서버
- claude.ai 커넥터
세 범위는 이름으로, 플러그인·커넥터는 **엔드포인트(URL/command)**로 중복을
판별합니다. 즉 로컬 .mcp.json과 claude.ai 커넥터가 같은 URL을 가리키면 로컬 설정이
우선하고, claude.ai 커넥터는 /mcp에서 hidden으로 표시됩니다.
MCP Elicitation
MCP 서버는 작업 도중 사용자에게 구조화된 입력을 요청할 수 있습니다(elicitation). 별도 설정 없이 서버가 요청하면 대화형 다이얼로그가 자동으로 뜨고, 응답이 서버로 전달됩니다. 모드는 두 가지입니다.
- Form 모드: 서버가 정의한 폼 필드(예: 사용자명·비밀번호)를 채워 제출
- URL 모드: 인증·승인을 위한 브라우저 URL을 열고, 완료 후 CLI에서 확인
다이얼로그 없이 자동 응답하려면 Elicitation 훅을
사용합니다.
운영 팁
elicitation은 MCP 서버가 사용자 앞에 있을 때만 유용합니다. CI/헤드리스 환경에서는
사전 설정(환경변수, config)이나 Elicitation 훅 자동 응답으로 대체하세요.
MCP Channels (연구 프리뷰, v2.1.80)
채널(Channel)은 세션에 메시지를 직접 푸시하는 MCP 서버입니다. 기존에는 Claude가 도구를 호출해야만 서버와 통신했지만, 채널을 쓰면 CI 결과·모니터링 알림·채팅 메시지 같은 외부 이벤트가 실행 중인 세션으로 들어와 Claude가 즉시 반응합니다.
현재 채널은 플러그인 형태로 설치하고, 시작할 때 --channels 플래그에 플러그인을
명시해 옵트인합니다. 연구 프리뷰에는 Telegram, Discord, iMessage, fakechat(로컬 데모)이
들어 있습니다. 서버는 claude/channel capability를 선언해야 하고, .mcp.json에 두는
것만으로는 부족합니다. 반드시 --channels에 지정해야 푸시할 수 있습니다.
# 플러그인 설치 후 채널을 옵트인하여 시작
claude --channels plugin:fakechat@claude-plugins-official
# 여러 플러그인을 공백으로 구분해 전달 가능
claude --channels plugin:telegram@claude-plugins-official퍼미션 릴레이
채널 서버가 permission relay capability를 선언하면, 도구 승인 프롬프트를 폰 등
원격으로 전달해 외출 중에도 도구 실행을 승인하거나 거부할 수 있습니다. 채널의 sender
allowlist에 등록된 사람만 응답하므로, 그 권한을 믿을 수 있는 발신자만
허용하세요. 무인 실행에는 신뢰하는 환경에서만 --dangerously-skip-permissions를
사용합니다.
실전 활용 시나리오
| 시나리오 | 채널/MCP 서버 | 동작 |
|---|---|---|
| CI 결과 알림 | Webhook 채널 | 빌드/테스트 완료 시 세션에 결과 푸시 → Claude가 실패 원인 분석 |
| 채팅 브리지 | Telegram/Discord/iMessage | 폰에서 질문 → 같은 대화로 응답, 작업은 로컬 파일에서 수행 |
| 에러 추적 알림 | Sentry 등 Webhook | 새 에러 발생 시 세션에 전달 → Claude가 스택 트레이스 분석 |
| 모니터링 알림 | Grafana/PagerDuty Webhook | 임계치 초과 알림 → Claude가 런북 참조하여 대응 제안 |
| 폰 승인 | Permission relay | 도구 실행 승인을 폰으로 전달 → 외출 중에도 에이전트 관리 |
연구 프리뷰
Channels는 연구 프리뷰 단계이며, --channels 문법과 프로토콜이 변경될 수 있습니다.
claude.ai와 API 키 인증에서만 동작하고 Bedrock/Vertex/Foundry에서는 사용할 수
없습니다. Team/Enterprise 조직은 관리자가 channelsEnabled를 true로 설정해야
하며(기본 차단), allowedChannelPlugins로 허용 플러그인을 제한할 수 있습니다.
Console(API 키) 조직은 기본 허용이나 managed settings 배포 시 channelsEnabled가
필요합니다(v2.1.115 이후 Console 지원).
MCP 서버 중복 제거 (v2.1.84)
로컬 설정과 claude.ai 커넥터에 같은 엔드포인트의 서버가 등록되면 로컬 설정이
우선합니다. 같은 서버가 두 번 로드되어 도구가 중복되던 문제도 이제 해결됐습니다.
/mcp는 중복으로 가려진 커넥터를 hidden으로 표시하고 중복 제거 힌트를 보여줍니다.
도구 검색(Tool Search)
서버 도구가 많으면 Tool Search로 도구 정의를 필요한 시점에 로드해 컨텍스트 사용을 줄입니다. 현재는 기본 활성화라서, 세션 시작 때는 도구 이름만 로드하고 Claude가 필요할 때 검색 도구로 관련 도구를 찾습니다. 사용자가 보기엔 기존과 똑같이 동작합니다.
ENABLE_TOOL_SEARCH 환경 변수로 동작을 제어합니다.
| 값 | 동작 |
|---|---|
| (미설정) | 모든 MCP 도구를 지연 로드. Vertex AI나 비1차 ANTHROPIC_BASE_URL에서는 선로드로 폴백 |
true | 모든 도구 지연. 프록시·Vertex에서도 beta 헤더 전송(미지원 모델/프록시에서는 실패) |
auto | 컨텍스트 윈도우의 10% 안에 들면 선로드, 초과분만 지연 |
auto:N | 임계 비율을 N%(0-100)로 지정. 예: auto:5 |
false | 모든 도구를 선로드(지연 없음) |
Tool Search는 tool_reference 블록을 지원하는 모델(Sonnet 4 / Opus 4 이상)이
필요하며, Haiku는 지원하지 않습니다. Vertex AI에서는 기본 비활성화되며 Sonnet 4.5 /
Opus 4.5 이상에서만 지원됩니다. ToolSearch 도구 자체를 끄려면 권한 deny 규칙
"deny": ["ToolSearch"]를 사용합니다.
서버를 지연에서 제외 (alwaysLoad)
특정 서버의 도구가 항상 보여야 한다면 그 서버 설정에 "alwaysLoad": true를 추가합니다.
그러면 해당 서버의 모든 도구가 ENABLE_TOOL_SEARCH 설정과 무관하게 세션 시작 때 컨텍스트에
로드됩니다(v2.1.121 이상). 이때는 서버 연결까지 시작이 블로킹되며 표준 5초 연결
타임아웃이 상한입니다. 개별 도구는 _meta에 "anthropic/alwaysLoad": true로 지정할
수 있습니다.
{
"mcpServers": {
"core-tools": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"alwaysLoad": true
}
}
}연결 대기 최적화
MCP 시작은 기본적으로 논블로킹이며, 서버는 백그라운드에서 연결됩니다. 다만 어떤
요청이 아직 연결 중인 서버의 도구를 필요로 하면 Claude가 그 서버를 기다립니다(Tool
Search 활성 시 ToolSearch 호출 안에서, 비활성 시 WaitForMcpServers 도구로 대기).
헤드리스 -p 실행에서는 MCP_CONNECTION_NONBLOCKING=true로 MCP 연결 대기를 완전히
건너뛸 수 있습니다. --mcp-config로 지정한 서버 연결은 느린 서버 하나 때문에
전체가 묶이지 않도록 서버당 5초로 상한을 둡니다.
타임아웃 관련 환경 변수/필드:
MCP_TIMEOUT— 서버 시작 타임아웃(예:MCP_TIMEOUT=10000은 10초)MCP_TOOL_TIMEOUT/ 서버별.mcp.json의timeout(ms) — 도구 호출 단위 하드 타임아웃. 서버별timeout이 환경 변수보다 우선하며, 1000 미만 값은 1초로 올림
도구 출력 제한
MCP 도구 출력에는 기본적으로 10,000 토큰 경고, 25,000 토큰 제한이 걸립니다.
환경 변수 MAX_MCP_OUTPUT_TOKENS로 상한을 조정합니다(예:
MAX_MCP_OUTPUT_TOKENS=50000). 이 변수는 자체 한도를 선언하지 않은 도구에만
적용됩니다.
결과 보존 크기 override
MCP 서버는 도구의 tools/list 항목에 _meta["anthropic/maxResultSizeChars"]를 붙여
결과 보존 한도를 최대 500K자까지 늘릴 수 있습니다. DB 스키마나 대형 파일 트리처럼
잘리면 안 되는 출력을 전달할 때 쓰면 좋습니다. 이 값은 텍스트 콘텐츠에 한해
MAX_MCP_OUTPUT_TOKENS와 따로 적용되지만, 이미지 데이터는 여전히 토큰 제한을
받습니다. 어노테이션이 없으면 기본 임계치를 넘는 결과는 디스크에 보존하고 대화에는
파일 참조로 대신합니다.
{
"name": "get_schema",
"description": "Returns the full database schema",
"_meta": { "anthropic/maxResultSizeChars": 200000 }
}MCP 도구 호출 표시 개선 (v2.1.81)
MCP read/search 도구 호출이 1줄로 접혀 표시되며, Ctrl+O로 확장할 수 있습니다.
대화 흐름이 깔끔해집니다.
바이너리/이미지 콘텐츠 처리
MCP 도구가 반환하는 바이너리 콘텐츠(PDF, Office 문서, 오디오 등)는 자동으로 디코딩해 디스크에 저장하므로, Claude가 파일 내용을 활용할 수 있습니다. 지원하지 않는 MIME 타입(예: SVG) 이미지도 대화를 깨뜨리지 않고 디스크에 저장한 뒤 결과에서 참조합니다.
MCP 리소스와 프롬프트
리소스 (@ 멘션)
MCP 서버가 노출한 리소스는 파일처럼 @로 참조합니다. 프롬프트에서 @를 입력하면
연결된 서버의 리소스가 자동완성에 나타나며, @server:protocol://resource/path 형식으로
지정합니다.
@github:issue://123 이슈를 분석하고 수정안을 제안해줘
@postgres:schema://users 와 @docs:file://database/user-model 를 비교해줘프롬프트 (슬래시 명령)
MCP 서버가 노출한 프롬프트는 /mcp__servername__promptname 형식의 슬래시 명령으로
사용합니다. 인자는 명령 뒤에 공백으로 구분해 전달합니다.
/mcp__github__pr_review 456
/mcp__jira__create_issue "Bug in login flow" highhooks·권한과 MCP 연동
MCP 도구는 mcp__<서버명>__<도구명> 패턴으로 이름이 지정됩니다.
hooks의 matcher나 권한 규칙에서 이 패턴을 활용할 수 있습니다.
{
"hooks": {
"PostToolUse": [
{
"matcher": "mcp__postgres__.*",
"hooks": [
{
"type": "command",
"command": "echo \"MCP tool used\" >> \"$CLAUDE_PROJECT_DIR/.claude/mcp-log.txt\""
}
]
}
]
}
}deny 규칙과 관리형 정책
"deny": ["mcp__servername"] 형태의 권한 규칙으로 특정 MCP 서버의 모든 도구를
차단할 수 있습니다. 조직 차원에서는 관리형 MCP 설정의
managed-mcp.json과 allowedMcpServers/deniedMcpServers로 연결 가능한 서버를
중앙에서 통제합니다.
참고 문서
- MCP 개요 및 설정 파일: https://code.claude.com/docs/en/mcp
- Channels(이벤트 푸시): https://code.claude.com/docs/en/channels
- 관리형 MCP 설정: https://code.claude.com/docs/en/managed-mcp
- 환경 변수: https://code.claude.com/docs/en/env-vars
- Changelog: https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md