SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor

VPS-এ MCP server রান করার সম্পূর্ণ গাইড

আপনার VPS-এ stdio এবং remote HTTP transport ব্যবহার করে MCP server কনফিগার করুন। systemd, TLS, এবং authentication সহ AI agent-এর জন্য নিরাপদ টুল সেটআপের বিস্তারিত পদ্ধতি জানুন।

আপনি যা তৈরি করছেন

একটি VPS-এ দুটি কার্যকর MCP setup। প্রথমটি একটি stdio server—এটি একটি filesystem বা database tool, যেটি Claude Code child process হিসেবে চালু করে এবং pipe-এর মাধ্যমে এর সঙ্গে যোগাযোগ করে। এরপর একটি remote HTTP server থাকবে, যা systemd এবং TLS-সহ nginx reverse proxy-এর পেছনে দীর্ঘমেয়াদি network service হিসেবে চলবে। আপনি যে কোনো MCP client-কে নির্দেশ করলে সেটি এই server-এ পৌঁছাতে পারবে। যেকোনো একটি setup-এর install প্রক্রিয়া ছোট। এই guide-এর মূল বিষয় দুটি: JSON-RPC stream পরিষ্কার রাখা এবং authentication ছাড়া কোনো tool endpoint কখনো public Internet-এ না রাখা।

MCP আসলে কী

Model Context Protocol হলো এমন একটি standard পদ্ধতি, যার মাধ্যমে কোনো AI client, যেমন Claude Code, Claude Desktop, একটি VPS-এ চলা Gemini CLI, অথবা আপনার নিজস্ব script, external tool কল করতে এবং external resource পড়তে পারে। Model নিজে কোনো কিছু চালায় না। এটি client-কে অনুরোধ করে, client JSON-RPC 2.0 ব্যবহার করে একটি MCP server-এর সঙ্গে যোগাযোগ করে, server tool চালায় এবং ফলাফল client-কে ফেরত দেয়। মানুষ যখন agent harness বলে, তখন সাধারণত এই client-কেই বোঝায়: এটি model-এর চারপাশের সেই loop, যা tool list, permission check এবং session state নিয়ন্ত্রণ করে। MCP কেবল এই loop-এর tool অংশ বাড়ানোর পদ্ধতি। একটি protocol ব্যবহার করার ফলে আপনি একবার যে server লিখবেন, MCP সমর্থনকারী প্রতিটি client-এর সঙ্গেই তা কাজ করবে। এই বিভাজনটি আপনার কাছে নতুন হলে, বিশেষ করে model কীভাবে কোনো tool ব্যবহারের সিদ্ধান্ত নেয়—এই প্রশ্নটি থাকলে, কোনো server-কে বাস্তব credential দেওয়ার আগে agent fundamentals বোঝার ধাপে ধাপে পথটি পড়তে এক ঘণ্টা ব্যয় করা উপকারী।

এখানে দুটি transport আছে, এবং এই guide-এর বাকি অংশও এই দুটির ভিত্তিতে বিভক্ত:

  • stdio। Client server-কে child process হিসেবে চালু করে এবং server-এর standard input ও standard output-এর মাধ্যমে newline-delimited JSON-RPC message আদান-প্রদান করে। কোনো network নেই, কোনো port নেই, কোনো auth নেই; trust boundary হলো process নিজেই। প্রায় সব local tool এই পদ্ধতিতে সরবরাহ করা হয়।
  • Streamable HTTP (এবং এর পুরোনো সংস্করণ HTTP+SSE)। Server একটি দীর্ঘসময় চলমান web service। Client HTTP-এর মাধ্যমে সংযোগ করে, এবং server Server-Sent Events হিসেবে response stream করতে পারে। একই server অনেক client-এর সঙ্গে ভাগ করে নেওয়ার জন্য, অথবা এমন কোনো tool চালানোর জন্য এই পদ্ধতি ব্যবহার করা হয়, যেটিকে সার্ভারে স্থায়ীভাবে চলতে হয়।

Tool যদি একটি machine এবং একজন user-এর জন্য নির্দিষ্ট হয়, তাহলে stdio বেছে নিন। এটি shared service হলে HTTP বেছে নিন।

পূর্বশর্ত এবং বাস্তব সীমাবদ্ধতা

