MCP 통합 시스템

Model Context Protocol 서버의 발견, 연결, 프록시, 인증 — stdio 서브프로세스부터 인프로세스 Chrome 브릿지까지.

01

개요

Claude Code가 MCP 서버를 발견, 연결, 프록시, 인증하는 방법을 살펴봅니다. MCP 통합은 여러 아키텍처 레이어로 구성되며, 각 레이어가 명확한 책임을 가집니다.

아키텍처 레이어: services/mcp/ (연결 생명주기, 설정 로드, OAuth) → tools/MCPTool/ (원격 MCP 호출을 래핑하는 프록시 도구) → commands/mcp/ (슬래시 커맨드) → components/mcp/ (React UI 패널)
02

전송 유형

MCP는 8가지 전송 유형을 지원하며, 공개(Public), 내부(Internal), 인프로세스(In-process)로 분류됩니다.

공개 전송 (Public)

내부 전송 (Internal)

인프로세스 전송 (In-process)

// in-process 전송 — 스택 오버플로 방지
// 동일 이벤트 루프에서 MCP 서버를 실행할 때
// 재귀적 호출 체인이 스택을 초과할 수 있음
queueMicrotask(() => {
  // 다음 마이크로태스크에서 처리하여 스택 깊이 초기화
  handleMessage(message)
})
03

설정 범위 계단식

MCP 서버 설정은 7단계 우선순위 계층으로 조립됩니다. 상위 범위가 하위 범위보다 우선합니다.

