SSD Nodes Learn 🎉 VPS dari $5.50/bln
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-08-13

Apa itu Pelayan MCP Tanpa Status (Stateless)?

Ketahui perubahan dalam semakan MCP 2026-07-28 yang membuang sesi dan jabat tangan initialize. Panduan ini menjelaskan kesan terhadap proksi, pemeriksaan kesihatan dan auth.

Apakah pelayan MCP tanpa status (stateless)

Pelayan MCP tanpa status tidak menyimpan sebarang status bagi setiap klien antara permintaan. Setiap permintaan membawa versi protokol, keupayaan klien, dan kelayakan yang diperlukan oleh pelayan untuk menjawabnya, jadi mana-mana proses pada mana-mana mesin boleh menjawab sebarang permintaan. MCP (Model Context Protocol, format talian yang digunakan oleh ejen untuk mencapai alatan) menjadikan ini sebagai peraturan dalam semakan 2026-07-28, yang membuang jabat tangan initialize dan sesi HTTP yang berada di bawahnya.

Itulah keseluruhan tujuan operasi tersebut. Pelayan yang tidak menyimpan apa-apa bagi setiap klien boleh diletakkan di belakang pengimbang beban (load balancer) biasa tanpa pertalian sesi (session affinity), dimulakan semula semasa penggunaan (deploy) tanpa memutuskan sambungan klien, dan dijalankan sebagai empat proses yang serupa dan bukannya satu. Pelayan yang berorientasikan sesi tidak boleh melakukan perkara tersebut tanpa jentera tambahan.

Model Context Protocol ialah protokol tanpa status: semua maklumat yang diperlukan untuk memproses permintaan terkandung dalam permintaan itu sendiri. Pelayan memproses setiap permintaan secara bebas; tiada status harus disimpulkan daripada permintaan sebelumnya, walaupun permintaan tersebut berada pada sambungan atau aliran yang sama.

Tanpa status tidak bermakna pelayan anda tidak menyimpan apa-apa. Pangkalan data, baris gilir (queue), dan cache anda masih ada. Ini bermakna protokol tersebut tidak membawa sebarang status pada sambungan, jadi pelayan tidak boleh menganggap sambungan, proses, atau soket terbuka sebagai ganti kepada "klien ini, di tengah-tengah perbualan".

Perkara yang dibuang dalam semakan 2026-07-28

2026-07-28 ialah semakan spesifikasi semasa setakat Ogos 2026. Berbanding dengan 2025-11-25, ia membuang lima perkara yang wujud untuk menyokong sesi.

  • Permintaan initialize dan pemberitahuan notifications/initialized. Tiada jabat tangan (handshake) langsung (SEP-2575).
  • Header Mcp-Session-Id, dan penamatan sesi dengan HTTP DELETE (SEP-2567).
  • Strim HTTP GET kendiri yang digunakan pelayan untuk menolak (push) pemberitahuan. Ia digantikan dengan subscriptions/listen, iaitu POST biasa yang responsnya merupakan strim jangka hayat panjang.
  • Kebolehsambungan semula strim SSE (server-sent events). Header Last-Event-ID dan ID bagi setiap peristiwa telah dibuang, jadi strim yang terputus akan menyebabkan permintaan yang sedang berjalan hilang dan klien mesti mengeluarkan semula permintaan tersebut sebagai permintaan baharu dengan ID permintaan baharu.
  • ping, logging/setLevel dan notifications/roots/list_changed. Tahap log kini merupakan medan bagi setiap permintaan, io.modelcontextprotocol/logLevel dalam _meta.

Satu kaedah telah ditambah, dan setiap pelayan mesti melaksanakannya. server/discover mengembalikan versi protokol, keupayaan dan identiti yang disokong oleh pelayan dalam satu panggilan. Ia merupakan perkara yang paling hampir dengan jabat tangan yang masih ada, dan memanggilnya adalah pilihan bagi klien.

Mengapa pengangkutan sesi sukar dijalankan dalam pengeluaran

