MCP 터널 퀵스타트

MCP 터널 퀵스타트 (MCP tunnels quickstart)

이 퀵스타트는 로컬 Docker Compose 배포로 Claude가 터널을 통해 사설 MCP 서버를 호출하는 지점까지 안내해요. 로컬 테스트에 가장 빠른 길인 수동 자격 증명 프로비저닝을 Docker Compose와 함께 사용해요. 프로덕션 배포는 Helm으로 배포 또는 Docker Compose로 배포를 참고하세요.

출처: 문서

본문

참고 (Note) MCP 터널은 연구 프리뷰(research preview) 상태예요. 사용해보려면 액세스를 요청하세요.

이 퀵스타트는 Claude가 터널을 통해 사설 MCP 서버를 호출하는 지점까지 안내해요. 로컬 테스트에 가장 빠른 수동 자격 증명 프로비저닝을 Docker Compose와 함께 사용해요. 프로덕션 배포는 Helm으로 배포 또는 Docker Compose로 배포를 참고하세요.

무엇을 만들게 될까요 (What you'll build)

두 컨테이너로 된 터널 스택(프록시cloudflared)에 그 옆에서 함께 실행되는 샘플 MCP 서버를 더한 구성이에요. 모든 것이 실행되면 샘플 서버는 공용 포트에서 아무것도 듣고 있지 않은데도 Claude에서 https://echo.<your-tunnel-domain>/mcp로 접근할 수 있게 돼요.

무엇이 필요할까요 (What you need)

  • 아웃바운드 인터넷 접근이 있는 머신에 Docker와 Docker Compose
  • MCP 터널을 관리할 수 있는 Claude Console의 역할. Console 가이드 사전 조건을 참고하세요.
  • OpenSSL 1.1.1 이상. macOS와 대부분의 Linux 배포판에는 사전 설치되어 있고, Windows에서는 별도로 설치해야 해요 (openssl 바이너리가 PATH에 있어야 해요).
  1. 터널 만들기 Claude Console 사이드바에서 Manage > MCP tunnels로 가서 New tunnel을 클릭해요. 이름을 지어주세요. Set up programmatic access는 끈 채로 두세요. 이 퀵스타트는 수동 자격 증명 프로비저닝을 사용해요.

    만든 후에는 터널을 열고 Connection 섹션에서 두 값을 복사해요:

    • Domain (abcd1234.tunnel.anthropic.com처럼 보여요)
    • Token (눈 아이콘을 클릭한 다음 복사)
  2. 배포 디렉터리 설정하기

    • macOS / Linux:
      mkdir -p mcp-tunnel/{config,data}
      cd mcp-tunnel
      export TUNNEL_DOMAIN=YOUR_TUNNEL_DOMAIN_HERE   # from step 1
      export TUNNEL_TOKEN='eyJ...'            # from step 1
      
    • Windows (PowerShell):
      New-Item -ItemType Directory -Force -Path mcp-tunnel/config, mcp-tunnel/data | Out-Null
      Set-Location mcp-tunnel
      $env:TUNNEL_DOMAIN = "YOUR_TUNNEL_DOMAIN_HERE"   # from step 1
      $env:TUNNEL_TOKEN  = "eyJ..."             # from step 1
      
  3. CA와 서버 인증서 생성하기 프록시는 여러분이 제어하는 CA가 서명한 인증서로 내부 TLS를 종료해요. 둘 다 생성해요:

    • macOS / Linux:
      openssl req -x509 -newkey rsa:2048 -nodes \
        -keyout data/ca.key -out data/ca.crt \
        -days 3650 -subj "/CN=mcp-tunnel-ca" \
        -addext "basicConstraints=critical,CA:TRUE" \
        -addext "keyUsage=critical,keyCertSign,cRLSign" \
        -addext "subjectKeyIdentifier=hash"
      
      cat > data/tls.ext <<EOF
      subjectAltName = DNS:${TUNNEL_DOMAIN},DNS:*.${TUNNEL_DOMAIN}
      authorityKeyIdentifier = keyid,issuer
      extendedKeyUsage = serverAuth
      EOF
      
      openssl req -newkey rsa:2048 -nodes \
        -keyout 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
      
      chmod 644 data/tls.key
      
    • Windows (PowerShell):
      openssl req -x509 -newkey rsa:2048 -nodes `
        -keyout data/ca.key -out data/ca.crt `
        -days 3650 -subj "/CN=mcp-tunnel-ca" `
        -addext "basicConstraints=critical,CA:TRUE" `
        -addext "keyUsage=critical,keyCertSign,cRLSign" `
        -addext "subjectKeyIdentifier=hash"
      
      @"
      subjectAltName = DNS:$env:TUNNEL_DOMAIN,DNS:*.$env:TUNNEL_DOMAIN
      authorityKeyIdentifier = keyid,issuer
      extendedKeyUsage = serverAuth
      "@ | Set-Content -NoNewline -Encoding ascii -Path data/tls.ext
      
      openssl req -newkey rsa:2048 -nodes `
        -keyout data/tls.key -out data/server.csr `
        -subj "/CN=$env:TUNNEL_DOMAIN"
      openssl x509 -req -in data/server.csr `
        -CA data/ca.crt -CAkey data/ca.key -CAcreateserial `
        -out data/tls.crt -days 90 -extfile data/tls.ext
      

    Console로 돌아와 터널 상세 페이지에서 Add certificate를 클릭하고 data/ca.crt를 업로드하거나 내용을 붙여넣어요. 터널 상태가 Active로 바뀌어요.

  4. 샘플 MCP 서버 작성하기

    • macOS / Linux:
      cat > 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
      
    • Windows (PowerShell):
      @'
      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")
      '@ | Set-Content -NoNewline -Encoding ascii -Path hello_server.py
      
  5. 프록시 설정과 compose 파일 작성하기

    • macOS / Linux:
      cat > config/mcp-proxy.yaml <<EOF
      listen_addr: ":8080"
      tunnel_domain: ${TUNNEL_DOMAIN}
      tls:
        cert_file: /data/tls.crt
        key_file: /data/tls.key
      routes:
        echo: http://hello-mcp:9000
      EOF
      
      cat > docker-compose.yaml <<'EOF'
      services:
        mcp-proxy:
          image: us-docker.pkg.dev/anthropic-public-registry/images/mcp-proxy@sha256:efb27b299d627e4134815663cb8896641eeaee025d734c0f695582b4df38f013
          volumes:
            - ./config/mcp-proxy.yaml:/etc/mcp-gateway/config.yaml:ro
            - ./data:/data:ro
          restart: unless-stopped
      
        cloudflared:
          image: cloudflare/cloudflared@sha256:6b599ca3e974349ead3286d178da61d291961182ec3fe9c505e1dd02c8ac31b0
          command: tunnel --no-autoupdate run --url http://localhost:8080
          environment:
            - TUNNEL_TOKEN
          network_mode: "service:mcp-proxy"
          restart: unless-stopped
      
        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
      
    • Windows (PowerShell):
      @"
      listen_addr: ":8080"
      tunnel_domain: $env:TUNNEL_DOMAIN
      tls:
        cert_file: /data/tls.crt
        key_file: /data/tls.key
      routes:
        echo: http://hello-mcp:9000
      "@ | Set-Content -NoNewline -Encoding ascii -Path config/mcp-proxy.yaml
      
      @'
      services:
        mcp-proxy:
          image: us-docker.pkg.dev/anthropic-public-registry/images/mcp-proxy@sha256:efb27b299d627e4134815663cb8896641eeaee025d734c0f695582b4df38f013
          volumes:
            - ./config/mcp-proxy.yaml:/etc/mcp-gateway/config.yaml:ro
            - ./data:/data:ro
          restart: unless-stopped
      
        cloudflared:
          image: cloudflare/cloudflared@sha256:6b599ca3e974349ead3286d178da61d291961182ec3fe9c505e1dd02c8ac31b0
          command: tunnel --no-autoupdate run --url http://localhost:8080
          environment:
            - TUNNEL_TOKEN
          network_mode: "service:mcp-proxy"
          restart: unless-stopped
      
        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
      '@ | Set-Content -NoNewline -Encoding ascii -Path docker-compose.yaml
      
  6. 시작하기

    • macOS / Linux:
      docker compose up -d
      docker compose logs mcp-proxy | grep "route configured"
      docker compose logs cloudflared | grep "Registered tunnel connection"
      
    • Windows (PowerShell):
      docker compose up -d
      docker compose logs mcp-proxy | Select-String "route configured"
      docker compose logs cloudflared | Select-String "Registered tunnel connection"
      

    echo에 대한 route configured 줄 하나와 Registered tunnel connection 줄 네 개가 보여야 해요. 컨테이너는 시작에 몇 초 걸리므로, 로그가 비어 있으면 로그 명령을 다시 실행하세요.

  7. Claude에서 호출하기 Console에서 Managed Agents > Sessions로 가 세션을 만들어요. 에이전트 선택기에서 Create new agent를 선택하고 이름을 지은 다음 미리 채워진 모델을 유지하세요. + MCP Server를 클릭하고 터널을 선택한 뒤 Subdomainecho로, Pathmcp로 설정하세요. 그런 다음 물어봐요:

    Use the hello tool to greet tunnel.

    도구 호출 다음에 그 결과가 보여야 해요.

다음 단계 (Next steps)

터널이 종단 간(end to end)으로 검증됐어요. 나만의 MCP 서버로 바꾸려면 docker-compose.yaml에 추가하고(또는 같은 Docker 네트워크에서 실행), config/mcp-proxy.yaml에 라우트를 추가한 다음 프록시를 재시작하세요 (docker compose restart mcp-proxy).

프로덕션 배포를 위해서는:

더 알아보기 (Learn more)