VPS پر AI coding agents کے لیے MCP servers چلائیں
VPS پر MCP servers چلانے کا عملی طریقہ: stdio اور remote HTTP، systemd، nginx، TLS اور authentication ترتیب دیں، جبکہ JSON-RPC کی عام خرابیوں سے بچیں۔
آپ کیا بنا رہے ہیں
ایک VPS پر دو فعال MCP سیٹ اپ۔ پہلے ایک stdio سرور، یعنی filesystem یا database tool، جسے Claude Code child process کے طور پر شروع کرتا ہے اور pipe کے ذریعے اس سے رابطہ کرتا ہے۔ اس کے بعد ایک remote HTTP سرور، جو systemd اور TLS کے ساتھ nginx reverse proxy کے پیچھے ایک طویل عرصے تک چلنے والی network service کے طور پر کام کرتا ہے۔ اسے آپ کے بتائے ہوئے کسی بھی MCP client سے قابل رسائی بنایا جا سکتا ہے۔ دونوں میں سے کسی ایک کی installation مختصر ہے۔ اس گائیڈ کا بیشتر حصہ ان دو عملی مسائل پر ہے جو واقعی رکاوٹ بنتے ہیں: JSON-RPC stream کو صاف رکھنا، اور unauthenticated tool endpoint کو public internet پر کبھی دستیاب نہ ہونے دینا۔
MCP اصل میں کیا ہے
Model Context Protocol ایک معیاری طریقہ ہے جس کے ذریعے AI client، Claude Code، Claude Desktop، VPS پر Gemini CLI، یا آپ کی اپنی script بیرونی tools کو call کر سکتی ہے اور بیرونی resources پڑھ سکتی ہے۔ Model خود کوئی چیز run نہیں کرتا۔ یہ client سے درخواست کرتا ہے، client MCP server کے ساتھ JSON-RPC 2.0 کے ذریعے بات کرتا ہے، server tool کو run کرتا ہے اور نتیجہ واپس فراہم کرتا ہے۔ اسی client کو لوگ agent harness کہتے ہیں: یہ model کے گرد موجود وہ loop ہے جو tools کی فہرست، permission checks اور session state کو manage کرتا ہے۔ MCP صرف اس loop کے tool حصے کو بڑھانے کا طریقہ ہے۔ ایک ہی protocol استعمال ہونے کی وجہ سے آپ کا لکھا ہوا server ہر ایسے client کے ساتھ کام کرتا ہے جو MCP کو support کرتا ہو۔ اگر یہ تقسیم آپ کے لیے نئی ہے، خاص طور پر یہ سوال کہ model کسی tool کو استعمال کرنے کا فیصلہ کیسے کرتا ہے، تو حقیقی credentials دینے سے پہلے agent fundamentals کا مرحلہ وار راستہ پڑھنے کے لیے ایک گھنٹہ نکالنا مفید ہوگا۔
اس کے 2 transports ہیں، اور اس guide کا باقی حصہ انہی کے مطابق تقسیم ہے:
- stdio۔ client server کو child process کے طور پر spawn کرتا ہے اور اس کے standard input اور standard output کے ذریعے newline-delimited JSON-RPC messages کا تبادلہ کرتا ہے۔ اس میں network، port یا auth نہیں ہوتا؛ trust boundary خود process ہوتا ہے۔ تقریباً ہر local tool اسی طریقے سے ship ہوتا ہے۔
- Streamable HTTP (اور اس کا پرانا متبادل HTTP+SSE)۔ server ایک طویل عرصے تک چلنے والی web service ہوتا ہے۔ client HTTP کے ذریعے connect کرتا ہے، اور server responses کو Server-Sent Events کے طور پر stream کر سکتا ہے۔ یہ طریقہ ایک server کو متعدد clients کے ساتھ share کرنے یا ایسے tool کو چلانے کے لیے استعمال ہوتا ہے جسے اس machine پر مستقل طور پر موجود رہنا ضروری ہو۔
جب tool ایک machine اور ایک user تک محدود ہو تو stdio منتخب کریں۔ جب یہ shared service ہو تو HTTP منتخب کریں۔
Prerequisites اور حقیقی احتیاطیں
فرض کریں کہ آپ کے پاس root یا sudo کے ساتھ نیا Ubuntu 24.04 KVM VPS موجود ہے۔ اس کے علاوہ درج ذیل چیزیں درکار ہیں:
- وہ runtime جس میں server لکھا گیا ہے۔ زیادہ تر reference servers Node یا Python میں لکھے گئے ہیں۔ Ubuntu 24.04 کے ساتھ Node 18 آتا ہے، جبکہ کئی موجودہ MCP packages کو Node 20 یا اس سے نیا ورژن درکار ہوتا ہے۔ اس لیے
aptپر بھروسا کرنے کے بجائے NodeSource یا nvm سے موجودہ LTS انسٹال کریں۔ Python 3.12 پہلے سے موجود ہے۔ - ایک domain اور DNS A record، لیکن صرف remote HTTP server کے لیے۔ TLS کے لیے ایسا نام درکار ہے جو اس VPS کے IP پتے پر resolve ہو۔ stdio مثال کے لیے DNS بالکل ضروری نہیں۔
- 512 MB RAM کافی ہے۔ MCP servers ہلکے JSON-RPC processes ہوتے ہیں۔ memory کی ضرورت protocol نہیں بلکہ اس tool کے مطابق ہوتی ہے جسے آپ استعمال کرتے ہیں، مثلاً database driver یا file cache۔
- یہ spec نئی ہے اور مسلسل تبدیل ہو رہی ہے۔ 2025-03-26 revision نے HTTP+SSE کو Streamable HTTP سے بدل دیا اور SSE کو deprecated قرار دیا۔ SSE اب بھی کام کرتی ہے اور بہت سے servers اب بھی اسے support کرتے ہیں۔ اس لیے کسی بھی transport pin کو حتمی اصول نہ سمجھیں؛ اسے server کی release notes کے مطابق دوبارہ جانچنے والی configuration سمجھیں۔
مرحلہ 1: stdio سرور کو Claude Code سے منسلک کریں
فائل سسٹم سرور سے شروع کریں۔ یہ official اور فعال طور پر maintained ہے، اور اسے صرف Node کی ضرورت ہوتی ہے۔ ذیل کی ایک command اسے Claude Code کے ساتھ رجسٹر کرتی ہے اور موجودہ project تک محدود رکھتی ہے، تاکہ configuration ایک ایسی file میں محفوظ ہو جسے commit کیا جا سکے:
cd /home/matt/projects/api
claude mcp add --scope project --transport stdio filesystem \
-- npx -y @modelcontextprotocol/server-filesystem /home/matt/projects/api-- separator اہم ہے۔ اس کے بعد آنے والی ہر چیز وہ command ہے جسے Claude Code چلائے گا، نہ کہ Claude Code کے لیے کوئی flag۔ اس سے project root میں .mcp.json بنتی ہے:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/home/matt/projects/api"
]
}
}
}ابھی کچھ نہیں چل رہا۔ جب آپ اگلی بار اس directory میں Claude Code شروع کریں گے، تو agent .mcp.json پڑھے گا، npx -y @modelcontextprotocol/server-filesystem ... کو child process کے طور پر شروع کرے گا، اور اسی process کے stdin/stdout کے ذریعے MCP handshake کرے گا۔ تصدیق کریں کہ یہ درست طور پر فعال ہوا ہے:
claude mcp listصحت مند server اپنی command اور سبز tick، filesystem: npx -y @modelcontextprotocol/server-filesystem ... - ✓ Connected، دکھاتا ہے۔ session کے اندر /mcp slash command server کے فراہم کردہ tools (read_file، write_file، list_directory) کی فہرست دکھاتی ہے، اور agent اب انہیں ان paths پر چلا سکتا ہے جن کی آپ نے اجازت دی ہے۔ database tool کی ساخت بھی یہی ہوتی ہے؛ package تبدیل کریں اور آخری argument کے طور پر connection string دیں، لیکن server کی اپنی repository میں موجودہ package name ضرور دیکھیں، کیونکہ reference Postgres server ایک سے زیادہ بار maintainers تبدیل کر چکا ہے۔
یہی اس agent کو اسی box پر چلانے کا بنیادی فائدہ ہے: Claude Code session VPS پر tmux کے اندر چلتا ہے، اور اس کے stdio servers براہ راست project files اور local services تک رسائی کے ساتھ اسی کے قریب چلتے ہیں؛ network round-trip کی ضرورت نہیں ہوتی۔ جب agent کے پاس write_file کے ساتھ read_file بھی ہو، تو اس رسائی کو ایسی skill کے ساتھ جوڑنا مفید ہے جو اسے کام کرنے والی کم سے کم تبدیلی کی طرف رہنمائی کرے، کیونکہ filesystem tool کے ذریعے وسیع rewrite کرنا دو سطروں کی fix جتنا ہی آسان ہو جاتا ہے۔ یہی wiring local files سے آگے بھی استعمال ہوتی ہے: اگر آپ VPS پر پہلے ہی search engine چلا رہے ہیں، تو اپنا SearXNG instance agent کو search tool کے طور پر دے سکتے ہیں؛ اس طرح queries آپ کے box پر رہتی ہیں، لیکن غیر معتبر page text براہ راست اس context میں آ جاتا ہے جس پر agent بعد میں عمل کرتا ہے۔
مرحلہ 2: remote HTTP server بنائیں
stdio server اپنے parent process کے ساتھ بند ہو جاتا ہے اور ہر client کے لیے الگ شروع ہوتا ہے۔ لہٰذا اگر آپ اس مشین پر Claude Code کے دو sessions چلائیں جو ایک دوسرے کو کام سونپتے ہوں، تو ہر session کو tool کی اپنی private copy ملے گی۔ جب آپ ایسا tool چاہتے ہیں جو ہر client کے لیے چلتا رہے، جیسے shared ops tool، database gateway، یا ایسا tool جسے آپ کا laptop اور CI دونوں call کریں، تو HTTP transport اور ایک حقیقی service درکار ہوتی ہے۔ یہاں official SDK استعمال کرنے والا ایک کم سے کم Python server ہے، جو ایک tool فراہم کرتا ہے:
# /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 ہوتا ہے۔ مشین کے باہر سے کوئی چیز براہ راست اس تک نہیں پہنچ سکتی، اور authentication موجود نہ ہونے سے پہلے یہی مطلوب ہے۔ اسے اپنی virtualenv میں install کریں تاکہ systemd کے لیے interpreter کا path مستقل رہے:
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]"مرحلہ 3: اسے systemd کے ساتھ فعال رکھیں
جو tool agent کے اسے استعمال کرنے کی کوشش کے وقت بند ہو، وہ کسی tool کے نہ ہونے سے بھی زیادہ نقصان دہ ہے۔ یہ خاص طور پر اس وقت اہم ہوتا ہے جب client خود ایک طویل عرصے تک چلنے والا process ہو: ایک ہمیشہ فعال agent جو reboots کے دوران اپنی memory اور schedules برقرار رکھتا ہے ان tools کو مقررہ schedule کے مطابق خود استعمال کرے گا اور اسے دیکھنے والا کوئی نہیں ہوگا، اس لیے server کو بھی خود بحال ہونا چاہیے۔ /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 پر مقرر کریں، اور process 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 کا مطلب ہے کہ process وہاں bind نہیں ہے جہاں آپ سمجھ رہے ہیں؛ journalctl -u mcp-ops -n 50 پڑھیں۔
مرحلہ 4: TLS اور reverse proxy کو سامنے رکھیں
سرور localhost پر listening کر رہا ہے۔ اسے کہیں سے بھی قابل رسائی بنانے کے لیے nginx پر TLS termination کریں اور درخواستیں اندرونی سروس تک proxy کریں۔ nginx انسٹال کریں، nginx پر Certbot اور Let's Encrypt کے ذریعے certificate حاصل کریں، پھر location block لکھیں۔ اہم نکتہ buffering کو غیر فعال کرنا ہے، کیونکہ nginx کا default رویہ response مکمل ہونے تک اسے روکے رکھتا ہے۔ اس سے SSE stream ہمیشہ کے لیے رک جاتی ہے:
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 کے ذریعے configuration reload کریں۔ اگر آپ پہلے ہی containers کا پورا fleet چلا رہے ہیں تو خودکار TLS والا Traefik reverse proxy یہی کام خود کرتا ہے۔ یہ certificate جاری کرتا ہے اور hostname کے مطابق route بناتا ہے۔ آپ کو صرف MCP container میں labels شامل کرنے ہوتے ہیں۔ دونوں صورتوں میں اب public port پر صرف reverse proxy موجود ہے، اور وہ ایسی service کی طرف اشارہ کر رہا ہے جسے آپ نے ابھی secure نہیں کیا۔ URL کو کہیں بھی register کرنے سے پہلے اسے درست کریں۔
موضوع پر حاوی سکیورٹی اصول
کبھی بھی authentication کے بغیر MCP endpoint کو expose نہ کریں۔ MCP server صرف read-only API نہیں ہے۔ یہ آپ کی files، database اور بعض اوقات shell تک tool access دیتا ہے۔ public internet پر کھلا ہوا /mcp ایسا اجنبی ہے جسے آپ کے AI agent جتنی ہی رسائی حاصل ہے: وہ پہلے آپ کے tools کی فہرست دیکھتا ہے، پھر انہیں call کرتا ہے۔ اسے بالکل غیر مصدقہ admin socket سمجھیں، کیونکہ حقیقت میں یہ وہی ہے۔ چوری شدہ token سے کتنا نقصان ہو سکتا ہے، اس کا انحصار اس کے پیچھے موجود server پر بھی ہوتا ہے: openGym workout tracker کے ساتھ فراہم کردہ read-only MCP server صرف training data واپس کر سکتا ہے، جبکہ filesystem یا shell tool پورا system دے سکتا ہے۔
ترجیح کے لحاظ سے 3 دفاعی اقدامات:
- اسے publish نہ کریں۔ server کو
127.0.0.1پر رکھیں اور SSH tunnel کے ذریعے اپنے laptop سے اس تک رسائی حاصل کریں:ssh -L 8000:127.0.0.1:8000 matt@vps، پھر client کوhttp://127.0.0.1:8000/mcpپر point کریں۔ کچھ بھی expose نہیں ہوتا۔ - اسے private network پر رکھیں۔ ایک self-hosted WireGuard VPN کے tunnel address پر bind کریں اور صرف VPN peers کو اس تک رسائی دیں۔ public internet کو بند port نظر آئے گا۔
- اگر اسے public رکھنا ضروری ہو تو token لازمی کریں۔ درست طریقہ MCP OAuth flow ہے، جسے HTTP transport native طور پر support کرتا ہے۔ عملی طور پر کم از کم shared bearer token ہے جسے proxy پر check کیا جائے۔ یہ کم خرچ ہے اور drive-by access کو مکمل طور پر روکتا ہے:
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 set کریں تاکہ secret plain text کی صورت میں کبھی .mcp.json میں محفوظ نہ ہو؛ Claude Code read time پر environment سے ${MCP_TOKEN} expand کرتا ہے۔
اوپر بیان کردہ ہر دفاع endpoint کو محفوظ بناتا ہے، نہ کہ اس agent کو جس کے پاس پہلے ہی token موجود ہے۔ مسئلے کا دوسرا حصہ یہی ہے: اگر آپ کا client DeepSeek Harness ہے تو وہ plugins جو یہ محدود کرتے ہیں کہ agent کون سے tools call کر سکتا ہے اور tool output کو injected instructions کے لیے scan کرتے ہیں اس پہلو کو سنبھالتے ہیں۔
مرحلہ 6: MCP Inspector کے ذریعے debugging کریں
جب server درست طریقے سے کام نہ کرے تو agent کے اندر سے اندازہ نہ لگائیں۔ اسے براہ راست Inspector کے ذریعے چلائیں۔ Inspector سرکاری web-based test client ہے۔ stdio server کے لیے وہی command دیں جو agent چلاتا ہے:
npx @modelcontextprotocol/inspector \
npx -y @modelcontextprotocol/server-filesystem /tmpیہ http://localhost:6274 پر UI شروع کرتا ہے۔ حالیہ versions میں MCP_PROXY_AUTH_TOKEN query string والا URL دکھایا جاتا ہے۔ وہی exact link استعمال کریں، ورنہ UI آپ کو قبول نہیں کرے گا۔ یہ 6277 پر proxy بھی شروع کرتا ہے۔ Connect پر click کریں، پھر List Tools پر، اور اس کے بعد حقیقی arguments کے ساتھ Call Tool پر click کریں۔ اگر یہ Inspector میں کام کرتا ہے لیکن agent میں ناکام ہوتا ہے تو مسئلہ server میں نہیں بلکہ client config میں ہے۔ remote HTTP server کے لیے Streamable HTTP transport منتخب کریں، https://mcp.example.com/mcp درج کریں، Authorization header شامل کریں، اور connect کریں۔ کسی بھی agent کو شامل کرنے سے پہلے authentication اور proxy کی درستگی ثابت کرنے کا یہ تیز ترین طریقہ ہے۔
سرورز کو اپ ڈیٹ رکھنا
MCP تیزی سے تبدیل ہوتا ہے، اس لیے patching کے لیے باقاعدہ schedule مقرر کریں۔ npx -y کے ساتھ شروع کیے گئے Node servers ہر بار spawn ہونے پر تازہ ترین version حاصل کرتے ہیں۔ یہ سہولت فراہم کرتا ہے، لیکن اس سے build reproducible نہیں رہتا۔ جس exact version کی آپ نے testing کی ہو، اسے pin کریں۔ اسے npm view @modelcontextprotocol/server-filesystem version سے پڑھیں اور جب کوئی server اہم ہو جائے تو .mcp.json میں package name کے ساتھ version شامل کریں (@modelcontextprotocol/server-filesystem@<version>)۔ اس کے بعد version کو جان بوجھ کر upgrade کریں۔ systemd کے تحت چلنے والے Python servers کو sudo -H -u mcp /opt/mcp-ops/.venv/bin/pip install -U "mcp[cli]" کے بعد sudo systemctl restart mcp-ops کے ساتھ update کریں۔ Upgrade کرتے وقت اس spec revision پر نظر رکھیں جسے آپ کا SDK target کرتا ہے۔ SSE سے Streamable-HTTP boundary کے پار jump کرنے سے وہ transport تبدیل ہو سکتا ہے جس کی clients کو request کرنی ہوتی ہے۔
خرابی کی صورتیں، اور دکھائی دینے والے پیغامات
ایجنٹ سرور کو failed دکھاتا ہے۔ claude mcp list، ✗ Failed to connect دکھاتا ہے اور TUI، MCP server 'filesystem' failed to start رپورٹ کرتا ہے۔ claude --debug چلائیں۔ عموماً Error: spawn npx ENOENT نظر آئے گا، یعنی کمانڈ ایجنٹ کے PATH میں موجود نہیں۔ Runtime غائب ہے یا اس جگہ موجود نہیں جہاں ایجنٹ اسے تلاش کرتا ہے: Node انسٹال نہیں، npx موجود نہیں، یا virtualenv کا Python مختصر نام سے استعمال کیا گیا ہے۔ کمانڈ کو absolute path پر درست کریں یا runtime انسٹال کریں، پھر دوبارہ connect کریں۔
stdio server connect ہونے کے فوراً بعد disconnect ہو جاتا ہے۔ Client logs میں JSON parse error آتا ہے، مثلاً Unexpected token 'S', "Server sta"... is not valid JSON یا Failed to parse message۔ وجہ ہمیشہ ایک ہی ہوتی ہے: server نے log line stdout پر لکھی۔ stdio میں stdout ہی JSON-RPC channel ہے، اس لیے کوئی بھی اضافی متن stream کو خراب کر دیتا ہے اور handshake ناکام ہو جاتا ہے۔ Node میں console.log stdout پر جاتا ہے؛ اس کے بجائے console.error استعمال کریں۔ Python میں سادہ print() stdout پر جاتا ہے۔ Logs کو logging کے ذریعے sys.stderr پر configure کریں، یا file=sys.stderr پاس کریں۔ اصول قطعی ہے: stdio میں stdout پر صرف JSON-RPC ہو، جبکہ انسانوں کے لیے تمام متن stderr پر جائے۔
Remote server timeout ہو جاتا ہے یا handshake کے دوران connection بند ہو جاتا ہے۔ Client MCP error -32000: Connection closed کے ساتھ ناکام ہوتا ہے، یا Inspector میں Connect پر عمل رکا رہتا ہے اور tools کی فہرست ظاہر نہیں ہوتی۔ nginx کے پیچھے یہ buffering کی وجہ سے ہوتا ہے: proxy SSE stream کو flush کرنے کے بجائے روک لیتا ہے، اس لیے client ایسے response کا انتظار کرتا رہتا ہے جو کبھی نہیں پہنچتا۔ proxy_buffering off; شامل کریں، اور Step 4 میں دیا گیا باقی block بھی location میں شامل کریں۔ Public URL کے خلاف curl -N سے تصدیق کریں۔ Event data آخر میں ایک ساتھ آنے کے بجائے بتدریج موصول ہونی چاہیے۔
Auth مسترد ہو جاتی ہے۔ Client Error POSTing to endpoint (HTTP 401) رپورٹ کرتا ہے یا واضح طور پر 401 Unauthorized۔ Header غائب ہو سکتا ہے، token غلط ہو سکتا ہے، یا client کے config پڑھنے کے وقت shell variable خالی ہو سکتی ہے۔ یہ عام مسئلہ ہے، کیونکہ variable unset ہونے پر ${MCP_TOKEN} خالی expand ہوتا ہے، اور nginx کو پھر Bearer بغیر کسی value کے نظر آتا ہے۔ Variable کو echo کریں، header دوبارہ شامل کریں، اور تصدیق کریں کہ اس کے exact bytes nginx کے if میں موجود token سے مطابقت رکھتے ہیں۔
Service systemd کے تحت start نہیں ہوتی۔ journalctl -u mcp-ops میں ModuleNotFoundError: No module named 'mcp' دکھائی دیتا ہے، جبکہ ExecStart virtualenv interpreter کے بجائے system Python کی طرف اشارہ کرتا ہے۔ یا Address already in use ظاہر ہوتا ہے، یعنی کوئی دوسرا process 8000 پر قابض ہے؛ اسے sudo ss -ltnp | grep 8000 سے تلاش کریں۔
FAQ
MCP server کیا ہوتا ہے؟
یہ ایسا پروگرام ہے جو Model Context Protocol کے ذریعے AI client کو tools اور resources فراہم کرتا ہے اور JSON-RPC 2.0 استعمال کرتا ہے۔ AI model خود tool نہیں چلاتا۔ یہ اپنے client سے درخواست کرتا ہے، client MCP server کو call کرتا ہے، اور server اسے execute کرکے result واپس کرتا ہے۔ چونکہ protocol standard ہے، اس لیے ایک server ہر compliant client کے ساتھ کام کرتا ہے، خواہ وہ Claude Code، Claude Desktop یا Gemini CLI ہو۔
stdio اور HTTP transport میں کیا فرق ہے؟
stdio server کو client child process کے طور پر launch کرتا ہے اور یہ stdin/stdout کے ذریعے communicate کرتا ہے۔ اس لیے یہ ایک machine پر ایک client کے ساتھ شروع اور بند ہوتا ہے، اور اسے network یا auth کی ضرورت نہیں ہوتی۔ HTTP server ایک طویل مدت تک چلنے والی network service ہے جس تک بیک وقت متعدد clients رسائی حاصل کر سکتے ہیں۔ اسی لیے اسے TLS اور authentication درکار ہوتی ہے۔ مقامی، single-user tools کے لیے stdio استعمال کریں۔ مشترکہ یا مستقل tools کے لیے HTTP استعمال کریں؛ موجودہ servers میں Streamable HTTP استعمال ہوتا ہے۔
remote MCP server کو کیسے محفوظ بناؤں؟
یہ فرض کریں کہ اسے آپ کی files، database یا shell تک tool access حاصل ہے، اور اسے کبھی بھی authentication کے بغیر expose نہ کریں۔ بہترین طریقہ یہ ہے کہ اسے localhost پر bind رکھیں اور SSH tunnel یا private VPN کے ذریعے اس تک رسائی حاصل کریں۔ اگر اسے public رکھنا ضروری ہو تو اسے ایسے reverse proxy کے پیچھے رکھیں جو bearer token یا MCP OAuth flow نافذ کرے۔ token بنانے کے لیے openssl rand -hex 32 استعمال کریں، اور ان میں سے کسی ایک حفاظتی انتظام کے بغیر server کو 0.0.0.0 پر کبھی bind نہ کریں۔
جو server start نہ ہو، اس کی debugging کیسے کروں؟
سب سے پہلے claude mcp list چیک کریں۔ ✗ Failed to connect کو spawn ... ENOENT کے ساتھ چلانے سے معلوم ہوتا ہے کہ command یا runtime موجود نہیں ہے؛ اس لیے path درست کریں یا اسے install کریں۔ اگر connection قائم ہو کر JSON parse error کے ساتھ ختم ہو جائے تو server stdout پر logging کر رہا ہے اور JSON-RPC stream خراب ہو رہی ہے۔ تمام logging کو stderr پر منتقل کریں۔ دیگر تمام صورتوں میں MCP Inspector کے تحت عین وہی command چلائیں۔ یہ server کو الگ ماحول میں چلاتا ہے، جس سے آپ server bug اور client-config bug میں فرق کر سکتے ہیں۔