Dalam 2025-11-25 dan versi sebelumnya, pelayan boleh menjana ID sesi semasa permulaan dan mengembalikannya dalam pengepala Mcp-Session-Id pada InitializeResult. Pelanggan kemudian perlu menghantar pengepala tersebut pada setiap permintaan seterusnya. Versi protokol yang dirundingkan dan keupayaan pelanggan disimpan dalam memori pelayan, dengan ID tersebut sebagai kunci. Setiap pilihan ini mempunyai kos operasi.

  • But semula akan memadamkan jadual sesi. Spesifikasi memerlukan pelayan menjawab sebarang permintaan yang membawa ID sesi yang tidak sah dengan 404 Not Found, dan memerlukan pelanggan bermula semula dengan InitializeRequest baharu. Setiap penggunaan (deploy) menjadi peristiwa penyambungan semula untuk setiap pelanggan yang bersambung.
  • Replika kedua tidak mengetahui sesi replika pertama. Penskalaan keluar bermakna penghalaan lekat (sticky routing) pada pengimbang beban, atau stor sesi kongsi yang dibaca oleh setiap replika pada setiap permintaan.
  • Jadual sesi adalah memori yang berkembang mengikut pelanggan yang melahu. DELETE adalah pilihan, dan pelanggan yang ditutup tanpa menghantarnya akan meninggalkan entri yang tidak dipadam.
  • Keputusan senarai boleh berbeza bagi setiap sambungan, jadi caching di hadapan pelayan adalah tidak selamat.

Membuang sesi menghapuskan keempat-empat masalah ini sekaligus. Itulah perubahan yang perlu difahami sebelum anda menyentuh sebarang konfigurasi.

Apa yang dibawa oleh setiap permintaan sekarang

Setiap POST ke endpoint MCP berdiri sendiri. Versi protokol dan keupayaan klien dihantar dalam badan permintaan di bawah _meta, dan medan terpilih dicerminkan ke dalam header HTTP supaya perantara boleh melakukan penghalaan berdasarkan medan tersebut tanpa perlu menghuraikan JSON.

POST /mcp HTTP/1.1
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: get_weather
Authorization: Bearer <access token>

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {"location": "Seattle, WA"},
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": {"name": "ExampleClient", "version": "1.0.0"},
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}

io.modelcontextprotocol/protocolVersion dan io.modelcontextprotocol/clientCapabilities diperlukan pada setiap permintaan. clientInfo tidak diperlukan, walaupun klien digalakkan untuk menghantarnya. Permintaan yang kehilangan medan wajib adalah tidak sah, jadi pelayan mesti menolaknya dengan ralat JSON-RPC -32602 dan HTTP 400 Bad Request.

Header Mcp-Method diperlukan pada setiap permintaan. Mcp-Name diperlukan pada tools/call, resources/read dan prompts/get. Nilai header mesti sepadan dengan badan permintaan, dan pelayan yang memproses badan permintaan mesti menolak ketidakpadanan dengan 400 Bad Request serta kod ralat -32020, HeaderMismatch. Peraturan ini wujud kerana pengimbang beban yang melakukan penghalaan berdasarkan header dan pelayan yang melaksanakan badan permintaan adalah dua sumber kebenaran yang berbeza. Jika anda melakukan penghalaan atau pengehadan kadar berdasarkan header ini, semak MCP-Protocol-Version dahulu: semakan terdahulu tidak pernah mengesahkan header terhadap badan permintaan, jadi pada versi tersebut nilai header tidak boleh dipercayai.

Ketidaksetujuan versi kini merupakan ralat biasa bagi setiap permintaan dan bukannya kegagalan jabat tangan. Pelayan yang tidak melaksanakan versi yang diminta akan menjawab 400 Bad Request dengan ralat -32022, UnsupportedProtocolVersion, dan menyenaraikan versi yang disokongnya dalam data.supported. Klien akan memilih satu daripada senarai tersebut dan mencuba semula.

Ke mana perginya status: token, kursor, dan langganan