ধরা হচ্ছে, root অথবা sudo সুবিধাসহ একটি নতুন Ubuntu 24.04 KVM VPS আছে। এর বাইরে আপনার যা লাগবে:

  • সার্ভারটি যে runtime-এ লেখা। অধিকাংশ reference server Node অথবা Python-এ লেখা। Ubuntu 24.04-এ Node 18 থাকে, কিন্তু বর্তমান বেশ কিছু MCP package-এর জন্য Node 20 বা তার পরের সংস্করণ প্রয়োজন। তাই apt-এর ওপর নির্ভর না করে NodeSource অথবা nvm থেকে একটি current LTS সংস্করণ ইনস্টল করুন। Python 3.12 আগে থেকেই উপস্থিত।
  • একটি domain এবং DNS A record, তবে এটি শুধু remote HTTP server-এর জন্য প্রয়োজন। TLS-এর জন্য এমন একটি name দরকার, যা এই VPS-এর দিকে resolve হয়। stdio উদাহরণের জন্য কোনো DNS দরকার নেই।
  • 512 MB RAM যথেষ্ট। MCP server-গুলো ছোট JSON-RPC process। Memory খরচ protocol-এর জন্য নয়; আপনার tool যা ব্যবহার করে, যেমন database driver বা file cache, তার ওপর নির্ভর করে।
  • Spec-টি নতুন এবং পরিবর্তনশীল। 2025-03-26 revision HTTP+SSE-এর পরিবর্তে Streamable HTTP চালু করেছে এবং SSE-কে deprecated হিসেবে চিহ্নিত করেছে। SSE এখনও কাজ করে এবং অনেক server এখনও এটি ব্যবহার করে। তাই কোনো transport নির্দিষ্ট করার আগে server-এর release notes দেখে তা আবার যাচাই করুন; এটিকে অমোঘ নিয়ম ধরে নেবেন না।

ধাপ 1: Claude Code-এ একটি stdio সার্ভার যুক্ত করা

filesystem সার্ভার দিয়ে শুরু করুন; এটি অফিসিয়াল, নিয়মিত আপডেট করা হয় এবং Node ছাড়া অন্য কিছুর প্রয়োজন হয় না। নিচের একটি কমান্ড এটিকে Claude Code-এর সাথে রেজিস্টার করে এবং বর্তমান প্রজেক্টের জন্য সীমাবদ্ধ করে, যাতে এটি একটি কমিটযোগ্য ফাইলে সংরক্ষিত হয়:

cd /home/matt/projects/api
claude mcp add --scope project --transport stdio filesystem \
  -- npx -y @modelcontextprotocol/server-filesystem /home/matt/projects/api

-- সেপারেটরটি গুরুত্বপূর্ণ: এর পরের সবকিছুই হলো সেই কমান্ড যা Claude Code চালাবে, এটি Claude Code-এর কোনো ফ্ল্যাগ নয়। এটি প্রজেক্টের রুটে একটি .mcp.json ফাইল তৈরি করে:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/home/matt/projects/api"
      ]
    }
  }
}

এখনো কিছু চলছে না। আপনি যখন এই ডিরেক্টরিতে পরবর্তীবার Claude Code শুরু করবেন, এজেন্ট তখন .mcp.json ফাইলটি পড়বে, npx -y @modelcontextprotocol/server-filesystem ...-কে একটি চাইল্ড প্রসেস হিসেবে চালু করবে এবং সেই প্রসেসের stdin/stdout-এর মাধ্যমে MCP হ্যান্ডশেক সম্পন্ন করবে। এটি কাজ করছে কি না নিশ্চিত করুন:

claude mcp list

একটি সচল সার্ভার তার কমান্ড এবং একটি সবুজ টিক চিহ্ন, filesystem: npx -y @modelcontextprotocol/server-filesystem ... - ✔ Connected প্রদর্শন করে। সেশনের ভেতরে, /mcp স্ল্যাশ কমান্ডটি সার্ভার দ্বারা উন্মুক্ত টুলগুলোর তালিকা দেখায় (read_text_file, write_file, list_directory), এবং এজেন্ট এখন আপনার অনুমোদিত পাথগুলোতে সেগুলো ব্যবহার করতে পারে। একটি ডাটাবেস টুলও একই রকম; শুধু প্যাকেজটি পরিবর্তন করুন এবং শেষ আর্গুমেন্ট হিসেবে একটি কানেকশন স্ট্রিং দিন। তবে বর্তমান প্যাকেজের নামের জন্য সার্ভারের নিজস্ব রিপোজিটরি চেক করে নিন, কারণ রেফারেন্স Postgres সার্ভারটি একাধিকবার হাতবদল হয়েছে।

