Belajar MCP - Multi-Round-Trip Requests (MRTR)
Episode 8 of 23

Belajar MCP - Multi-Round-Trip Requests (MRTR)

Episode ini membedah fitur headline spesifikasi 2026-07-28: Multi-Round-Trip Requests. Pelajari peran messageId dan routingId untuk interaksi mid-call seperti konfirmasi user dan authorization step-up, lengkap dengan best practice mendesain flow interaktif.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Pendahuluan

Episode 7 menutup lingkaran dasar: client di TypeScript dan Python sudah bisa menghubungi server buatan episode 6, plus MCP Inspector untuk menguji semuanya. Sekarang kita masuk ke fitur yang menjadi salah satu headline spesifikasi 2026-07-28: Multi-Round-Trip Requests (MRTR). Fitur ini mengubah cara server dan client berinteraksi di tengah satu pemanggilan tool.

Roadmap episode ini: pahami masalah yang coba diselesaikan MRTR, bedah anatomi request-nya (messageId dan routingId), ikuti pola dua langkah minta-konfirmasi sampai lanjutkan eksekusi, lihat implementasinya di sisi server, lalu tutup dengan best practice mendesain flow interaktif.

Masalah di Balik MRTR

Sebelum 2026-07-28, skenario "server butuh konfirmasi user di tengah eksekusi" sangat merepotkan. Salah satu caranya adalah menahan koneksi SSE tetap terbuka berjam-jam sampai user merespons — mahal untuk resource, rapuh terhadap timeout dan proxy, dan menyulitkan multi-hop routing. Belum lagi alur step-up authorization yang butuh beberapa pertukaran pesan secara sekuensial.

MRTR menjawabnya dengan satu ide sederhana: setiap request sekarang bisa membawa identitas yang sama di beberapa putaran. Dengan begitu, satu pemanggilan tool yang "masih berjalan" bisa dilanjutkan lewat request berikutnya — tanpa menahan koneksi streaming apa pun.

Info

MRTR tidak menghidupkan kembali sesi stateful. Core tetap stateless; yang berubah adalah identitas yang memungkinkan request-request terpisah di-route menuju satu pekerjaan yang sedang berlangsung.

Anatomi MRTR: messageId dan routingId

Dua nilai kunci membedakan request dalam alur MRTR:

  • messageId — pengenal unik untuk satu pemanggilan logis. Request awal dan semua lanjutan (follow-up) yang berhubungan memakai nilai yang sama.
  • routingId — identitas routing yang dipakai infrastruktur untuk mengarahkan follow-up ke instance yang sedang menangani request. Saat lewat HTTP, ia dikirim sebagai header Mcp-Routing-Id.

Request awal membawa messageId dan method yang dijalankan:

request-awal.json
{
  "jsonrpc": "2.0",
  "id": 3,
  "messageId": "transfer-1",
  "method": "tools/call",
  "params": {
    "name": "transfer-funds",
    "arguments": {
      "to": "123-456-789",
      "amount": 500000
    }
  }
}

Server menjawab bahwa pekerjaan belum selesai dan menunggu konfirmasi:

respons-pending.json
{
  "jsonrpc": "2.0",
  "id": 3,
  "messageId": "transfer-1",
  "result": {
    "pending": true,
    "requested": "confirmation",
    "permission": "transfer-funds.approve"
  }
}

Kemudian client mengirim balasan dengan messageId yang sama:

balasan-klien.json
{
  "jsonrpc": "2.0",
  "id": 7,
  "messageId": "transfer-1",
  "method": "confirm",
  "params": {
    "approved": true
  }
}

Dengan messageId yang konsisten, server (atau load balancer di depannya) tahu persis lanjutan ini milik pekerjaan transfer-1. Tidak ada koneksi yang dipegang selama menunggu — semuanya request/response biasa.

Alur Dua Langkah: Minta Konfirmasi, Lalu Lanjutkan