Status tidak hilang. Ia berpindah ke tempat yang boleh anda lihat dan log.

Kredensial berpindah ke dalam setiap permintaan. Tiada sesi untuk mengaitkan identiti, jadi token akses dibawa bersama setiap panggilan HTTP dan disahkan setiap kali. Butiran lanjut ada dalam bahagian pengesahan di bawah.

Kursor perlu membawa kedudukannya sendiri. Paginasi pada tools/list, resources/list, prompts/list dan resources/templates/list menggunakan rentetan kursor legap (opaque), dan klien tidak boleh menghurai atau mengubah suainya. Pada pelayan proses tunggal, adalah perkara biasa untuk menyimpan offset dalam memori, yang dikunci oleh sesi. Tanpa sesi, kursor mestilah mencukupi untuk mana-mana replika menyambung semula penyenaraian, jadi kodkan kedudukan di dalam kursor dan tandatanganinya, atau simpan dalam storan yang dikongsi oleh semua replika. Kursor yang tidak sah harus mengembalikan -32602. Tandatanganinya kerana kursor legap masih merupakan input yang dibekalkan oleh klien yang dinyahkod dan dipercayai oleh kod anda.

Langganan tergolong dalam permintaan, bukan sambungan. Klien yang mahukan pemberitahuan perubahan menghantar subscriptions/listen dengan penapis yang menamakan jenis yang diingini: toolsListChanged, promptsListChanged, resourcesListChanged dan resourceSubscriptions. Pelayan membalas dengan notifications/subscriptions/acknowledged dan membiarkan aliran respons itu terbuka. Jika aliran terputus, pelayan tidak menyimpan apa-apa, dan klien menghantar semula subscriptions/listen untuk mendapatkannya kembali.

Status aplikasi rentas-panggilan menjadi pemegang (handle) eksplisit. Apabila pelayan benar-benar perlu mengingati sesuatu antara panggilan, jawapan spesifikasi ialah pengecam yang dijana oleh pelayan yang dihantar kembali sebagai argumen alat biasa. Ia muncul dalam skema alat, ia boleh direkodkan dalam log, dan ia tidak pernah tersirat oleh sambungan. Pelayan yang mempunyai data sebenar bagi setiap pengguna, seperti pelayan e-mel MCP yang dihoskan sendiri, menggunakan corak ini dan bukannya sesi: pengecam peti mel atau draf adalah argumen alat, jadi mana-mana replika boleh mengambil panggilan seterusnya. Banyak alat tidak memerlukan pemegang langsung: alat carian yang disokong oleh instans SearXNG anda sendiri mengambil pertanyaan dan memberikan hasil kembali, tanpa perlu menyambung semula panggilan seterusnya dan tidak perlu mengambil kira replika mana yang menjawab.

Pengerahan: reverse proxy, tamat masa, dan pemeriksaan kesihatan

Endpoint MCP ialah satu laluan yang menerima POST. Kebanyakan trafik adalah permintaan ringkas dan respons JSON, yang boleh dikendalikan oleh mana-mana proksi. Pengecualiannya ialah respons penstriman, di mana tetapan lalai proksi akan menjejaskan prestasi anda. Ini adalah bahagian yang berubah apabila anda beralih daripada demo komputer riba kepada pelayan MCP yang berjalan pada VPS.

location /mcp {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_buffering off;
    proxy_read_timeout 1h;
    proxy_send_timeout 1h;
}

proxy_buffering off penting kerana nginx menimbal (buffer) respons proksi secara lalai, yang menahan peristiwa SSE sehingga penimbal penuh atau respons tamat. Spesifikasi juga meminta pelayan menghantar X-Accel-Buffering: no pada respons SSE, dan nginx mematuhi header tersebut, jadi pelayan yang betul akan memberitahu proksi anda perkara yang tepat dengan sendirinya. Tetapkan arahan tersebut juga, kerana itu adalah bahagian yang anda kawal.