সার্ভারে এজেন্ট চালানোর মূল উদ্দেশ্যই এটি: Claude Code সেশনটি tmux-এর ভেতরে VPS-এ চলে, এবং এর stdio সার্ভারগুলো সরাসরি প্রজেক্ট ফাইল ও লোকাল সার্ভিসের অ্যাক্সেস নিয়ে তার পাশেই চলে, কোনো নেটওয়ার্ক রাউন্ড-ট্রিপের প্রয়োজন হয় না। একবার এজেন্টের কাছে write_file এবং read_text_file উভয়ই থাকলে, সেই সক্ষমতাকে এমন একটি দক্ষতার সাথে যুক্ত করা উচিত যা এটিকে সবচেয়ে ছোট কার্যকর পরিবর্তনের দিকে ধাবিত করে, কারণ একটি filesystem টুল থাকলে বড় ধরনের রিরাইট করাও দুই লাইনের ফিক্সের মতোই সহজ হয়ে যায়। এই সংযোগটি লোকাল ফাইলের বাইরেও বিস্তৃত: যদি আপনি ইতিমধ্যে VPS-এ একটি সার্চ ইঞ্জিন চালান, তবে আপনি আপনার নিজস্ব SearXNG ইনস্ট্যান্সকে সার্চ টুল হিসেবে এজেন্টকে দিতে পারেন, যা কুয়েরিগুলোকে আপনার বক্সে সীমাবদ্ধ রাখে কিন্তু অবিশ্বস্ত পেজের টেক্সট সরাসরি এজেন্টের কনটেক্সটে নিয়ে আসে, যার ওপর ভিত্তি করে সে কাজ করে।

ধাপ 2: একটি রিমোট HTTP সার্ভার তৈরি করা

একটি stdio সার্ভার তার প্যারেন্ট প্রসেসের সাথে বন্ধ হয়ে যায় এবং প্রতি ক্লায়েন্টের জন্য একবার করে এটি স্পন (spawn) করা হয়। তাই আপনি যদি বক্সে দুটি Claude Code সেশন চালান যারা একে অপরের সাথে কাজ আদান-প্রদান করে, তবে প্রতিটি সেশন টুলের নিজস্ব কপি পায়। যখন আপনি এমন একটি টুল চান যা প্রতিটি ক্লায়েন্টের জন্য চালু থাকবে, যেমন একটি শেয়ারড অপস টুল, ডাটাবেস গেটওয়ে, অথবা এমন কিছু যা আপনার ল্যাপটপ এবং CI উভয়ই কল করে, তখন আপনার HTTP ট্রান্সপোর্ট এবং একটি প্রকৃত সার্ভিসের প্রয়োজন হবে। নিচে অফিসিয়াল SDK ব্যবহার করে একটি ন্যূনতম পাইথন সার্ভার দেওয়া হলো, যা একটি টুল এক্সপোজ করে:

# /opt/mcp-ops/server.py
from mcp.server.mcpserver import MCPServer
import subprocess

mcp = MCPServer("ops-tools")

@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", port=8000)

host="127.0.0.1" লক্ষ্য করুন। সার্ভারটি শুধুমাত্র localhost-এ বাইন্ড করে, তাই বক্সের বাইরের কেউ সরাসরি এটি অ্যাক্সেস করতে পারবে না। অথেন্টিকেশন (auth) ব্যবস্থা চালু করার আগে এটিই আপনার কাঙ্ক্ষিত নিরাপত্তা। এটি 2.x SDK যা pip install "mcp[cli]" বর্তমানে ব্যবহার করে (2026-10-20 তারিখ অনুযায়ী এটি 2.3.0)। এটি FastMCP-এর নাম পরিবর্তন করে MCPServer করেছে এবং host ও port-কে কনস্ট্রাক্টর থেকে run()-এ সরিয়ে নিয়েছে। এখন পুরনো mcp.server.fastmcp ইমপোর্ট ব্যবহার করলে ModuleNotFoundError এরর দেখাবে। এটিকে নিজস্ব virtualenv-এ ইনস্টল করুন যাতে systemd একটি স্থিতিশীল ইন্টারপ্রেটার পাথ পায়:

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 ব্যবহার করে service চালু রাখুন

