English ← MyDocs

MCP 隧道快速入门

使用本地 Docker Compose 部署将 Claude 连接到私有 MCP 服务器。


Note

MCP 隧道是一项研究预览功能。申请访问权限 即可试用。

本快速入门将带您从零开始,通过隧道让 Claude 调用私有 MCP 服务器。它使用 Docker Compose 和手动提供的凭据,这是本地测试的最短路径。有关生产部署,请参阅 使用 Helm 部署使用 Docker Compose 部署

您将构建的内容

在您的机器上运行一个三容器技术栈:一个示例 MCP 服务器、隧道代理和出站连接器。运行后,即使没有在公共端口上监听,示例服务器也可以通过 https://echo.<your-tunnel-domain>/mcp 从 Claude 访问。

准备工作

  1. 创建隧道

    在 Claude 控制台侧边栏中,前往 Manage > MCP tunnels 并点击 New tunnel。为其命名。保持 Set up programmatic access 关闭;本快速入门使用手动提供的凭据。

    创建后,打开隧道。从 Connection 部分复制两个值:

    • Domain(格式类似 abcd1234.tunnel.anthropic.com
    • Token(点击眼睛图标,然后复制)
  2. 设置部署目录

    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
    
    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 握手。生成两者:

    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
    
    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
    

    回到控制台,在隧道详情页上,点击 Add certificate 并上传 data/ca.crt(或粘贴其内容)。隧道状态会变为 Active

  4. 编写示例 MCP 服务器

    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.py
    
  5. 编写代理配置和 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:6b9adedbf2763143ec72f106ecaf0ce7fd3294e89b208f54a1db97a33d14c5ba
        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
    
    @"
    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:6b9adedbf2763143ec72f106ecaf0ce7fd3294e89b208f54a1db97a33d14c5ba
        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. 启动

    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"
    

    您应该看到一行 route configured(对应 echo)和四行 Registered tunnel connection。容器需要几秒钟启动;如果返回为空,请重新运行日志命令。

  7. 从 Claude 调用

    在控制台中,前往 Managed Agents > Sessions 并创建会话。在智能体选择器中选择 Create new agent,然后点击 + MCP Server,选择您的隧道,将 Subdomain 设置为 echoPath 设置为 mcp。然后提问:

    Use the hello tool to greet tunnel.

    您应该看到工具调用及其结果。

后续步骤

隧道已通过端到端验证。有关生产部署: