−25%

Windows के सालाना भुगतान पर, 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. 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 पर नहीं, सभी इंटरफ़ेस पर सुनता है, और बहुत से दूसरे भी ऐसा ही करते हैं। तीसरा कदम इसे संभालता है।

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 प्रति माह से शुरू होते हैं।

FAQ

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 तक नहीं पहुँचते। यह तभी चलता है जब सभी क्लाइंट उसी सर्वर पर हों।

टिप्पणियाँ

अभी तक कोई टिप्पणी नहीं। पहले बनें।

एक टिप्पणी छोड़ें

टिप्पणियाँ दिखने से पहले मॉडरेट की जाती हैं।