MCP 터널은 리서치 프리뷰 단계입니다. 사용해 보시려면 액세스를 요청하세요.
이 가이드는 터널 스택을 단일 호스트에 강화된(hardened) 컨테이너로 배포합니다. 동일한 구성을 여러 호스트에 복제하여 가용성을 확보할 수 있습니다.
다음이 필요합니다:
tnl_...)를 기록해 두세요. 수동 프로비저닝은 항상 Console에서 생성한 터널에서 시작합니다.fdrl_...)와 조직 ID를 기록해 두세요.openssl(1.1.1 이상)도 필요합니다.api.anthropic.com(443 TCP) 및 터널 엣지(7844 TCP 및 UDP)로의 아웃바운드 네트워크 연결. 전체 네트워크 요구 사항을 참조하세요.routes 아래에 구성할 주소에서 호스트로부터 접근 가능하고 실행 중인 하나 이상의 MCP 서버. 아직 없다면 샘플 서버를 사용하세요.테스트에 사용할 수 있는 MCP 서버가 없다면 다음의 최소 구성 서버를 사용하세요:
mkdir -p mcp-tunnel
cat > mcp-tunnel/hello_server.py <<'EOF'
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("hello-server", host="0.0.0.0", port=9000)
@mcp.tool()
def hello(name: str = "world") -> str:
"""Say hello to someone."""
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.run(transport="streamable-http")
EOF다음 설치 단계에서는 mcp-tunnel/로 cd하며, 해당 서비스와 라우트를 추가할 위치를 안내합니다.
이 가이드는 Docker Compose를 사용하는 하나의 참조 접근 방식을 제공합니다. 조직의 보안 요구 사항에 맞게 조정하는 것은 사용자의 책임입니다.
이 경로는 호스트에 OIDC 자격 증명 공급자(클라우드 VM 메타데이터 서버 또는 SPIFFE 등)가 있어야 합니다. 없다면 프로그래밍 방식 액세스 미사용 탭을 대신 사용하세요.
설정 컴포넌트는 Workload Identity Federation을 사용하여 터널 토큰을 가져오고, CA와 서버 인증서를 생성하며, CA를 Anthropic에 등록합니다.
배포 디렉터리 준비
mkdir -p mcp-tunnel/{config,data}
cd mcp-tunnel
sudo chown 65532:65532 data컨테이너는 비루트(non-root) UID 65532로 실행되며 data/에 대한 쓰기 권한이 필요합니다.
docker-compose.yaml 작성
이 compose 파일은 이미지를 SHA-256 다이제스트로 고정하고, 모든 컨테이너를 읽기 전용 파일시스템의 비루트로 실행하며, 모든 Linux capability를 제거하고, 권한 상승을 비활성화합니다.
cat > docker-compose.yaml <<'EOF'
services:
setup:
image: us-docker.pkg.dev/anthropic-public-registry/images/mcp-proxy@sha256:9d4c80593b559fc3ca3814866418744fa94858b02a4d4a4cc52d423e732ccc81
entrypoint: ["/setup"]
command:
- init
- --api-url=https://api.anthropic.com
- --output=dir:/data
- --token-version=1
environment:
- TUNNEL_ID
- ANTHROPIC_FEDERATION_RULE_ID
- ANTHROPIC_ORGANIZATION_ID
- ANTHROPIC_WORKSPACE_ID
- ANTHROPIC_IDENTITY_TOKEN
volumes:
- ./data:/data
user: "65532:65532"
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
profiles: ["setup"]
cloudflared:
image: cloudflare/cloudflared@sha256:6b599ca3e974349ead3286d178da61d291961182ec3fe9c505e1dd02c8ac31b0
command: tunnel --no-autoupdate run --url http://localhost:8080
environment:
- TUNNEL_TOKEN
# 프록시의 netns를 공유하여 localhost:8080으로 접근할 수 있도록 합니다.
network_mode: "service:mcp-proxy"
restart: unless-stopped
user: "65532:65532"
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
stop_grace_period: 30s
logging:
options:
max-size: "10m"
max-file: "3"
mcp-proxy:
image: us-docker.pkg.dev/anthropic-public-registry/images/mcp-proxy@sha256:9d4c80593b559fc3ca3814866418744fa94858b02a4d4a4cc52d423e732ccc81
volumes:
- ./config/mcp-proxy.yaml:/etc/mcp-gateway/config.yaml:ro
- ./data:/data:ro
restart: unless-stopped
user: "65532:65532"
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
stop_grace_period: 30s
logging:
options:
max-size: "10m"
max-file: "3"
EOF샘플 MCP 서버를 사용하는 경우 서비스로 추가하세요:
cat >> docker-compose.yaml <<'EOF'
hello-mcp:
image: python:3.13-slim
working_dir: /app
volumes:
- ./hello_server.py:/app/hello_server.py:ro
command: sh -c "pip install --quiet mcp && python hello_server.py"
restart: unless-stopped
EOF터널 프로비저닝
식별자를 설정합니다. TUNNEL_ID를 설정하지 않으면 설정 컴포넌트가 터널을 생성합니다. Console에서 생성한 기존 터널에 연결하려면 이 값을 설정하세요:
# export TUNNEL_ID=tnl_... # 기존 터널에 연결하려면 설정하세요
export ANTHROPIC_FEDERATION_RULE_ID=fdrl_...
export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000페더레이션 규칙이 조직의 기본 워크스페이스가 아닌 다른 워크스페이스로 범위가 지정된 경우 ANTHROPIC_WORKSPACE_ID=wrkspc_...도 설정하세요. 그렇지 않으면 설정 컴포넌트는 기본 워크스페이스를 사용합니다. 자동 생성된 터널은 해당 워크스페이스에 생성됩니다.
ANTHROPIC_IDENTITY_TOKEN을 이 호스트의 자격 증명 공급자에서 발급한 OIDC JWT로 설정하세요. 공급자별 WIF 가이드를 따라 발급자(issuer)를 등록하고, 규칙의 subject를 설정하고, 토큰을 발급하세요. 규칙의 audience는 토큰 발급 시 요청하는 audience와 일치해야 합니다.
설정 컴포넌트를 실행합니다:
docker compose run --rm setupsetup init은 data/에 대해 멱등(idempotent)합니다. 다시 실행하면 이미 저장된 터널 ID와 CA를 재사용하며 두 번째 터널을 생성하지 않습니다. 새 CA는 data/가 비어 있거나 TUNNEL_ID가 변경된 경우에만 생성 및 등록됩니다. 이 경우 활성 인증서 2개 제한이 적용되므로, 두 슬롯이 모두 채워져 있다면 먼저 Console에서 하나를 폐기하세요.
오류가 발생하면 설정 컴포넌트 인증 실패를 참조하세요.
터널 도메인을 가져와 이후 단계를 위해 내보냅니다:
export TUNNEL_DOMAIN=$(sudo cat data/tunnel-domain)
echo "$TUNNEL_DOMAIN"Workload Identity Federation 토큰은 수명이 짧고(기본 1시간) 자동으로 만료되므로, 설정 완료 후 폐기할 것이 없습니다.
프록시 구성 작성
tunnel_domain은 필수입니다. 프록시는 routes에서 서브도메인을 조회하기 전에 들어오는 호스트명에서 도메인 접미사를 제거하는 데 이 값을 사용합니다. routes는 리스트가 아니라 서브도메인에서 업스트림 URL로의 평면 맵(flat map)입니다.
cat > config/mcp-proxy.yaml <<EOF
listen_addr: ":8080"
log_level: info
shutdown_timeout: 30s
tunnel_domain: ${TUNNEL_DOMAIN}
tls:
cert_file: /data/tls.crt
key_file: /data/tls.key
routes:
echo: http://hello-mcp:9000
EOFecho: 라우트는 샘플 MCP 서버를 대상으로 합니다. 이를 자신의 라우트로 교체하거나 추가하세요. 사용 가능한 모든 필드는 프록시 구성 참조를 확인하세요.
배포 시작
export TUNNEL_TOKEN=$(sudo cat data/tunnel-token)
docker compose up -dcompose 파일은 기본값 없이 호스트 환경에서 TUNNEL_TOKEN을 읽으므로, 새 셸을 열 때마다 그리고 재부팅 후에는 export를 반복해야 합니다.
다중 VM 배포의 경우 mcp-tunnel/ 디렉터리를 각 호스트에 복사하고 TUNNEL_TOKEN을 설정한 다음 docker compose up -d를 실행하세요. 프로그래밍 방식 흐름에서 TUNNEL_TOKEN은 $(sudo cat data/tunnel-token)이고, 수동 흐름에서는 Console에서 복사한 값입니다. 동일한 터널 토큰과 인증서가 모든 복제본에서 작동합니다.
Anthropic 측에서 업스트림 MCP 서버를 호출하여 엔드 투 엔드로 확인하세요. 터널링된 MCP 서버 사용을 참조하세요. 샘플 MCP 서버를 사용하는 경우 라우팅된 URL은 https://echo.<your-tunnel-domain>/mcp입니다. 확인에 실패하면 문제 해결을 참조하세요.
이 섹션의 명령은 mcp-tunnel/ 배포 디렉터리 내부에서 실행하세요.
프로그래밍 방식 액세스를 사용하는 경우, setup 서비스 명령에서 --token-version을 증가시키고, Workload Identity Federation 식별자를 설정하고, 새 OIDC JWT를 발급한 다음, 설정 컴포넌트를 다시 실행하세요:
# docker-compose.yaml을 편집하세요: setup 서비스의
# --token-version 인수의 정수를 증가시킵니다 (예: --token-version=1에서
# --token-version=2로). 값이 변경되지 않으면 setup 바이너리가
# 교체를 거부합니다.
# export TUNNEL_ID=tnl_... # 설치 중에 설정한 경우에만 설정하세요
export ANTHROPIC_FEDERATION_RULE_ID=fdrl_...
export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000
# export ANTHROPIC_WORKSPACE_ID=wrkspc_... # 규칙이 워크스페이스 범위인 경우
# 환경에 맞는 WIF 공급자 가이드에 따라 ANTHROPIC_IDENTITY_TOKEN을
# 다시 발급하세요 (설치 이후 만료되었을 것입니다).
export ANTHROPIC_IDENTITY_TOKEN=...
docker compose run --rm setup
export TUNNEL_TOKEN=$(sudo cat data/tunnel-token)
docker compose up -d cloudflared--token-version 인수는 명령줄에서 전달하는 대신 docker-compose.yaml에서 편집하므로, 새 값이 이후 설정 컴포넌트 실행에도 유지됩니다. 설정 컴포넌트는 Workload Identity Federation으로 인증하므로 폐기할 API 토큰이 없습니다.
프로그래밍 방식 액세스를 사용하지 않는 경우, Console의 터널 상세 페이지에서 Rotate token을 클릭한 다음, 각 호스트에서 TUNNEL_TOKEN 환경 변수를 업데이트하고 cloudflared를 재시작하세요(docker compose up -d cloudflared).
Rotate token을 클릭하면 현재 토큰이 즉시 무효화됩니다. 그 시점부터 모든 호스트에서 TUNNEL_TOKEN을 업데이트하고 cloudflared를 재시작할 때까지, cloudflared가 재시작되는(크래시, 호스트 재부팅) 호스트는 다시 연결할 수 없습니다. 교체 후 각 호스트를 신속하게 업데이트하세요.
만료를 모니터링하고 만료 전에 서버 인증서를 갱신하는 것은 사용자의 책임입니다.
프로그래밍 방식 액세스를 사용하는 경우:
docker compose run --rm setup renew-cert --output=dir:/data이 CLI 인수는 setup 서비스의 command(init 인수)를 대체하지만 entrypoint는 유지하므로, /setup renew-cert --output=dir:/data가 실행됩니다.
--renew-before=720h를 전달하면 유효 기간이 30일 이상 남아 있을 때 명령이 아무 작업도 하지 않습니다(no-op). 이렇게 하면 고정된 일정으로 안전하게 실행할 수 있습니다.
프로그래밍 방식 액세스를 사용하지 않는 경우, 기존 CA로 새 서버 인증서에 서명하고(Console에 등록된 CA는 변경되지 않음) data/tls.crt를 교체하세요. 새 셸에서 실행하는 경우 먼저 TUNNEL_DOMAIN을 설정하세요.
export TUNNEL_DOMAIN=YOUR_TUNNEL_DOMAIN_HERE
openssl req -new -key data/tls.key -out /tmp/server.csr \
-subj "/CN=${TUNNEL_DOMAIN}"
openssl x509 -req -in /tmp/server.csr \
-CA data/ca.crt -CAkey data/ca.key -CAcreateserial \
-out data/tls.crt -days 90 \
-extfile data/tls.ext어느 흐름에서든 프록시는 tls.cert_file을 폴링하여 자동으로 다시 로드하므로 재시작이 필요하지 않습니다.
업스트림 MCP 서버를 Managed Agent 또는 Messages API에 연결합니다.
강화 지침, 자격 증명 교체 및 침해 대응.
연결, TLS 및 라우팅 문제를 진단합니다.
Was this page helpful?