−25%

Windows 年繳方案適用,至 10 月 31 日。 檢視方案

EQVPS
開始使用

用於 MCP 閘道的 VPS:多台 MCP 伺服器共用一個位址和一個權杖

團隊在用三台自架的 MCP 伺服器,每個人手上都有三個 URL 和三組密鑰。把它們放到一台小 VPS 的同一個 HTTPS 位址後面:Caddy 驗證 bearer 權杖、依路徑轉送,並讓伺服器本身不暴露在網際網路上。這是一套測試過的設定。

自架的 MCP 伺服器會越來越多。先是一台給內部文件,接著一台給資料庫,後來有人替部署流程寫了台小的。每台都有自己的連接埠、URL 和密鑰,團隊裡每個人都得把三組全貼進用戶端設定。換一次權杖就得通知所有人。

閘道把這一切變成一個位址和一個權杖。用戶端連到 https://mcp.example.com/docs/mcp、.../db/mcp 等位址。閘道驗證權杖,把每個路徑轉到 localhost 上對應的伺服器,伺服器本身從不對外暴露。需要的東西很少:一台有獨立 IPv4 的小 VPS 加上 Caddy。

下面的設定我們先在測試伺服器上架好,並用真實用戶端驗證過才寫出來。

需要準備什麼

  • 一台有公開 IPv4 的 VPS,讓用戶端能連到 443。除非你的 MCP 伺服器本身要做重活,Nano-IP 就夠了。
  • 一個 A 記錄指向伺服器的網域,這裡用 mcp.example.com。
  • Ubuntu 24.04 或 Debian 12/13。兩者的標準套件庫裡都有 Caddy。

1. 在 localhost 上執行 MCP 伺服器

每台伺服器都以 systemd 服務執行。為了讓範例自成一體,這裡把參考伺服器 server-everything 跑了兩份;實際上換成你自己的。需要 Node.js 20 或更新版本:

mkdir -p /opt/mcp && cd /opt/mcp
npm install @modelcontextprotocol/server-everything
# /etc/systemd/system/mcp-everything-1.service
[Unit]
Description=MCP server everything #1
After=network.target

[Service]
WorkingDirectory=/opt/mcp
Environment=PORT=3101
ExecStart=/opt/mcp/node_modules/.bin/mcp-server-everything streamableHttp
Restart=always
User=nobody

[Install]
WantedBy=multi-user.target

第二份使用 3102 連接埠。接著:

systemctl daemon-reload
systemctl enable --now mcp-everything-1 mcp-everything-2

測試時我們發現:這台伺服器監聽所有網路介面,而不只是 127.0.0.1,很多其他伺服器也一樣。第 3 步會處理這件事。

2. Caddy:先驗證權杖,再依路徑轉送

產生一個權杖,透過環境檔交給 Caddy:

apt install -y caddy
echo "MCP_GATEWAY_TOKEN=$(openssl rand -hex 32)" > /etc/caddy/gateway.env
chmod 600 /etc/caddy/gateway.env
mkdir -p /etc/systemd/system/caddy.service.d
printf '[Service]\nEnvironmentFile=/etc/caddy/gateway.env\n' > /etc/systemd/system/caddy.service.d/env.conf
systemctl daemon-reload

Caddyfile:

