საკუთარი MCP სერვერები მრავლდება. ჯერ ჩნდება ერთი შიდა დოკუმენტაციისთვის, მერე ბაზისთვის, მერე ვიღაც დეპლოის პაიპლაინისთვის პატარას წერს. თითოეულს თავისი პორტი, თავისი მისამართი და თავისი საიდუმლო აქვს, და გუნდის ყოველი წევრი სამივეს თავისი კლიენტის კონფიგში სვამს. ტოკენის შეცვლა ყველასთვის მიწერას ნიშნავს.
კარიბჭე ამას ერთ მისამართად და ერთ ტოკენად აქცევს. კლიენტები უკავშირდებიან https://mcp.example.com/docs/mcp-ს, .../db/mcp-ს და ა.შ. კარიბჭე ამოწმებს ტოკენს, ყოველ ბილიკს localhost-ზე სწორ სერვერთან აგზავნის, თავად სერვერები კი გარეთ არასოდეს ჩანს. ძალიან ცოტაა საჭირო: პატარა VPS საკუთარი IPv4-ით და Caddy.
ქვემოთ მოცემული კონფიგურაცია სატესტო სერვერზე ავაწყვეთ და ნამდვილი კლიენტებით შევამოწმეთ, სანამ აღვწერდით.
რა არის საჭირო
- VPS საჯარო IPv4-ით, რომ კლიენტებმა 443-ს მიაღწიონ. Nano-IP საკმარისია, თუ თქვენი MCP სერვერები თავად მძიმე სამუშაოს არ ასრულებენ.
- დომენი, რომლის 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. არავის კონფიგი არ იცვლება, გარდა ახალი მისამართისა იმავე ჰოსტზე და იმავე ტოკენით.
შეზღუდვები, რომელთა ცოდნაც ღირს
- ერთი ტოკენი ყველასთვის მარტივია და ერთი ფაილით იცვლება, მაგრამ ერთი ადამიანისთვის წვდომის გაუქმება ყველასთვის შეცვლის გარეშე ვერ მოხერხდება. ცალკეული მომხმარებლის წვდომისთვის კარიბჭის წინ auth-პროქსი დააყენეთ ან თითოეულს საკუთარი მარშრუტი და ტოკენი მიეცით.
- კარიბჭე სერვერს უსაფრთხოს არ ხდის. MCP სერვერი, რომელიც shell ბრძანებებს ასრულებს, shell-ად რჩება ყველასთვის, ვისაც ტოკენი აქვს. ტოკენები საერთო კონფიგებსა და git-ში ნუ შეინახავთ.
- ზომა სერვერების მიხედვით შეარჩიეთ და არა კარიბჭის. თავად Caddy რამდენიმე ათეულ მეგაბაიტს იკავებს. თუ რომელიმე სერვერი ლოკალურ მოდელს უშვებს ან დიდ რეპოზიტორიას აინდექსებს, ტარიფს ის განსაზღვრავს და არა პროქსი.
მხოლოდ ერთი MCP სერვერი გაქვთ? უფრო მარტივი შემთხვევა განხილულია VPS MCP სერვერებისთვის-ში. გინდათ, აგენტებმა ის სერვერიც მართონ, რომელზეც ცხოვრობენ? ამას აკეთებს EQVPS-ის MCP სერვერი (ან REST API, თუ სკრიპტები გირჩევნიათ), ხოლო საკუთარი IPv4-ის მქონე ტარიფები თვეში $8-დან იწყება.
კომენტარები
ჯერ არ არის კომენტარები. იყავით პირველი.