−25%

על Windows בתשלום שנתי, עד 31.10. לחבילות

EQVPS
התחלה

VPS לשער MCP: כמה שרתי MCP מאחורי כתובת אחת וטוקן אחד

הצוות שלכם משתמש בשלושה שרתי MCP באירוח עצמי, ולכל אחד שלוש כתובות ושלושה סודות. שימו אותם מאחורי כתובת HTTPS אחת על VPS קטן: Caddy בודק bearer token, מנתב לפי נתיב ומרחיק את השרתים עצמם מהאינטרנט. תצורה שנבדקה.

שרתי MCP באירוח עצמי מתרבים. קודם יש אחד לתיעוד הפנימי, אחר כך אחד למסד הנתונים, ואז מישהו כותב שרת קטן לצינור הפריסה. לכל אחד פורט משלו, כתובת משלו וסוד משלו, וכל אחד בצוות מדביק את שלושתם בתצורת הלקוח שלו. להחליף טוקן פירושו לשלוח הודעה לכולם.

שער הופך את כל זה לכתובת אחת וטוקן אחד. הלקוחות מתחברים ל-https://mcp.example.com/docs/mcp, ל-.../db/mcp וכן הלאה. השער בודק את הטוקן, שולח כל נתיב לשרת הנכון ב-localhost, והשרתים עצמם אף פעם לא חשופים. צריך מעט מאוד: VPS קטן עם IPv4 משלו ו-Caddy.

בנינו את התצורה שלהלן על שרת בדיקות ובדקנו אותה עם לקוחות אמיתיים לפני שכתבנו את זה.

מה צריך

  • VPS עם IPv4 ציבורי, כדי שלקוחות יגיעו ל-443. ‏Nano-IP מספיק, אלא אם שרתי ה-MCP שלכם עושים בעצמם עבודה כבדה.
  • דומיין עם רשומת A שמצביעה על השרת, כאן mcp.example.com.
  • Ubuntu 24.04 או Debian 12/13. ‏Caddy נמצא במאגרים הרגילים של שניהם.

1. מריצים את שרתי ה-MCP על localhost

כל שרת רץ כשירות 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. התצורה של אף אחד לא משתנה, מלבד כתובת חדשה תחת אותו מארח ועם אותו טוקן.

מגבלות שכדאי להכיר

  • טוקן אחד לכולם פשוט, והחלפתו היא קובץ אחד, אבל אי אפשר לבטל גישה לאדם אחד בלי לשנות לכולם. לגישה לכל משתמש, שימו proxy אימות לפני השער או תנו לכל אחד נתיב וטוקן משלו.
  • השער לא הופך שרת לבטוח. שרת MCP שמריץ פקודות shell נשאר shell לכל מי שמחזיק בטוקן. הרחיקו טוקנים מתצורות משותפות ומ-git.
  • בחרו גודל לפי השרתים, לא לפי השער. ‏Caddy עצמו צורך כמה עשרות מגה-בייט. אם אחד השרתים מריץ מודל מקומי או מאנדקס מאגר גדול, הוא קובע את התוכנית, לא ה-proxy.

רק שרת MCP אחד? ‏VPS לשרתי MCP מכסה את המקרה הפשוט הזה. רוצים שהסוכנים שלכם ינהלו גם את השרת שעליו הם חיים? את זה עושה שרת ה-MCP של EQVPS (או 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 ב-reverse proxy כדי שאירועים יעברו מיד במקום להיתקע בבאפר.

טוקן משותף אחד בטוח מספיק?

לצוות קטן זו התחלה סבירה: הטוקן לעולם לא יוצא מ-HTTPS, ומחליפים אותו בשינוי קובץ אחד. כשתצטרכו גישה לכל אדם בנפרד או אפשרות לבטל, שימו שכבת אימות אמיתית לפניו. הטוקן המשותף הוא הרצפה, לא התקרה.

אפשר להריץ את זה על תוכנית NAT?

לא כשער ציבורי. בתוכנית NAT יש פורט מועבר אחד ל-SSH ושום דבר נכנס מלבדו, כך שהלקוחות לא יגיעו ל-443. זה עובד רק אם כל הלקוחות נמצאים על אותו שרת.

תגובות

אין עדיין תגובות. היו הראשונים.

השאירו תגובה

התגובות עוברות מודרציה לפני שהן מופיעות.