proxy_read_timeout ditetapkan kepada 60 saat secara lalai. Strim subscriptions/listen yang senyap lebih lama daripada tempoh tersebut akan ditutup oleh nginx, bukan oleh pelayan anda, jadi log anda menunjukkan proses yang sihat manakala klien anda menunjukkan strim yang terputus. Tingkatkan tetapan ini pada lokasi MCP sahaja, bukan pada keseluruhan pelayan. Pelayan juga digalakkan untuk menghantar baris komen SSE (baris yang bermula dengan titik bertindih) sebagai keep-alive semasa tempoh senyap, yang menghalang perantara daripada menamatkan strim tersebut.

Caddy memerlukan kurang konfigurasi. Ia menimbal secara separa secara lalai untuk kecekapan rangkaian dan melakukan flush serta-merta apabila respons membawa Content-Type: text/event-stream, jadi penstriman berfungsi tanpa arahan tambahan.

mcp.example.com {
	reverse_proxy 127.0.0.1:8080 {
		health_uri /healthz
		health_interval 10s
	}
}

Perhatikan ke mana pemeriksaan kesihatan itu dihalakan. Jangan halakan pemeriksaan aktif ke endpoint MCP dengan GET, kerana pelayan yang hanya melaksanakan semakan ini akan menjawab 405 Method Not Allowed kepada GET dan DELETE, manakala kaedah kesihatan lalai Caddy ialah GET. Proksi kemudiannya akan menandakan backend yang sihat sebagai tidak berfungsi. Sediakan laluan biasa seperti /healthz untuk proksi, dan periksa protokol secara berasingan dengan POST.

curl -sS https://mcp.example.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -H 'Mcp-Method: server/discover' \
  -d '{"jsonrpc":"2.0","id":"health-1","method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}'

200 yang membawa senarai supportedVersions bermakna proses tersebut sedang berjalan dan menggunakan protokol tersebut. 404 dengan ralat JSON-RPC -32601 bermakna proses tersebut sedang berjalan tetapi tidak menyediakan server/discover, yang wajib dilaksanakan oleh setiap pelayan 2026-07-28. 400 dengan -32022 bermakna pemeriksa anda meminta versi yang tidak disokong oleh binaan ini, yang merupakan perkara yang anda ingin kesan selepas peningkatan dependensi. Nginx sumber terbuka tidak mempunyai pemeriksaan kesihatan aktif, jadi gunakan max_fails dan fail_timeout pasif pada upstream dan jalankan pemeriksaan protokol daripada pemantauan anda.

Mulakan semula secara bergilir (rolling restart) kini hanya menyebabkan permintaan yang sedang berjalan terhenti dan tiada kesan lain. Lakukan drain, biarkan POST yang terbuka selesai, mulakan proses baharu, dan klien akan menghantar semula permintaan yang gagal. Satu-satunya perkara yang masih terputus ialah sebarang strim subscriptions/listen yang terbuka, kerana strim tersebut adalah sambungan langsung ke satu proses tertentu. Tanpa status (statelessness) telah membuang pertalian sesi (session affinity). Ia tidak membuang pertalian sambungan untuk strim yang sedang terbuka sekarang, dan tiada peraturan penghalaan yang boleh membetulkannya. Klien boleh membezakannya: strim yang berakhir dengan hasil subscriptions/listen kosong ditutup dengan sempurna, manakala strim yang berakhir tanpa hasil tersebut dianggap terputus, yang mungkin dianggap oleh klien sebagai sebab untuk menyambung semula.

Caching menjadi mungkin buat pertama kalinya. Hasil daripada kaedah senarai kini membawa ttlMs dan cacheScope, dan cacheScope: "public" memberitahu perantara kongsi bahawa mereka boleh menyimpan respons tersebut dalam cache. Ini hanya selamat kerana hasil senarai tidak lagi berubah mengikut sambungan, yang merupakan akibat langsung daripada pembuangan sesi.

Mengapa pengesahan berubah apabila tiada sesi

Dengan adanya sesi, adalah mudah untuk melakukan pengesahan sekali sahaja di initialize dan kemudian menganggap ID sesi sebagai bukti untuk segala-galanya selepas itu. ID sesi yang digunakan dengan cara tersebut merupakan kelayakan pembawa (bearer credential) tanpa audiens, tanpa tarikh luput, dan tanpa laluan pembatalan, yang dijana oleh pelayan anda sendiri. Menghapuskan sesi bermakna menghapuskan jalan pintas tersebut, dan penggantinya adalah lebih ketat.

Pelayan MCP yang dilindungi bertindak sebagai pelayan sumber OAuth 2.1. Setiap permintaan HTTP daripada klien mesti membawa Authorization: Bearer <access token>, dan pelayan akan mengesahkan token tersebut pada setiap permintaan. Pengesahan merangkumi audiens: pelayan mesti mengesahkan bahawa token tersebut dikeluarkan khusus untuknya, mengikut RFC 8707 (Resource Indicators for OAuth 2.0), dan tidak boleh menerima atau meneruskan token yang ditujukan untuk perkara lain. Klien meminta audiens yang betul dengan menghantar parameter resource bersama URI kanonik pelayan.

Penemuan (discovery) dijalankan berdasarkan cabaran. Apabila permintaan tiba tanpa token yang boleh digunakan, pelayan akan menjawab dengan 401 Unauthorized.

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource",
                         scope="files:read"

Klien membaca resource_metadata, mengambil dokumen tersebut (RFC 9728, OAuth 2.0 Protected Resource Metadata, yang mesti dilaksanakan oleh pelayan MCP), mencari pelayan kebenaran, dan menjalankan aliran tersebut. Token sah yang mempunyai kebenaran yang tidak mencukupi akan menerima 403 Forbidden bersama error="insufficient_scope" dan skop yang diperlukan untuk operasi tersebut.

Terdapat dua kesan terhadap cara anda menjalankannya. Pengesahan token kini berlaku pada setiap permintaan dan bukannya sekali bagi setiap sesi, jadi perjalanan rangkaian (network round trip) ke titik akhir introspeksi bagi setiap panggilan akan kelihatan dalam kependaman (latency) anda: utamakan token yang boleh anda sahkan secara setempat berdasarkan tandatangan, audiens, dan tarikh luput, atau simpan hasil pengesahan dalam cache untuk tempoh singkat yang dikunci mengikut token. Selain itu, oleh kerana tiada sesi yang memegang identiti, kebenaran mesti dikira daripada token pada setiap panggilan. Ini adalah lebih telus berbanding model sesi, dan ia selari dengan amalan meluas untuk memastikan kelayakan tidak disimpan dalam proses ejen, yang dibincangkan dalam menyimpan rahsia di luar ejen AI.

Perkara yang benar dan tidak benar tentang semakan ini

Segala yang diterangkan di atas merujuk kepada semakan 2026-07-28. Ia tidak menerangkan MCP selama-lamanya, dan ia tidak menerangkan pelayan yang anda gunakan pada tahun lepas.

Pelanggan dan pelayan pada 2025-11-25 dan sebelumnya masih menggunakan model jabat tangan (handshake). Spesifikasi tersebut memanggil semakan-semakan itu sebagai legasi, dan memanggil semakan metadata setiap permintaan sebagai moden. Pelayan yang hanya menyokong semakan ini, apabila bertemu dengan pelanggan yang lebih lama, harus menjawab 405 Method Not Allowed kepada GET atau DELETE pada titik tamat MCP, mengabaikan sebarang pengepala Mcp-Session-Id tanpa mencipta atau menggemakannya, dan mengabaikan Last-Event-ID kerana strim tidak boleh disambung semula. Pelayan dwi-era boleh melayani kedua-duanya pada satu titik tamat: permintaan yang membawa _meta moden dilayani tanpa status (stateless), dan permintaan initialize memilih semantik sesi yang lebih lama.