mcp.example.com {
	route {
		@unauthorized not header Authorization "Bearer {$MCP_GATEWAY_TOKEN}"
		respond @unauthorized 401

		handle_path /everything/* {
			reverse_proxy 127.0.0.1:3101 {
				flush_interval -1
			}
		}
		handle_path /tools2/* {
			reverse_proxy 127.0.0.1:3102 {
				flush_interval -1
			}
		}
		respond 404
	}
}
caddy validate --config /etc/caddy/Caddyfile && systemctl restart caddy

mcp.example.com 的憑證由 Caddy 自動取得。

route 區塊不是裝飾。我們第一版把權杖驗證和 handle_path 區塊並排放在最上層,結果沒帶權杖的請求直接以 200 通過。Caddy 會依自己的順序排列指令,handle_path 比 respond 先執行。在 route 裡面,它們則依書寫順序執行。如果你要改這份設定,第一件事就是測試「不帶權杖」的情況。

handle_path 會去掉前綴,所以 /everything/mcp 到達伺服器時是 /mcp。flush_interval -1 讓串流事件一到就轉送。

3. 除了 SSH 和 HTTPS 全部關閉

apt install -y ufw
ufw default deny incoming
ufw allow OpenSSH
ufw allow 80,443/tcp
ufw enable

這樣之後,在我們的測試中,3101 和 3102 連接埠從伺服器外部連不到,而 22 和 443 正常回應。80 連接埠保持開放,只是為了讓 Caddy 申請與續期憑證,並重新導向到 HTTPS。

4. 驗證

TOKEN=$(cut -d= -f2 /etc/caddy/gateway.env)
INIT='{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"check","version":"1"}}}'
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://mcp.example.com/everything/mcp \
  -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -d "$INIT"
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://mcp.example.com/everything/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -d "$INIT"

第一個請求應輸出 401,第二個輸出 200。我們實測時,錯誤的權杖和截斷的權杖都得到 401,未知路徑即使帶著正確權杖也得到 404。

接著從用戶端測試,例如 Claude Code:

claude mcp add --transport http everything https://mcp.example.com/everything/mcp \
  --header "Authorization: Bearer $TOKEN"
claude mcp list

兩台伺服器都顯示 ✔ Connected。同一個用戶端換成錯誤權杖後顯示 ✘ Failed to connect。用戶端設定的更多內容請見將 EQVPS MCP 接上 Claude Code 和 Codex。

加入下一台伺服器

在新的 localhost 連接埠啟動它,加一個 handle_path 區塊,重新載入 Caddy。誰的設定都不用改,只是在同一個主機、同一個權杖下多了一個新 URL。

需要了解的限制

  • 所有人共用一個權杖很簡單,輪替也只需一個檔案,但你沒辦法只撤銷一個人的權限而不影響所有人。需要依使用者授權時,在前面加一個驗證代理,或給每個人獨立的路由與權杖。
  • 閘道不會讓伺服器變安全。 能執行 shell 指令的 MCP 伺服器,對任何持有權杖的人來說仍然是一個 shell。別把權杖放在共用設定或 git 裡。
  • 依伺服器而不是依閘道選規格。 Caddy 本身只占幾十 MB。如果某台伺服器要跑本地模型或為大型程式庫建立索引,決定方案的是它,而不是代理。

只有一台 MCP 伺服器?用於 MCP 伺服器的 VPS 談的是那種更簡單的情況。想讓你的代理也管理它們所在的伺服器?EQVPS MCP 伺服器做得到(偏好寫腳本的話用 REST API),有獨立 IPv4 的方案每月 $8 起。

常見問題

為什麼要把 MCP 伺服器放在閘道後面?

整個團隊只用一個位址和一個權杖,而不是每台伺服器各一套;TLS 集中在一處處理;伺服器本身只監聽 localhost。加第四台伺服器只要改閘道的三行設定,不必再發新密鑰給所有人。

需要什麼方案?

有獨立 IPv4 的方案,因為用戶端必須能連到 80 和 443 連接埠。Nano-IP(每月 $8,2 vCPU,1 GB)足以跑閘道和幾台輕量 MCP 伺服器。如果某台伺服器本身要做重活,就依它來選規格。

串流能經過 Caddy 嗎?

可以。Streamable HTTP 使用一般的 POST 請求加上 server-sent events。在反向代理設定 flush_interval -1,事件就會立即轉送,而不是卡在緩衝區。

一個共用權杖夠安全嗎?

對小團隊來說是合理的起點:權杖從不離開 HTTPS,改一個檔案就能輪替。需要依人授權或撤銷權限時,在前面加一層真正的驗證。共用權杖是底線,不是上限。

NAT 方案可以用嗎?

不能當公開閘道。NAT 方案只有一個給 SSH 的轉發連接埠,沒有其他入站,用戶端連不到 443。只有所有用戶端都在同一台伺服器上時才行得通。

評論

目前還沒有評論。歡迎成為第一位。

發表評論

評論在顯示前會經過審核。