Agent কোনো tool ব্যবহার করতে যাওয়ার সময় সেটি বন্ধ থাকলে, tool না থাকার চেয়েও পরিস্থিতি খারাপ হয়। Client নিজেই দীর্ঘসময় চলমান process হলে বিষয়টি আরও গুরুত্বপূর্ণ। reboot-এর পরেও memory ও schedule ধরে রাখা always-on agent কোনো তদারকি ছাড়াই নির্ধারিত সময়ে এই tool-গুলো কল করবে। তাই 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.target

ExecStart-এ 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/mcp

status-এর মান active (running) হওয়া উচিত। curl body-তে JSON-RPC error সহ HTTP/1.1 400 Bad Request ফিরে আসবে। Request-এ কোনো session বা বৈধ JSON payload ছিল না। আপনি ঠিক এটাই চান। এর মাধ্যমে প্রমাণ হয় যে port উত্তর দিচ্ছে এবং protocol অনুযায়ী কাজ করছে। Connection refused বা খালি reply-এর অর্থ process-টি আপনার ধারণার interface-এ bind করা নেই। journalctl -u mcp-ops -n 50 পড়ুন।

ধাপ 4: সামনে TLS এবং একটি reverse proxy বসান

সার্ভারটি localhost-এ listening করে। যেকোনো স্থান থেকে এতে পৌঁছাতে nginx-এ TLS termination করুন এবং অনুরোধ ভেতরের দিকে proxy করুন। nginx install করুন, 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 দিয়ে reload করুন। আপনি যদি ইতিমধ্যে অনেকগুলো container চালান, তাহলে automatic TLS-সহ Traefik reverse proxy একই কাজ করে দেবে। এটি certificate issue করে এবং hostname অনুযায়ী route করে। আপনাকে শুধু MCP container-এ label যোগ করতে হবে। যেকোনো ক্ষেত্রেই এখন public port-এ একমাত্র reverse proxy-ই listening করছে। এটি এমন একটি service-এর দিকে নির্দেশ করছে, যেটি আপনি এখনও secure করেননি। কোথাও URL register করার আগে এটি ঠিক করুন।

ধাপ 5: এই বিষয়ের প্রধান নিরাপত্তা নিয়ম

কখনোই কোনো unauthenticated MCP endpoint উন্মুক্ত করবেন না। একটি MCP server কেবল read-only API নয়। এটি আপনার ফাইল, ডাটাবেস এবং ক্ষেত্রবিশেষে shell-এ টুল অ্যাক্সেস প্রদান করে। পাবলিক ইন্টারনেটে একটি উন্মুক্ত /mcp মানে হলো, একজন অপরিচিত ব্যক্তি আপনার AI agent-এর সমান ক্ষমতা পেয়ে গেল: তারা আপনার টুলগুলোর তালিকা দেখবে এবং সেগুলো কল করবে। এটিকে একটি unauthenticated admin socket হিসেবে বিবেচনা করুন, কারণ এটি আসলে তাই। একটি চুরি হওয়া টোকেন দিয়ে কতটুকু ক্ষতি করা সম্ভব তা নির্ভর করে সার্ভারের ওপর: openGym workout tracker-এর সাথে আসা read-only MCP server কেবল ট্রেনিং ডাটা ফেরত দিতে পারে, কিন্তু একটি filesystem বা shell টুল পুরো সিস্টেমের নিয়ন্ত্রণ দিয়ে দিতে পারে।

