खुद होस्ट किए गए 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 प्रति माह से शुरू होते हैं।
टिप्पणियाँ
अभी तक कोई टिप्पणी नहीं। पहले बनें।