Pada 28 Juli 2026 Model Context Protocol menerbitkan revisi baru spesifikasinya. Changelog-nya dibuka dengan dua poin yang mengubah cara kerja setiap server remote: sesi di tingkat protokol dihapus, begitu pula handshake initialize. Setiap request kini membawa semua yang dibutuhkan server untuk menjawabnya.
Bagi banyak server, itu berarti migrasi. Bagi server yang membaca dokumen identitas, ini lebih mirip konfirmasi, karena server semacam itu memang sudah punya alasan kuat untuk stateless. Tulisan ini membahas revisi tersebut dari sudut pandang server tool: perubahan mana yang bisa diabaikan, mana yang harus dibangun, dan mana yang layak diadopsi lebih awal. Contohnya diambil dari server yang kami jalankan, jadi kekurangan yang disebut di bawah juga milik kami.
Ini adalah blog doc.cheap, sebuah API OCR untuk paspor dan kartu identitas dengan server MCP di depannya. Baca bagian tentang produk dengan mengingat hal itu.
Versi singkat
| Perubahan di 2026-07-28 | Yang dilakukan server tool stateless |
|---|---|
Tanpa Mcp-Session-Id, tanpa sesi |
Tidak ada, jika memang tidak pernah menyimpan sesi |
Tanpa handshake initialize; versi dan capability di _meta setiap request |
Membacanya per request, mencocokkannya dengan header MCP-Protocol-Version |
server/discover |
Mengimplementasikannya: ini MUST |
Header Mcp-Method dan Mcp-Name wajib |
Memeriksa bahwa keduanya cocok dengan body |
resultType di setiap hasil |
Mengirim "complete" |
ttlMs dan cacheScope di hasil list dan read |
Memilih masa berlaku cache dan cakupannya |
| Tool dalam urutan deterministik | Menjaga urutan registrasi tetap stabil |
| Stream HTTP GET dan resumability dihapus | Menjawab GET dan DELETE dengan 405 |
| Roots, Sampling, dan Logging deprecated | Menerima file sebagai argumen tool, menulis log ke stderr atau OpenTelemetry |
Sisa tulisan ini menjelaskan setiap baris dan mengapa baris itu lebih penting bagi server yang menangani dokumen.
Sesi dihapus, dan itu cocok untuk server dokumen
Poin pertama changelog menghapus "protocol-level sessions and the Mcp-Session-Id header from the Streamable HTTP transport". Endpoint list seperti tools/list "no longer vary per-connection", dan server yang butuh state di antara panggilan "use explicit, server-minted handles passed as ordinary tool arguments", yaitu handle eksplisit yang dibuat server dan dikirim sebagai argumen tool biasa.
Server dokumen jarang membutuhkan sesi sejak awal. Pikirkan apa yang akan disimpan sebuah sesi: API key, mungkin gambar yang menunggu dibaca, mungkin hasil terakhir. Semua itu adalah data yang sebaiknya tidak disimpan di memori proses di antara panggilan, tempat sebuah bug bisa menyerahkannya ke pemanggil berikutnya.
Server hosted kami di https://mcp.doc.cheap/mcp sudah dibangun seperti itu sebelum revisi ini. Kodenya menyebut server ini "stateless on purpose": setiap POST mendapat server baru dan transport baru, menjawab, lalu dibuang, sehingga "no session lives in memory, a restart loses nothing, and one caller's key can never be seen by another caller's request". Transport dibuat tanpa generator session id, yang di SDK TypeScript membuatnya stateless, dan menjawab dengan JSON biasa, bukan stream.
Pola handle yang dijelaskan revisi ini juga sudah ada. Ketika agen ingin mengambil kembali hasil yang tersimpan, ia tidak bergantung pada sesi untuk mengingatnya. scan_document mengembalikan scan id, dan tool get_scan serta delete_scan menerima id itu sebagai argumen biasa scan_id. Id itulah handle-nya. Instance server mana pun bisa menjawabnya, begitu pula klien yang tersambung ulang besok.
Jika server Anda menyimpan sesuatu per sesi, pertanyaannya sama: bisakah itu menjadi id yang dikembalikan server dan dikirim balik oleh klien? Untuk pekerjaan dokumen, jawabannya biasanya ya, dan biasanya juga menambah privasi.
Tanpa handshake: versi ikut di setiap request
Poin kedua membuat MCP stateless di tingkat protokol. Pertukaran initialize dan notifications/initialized dihapus, dan "every request now carries its protocol version and client capabilities in _meta". Di HTTP, versi juga dikirim lewat header. Halaman Streamable HTTP menyatakan setiap POST "MUST include an MCP-Protocol-Version header", dan nilainya harus sama dengan yang ada di _meta; jika tidak, server menjawab 400 dengan error HeaderMismatch.
Beginilah bentuk baru panggilan ke tool dokumen. Header dan kunci _meta mengikuti contoh dari spesifikasi itu sendiri; tool dan argumennya milik kami, dengan placeholder:
POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: scan_document
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "scan_document",
"arguments": { "image_base64": "<base64 image>", "retain_hours": 0 },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": { "name": "<client>", "version": "<version>" },
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
Bagi server, ini berarti tiga pemeriksaan di setiap request, menggantikan satu handshake:
- Versi. Jika server tidak mendukung versi yang diminta, ia menjawab 400 dengan
UnsupportedProtocolVersionErroryang mencantumkan versi yang didukungnya. - Header terhadap body.
Mcp-Methodwajib di setiap request, danMcp-Nameditools/call,resources/read, danprompts/get. Keduanya mencerminkan method dan nama tool, dan ketidakcocokan adalah errorHeaderMismatch. - Capability. Apa pun yang dulu diingat server dari
initializekini dibaca dari request yang sedang diproses.
Header ini lebih penting daripada kelihatannya bagi server dokumen. Panggilan scan_document membawa seluruh gambar dalam base64; server hosted kami menerima body request hingga 36 MiB. Dengan Mcp-Method dan Mcp-Name di header, sebuah gateway bisa merutekan, menghitung, atau membatasi laju tool yang mahal secara terpisah dari yang murah tanpa membaca body itu. Spesifikasi menambahkan satu peringatan untuk gateway semacam itu: mereka "SHOULD verify" bahwa header versi menyebut versi yang mewajibkan validasi header dan body, dan menolak request jika tidak, alih-alih memercayai header yang tidak pernah diperiksa siapa pun.
server/discover wajib
Poin ketiga menambahkan server/discover, dan "servers MUST implement this RPC to advertise their supported protocol versions, capabilities, and identity". Klien bisa memanggilnya lebih dulu untuk memilih versi, atau memakainya sebagai uji kompatibilitas di stdio.
Inilah satu-satunya perubahan yang tidak bisa dilewati server stateless. Server kami masih menyediakan dokumen discovery kecil di GET / (nama, versi, transport, dan endpoint), tetapi itu halaman web biasa, bukan method protokol. Server yang ingin berbicara 2026-07-28 harus menjawab server/discover sendiri.
Hasil: resultType, caching, dan urutan
Tiga poin yang lebih kecil mengubah bentuk sebuah hasil.
resultType. Setiap hasil kini membawanya:"complete"untuk jawaban biasa,"input_required"untuk jawaban sementara dari request multi round-trip. Klien "MUST treat results from earlier-protocol servers that omit the field as"complete"", jadi server lama tetap berfungsi, tetapi server baru mengirimkannya.ttlMsdancacheScope. Hasil daritools/list,prompts/list,resources/list,resources/read, danresources/templates/listharus membawa petunjuk kesegaran dalam milidetik dan cakupan,"public"atau"private". Untuk server yang daftar tool-nya hanya berubah saat deploy dan resource-nya berupa dokumentasi bawaan,ttlMsyang panjang dengan"public"adalah pilihan yang wajar. Resource yang bergantung pada key pemanggil akan bernilai"private".- Urutan tool yang deterministik. Server "SHOULD return tools from
tools/listin a deterministic order", untuk membantu caching di klien dan cache hit pada prompt. Jika tool didaftarkan di kode dalam urutan tetap, pertahankan; server kami mendaftarkan enam tool dalam urutan yang sama setiap kali.
Meminta input tambahan dari pengguna: request multi round-trip
Revisi sebelumnya membolehkan server mengirim request-nya sendiri ke klien di tengah sebuah panggilan: elicitation/create untuk bertanya kepada pengguna, sampling/createMessage untuk meminjam model milik klien, roots/list untuk mengetahui folder yang diizinkan. Revisi ini menggantinya dengan pola Multi Round-Trip Requests. Server menjawab dengan resultType: "input_required" dan daftar inputRequests, lalu klien mengulang request awal dengan inputResponses.
Bagi tool dokumen, inilah tempat yang rapi untuk pertanyaan seperti "fotonya terpotong di sisi kiri, kirim foto lain?". Karena pengulangan itu adalah request yang sama lagi, tidak ada yang perlu disimpan di server di antara kedua panggilan. Server yang tidak memakai satu pun request yang dimulai server, seperti server kami, tidak punya apa pun untuk dimigrasikan di sini.
Apa yang deprecated, dan apa penggantinya
Roots, Sampling, dan Logging kini deprecated. Ketiganya tetap berfungsi selama masa deprecation minimal dua belas bulan, tetapi "new implementations should not add support for them". Pengganti yang disarankan cocok untuk server dokumen:
- Sebagai ganti Roots, kirim file sebagai argumen tool atau konfigurasi. Server lokal kami hanya membaca path file jika direktori gambar diatur di konfigurasinya, dan hanya di dalam direktori itu; path di luarnya ditolak. Model memilih argumennya; operator menentukan pagarnya.
- Sebagai ganti Logging, tulis log ke stderr atau OpenTelemetry. Revisi ini juga menghapus
logging/setLevel; level log kini dikirim per request di_meta, dan server tidak boleh mengirim pesan log untuk request yang tidak memintanya. Konteks trace (traceparent) juga bisa ikut di_meta.
Klien lama akan tetap memanggil
Tidak semua klien berpindah pada hari yang sama, jadi halaman transport menjelaskan apa yang harus dilakukan server yang hanya mendukung 2026-07-28 terhadap trafik lama:
- GET atau DELETE ke endpoint MCP: 405 Method Not Allowed.
- Header
Mcp-Session-Id: abaikan, dan jangan pernah membuat atau mengembalikannya. - Header
Last-Event-ID: abaikan, karena stream tidak lagi bisa dilanjutkan.
Server hosted kami sudah menjawab GET dan DELETE di endpoint-nya dengan 405 dan header Allow: POST, OPTIONS, serta tidak membuat session id. Klien yang masih memakai revisi lama mengetahuinya dari body error: spesifikasi memintanya kembali ke initialize hanya jika body 400 bukan error modern yang dikenali.
Posisi server kami
Agar tepat: server hosted dibangun di atas versi 1.30.0 SDK TypeScript, dan kode kami sendiri belum menyebut 2026-07-28 di mana pun. Bagian di atas yang sudah berlaku untuknya adalah yang berasal dari desainnya: tanpa sesi, id sebagai handle, 405 untuk GET dan DELETE, file dibatasi oleh konfigurasi. server/discover, pemeriksaan header, resultType, dan field cache adalah pekerjaan yang tersisa. Halaman server MCP OCR paspor dan panduan server MCP menjelaskan apa yang dihubungkan klien saat ini.
Jika Anda sedang memilih API dokumen untuk agen, perbandingan API OCR paspor mencantumkan layanan-layanannya; sisi MCP layak ditanyakan ke masing-masing secara terpisah.
Checklist untuk server tool Anda sendiri
- Tidak ada state yang hidup di antara request; apa pun yang dibutuhkan panggilan berikutnya adalah id yang dikembalikan server.
- Versi setiap request diperiksa terhadap header
MCP-Protocol-Version, denganUnsupportedProtocolVersionErroruntuk versi yang tidak Anda dukung. Mcp-MethoddanMcp-Namediperiksa terhadap body.server/discovermenjawab dengan versi, capability, dan identitas.- Hasil membawa
resultType; hasil list dan read membawattlMsdancacheScope. tools/listselalu mengembalikan urutan yang sama.- GET dan DELETE mendapat 405; header sesi dan event id diabaikan.
- File masuk sebagai argumen di dalam pagar yang dikonfigurasi, bukan lewat Roots.
- Log dikirim ke stderr atau OpenTelemetry, bukan ke klien.
Teks lengkapnya ada di modelcontextprotocol.io, dan tulisan rilisnya memberi latar belakang. Informasi lebih lanjut tentang server kami ada di halaman server MCP OCR paspor.
Pertanyaan untuk Anda: apakah server MCP Anda menyimpan sesuatu di sesi yang kini harus diubah menjadi handle? Ceritakan di kolom komentar di bawah.