VPS वर MCP servers कसे चालवायचे?
AI coding agents साठी VPS वर MCP servers सेटअप करा. stdio आणि remote HTTP transports, systemd, TLS आणि authentication बद्दल सविस्तर माहिती मिळवा.
तुम्ही काय तयार करत आहात
एका VPS वर दोन कार्यरत MCP सेटअप. पहिले stdio सर्व्हर — हे एक filesystem किंवा database टूल आहे जे Claude Code द्वारे child process म्हणून सुरू केले जाते आणि pipe द्वारे संवाद साधते. दुसरे remote HTTP सर्व्हर जे systemd आणि nginx reverse proxy (TLS सह) च्या मागे long-lived network service म्हणून चालते; हे कोणत्याही MCP client द्वारे एक्सेस केले जाऊ शकते. दोन्हीची installation प्रक्रिया लहान आहे. या मार्गदर्शिकेतील मुख्य भाग म्हणजे दोन आव्हाने: JSON-RPC stream शुद्ध ठेवणे आणि कोणतेही unauthenticated tool endpoint सार्वजनिक इंटरनेटवर न ठेवणे.
MCP नक्की काय आहे
Model Context Protocol हा एक मानक मार्ग आहे ज्याद्वारे AI client — जसे की Claude Code, Claude Desktop, Gemini CLI on a VPS, किंवा तुमचा स्वतःचा script — बाह्य tools कॉल करू शकतो आणि बाह्य resources वाचू शकतो. मॉडेल स्वतः काहीही रन करत नाही. ते client ला विनंती करते, client MCP server ला JSON-RPC 2.0 द्वारे संदेश पाठवते, आणि server tool रन करून त्याचे निकाल परत देते. एकच protocol असल्याने, तुम्ही एकदा लिहिलेला server MCP सपोर्ट करणाऱ्या प्रत्येक client सोबत काम करू शकतो.
यात दोन transports आहेत आणि या मार्गदर्शिकेचे पुढील भाग त्यांच्यानुसार विभागलेले आहेत:
- stdio. Client, server ला child process म्हणून सुरू करतो आणि standard input व standard output वर newline-delimited JSON-RPC messages ची देवाणघेवाण करतो. यात कोणतेही network, port किंवा auth नसते — trust boundary ही स्वतः process असते. जवळजवळ सर्व local tools याच पद्धतीने काम करतात.
- Streamable HTTP (आणि त्याचा जुना प्रकार, HTTP+SSE). Server ही एक long-running web service असते. Client HTTP द्वारे कनेक्ट होतो आणि server Server-Sent Events द्वारे प्रतिसाद stream करू शकते. एका server ला अनेक clients सोबत शेअर करण्यासाठी किंवा कायमस्वरूपी चालणाऱ्या tool साठी याचा वापर होतो.
जेव्हा tool एकाच machine आणि एकाच user साठी असेल, तेव्हा stdio निवडा. जेव्हा ते shared service असेल, तेव्हा HTTP निवडा.
Prerequisites and the honest gotchas
root किंवा sudo परवान्यांसह एक नवीन Ubuntu 24.04 KVM VPS गृहीत धरा. त्याव्यतिरिक्त:
- सर्व्हरसाठी आवश्यक runtime. बहुतेक संदर्भ सर्व्हर Node किंवा Python मध्ये असतात. Ubuntu 24.04 मध्ये Node 18 असते, परंतु अनेक सध्याचे MCP packages साठी Node 20 किंवा त्यापुढील आवृत्ती आवश्यक असते. त्यामुळे
aptवर अवलंबून राहण्याऐवजी NodeSource किंवा nvm कडून सध्याची LTS आवृत्ती स्थापित करा. Python 3.12 आधीच उपलब्ध आहे. - Domain आणि DNS A record, परंतु फक्त रिमोट HTTP सर्व्हरसाठी — TLS साठी अशा नावाचा वापर आवश्यक आहे ज्याचा रिझोल्यूशन या VPS कडे होते. stdio उदाहरणासाठी DNS ची आवश्यकता नाही.
- 512 MB RAM पुरेसा आहे. MCP सर्व्हर हे हलके JSON-RPC processes आहेत; मेमरीचा वापर तुमच्या टूलवर अवलंबून असतो (उदा. database driver, file cache), प्रोटोकॉलवर नाही.
- Spec नवीन आहे आणि बदलत आहे. 2025-03-26 च्या रिव्हिजनमध्ये HTTP+SSE च्या जागी Streamable HTTP आणले आहे आणि SSE deprecated म्हणून घोषित केले आहे. SSE अजूनही काम करते आणि अनेक सर्व्हर त्याचा वापर करतात, त्यामुळे कोणत्याही transport प्रकाराला अंतिम न मानता सर्व्हरच्या release notes नुसार पुन्हा तपासा.
Step 1: Claude Code मध्ये stdio server जोडा
filesystem server ने सुरुवात करा — हे अधिकृत आहे, याचे नियमित अपडेट्स येतात आणि यासाठी फक्त Node ची आवश्यकता असते. खालील कमांड वापरून तुम्ही ते Claude Code मध्ये रजिस्टर करू शकता; हे सध्याच्या प्रोजेक्टसाठी मर्यादित (scope) असेल आणि committable फाईलमध्ये सेव्ह होईल:
cd /home/matt/projects/api
claude mcp add --scope project --transport stdio filesystem \
-- npx -y @modelcontextprotocol/server-filesystem /home/matt/projects/api-- separator महत्त्वाचा आहे: यानंतरचा सर्व भाग Claude Code द्वारे रन केली जाणारी कमांड आहे, ती Claude Code ची flag नाही. यामुळे प्रोजेक्ट रूटमध्ये .mcp.json तयार होईल:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/home/matt/projects/api"
]
}
}
}अजून काहीही रन होत नाहीये. जेव्हा तुम्ही या डिरेक्टरीमध्ये पुढच्या वेळी Claude Code सुरू कराल, तेव्हा agent .mcp.json वाचेल, npx -y @modelcontextprotocol/server-filesystem ... ला child process म्हणून सुरू करेल आणि त्या process च्या stdin/stdout वरून MCP handshake पूर्ण करेल. ते यशस्वी झाले आहे की नाही हे तपासा:
claude mcp listयोग्यरित्या सुरू झालेला server त्याची कमांड आणि हिरवे टिक मार्क — filesystem: npx -y @modelcontextprotocol/server-filesystem ... - ✓ Connected — प्रिंट करतो. सेशनमध्ये, /mcp slash command द्वारे server कडील टूल्सची यादी (read_file, write_file, list_directory) पाहता येते, आणि agent आता तुम्ही दिलेल्या paths वर ती टूल्स वापरू शकतो. डेटाबेस टूल देखील अशाच प्रकारे काम करते — फक्त package बदला आणि शेवटचा argument म्हणून connection string द्या — परंतु सध्याच्या package नावासाठी server च्या स्वतःच्या repository तपासा, कारण reference Postgres server मध्ये अनेकदा बदल झाले आहेत.
एजंटला थेट मशीनवर रन करण्याचा मुख्य उद्देश हाच आहे: Claude Code session tmux मध्ये VPS वर चालते, आणि त्याचे stdio servers प्रोजेक्ट फाइल्स आणि local services ला थेट ॲक्सेस मिळवून त्याच्या शेजारीच चालतात, ज्यामुळे network round-trip ची गरज पडत नाही.
Step 2: remote HTTP server तयार करा
stdio server त्याच्या parent process सोबत बंद होतो. जेव्हा तुम्हाला असा tool हवा असतो जो प्रत्येक client साठी सुरू राहील — जसे की shared ops tool, database gateway, किंवा असे काही जे तुमचे laptop आणि CI दोन्ही वापरतात — तेव्हा तुम्हाला HTTP transport आणि एक real service आवश्यक असते. खाली official SDK वापरून तयार केलेला एक minimal Python server आहे, जो एक tool expose करतो:
# /opt/mcp-ops/server.py
from mcp.server.fastmcp import FastMCP
import subprocess
mcp = FastMCP("ops-tools", host="127.0.0.1", port=8000)
@mcp.tool()
def disk_free() -> str:
"""Return `df -h` for the server."""
out = subprocess.run(["df", "-h"], capture_output=True, text=True)
return out.stdout
if __name__ == "__main__":
# Serves Streamable HTTP at /mcp on 127.0.0.1:8000
mcp.run(transport="streamable-http")host="127.0.0.1" कडे लक्ष द्या. हा server फक्त localhost ला bind होतो — बाहेरील कोणताही घटक त्याला थेट reach करू शकत नाही, जे authentication उपलब्ध होण्यापूर्वी आवश्यक असते. systemd ला stable interpreter path मिळावा यासाठी तो स्वतःच्या virtualenv मध्ये install करा:
sudo useradd --system --home /opt/mcp-ops --shell /usr/sbin/nologin mcp
sudo install -d -o mcp -g mcp /opt/mcp-ops
sudo -H -u mcp python3 -m venv /opt/mcp-ops/.venv
sudo -H -u mcp /opt/mcp-ops/.venv/bin/pip install "mcp[cli]"Step 3: systemd वापरून प्रक्रिया सुरू ठेवा
जेव्हा agent ला आवश्यक असते तेव्हा tool बंद असेल, तर ते tool नसावे त्यापेक्षाही वाईट आहे. /etc/systemd/system/mcp-ops.service लिहा:
[Unit]
Description=MCP ops-tools server
After=network.target
[Service]
Type=simple
User=mcp
WorkingDirectory=/opt/mcp-ops
ExecStart=/opt/mcp-ops/.venv/bin/python /opt/mcp-ops/server.py
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
[Install]
WantedBy=multi-user.targetExecStart मधील venv Python चा absolute path देणे अनिवार्य आहे — ते /usr/bin/python3 कडे निर्देशित करा आणि प्रक्रिया ModuleNotFoundError: No module named 'mcp' ने सुरू होईल, कारण system interpreter ला तुमचा pip install सापडणार नाही. enable करा आणि तपासा:
sudo systemctl daemon-reload
sudo systemctl enable --now mcp-ops
sudo systemctl status mcp-ops
curl -si -H 'Accept: application/json, text/event-stream' \
-H 'Content-Type: application/json' \
-X POST http://127.0.0.1:8000/mcpstatus मध्ये active (running) असावे. curl कडून body मध्ये JSON-RPC error सह HTTP/1.1 400 Bad Request प्रतिसाद मिळेल — कारण त्या request मध्ये session आणि वैध JSON payload नव्हता — आणि तुम्हाला नेमके हेच हवे आहे: यामुळे port प्रतिसाद देतो आणि protocol समजतो हे सिद्ध होते. Connection refused किंवा रिकामी reply म्हणजे प्रक्रिया तुम्ही विचारलेल्या ठिकाणी bound नाही; journalctl -u mcp-ops -n 50 वाचा.
Step 4: TLS आणि reverse proxy सेट करा
सर्व्हर localhost वरून listen करतो. तो कोठूनही एक्सेस करण्यासाठी, nginx वर TLS terminate करा आणि आतल्या बाजूला proxy करा. nginx इंस्टॉल करा, Certbot and Let's Encrypt on nginx वापरून certificate मिळवा, आणि नंतर location block लिहा. buffering disable करणे अत्यंत महत्त्वाचे आहे, कारण nginx च्या default वर्तनामुळे response पूर्ण होईपर्यंत तो थांबवून ठेवला जातो, ज्यामुळे SSE stream कायमचा stall होऊ शकतो:
server {
listen 443 ssl;
server_name mcp.example.com;
# ssl_certificate lines managed by Certbot
location /mcp {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
# The four lines that make SSE work through nginx:
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
chunked_transfer_encoding off;
}
}sudo nginx -t && sudo systemctl reload nginx वापरून reload करा. जर तुम्ही आधीच containers चा fleet वापरत असाल, तर Traefik reverse proxy with automatic TLS हे काम तुमच्यासाठी आपोआप करते — ते certificate जारी करते आणि hostname नुसार routing करते, तुम्हाला फक्त MCP container ला labels जोडायचे आहेत. कोणत्याही परिस्थितीत, आता reverse proxy हाच एकमेव public port वर असलेला घटक आहे, आणि तो अशा service कडे निर्देश करतो जी तुम्ही अजून secure केलेली नाही. URL कुठेही रजिस्टर करण्यापूर्वी ती secure करा.
Step 5: या विषयातील सर्वात महत्त्वाचा सुरक्षा नियम
कधीही unauthenticated MCP endpoint उघड करू नका. MCP server ही केवळ read-only API नाही. ते tool access प्रदान करते — तुमच्या files, database आणि कधीकधी shell साठी. सार्वजनिक internet वर उघडलेला /mcp तुमच्या AI agent इतकाच अधिकार असलेला एक अनोळखी व्यक्ती आहे: ते तुमचे tools list करतात आणि नंतर त्यांना call करतात. याला unauthenticated admin socket प्रमाणेच वागवा, कारण ते तसंच आहे.
तीन संरक्षण पद्धती, पसंतीनुसार:
- ते publish करू नका. server
127.0.0.1वर ठेवा आणि तुमच्या laptop वरून SSH tunnel द्वारे त्याला access करा:ssh -L 8000:127.0.0.1:8000 matt@vps, त्यानंतर client लाhttp://127.0.0.1:8000/mcpकडे निर्देशित करा. यामुळे काहीही उघड होत नाही. - ते private network वर ठेवा. self-hosted WireGuard VPN चा tunnel address bind करा आणि फक्त VPN peers लाच त्याचा access द्या. सार्वजनिक internet ला फक्त एक closed port दिसेल.
- जर ते public असणे आवश्यक असेल, तर token आवश्यक करा. योग्य उपाय म्हणजे MCP OAuth flow जो HTTP transport ला natively support करतो. व्यावहारिक किमान उपाय म्हणजे proxy वर तपासले जाणारे shared bearer token — हे सोपे आहे आणि 'drive-by' हल्ले पूर्णपणे थांबवते:
location /mcp {
if ($http_authorization != "Bearer REPLACE_WITH_LONG_RANDOM") {
return 401;
}
proxy_pass http://127.0.0.1:8000;
# ...buffering-off block from above...
}openssl rand -hex 32 वापरून token generate करा, आणि यापैकी एक सुरक्षा उपाय नसेल तर server ला कधीही 0.0.0.0 ला bind करू नका. त्यानंतर client token header म्हणून पाठवतो. Claude Code मध्ये:
claude mcp add --scope project --transport http ops-tools https://mcp.example.com/mcp \
--header 'Authorization: Bearer ${MCP_TOKEN}'तुमच्या shell मध्ये MCP_TOKEN सेट करा जेणेकरून secret कधीही .mcp.json मध्ये plaintext स्वरूपात साठवले जाणार नाही — Claude Code read time ला environment मधून ${MCP_TOKEN} expand करते.
Step 6: MCP Inspector वापरून debug करा
जेव्हा server चुकीच्या पद्धतीने काम करते, तेव्हा agent च्या आतून अंदाज लावू नका — थेट Inspector वापरून ते तपासा, जो एक अधिकृत web-based test client आहे. stdio server साठी, agent वापरत असलेलीच command वापरा:
npx @modelcontextprotocol/inspector \
npx -y @modelcontextprotocol/server-filesystem /tmpहे http://localhost:6274 वर UI सुरू करते (नवीन versions मध्ये MCP_PROXY_AUTH_TOKEN query string सह URL दिसते — तोच exact link वापरा अन्यथा UI reject होईल) आणि 6277 वर proxy सुरू करते. Connect वर क्लिक करा, त्यानंतर List Tools निवडा, आणि नंतर real arguments सह Call Tool निवडा. जर Inspector मध्ये सर्व काही व्यवस्थित चालले असेल पण agent मध्ये fail होत असेल, तर bug तुमच्या client config मध्ये आहे, server मध्ये नाही. remote HTTP server साठी, Streamable HTTP transport निवडा, https://mcp.example.com/mcp प्रविष्ट करा, Authorization header जोडा आणि connect करा — agent वापरण्यापूर्वी auth आणि proxy बरोबर आहेत हे तपासण्यासाठी ही सर्वात जलद पद्धत आहे.
Keeping servers updated
MCP वेगाने विकसित होत आहे, म्हणून ठराविक वेळापत्रकानुसार पॅच (patch) करा. npx -y वापरून सुरू केलेले Node servers प्रत्येक वेळी नवीनतम आवृत्ती (version) मिळवतात; हे सोयीचे आहे पण पुनरावृत्ती करण्यायोग्य (reproducible) नाही. तुम्ही ज्या आवृत्तीचे परीक्षण केले आहे तीच आवृत्ती निश्चित करा — npm view @modelcontextprotocol/server-filesystem version मधून ती वाचा आणि .mcp.json (@modelcontextprotocol/server-filesystem@<version>) मधील package name मध्ये जोडा. एकदा सर्व्हर स्थिर झाला की, आवृत्ती बदलताना ती जाणीवपूर्वक करा. systemd अंतर्गत चालणारे Python servers sudo -H -u mcp /opt/mcp-ops/.venv/bin/pip install -U "mcp[cli]" आणि त्यानंतर sudo systemctl restart mcp-ops वापरून अपडेट करा. अपग्रेड करताना तुमचे SDK ज्या spec revision ला लक्ष्य करते त्यावर लक्ष द्या — SSE-to-Streamable-HTTP मर्यादेपलीकडे होणाऱ्या बदलामुळे क्लायंटला विनंती करण्यासाठी लागणारे transport बदलू शकते.
Failure modes, with the strings you will see
The agent shows the server failed. claude mcp list prints ✗ Failed to connect, आणि TUI मध्ये MCP server 'filesystem' failed to start असा error येतो. claude --debug रन केल्यास सहसा Error: spawn npx ENOENT दिसेल — याचा अर्थ तो command agent च्या PATH मध्ये नाही. Runtime उपलब्ध नाही किंवा agent ला अपेक्षित ठिकाणी नाही: Node इंस्टॉल केलेले नाही, npx गहाळ आहे, किंवा Python venv साठी फक्त bare name वापरला आहे. Command साठी absolute path वापरा किंवा runtime इंस्टॉल करा, त्यानंतर पुन्हा reconnect करा.
A stdio server connects, then instantly drops. Client मध्ये JSON parse error येतो — जसे की Unexpected token 'S', "Server sta"... is not valid JSON किंवा Failed to parse message. याचे कारण नेहमी एकच असते: server ने stdout वर log line लिहिली आहे. stdio मध्ये, stdout हाच JSON-RPC channel असतो, त्यामुळे कोणताही अतिरिक्त text stream खराब करतो आणि handshake निकामी होते. Node मध्ये, console.log stdout वर जातो — त्यासाठी console.error वापरा. Python मध्ये, साधा print() stdout वर जातो — logs लिहिण्यासाठी logging वापरा आणि तो sys.stderr ला configure करा, किंवा file=sys.stderr पास करा. हा नियम अनिवार्य आहे: stdio मध्ये, stdout वर फक्त JSON-RPC असावा आणि सर्व human-readable text stderr वर असावे.
A remote server times out or closes mid-handshake. Client MCP error -32000: Connection closed ने fail होतो, किंवा Inspector Connect वर अडकून पडतो आणि tools ची यादी दाखवत नाही. nginx च्या मागे हे buffering मुळे होते: proxy SSE stream flush करण्याऐवजी ती धरून ठेवतो, ज्यामुळे client प्रतिसाद येण्याची वाट पाहत राहतो पण तो येत नाही. location मध्ये proxy_buffering off; (आणि Step 4 मधील उर्वरित block) जोडा. public URL वरून curl -N ने तपासा — तुम्हाला event data टप्प्याटप्प्याने प्राप्त होताना दिसेल, शेवटी एकदम नाही.
Auth is rejected. Client Error POSTing to endpoint (HTTP 401) किंवा थेट 401 Unauthorized असा error देतो. एकतर header गहाळ आहे, token चुकीचे आहे, किंवा client ने config वाचताना shell variable रिकामे होते — ही एक सामान्य चूक आहे, कारण जर variable unset असेल तर ${MCP_TOKEN} रिकामे होते आणि nginx ला Bearer मध्ये कोणतीही value दिसत नाही. variable echo करून पहा, header पुन्हा जोडा, आणि nginx if मधील token आणि bytes तंतोतंत मॅच होतात की नाही याची खात्री करा.
The service will not start under systemd. journalctl -u mcp-ops मध्ये ModuleNotFoundError: No module named 'mcp' दिसेल — ExecStart venv interpreter ऐवजी system Python कडे निर्देश करते. किंवा Address already in use — दुसरा एखादा process 8000 port वापरत आहे; तो sudo ss -ltnp | grep 8000 वापरून शोधा.
FAQ
MCP server म्हणजे नक्की काय?
हे एक प्रोग्राम आहे जे Model Context Protocol वापरून JSON-RPC 2.0 द्वारे AI client ला tools आणि resources उपलब्ध करून देते. AI model स्वतः tool रन करत नाही — ते त्याच्या client ला विनंती करते, client MCP server ला कॉल करते, आणि server ते कार्यान्वित करून निकाल परत करते. हा protocol standard असल्याने, एक server कोणत्याही compliant client सोबत काम करू शकतो, मग तो Claude Code असो, Claude Desktop असो किंवा Gemini CLI असो.
stdio आणि HTTP transport मधील फरक काय आहे?
stdio server client द्वारे child process म्हणून सुरू केला जातो आणि stdin/stdout द्वारे संवाद साधतो; त्यामुळे ते एका मशीनवरील एकाच client सोबत चालते आणि त्याला network किंवा auth ची गरज नसते. HTTP server ही एक long-running network service आहे ज्यापर्यंत अनेक clients एकाच वेळी पोहोचू शकतात, म्हणूनच त्याला TLS आणि authentication आवश्यक असते. स्थानिक (local) आणि single-user tools साठी stdio वापरा; shared किंवा persistent गोष्टींसाठी HTTP (current servers वर Streamable HTTP) वापरा.
मी remote MCP server सुरक्षित कसा करू?
समजा की तो तुमच्या files, database, किंवा shell ला tool access देतो, म्हणून त्याला कधीही unauthenticated ठेवू नका. तो localhost ला bind करून ठेवणे आणि SSH tunnel किंवा private VPN द्वारे वापरणे सर्वोत्तम आहे; जर तो public असणे आवश्यक असेल, तर त्याला reverse proxy च्या मागे ठेवा जो bearer token किंवा MCP OAuth flow लागू करतो. openssl rand -hex 32 वापरून token तयार करा आणि यापैकी एक पर्याय नसेल तर server ला 0.0.0.0 वर कधीही bind करू नका.
सुरू न होणाऱ्या server ला मी debug कसे करू?
प्रथम claude mcp list तपासा — ✗ Failed to connect सोबत spawn ... ENOENT याचा अर्थ command किंवा runtime उपलब्ध नाही, म्हणून path दुरुस्त करा किंवा ते install करा. जर connection होऊन JSON parse error येत असेल, तर server stdout वर log करत आहे आणि JSON-RPC stream खराब करत आहे; सर्व logging stderr वर हलवा. इतर कोणत्याही समस्येसाठी, नेमकी command MCP Inspector अंतर्गत रन करा, जो server ला isolation मध्ये चालवतो जेणेकरून तुम्हाला server bug आणि client-config bug मधील फरक समजेल.