flowchart TD A["1. enterprise (최고 우선순위)
managed-mcp.json — MDM 관리"] --> B["2. dynamic
CLI 플래그로 전달"] B --> C["3. claudeai
Claude.ai 커넥터 API"] C --> D["4. project
.mcp.json — CWD 및 상위 디렉토리"] D --> E["5. 로컬
~/.claude/projects/<hash>/"] E --> F["6. 사용자
~/.claude/settings.json"] F --> G["7. managed (최저 우선순위)
플러그인 제공"] style A fill:#c47a50,color:#1a1816 style G fill:#7d9ab8,color:#1a1816
  1. enterprise (최고 우선순위) — managed-mcp.json. MDM(모바일 디바이스 관리)으로 배포. 엔터프라이즈 IT 관리자가 제어
  2. dynamic — CLI 플래그(--mcp-server 등)로 전달된 서버 설정
  3. claudeai — Claude.ai 커넥터 API에서 제공하는 서버 구성
  4. project.mcp.json 파일. CWD 및 상위 디렉토리를 순회하며 탐색
  5. local~/.claude/projects/<hash>/. 프로젝트별 로컬 오버라이드
  6. user~/.claude/settings.json. 사용자 전역 설정
  7. managed (최저 우선순위) — 플러그인이 제공하는 서버 설정
엔터프라이즈 잠금

managed-mcp.json이 존재하면 addMcpConfig()가 수동 서버 추가/제거를 차단합니다. claude mcp add my-tool 실행 시 "엔터프라이즈 MCP 구성이 활성화되어 독점 제어" 오류가 발생합니다. 이를 통해 엔터프라이즈 환경에서 승인된 MCP 서버만 사용하도록 보장합니다.

04

연결 생명주기

MCP 서버 연결은 8단계를 거칩니다.

  1. 설정 조립 — 7단계 계단식에서 서버 설정을 수집하고 병합
  2. 배치 연결 — 동시 연결 제한 적용. stdio: 최대 3개 동시, remote(SSE/HTTP/WS): 최대 20개 동시
  3. 전송 구성 — 전송 유형에 따라 적절한 클라이언트 전송 인스턴스 생성
  4. client.connect() 타임아웃 — 기본 30초 타임아웃. 응답 없으면 연결 실패로 처리
  5. 인증 처리 — 401 응답 수신 시 상태를 needs-auth로 전환. McpAuthTool 의사 도구를 모델의 도구 목록에 주입하여 모델이 OAuth 흐름을 시작할 수 있게 함
  6. 기능 협상 — 서버가 지원하는 기능(도구, 리소스, 프롬프트, elicitation 등)을 협상
  7. 도구/리소스/프롬프트 가져오기 — 협상된 기능에 따라 사용 가능한 도구, 리소스, 프롬프트 메타데이터를 수집
  8. 라이브 알림ToolListChanged 등 서버 알림을 구독. 연결 끊김 시 지수적 백오프로 재연결 (1초 ~ 30초)
// 배치 연결 — 전송 유형별 동시성 제한
const STDIO_CONCURRENCY = 3   // 서브프로세스 폭주 방지
const REMOTE_CONCURRENCY = 20  // 네트워크 연결은 더 관대

// 재연결 지수적 백오프
const RECONNECT_BASE = 1000   // 1초
const RECONNECT_MAX  = 30000  // 30초 상한
딥 다이브 — 401 인증 흐름

원격 MCP 서버가 401을 반환하면, 해당 서버 상태가 needs-auth로 전환됩니다. 이 시점에서 McpAuthTool이라는 의사 도구가 모델의 도구 목록에 주입됩니다. 모델이 이 도구를 호출하면 OAuth PKCE 흐름이 시작되고, 사용자에게 브라우저 인증을 안내합니다. 인증 완료 후 해당 서버의 모든 도구가 정상적으로 도구 목록에 등장합니다.

05

도구 프록시

MCPTool은 모든 MCP 서버 도구의 공통 템플릿입니다. 실제 도구 인스턴스는 fetchToolsForClient()가 서버에서 메타데이터를 가져온 후 딥 클론으로 생성합니다.

이름 정규화

MCP 도구 이름은 mcp__<server>__<tool> 형식으로 정규화됩니다. 이를 통해 여러 MCP 서버에서 동일한 이름의 도구가 존재하더라도 충돌을 방지합니다.

// 도구 이름 정규화 예시
// 서버 "github"의 "create_issue" 도구 →
"mcp__github__create_issue"

// 서버 "slack"의 "send_message" 도구 →
"mcp__slack__send_message"

제한 사항

딥 다이브 — 딥 클론과 템플릿 패턴

MCPTool은 직접 사용되지 않고 템플릿 역할을 합니다. fetchToolsForClient()가 서버에서 도구 목록을 받으면, 각 도구에 대해 MCPTool을 딥 클론하고 실제 메타데이터(이름, 설명, 입력 스키마)를 주입합니다. 이 패턴을 통해 모든 MCP 도구가 동일한 실행 로직(원격 호출, 에러 처리, 결과 변환)을 공유하면서도 개별적인 도구 정의를 가질 수 있습니다.

06

OAuth 인증

MCP는 전체 PKCE(Proof Key for Code Exchange) 흐름과 XAA(교차 앱 액세스) 확장을 지원합니다.

McpAuthTool 흐름

  1. 원격 MCP 서버가 401 반환
  2. 서버 상태가 needs-auth로 전환
  3. McpAuthTool 의사 도구가 모델 도구 목록에 주입
  4. 모델이 McpAuthTool을 호출하여 OAuth PKCE 흐름 시작
  5. 사용자에게 브라우저 인증 URL 제공
  6. 인증 완료 후 토큰 저장, 서버 재연결
Slack 특이점

Slack API는 HTTP 200 상태 코드에 에러를 포함하여 반환하는 비표준 동작을 합니다. 예를 들어 invalid_refresh_token 에러가 200 OK 응답 본문에 포함됩니다. MCP 클라이언트는 이를 invalid_grant로 정규화하고, 합성 400 응답으로 재작성하여 표준 OAuth 에러 처리 경로를 태웁니다.

XAA (교차 앱 액세스)

XAA는 엔터프라이즈 SSO(Single Sign-On) 확장입니다. 기업 환경에서 중앙 인증 서버를 통해 여러 MCP 서버에 대한 액세스를 일괄 관리할 수 있게 합니다.

07

Elicitation

Elicitation은 MCP 서버가 작업 도중 사용자에게 구조화된 입력을 요청하는 메커니즘입니다.

두 가지 모드

딥 다이브 — 훅을 통한 프로그래밍 방식 응답

Elicitation 요청은 훅(hook)이 프로그래밍 방식으로 충족할 수 있습니다. 예를 들어, CI/CD 파이프라인에서 MCP 서버가 배포 승인을 요청할 때 훅이 자동으로 승인 응답을 제공할 수 있습니다. 이를 통해 비대화형 환경에서도 elicitation 기반 워크플로를 자동화할 수 있습니다.

08

서버 중복 제거

여러 설정 범위에 동일한 MCP 서버가 중복 등록될 수 있습니다. MCP 통합은 콘텐츠 기반(이름 기반이 아님) 중복 제거를 수행합니다.

서명 생성 규칙

// 중복 제거 서명 예시
// stdio 서버: 명령어 + 인수가 동일하면 같은 서버
'stdio:["npx","@modelcontextprotocol/server-github"]'

// 원격 서버: URL이 동일하면 같은 서버
'url:https://slack.mcp.example.com/sse'

추가 규칙

09

핵심 요약

핵심 포인트

  • MCP 통합은 4개 레이어로 구성됩니다: services/mcp/(연결), tools/MCPTool/(프록시), commands/mcp/(CLI), components/mcp/(UI)
  • 8가지 전송 유형을 지원하며, in-process는 Chrome MCP 전용으로 queueMicrotask()로 스택 오버플로를 방지합니다
  • 설정은 7단계 계단식 우선순위를 따릅니다: enterprise(최고) ~ managed(최저). managed-mcp.json 존재 시 수동 추가/제거가 차단됩니다
  • 연결은 배치 동시성 제한(stdio: 3, remote: 20)과 지수적 백오프 재연결(1s ~ 30s)을 적용합니다
  • 도구 이름은 mcp__<server>__<tool> 형식으로 정규화되며, 설명 2048자 캡과 결과 100KB 캡이 적용됩니다
  • OAuth는 PKCE + XAA 확장을 지원하며, McpAuthTool 의사 도구 주입으로 모델이 인증을 트리거합니다
  • 서버 중복 제거는 이름이 아닌 콘텐츠(명령어/URL) 기반 서명으로 수행됩니다
  • Slack API의 HTTP 200 에러 반환 같은 비표준 동작은 invalid_grant 정규화로 처리됩니다
10

지식 확인

퀴즈 — 5문제

Q1. 같은 MCP 서버가 .mcp.json(프로젝트)과 ~/.claude/settings.json(사용자)에 모두 정의되어 있으면 어느 것이 적용되나요?

  • A) 사용자 레벨이 적용됨
  • B) 프로젝트 레벨 .mcp.json이 우선순위가 높으므로 적용됨
  • C) 충돌 오류 발생
  • D) 두 설정이 병합됨