Oleh itu, semak rentetan semakan sebelum anda mempercayai mana-mana maklumat ini. Jika SDK anda masih menghantar initialize, sesi masih wujud untuk penggunaan anda dan masalah berkaitan sesi di atas masih perlu anda uruskan. Perkara yang sama terpakai pada bahagian pelanggan: proses ejen pada mesin anda sendiri, seperti persediaan dalam menjalankan ejen pengekodan pada VPS, hanya bersifat tanpa status dalam pengertian ini jika pustaka yang digunakannya menggunakan semakan moden. Baca versi yang dirundingkan oleh runtime anda, kemudian baca semakan spesifikasi yang sepadan, dan anggap halaman ini menerangkan satu semakan yang dinamakan dan bukannya protokol secara umum.

FAQ

Adakah pelayan MCP tanpa status (stateless) bermakna saya tidak boleh menyimpan apa-apa?

Tidak. Tanpa status (stateless) merujuk kepada protokol, bukan aplikasi anda. Pangkalan data, baris gilir (queues) dan cache semuanya berfungsi seperti biasa. Apa yang berubah ialah status yang merangkumi beberapa panggilan mesti dirujuk oleh pengecam eksplisit yang dihantar oleh klien pada setiap permintaan, seperti pemegang (handle) yang dijana pelayan dalam argumen alat. Apa yang anda tidak boleh lakukan ialah membuat inferens konteks daripada sambungan: spesifikasi menyatakan pelayan tidak boleh bergantung pada permintaan terdahulu melalui sambungan yang sama untuk menetapkan keupayaan, versi protokol atau identiti klien, kerana setiap permintaan membekalkan maklumat tersebut dalam _meta.

Adakah saya masih memerlukan sesi melekit (sticky sessions) pada pengimbang beban (load balancer) saya?

Tidak untuk permintaan biasa. Di bawah semakan 2026-07-28, setiap POST membawa versi protokol, keupayaan dan kelayakan tersendiri, jadi mana-mana replika boleh menjawab mana-mana permintaan dan round-robin adalah memadai. Satu-satunya perkara yang kekal lama ialah aliran respons subscriptions/listen, iaitu satu sambungan terbuka kepada satu proses. Ia berakhir apabila proses itu berakhir, dan klien menghantar semula subscriptions/listen untuk mewujudkannya semula. Itu adalah jangka hayat sambungan dan bukannya pertalian sesi (session affinity), dan tiada peraturan penghalaan yang menghalangnya.

Apa yang berlaku kepada Mcp-Session-Id dan aliran HTTP GET?

Kedua-duanya telah dialih keluar dalam semakan 2026-07-28, di bawah SEP-2567 dan SEP-2575. Pelayan yang melaksanakan semakan ini sahaja harus menjawab 405 Method Not Allowed kepada GET dan DELETE pada titik akhir MCP, dan harus mengabaikan pengepala Mcp-Session-Id dan bukannya menggemakannya semula. Pemberitahuan perubahan yang dimulakan oleh pelayan kini bergerak pada aliran respons permintaan subscriptions/listen dan bukannya aliran GET yang berdiri sendiri. Pelayan yang mesti terus melayani klien lama melaksanakan tingkah laku semakan terdahulu bersama-sama dengan yang ini.

Bagaimanakah cara saya melakukan pemeriksaan kesihatan (health check) pelayan MCP tanpa jabat tangan (handshake)?

Gunakan dua tahap. Halakan pemeriksaan aktif proksi kepada laluan HTTP biasa yang disediakan oleh aplikasi anda, kerana GET kepada titik akhir MCP akan memulangkan 405 dengan betul dan akan menandakan backend yang sihat sebagai tidak berfungsi (down). Kemudian, periksa protokol itu sendiri dengan menghantar POST server/discover, yang mesti dilaksanakan oleh setiap pelayan 2026-07-28, dan pastikan balasan tersebut adalah HTTP 200 serta menyenaraikan versi protokol yang digunakan oleh klien anda. 404 dengan ralat JSON-RPC -32601 bermakna proses sedang berjalan tetapi tidak menyediakan kaedah tersebut, dan 400 dengan -32022 bermakna versi yang anda minta tidak disokong oleh binaan tersebut.