পছন্দের ক্রমানুসারে তিনটি প্রতিরক্ষা ব্যবস্থা:

  1. এটি প্রকাশ করবেন না। সার্ভারটিকে 127.0.0.1-এ রাখুন এবং SSH tunnel ব্যবহার করে আপনার ল্যাপটপ থেকে এটি অ্যাক্সেস করুন: ssh -L 8000:127.0.0.1:8000 matt@vps, তারপর ক্লায়েন্টকে http://127.0.0.1:8000/mcp-এ নির্দেশ করুন। এতে কিছুই উন্মুক্ত থাকে না।
  2. এটি একটি প্রাইভেট নেটওয়ার্কে রাখুন। একটি self-hosted WireGuard VPN-এর tunnel address bind করুন এবং শুধুমাত্র VPN peers-দের এটি অ্যাক্সেস করতে দিন। পাবলিক ইন্টারনেটের কাছে পোর্টটি বন্ধ থাকবে।
  3. যদি এটি পাবলিক করতেই হয়, তবে টোকেন বাধ্যতামূলক করুন। সঠিক উপায় হলো MCP OAuth flow, যা HTTP transport নেটিভভাবে সমর্থন করে। ব্যবহারিক দিক থেকে ন্যূনতম ব্যবস্থা হলো প্রক্সিতে একটি shared bearer token চেক করা; এটি সাশ্রয়ী এবং এটি অনাকাঙ্ক্ষিত অ্যাক্সেস পুরোপুরি বন্ধ করে দেয়:
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 দিয়ে টোকেন তৈরি করুন এবং এর সামনে এই নিরাপত্তা ব্যবস্থাগুলোর কোনোটি ছাড়া সার্ভারকে কখনোই 0.0.0.0-এ bind করবেন না। ক্লায়েন্ট তখন টোকেনটিকে 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 কখনোই plaintext হিসেবে .mcp.json-এ না থাকে। Claude Code রিড করার সময় environment থেকে ${MCP_TOKEN} এক্সপ্যান্ড করে। যদি variable-টি unset থাকে, তবে Claude Code খালি স্ট্রিং প্রতিস্থাপন করে না: এটি claude mcp list-এ missing variable-এর সংকেত দেয় এবং আক্ষরিক ${MCP_TOKEN} টেক্সট ব্যবহার করে। নিজের পছন্দমতো একটি নাম বেছে নিন, কারণ রিমোট সার্ভারের হেডারে Claude Code ইচ্ছাকৃতভাবে তার নিজের এবং আপনার ক্লাউড প্রোভাইডারের credential variable-গুলোকে (যেমন ANTHROPIC_API_KEY) খালি হিসেবে পড়ে, সেই সাথে আপনার এনভায়রনমেন্টে থাকা অন্যান্য credential-ও (যেমন NPM_TOKEN) একইভাবে পড়ে।

উপরের প্রতিটি প্রতিরক্ষা ব্যবস্থা endpoint-কে রক্ষা করে, কিন্তু টোকেন ধারণকারী agent-কে নয়, যা সমস্যার অন্য অর্ধেক অংশ: যদি আপনার ক্লায়েন্ট DeepSeek Harness হয়, তবে plugins that gate which tools an agent may call and scan tool output for injected instructions সেই দিকটি নিয়ন্ত্রণ করে।

ধাপ 6: MCP Inspector দিয়ে ডিবাগ করুন

যখন কোনো সার্ভার সঠিকভাবে কাজ করে না, তখন agent-এর ভেতর থেকে অনুমান না করে সরাসরি Inspector দিয়ে সেটি চালান, যা একটি অফিসিয়াল ওয়েব-ভিত্তিক টেস্ট ক্লায়েন্ট। stdio সার্ভারের জন্য, agent যে কমান্ডটি চালায় সেটিই এতে দিন:

npx @modelcontextprotocol/inspector \
  npx -y @modelcontextprotocol/server-filesystem /tmp

এটি http://localhost:6274-এ একটি ওয়েব সার্ভার থেকে UI পরিবেশন করে এবং একটি MCP_INSPECTOR_API_TOKEN কুয়েরি স্ট্রিং বহনকারী URL প্রিন্ট করে; মেমোরি থেকে ঠিকানা টাইপ না করে সেই লিঙ্কে ক্লিক করুন। v2 (2026-10-20 অনুযায়ী 2.11.0 বর্তমান) থেকে ব্যাকএন্ড প্রতিবার লোড হওয়ার সময় পেজে টোকেন ইনজেক্ট করে, তাই রিলোড দিলেও কাজ করে এবং টোকেনটি /api/* রুটগুলোকে রক্ষা করে যা প্রসেস তৈরি করতে পারে। 6277-এ থাকা আলাদা v1 প্রক্সি এখন আর নেই, তবে ওয়েব সার্ভারই একমাত্র লিসেনার নয়: v2 এছাড়াও MCP Apps-এর জন্য MCP_SANDBOX_PORT-এ (ডিফল্ট 6275) একটি স্যান্ডবক্স এবং MCP_APP_ORIGIN_PORT-এ (ডিফল্ট 6278) একটি ডেডিকেটেড app-origin সার্ভার চালু করে, যা যেকোনো MCP App পরিবেশন করে যার UI রিসোর্স _meta.ui.domain ঘোষণা করে। যদি আপনি SSH tunnel-এর মাধ্যমে Inspector-এ পৌঁছান বা কন্টেইনারে চালান এবং Apps ট্যাব প্রয়োজন হয়, তবে 6274-এর সাথে 6275 এবং 6278 ফরোয়ার্ড করুন। কানেক্ট করুন, Tools ট্যাব খুলুন, একটি টুল বেছে নিন, সঠিক আর্গুমেন্ট দিন এবং এটি কল করুন। যদি এটি Inspector-এ কাজ করে কিন্তু agent-এ ব্যর্থ হয়, তবে সমস্যাটি আপনার ক্লায়েন্ট কনফিগারেশনে, সার্ভারে নয়। রিমোট HTTP সার্ভারের জন্য, কোনো কমান্ড ছাড়াই Inspector চালু করুন, Streamable HTTP ট্রান্সপোর্ট এবং https://mcp.example.com/mcp দিয়ে একটি সার্ভার যোগ করুন, এর সেটিংসে Authorization হেডার দিন এবং কানেক্ট করুন; কোনো agent যুক্ত করার আগেই auth এবং প্রক্সি সঠিক কি না তা যাচাই করার এটিই দ্রুততম উপায়। Inspector হেডারগুলোকে সার্ভার ক্যাটালগে হুবহু সেভ করে রাখে, তাই টোকেনটি এখন ~/.mcp-inspector/mcp.json-এও সংরক্ষিত থাকে।