7단계 계단식에서 project(4단계)가 user(6단계)보다 우선순위가 높습니다. 따라서 .mcp.json의 설정이 ~/.claude/settings.json보다 우선 적용됩니다.

Q2. stdio MCP 서버의 stderr 노이즈는 어떻게 처리되나요?

  • A) stderr 출력을 완전히 삭제
  • B) 임시 파일로 리다이렉트하여 나중에 분석
  • C) StdioClientTransportstderr: 'pipe'로 생성하고, 축적 후 logMCPError로 로그
  • D) stderr를 모델 컨텍스트에 직접 전달
StdioClientTransport는 자식 프로세스를 stderr: 'pipe' 옵션으로 spawn합니다. stderr 출력은 축적된 후 logMCPError를 통해 로그됩니다. 64MB 하드 캡이 적용되어 과도한 stderr 노이즈가 메모리를 소진하는 것을 방지합니다.

Q3. wrapFetchWithTimeout()의 목적과 GET 요청을 건너뛰는 이유는?

  • A) POST 요청에 60초 타임아웃 적용; GET은 SSE 장기 연결이므로 건너뜀
  • B) 모든 요청에 30초 타임아웃 적용
  • C) 대용량 요청을 취소하기 위한 메커니즘
  • D) 실패한 요청의 자동 재시도를 처리
wrapFetchWithTimeout()은 POST 요청에 60초 타임아웃을 적용합니다. GET 요청은 SSE(Server-Sent Events) 연결에 사용되며, 이는 의도적으로 장기간 유지되는 연결이므로 타임아웃을 적용하면 정상 동작이 중단됩니다.

Q4. Slack이 HTTP 200 응답에 invalid_refresh_token 에러를 반환하면 MCP 클라이언트는 어떻게 처리하나요?

  • A) ZodError로 영구 실패 처리
  • B) 에러를 무시하고 같은 토큰으로 재시도
  • C) 정규화 없이 바로 needs-auth 상태로 전환
  • D) invalid_grant로 정규화하고 합성 400 응답으로 재작성
Slack API는 비표준적으로 HTTP 200에 에러를 포함합니다. MCP 클라이언트는 invalid_refresh_token을 표준 OAuth 에러인 invalid_grant로 정규화하고, 200 응답을 합성 400으로 재작성합니다. 이를 통해 표준 OAuth 에러 처리 로직이 정상 동작합니다.

Q5. 엔터프라이즈 managed-mcp.json이 존재할 때 claude mcp add my-tool을 실행하면 어떻게 되나요?

  • A) 사용자 범위에 정상 추가됨
  • B) addMcpConfig()가 "엔터프라이즈 MCP 구성이 활성화되어 독점 제어" 오류를 발생시킴
  • C) 관리자 승인 대기 상태로 추가됨
  • D) 섀도 목록에 추가되어 비공식적으로 사용 가능
managed-mcp.json이 존재하면 엔터프라이즈 잠금이 활성화됩니다. addMcpConfig()는 수동 서버 추가를 차단하고 "엔터프라이즈 MCP 구성이 활성화되어 독점 제어" 오류를 발생시킵니다. 이는 기업 환경에서 승인된 도구만 사용하도록 보장하는 보안 메커니즘입니다.
0 / 5