Mulai cepat MCP tunnels
Hubungkan Claude ke server MCP privat menggunakan deployment Docker Compose lokal.
Panduan mulai cepat ini membawa Anda mulai dari membuat tunnel hingga Claude memanggil server MCP privat melaluinya. Panduan ini menggunakan Docker Compose dengan penyediaan kredensial manual, yang merupakan jalur terpendek untuk pengujian lokal. Untuk deployment produksi, lihat Deploy dengan Helm atau Deploy dengan Docker Compose.
Apa yang akan Anda bangun
Sebuah tunnel stack dua kontainer (proxy dan cloudflared) ditambah server MCP contoh yang berjalan di sampingnya. Ketika semuanya berjalan, server contoh dapat dijangkau dari Claude di https://echo.<your-tunnel-domain>/mcp meskipun tidak ada yang mendengarkan di port publik.
Apa yang Anda butuhkan
- Docker dan Docker Compose pada mesin dengan akses internet keluar.
- Peran di Claude Console yang dapat mengelola MCP tunnels. Lihat prasyarat panduan Console.
- OpenSSL 1.1.1 atau lebih baru. Sudah terpasang di macOS dan sebagian besar distribusi Linux. Di Windows, instal secara terpisah (binary
opensslharus ada diPATHAnda).
Buat tunnel
Di Claude Console, buka halaman MCP tunnels (
platform.claude.com/settings/workspaces/default/mcp-tunnels). Setiap tunnel dimiliki oleh satu workspace. Pilih workspace yang Anda inginkan di pemilih workspace pada sidebar. Klik New tunnel dan beri nama. Biarkan Set up programmatic access nonaktif; panduan mulai cepat ini menggunakan penyediaan kredensial manual.Setelah dibuat, buka tunnel tersebut. Salin dua nilai dari bagian Connection:
- Domain (terlihat seperti
abcd1234.tunnel.anthropic.com) - Token (klik ikon mata, lalu salin)
- Domain (terlihat seperti
Siapkan direktori deployment
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 1New-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 1Buat CA dan sertifikat server
Proxy mengakhiri inner TLS menggunakan sertifikat yang ditandatangani oleh CA yang Anda kendalikan. Buat keduanya:
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.keyopenssl 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.extKembali ke Console, di halaman detail tunnel, klik Add certificate dan unggah
data/ca.crt(atau tempel isinya). Lencana Needs certificate di samping nama tunnel akan hilang.Tulis server MCP contoh
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@' 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.pyTulis konfigurasi proxy dan file compose
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:d243d30642d39857a0579e465cb3b9bf3ae7c1141e83143bb6856777a31467a5 volumes: - ./config/mcp-proxy.yaml:/etc/mcp-gateway/config.yaml:ro - ./data:/data:ro restart: unless-stopped cloudflared: image: cloudflare/cloudflared@sha256:0e56c13c7058fcef9c4f0e7d83372f82330548dbf8f8b366f3d8b506526d93b2 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@" 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:d243d30642d39857a0579e465cb3b9bf3ae7c1141e83143bb6856777a31467a5 volumes: - ./config/mcp-proxy.yaml:/etc/mcp-gateway/config.yaml:ro - ./data:/data:ro restart: unless-stopped cloudflared: image: cloudflare/cloudflared@sha256:0e56c13c7058fcef9c4f0e7d83372f82330548dbf8f8b366f3d8b506526d93b2 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.yamlJalankan
docker compose up -d docker compose logs mcp-proxy | grep "route configured" docker compose logs cloudflared | grep "Registered tunnel connection"docker compose up -d docker compose logs mcp-proxy | Select-String "route configured" docker compose logs cloudflared | Select-String "Registered tunnel connection"Anda akan melihat satu baris
route configureduntukechodan empat barisRegistered tunnel connection. Kontainer membutuhkan beberapa detik untuk mulai; jalankan ulang perintah log jika hasilnya kosong.Panggil dari Claude
Di Console, buka halaman Sessions (
platform.claude.com/sessions) dan buat sesi. Di pemilih agen, pilih Create new agent, beri nama agen, dan pertahankan model yang sudah terisi. Klik + MCP Server, pilih tunnel Anda, dan atur Subdomain keechodan Path kemcp. Lalu tanyakan:Use the hello tool to greet tunnel.
Anda akan melihat pemanggilan alat diikuti oleh hasilnya.
Langkah selanjutnya
Tunnel telah diverifikasi secara menyeluruh. Untuk mengganti dengan server MCP Anda sendiri, tambahkan ke docker-compose.yaml (atau jalankan di jaringan Docker yang sama), tambahkan rute untuknya di config/mcp-proxy.yaml, lalu mulai ulang proxy (docker compose restart mcp-proxy).
Untuk deployment produksi:
Deployment host tunggal yang diperkuat, dengan atau tanpa akses terprogram.
Deployment Kubernetes dengan manajemen kredensial otomatis.
Was this page helpful?