সার্ভার আপডেট রাখা

MCP দ্রুত পরিবর্তিত হয়, তাই একটি নির্দিষ্ট সময়সূচী মেনে প্যাচ করুন। যে Node সার্ভারগুলো কোনো নির্দিষ্ট ভার্সন উল্লেখ না করে npx -y দিয়ে চালানো হয়, সেগুলো npx যে ভার্সনটি খুঁজে পায় তাতেই চলে: যদি লোকাল প্রজেক্টে কোনো ভার্সন ইনস্টল করা থাকে তবে সেটি, অন্যথায় npm ক্যাশে ইনস্টল করা একটি কপি। -y শুধুমাত্র ইনস্টল প্রম্পটটি এড়িয়ে যায়, এটি কোনো আপডেট জোরপূর্বক কার্যকর করে না; ফলে আপনি সর্বশেষ রিলিজটি ট্র্যাক করতে পারেন না বা আপনি ঠিক কোন ভার্সনটি চালাচ্ছেন তা নিশ্চিতভাবে জানতে পারেন না। যখন কোনো সার্ভার গুরুত্বপূর্ণ হয়ে ওঠে, তখন আপনি যে ভার্সনটি পরীক্ষা করেছেন সেটি পিন করুন, npm view @modelcontextprotocol/server-filesystem version থেকে সেটি দেখে নিন এবং .mcp.json-এ প্যাকেজ নামের সাথে যুক্ত করুন (@modelcontextprotocol/server-filesystem@<version>), এবং সচেতনভাবে ভার্সন আপডেট করুন। systemd-এর অধীনে থাকা Python সার্ভারগুলো sudo -H -u mcp /opt/mcp-ops/.venv/bin/pip install -U "mcp[cli]" এবং তার পরে sudo systemctl restart mcp-ops চালিয়ে আপডেট করা হয়। কোনো মেজর ভার্সন আপডেটের আগে রিলিজ নোটগুলো পড়ুন: 1.x থেকে 2.x Python SDK-তে রূপান্তর করার সময় ইমপোর্ট করার সময়ই 1.x কোড কাজ করা বন্ধ করে দেয়, এবং SDK-এর নিজস্ব মাইগ্রেশন গাইড পরামর্শ দেয় যে মাইগ্রেশন সম্পন্ন না হওয়া পর্যন্ত <2-এর একটি আপার বাউন্ড, যেমন "mcp[cli]<2", বজায় রাখুন। আপগ্রেড করার সময় আপনার SDK কোন স্পেক রিভিশন (spec revision) লক্ষ্য করছে তা খেয়াল রাখুন, কারণ SSE-থেকে-Streamable-HTTP সীমানা অতিক্রম করলে আপনার ক্লায়েন্টদের প্রয়োজনীয় ট্রান্সপোর্ট পদ্ধতি পরিবর্তিত হতে পারে।

ব্যর্থতার ধরন এবং যে স্ট্রিংগুলো আপনি দেখবেন