Pola paling umum MRTR adalah konfirmasi dua langkah:

  1. Server meminta — client memanggil tools/call; server membalas status pending plus jenis izin yang diminta, misalnya konfirmasi transfer atau approval scope baru.
  2. Client menanggapi — aplikasi host menampilkan dialog ke user; setelah user memutuskan, client mengirim follow-up dengan messageId yang sama.
  3. Server menyelesaikan — server meneruskan eksekusi sesuai jawaban, lalu mengembalikan hasil akhir (atau error bila ditolak).

Flow yang sama berlaku untuk authorization step-up: request awal ternyata butuh scope yang lebih tinggi, server membalas permintaan otorisasi tambahan, client menjalankan alur OAuth (episode 10), lalu mengirim kembali hasilnya dengan messageId yang sama.

Implementasi di Server SDK

Secara konseptual, di sisi server kalian menggantung eksekusi tool pada promise yang diselesaikan oleh follow-up:

mrtp-server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 
const pending = new Map();
 
server.registerTool(
  "transfer-funds",
  {
    description: "Transfer antar rekening",
    inputSchema: {
      type: "object",
      properties: {
        to: { type: "string" },
        amount: { type: "number" },
      },
      required: ["to", "amount"],
    },
  },
  async ({ to, amount }, context) => {
    const messageId = context.request.messageId;
    const approved = await waitForConfirmation(messageId, { to, amount });
    if (!approved) {
      return { content: [{ type: "text", text: "Transfer dibatalkan" }] };
    }
    return { content: [{ type: "text", text: "Transfer berhasil" }] };
  }
);

Di balik layar, waitForConfirmation(messageId, ...) mencatat promise di Map, dan handler untuk method confirm akan me-resolve promise itu dengan messageId yang cocok. Detail API tepatnya bergantung versi SDK, tapi polanya selalu sama: simpan state in-flight per messageId, selesaikan saat follow-up tiba.

Best Practice Desain Flow Interaktif

Merancang flow interaktif butuh kedisiplinan supaya tidak menjadi panggung bug:

  • Selalu ada timeout. Konfirmasi user bisa tidak pernah datang; definisikan batas waktu dan batalkan pekerjaan yang menggantung.
  • Idempoten. Client bisa mengulang follow-up karena jaringan; pastikan balasan kedua tidak mengeksekusi dua kali.
  • Batasi jumlah putaran. Semakin banyak round-trip, semakin besar risiko deadlock; rancang state machine yang eksplisit.
  • Kembalikan konteks yang jelas. Pesan pending harus menyebut izin apa yang diminta supaya host bisa menampilkan dialog yang informatif.
  • Jangan abuse MRTR untuk komputasi ringan. Kalau hasil bisa dihitung dalam satu request, lakukan dalam satu request.

Penutup

MRTR adalah pembeda besar spesifikasi 2026-07-28: interaksi mid-call — konfirmasi user, step-up authorization, pengumpulan data tambahan — kini bisa dilakukan dengan request/response biasa yang membawa messageId dan routingId, tanpa menahan SSE. Kalian sudah memahami anatominya, pola dua langkahnya, dan bagaimana menempatkannya di server SDK.

Inti yang harus dibawa pulang:

  • messageId menyatukan satu pemanggilan logis lintas beberapa request.
  • routingId mengarahkan follow-up ke instance yang benar, bahkan di belakang load balancer.
  • Core tetap stateless — MRTR bukan kembali ke sesi stateful.
  • Time out dan idempotensi wajib untuk flow konfirmasi yang andal.
  • Gunakan hanya saat perlu — satu round-trip selalu lebih baik daripada lima.

Di episode 9 berikutnya kita bawa server keluar dari lokal: deployment server MCP sebagai service HTTP dengan Express, Fastify, dan Next.js, kontainerisasi dengan Docker, discovery lewat .well-known, dan eksploitasi sifat stateless untuk scaling horizontal. Sampai jumpa!

Belajar MCP - Multi-Round-Trip Requests (MRTR) | Belajar MCP