এজেন্ট দেখায় যে সার্ভার ব্যর্থ হয়েছে। claude mcp list প্রিন্ট করে ✘ Failed to connect, এবং বর্তমান সংস্করণগুলোতে সেই লাইনের শেষে ব্যর্থতার বিস্তারিত যুক্ত থাকে। claude --debug চালান এবং সাধারণত আপনি Error: spawn npx ENOENT দেখতে পাবেন, যার অর্থ কমান্ডটি এজেন্টের PATH-এ নেই। রানটাইম অনুপস্থিত অথবা এজেন্ট যেখানে খুঁজছে সেখানে নেই: Node ইনস্টল করা নেই, npx অনুপস্থিত, অথবা সরাসরি নাম উল্লেখ করা একটি virtualenv Python। কমান্ডটিকে অ্যাবসোলিউট পাথে পরিবর্তন করুন অথবা রানটাইম ইনস্টল করুন, তারপর পুনরায় সংযোগ করুন।

একটি stdio সার্ভার সংযোগ করার পরপরই বিচ্ছিন্ন হয়ে যায়। ক্লায়েন্ট একটি JSON পার্স এরর লগ করে, যা অনেকটা Unexpected token 'S', "Server sta"... is not valid JSON বা Failed to parse message এর মতো। এর কারণ সবসময় একই: সার্ভার stdout-এ একটি লগ লাইন লিখেছে। stdio-এর ক্ষেত্রে, stdout নিজেই JSON-RPC চ্যানেল, তাই যেকোনো বাড়তি টেক্সট স্ট্রিমটিকে নষ্ট করে দেয় এবং হ্যান্ডশেক ব্যর্থ হয়। Node-এ, console.log stdout-এ যায়, তাই console.error ব্যবহার করুন। Python-এ, একটি সাধারণ print() stdout-এ যায়, তাই লগগুলো logging ব্যবহার করে লিখুন যা sys.stderr-এ কনফিগার করা, অথবা file=sys.stderr পাস করুন। নিয়মটি অমোঘ: stdio-এর ক্ষেত্রে, stdout-এ শুধুমাত্র JSON-RPC থাকবে, মানুষের পড়ার উপযোগী সবকিছু stderr-এ থাকবে।

একটি রিমোট সার্ভার টাইম আউট হয় অথবা হ্যান্ডশেকের মাঝপথে বন্ধ হয়ে যায়। ক্লায়েন্ট MCP error -32000: Connection closed এরর দেখায়, অথবা ইন্সপেক্টর Connect-এ আটকে থাকে এবং কোনো টুল তালিকাভুক্ত করে না। nginx-এর পেছনে এটি বাফারিংয়ের কারণে ঘটে: প্রক্সি SSE স্ট্রিমটিকে ফ্লাশ না করে ধরে রাখে, তাই ক্লায়েন্ট এমন একটি উত্তরের জন্য অপেক্ষা করে যা কখনোই আসে না। proxy_buffering off; (এবং ধাপ 4-এর বাকি অংশ) location-এ যোগ করুন। পাবলিক URL-এর বিপরীতে curl -N দিয়ে নিশ্চিত করুন, আপনি দেখবেন ইভেন্ট ডেটা ধীরে ধীরে আসছে, শেষে একসাথে নয়।

অথেন্টিকেশন প্রত্যাখ্যাত হয়েছে। ক্লায়েন্ট Error POSTing to endpoint (HTTP 401) অথবা সরাসরি 401 Unauthorized রিপোর্ট করে। হয় হেডারটি অনুপস্থিত, টোকেনটি ভুল, অথবা ভেরিয়েবলটি এক্সপ্যান্ড হয়নি, যা একটি সাধারণ ভুল। ক্লায়েন্ট যখন কনফিগারেশন পড়ে তখন যদি MCP_TOKEN সেট করা না থাকে, Claude Code claude mcp list-এ অনুপস্থিত ভেরিয়েবল সম্পর্কে সতর্ক করে এবং আক্ষরিক টেক্সট পাঠায়, তাই nginx Bearer ${MCP_TOKEN} দেখে। Claude Code, আপনার ক্লাউড প্রোভাইডার বা আপনার এনভায়রনমেন্টের অন্য কোনো ক্রেডেনশিয়ালের নামে থাকা ভেরিয়েবল খালি হিসেবে পড়া হয় এবং nginx কোনো মান ছাড়াই Bearer দেখে। ভেরিয়েবলটি echo করুন, হেডারটি পুনরায় যোগ করুন এবং নিশ্চিত করুন যে সঠিক বাইটগুলো nginx if-এর টোকেনের সাথে মিলে যাচ্ছে।

systemd-এর অধীনে সার্ভিসটি চালু হচ্ছে না। journalctl -u mcp-ops দেখাচ্ছে ModuleNotFoundError: No module named 'mcp', ExecStart venv ইন্টারপ্রেটারের পরিবর্তে সিস্টেম Python-কে নির্দেশ করছে। অথবা Address already in use, অন্য কোনো প্রসেস 8000 পোর্টটি দখল করে রেখেছে; sudo ss -ltnp | grep 8000 ব্যবহার করে সেটিকে খুঁজে বের করুন। systemd, TLS, auth এবং প্রতিটি ব্যর্থতার মোড সম্পর্কে জানুন।

FAQ

MCP server আসলে কী?

এটি এমন একটি প্রোগ্রাম যা Model Context Protocol-এর মাধ্যমে JSON-RPC 2.0 ব্যবহার করে AI ক্লায়েন্টকে টুল এবং রিসোর্স প্রদান করে। AI মডেল নিজে টুলটি চালায় না, এটি তার ক্লায়েন্টকে অনুরোধ করে, ক্লায়েন্ট MCP server-কে কল করে এবং সার্ভার তা এক্সিকিউট করে ফলাফল ফেরত দেয়। প্রোটোকলটি স্ট্যান্ডার্ড হওয়ায়, একটি সার্ভার যেকোনো compliant ক্লায়েন্টের সাথে কাজ করে, তা Claude Code, Claude Desktop বা Gemini CLI যাই হোক না কেন।

stdio এবং HTTP ট্রান্সপোর্টের মধ্যে পার্থক্য কী?

একটি stdio সার্ভার ক্লায়েন্ট দ্বারা child process হিসেবে চালু হয় এবং stdin/stdout-এর মাধ্যমে যোগাযোগ করে, তাই এটি একটি মেশিনে একটি ক্লায়েন্টের সাথেই বাঁচে এবং মরে, এর কোনো নেটওয়ার্ক বা auth-এর প্রয়োজন হয় না। একটি HTTP সার্ভার হলো দীর্ঘস্থায়ী নেটওয়ার্ক সার্ভিস যা অনেক ক্লায়েন্ট একসাথে অ্যাক্সেস করতে পারে, যে কারণে এতে TLS এবং অথেন্টিকেশন প্রয়োজন। লোকাল, একক ব্যবহারকারীর টুলের জন্য stdio ব্যবহার করুন; শেয়ারড বা পারসিস্টেন্ট যেকোনো কিছুর জন্য HTTP (বর্তমান সার্ভারে Streamable HTTP) ব্যবহার করুন।

রিমোট MCP server কীভাবে সুরক্ষিত করব?

ধরে নিন এটি আপনার ফাইল, ডাটাবেস বা shell-এ টুল অ্যাক্সেস দেয়, তাই কখনোই unauthenticated অবস্থায় এটি উন্মুক্ত করবেন না। সবচেয়ে ভালো উপায় হলো এটিকে localhost-এ bind করে রাখা এবং SSH tunnel বা প্রাইভেট VPN-এর মাধ্যমে অ্যাক্সেস করা; যদি এটি পাবলিক করতেই হয়, তবে এমন একটি reverse proxy-র পেছনে রাখুন যা bearer token বা MCP OAuth flow কার্যকর করে। openssl rand -hex 32 দিয়ে টোকেন তৈরি করুন এবং এর সামনে এই নিরাপত্তা ব্যবস্থাগুলোর কোনোটি ছাড়া সার্ভারকে কখনোই 0.0.0.0-এ bind করবেন না।

সার্ভার চালু না হলে কীভাবে ডিবাগ করব?

প্রথমে claude mcp list, ✘ Failed to connect চেক করুন; spawn ... ENOENT মানে হলো কমান্ড বা রানটাইম অনুপস্থিত, তাই পাথ ঠিক করুন বা এটি ইনস্টল করুন। যদি এটি কানেক্ট হওয়ার পর JSON parse error দিয়ে বন্ধ হয়ে যায়, তবে সার্ভার stdout-এ লগ করছে এবং JSON-RPC স্ট্রিম নষ্ট করছে; সব লগ stderr-এ সরিয়ে নিন। অন্য যেকোনো সমস্যার জন্য, MCP Inspector-এর অধীনে সঠিক কমান্ডটি চালান, যা সার্ভারকে আলাদাভাবে চালায় যাতে আপনি সার্ভারের বাগ এবং ক্লায়েন্ট-কনফিগ বাগের মধ্যে পার্থক্য করতে পারেন।