Di halaman ini
Pada 8 Juni 2026, Anthropic memberi pemilik konektor di direktori Claude sebuah dasbor. Dasbor itu menampilkan pengguna aktif, total panggilan tool, dan peringkat di direktori. Dasbor itu juga menampilkan “skor kesehatan, tingkat error, dan latensi dalam sekali lihat, dengan rincian error per tool untuk menemukan dengan tepat apa yang gagal”.
Setahun sebelumnya, Alex Volkov dari Weights & Biases telah menggambarkan masalah yang sama dari sisi yang berlawanan. Begitu agennya memanggil tool melalui MCP, “semua observability yang biasa saya dapatkan saat kode saya sendiri berjalan dari awal sampai akhir menjadi sedikit gelap”. Rekan pembicaranya, Benjamin Eckel dari Dylibso, menunjukkan alasannya. Server MCP jarak jauh “muncul bagi kami di trace sebagai satu span layanan” karena ia berjalan di luar kendali pemanggil.
Kedua sudut pandang itu berada di luar server. Klien melihat satu span yang tidak tembus pandang. Direktori melihat total. Tidak satu pun melihat apa yang diminta dari server, apa yang ditolaknya, dan apa yang disentuhnya. Hanya server yang melihatnya, jadi hanya server yang bisa mencatatnya.
Inilah yang dicatat oleh server MCP Tajo, dibaca dari kode yang menjalankannya dan dijelaskan di dokumentasi. Apa itu server MCP membahas protokolnya. Artikel ini membahas barisnya.
Satu baris per panggilan
Dasbor adalah sudut pandang syahbandar: kapal masuk, kapal keluar, mana yang terlambat. Log request adalah buku log milik kapal itu sendiri, ditulis di atas kapal pada saat kejadian.
Setiap tools/call di server workspace Tajo dan di setiap server konektor berakhir menjadi satu baris. Baris itu ditulis setelah respons dibuat, apa pun isi responsnya. Panggilan yang ditolak karena key tidak boleh menulis, atau karena endpoint-nya hanya-baca, mendapat baris seperti panggilan lain. Begitu pula panggilan ke tool yang tidak ada.
Berikut isi baris itu, dan apa yang ditolak untuk disimpannya.
| Field | Disimpan | Tidak disimpan |
|---|---|---|
| Siapa | Id API key yang memanggil. Token dari login OAuth juga dihitung sebagai key. | Rahasia key atau prefiksnya. |
| Di mana | Server workspace atau server konektor, beserta konektor dan profilnya. | |
| Tool | Namanya, jika server memiliki tool dengan nama itu. | Nama lain apa pun yang dikirim klien: disimpan sebagai (unknown). |
| Efek | read, write, send, atau destructive: efek terberat yang mungkin ditimbulkan panggilan itu. | |
| Hasil | ok, atau kode error snake_case singkat seperti unknown_tool. | Teks penjelasan error: apa pun yang bukan kode disimpan sebagai tool_error. |
| Durasi dan ukuran | Milidetik sejak diterima hingga respons, dan byte yang diterima pemanggil. | |
| Trace id | Id permintaan, dari header x-request-id, x-trace-id, atau W3C traceparent, atau id baru jika tidak ada. | Nilai header yang bukan hex atau UUID. |
| Record | Hingga 20 id record yang disebut atau dihasilkan panggilan: kontak, pesan, persetujuan. | Record itu sendiri. |
| Body | Argumen dan jawaban, dibersihkan, masing-masing paling banyak 4 KB. | Rahasia, teks bebas, dan data pribadi yang tercantum di bawah. |
Tiga dari penolakan itu menyangkut klien, bukan data. Nama tool, kode error, dan trace id semuanya datang dari luar. Masing-masing hanya disimpan dalam bentuk yang bisa dijamin oleh server. Log yang menyimpan apa pun yang dikirim pemanggil bisa diisi dengan apa saja, termasuk alamat email pelanggan di kolom nama tool.
Pertanyaan terbuka Benjamin Eckel di akhir presentasinya adalah bagaimana sebuah kolektor tahu “bahwa itu adalah panggilan tool MCP yang mengalami error”. Di satu server, jawabannya adalah sebuah kolom. ok bernilai false, dan kodenya menyebutkan error yang mana.
Argumen: aturan yang kami balik
Keberatannya wajar, dan itu keberatan kami sendiri. Catat argumennya dan Anda telah membuat salinan kedua data pelanggan Anda, di luar jangkauan setiap permintaan penghapusan. Hingga 18 Oktober 2026, itulah aturan kami sendiri. Log tidak menyimpan argumen maupun body hasil, karena keduanya bisa memuat data pribadi.
Itu kompromi yang salah. Log request yang tidak bisa menunjukkan apa yang dikirim dan apa yang kembali tidak bisa menjawab satu-satunya pertanyaan yang menjadi alasan keberadaannya: mengapa panggilan agen saya gagal?
Jadi body disimpan, dan alasan dulu body tidak disimpan dipenuhi dengan cara lain. Setiap body melewati satu proses deterministik sebelum masuk antrean.
- Tidak ada rahasia yang lolos. Field yang namanya menyebut token, password, secret, signature, cookie, session, atau sekitar dua puluh kata serupa hanya menyimpan
[secret]. Begitu juga nilai yang berbentuk kredensial yang dikenal, di mana pun ia muncul. Itu mencakup bearer token, JWT, private key, URL yang memuat password, dan setiap rangkaian buram berisi 40 karakter key atau lebih. - Teks prosa tidak disimpan sama sekali. Field bernama
html,text,body,markdown, ataucontenthanya menyimpan[redacted]. Prosa memuat nama dan alamat jalan yang tidak bisa ditemukan oleh pola apa pun. - Data pribadi disamarkan secara permanen. Field yang namanya menandakan data pribadi, seperti email, telepon, nama, alamat, atau catatan, hanya menyimpan
[redacted]. Alamat email, nomor telepon, kartu, atau IBAN di dalam string lain mana pun disamarkan. - Body tetap kecil. String dipotong pada 512 karakter, list pada 20 item, objek pada 50 key, dan nesting pada 6 tingkat. Seluruh body dipotong pada 4 KB dan ditandai terpotong.
Dua jenis panggilan menyimpan lebih sedikit lagi. Kontak yang dibawa chat seseorang dari aplikasi lain dicatat sebagai penanda dan jumlah, tidak pernah sebagai body. Panggilan yang membaca log tidak menyimpan jawaban, karena jawabannya hanyalah baris log lain.
Sekarang biayanya. Penyamaran ini permanen, bukan enkripsi dengan key yang dipegang seseorang. Log tidak bisa menunjukkan alamat email yang terpental. Log menunjukkan id kontak, dan kontak itu, dengan aturannya sendiri, hanya berjarak satu panggilan. Log berada di luar proses penghapusan data workspace, itulah sebabnya penyamaran tidak bisa menunggu proses itu.
Mengapa log ini bukan jejak audit
Tajo sudah memiliki log audit append-only. Setiap baris membawa hash dari baris sebelumnya, sehingga suntingan di mana pun memutus rantainya. Mengapa tidak menulis panggilan tool di sana?
Karena rantai itu ada harganya. Setiap penambahan mengambil lock per workspace dan membaca baris sebelumnya untuk memperpanjang rantai. Menulis setiap pembacaan ke sana akan membuat panggilan sebuah workspace mengantre di belakang satu lock. Itu juga akan mengubur perubahan status, yang justru ingin ditunjukkan oleh log audit, di bawah ribuan pembacaan.
Jadi kedua catatan itu dibagi menurut pertanyaannya. Log request mengatakan apa yang diminta agen dan apa yang terjadi, selama 30 hari. Log audit mengatakan apa yang berubah, siapa yang mengizinkannya, dan apakah ada yang menyunting catatan itu sejak saat itu.
Persetujuan berada di sisi audit. Di profil konektor Tajo, tool propose menyiapkan aksi yang dideklarasikan dan tool apply menjalankannya setelah disetujui. Tidak ada yang sampai ke provider sampai proposal disetujui, oleh seseorang atau oleh aturan yang diaktifkan workspace. Baris panggilan propose mencantumkan persetujuan yang dibuatnya di antara record-nya. Persetujuan itu sendiri terikat pada digest SHA-256 dari input yang persis. Persetujuan berlaku untuk input persis yang Anda lihat: ubah satu field dan persetujuan itu tidak lagi cocok. Saat penulisan terjadi, baris auditnya menyimpan digest input dan digest respons provider, tidak pernah nilai-nilai respons itu.
Biaya satu baris
Satu baris adalah satu penulisan ke database, dan penulisan memerlukan commit. Hingga 8 Oktober 2026, setiap panggilan menunggu commit-nya sendiri sebelum respons, sekitar 2,6 ms di host kami. Bagi satu klien, itu seperempat dari waktu sebuah panggilan tool kecil.
Kini baris dibuat saat panggilan selesai lalu dimasukkan ke antrean. Proses flush menulis antrean paling lambat 100 ms kemudian, satu transaksi per workspace, sehingga banyak panggilan berbagi satu commit. Tidak ada yang berubah pada baris, termasuk timestamp-nya. Jika 5.000 baris sedang menunggu, panggilan berikutnya menunggu flush alih-alih membuang satu baris.
Pencatatan tidak pernah menggagalkan panggilan. Penulisan yang gagal dicoba ulang baris demi baris, lalu dicatat dan dibuang. Yang hilang saat proses dihentikan paksa adalah apa pun yang masih ada di antrean: paling banyak panggilan dalam 100 ms terakhir.
Membacanya kembali
logs.list mengembalikan panggilan workspace, yang terbaru lebih dulu, tanpa body. Ia memfilter berdasarkan waktu, hasil atau status HTTP, sumber (MCP atau REST API, yang memakai tabel yang sama), dan API key. Secara default ia menampilkan 50 per halaman, hingga 100. logs.get mengembalikan satu panggilan beserta nama key saat ini, statusnya, durasinya, request dan respons yang sudah dibersihkan, serta record yang disentuhnya.
Keduanya hanya membaca workspace milik pemanggil. Id baris dari workspace lain tidak akan ditemukan.
Error tool membawa id permintaan. Jika server yang membuat id itu, atau id itu datang sebagai hex atau UUID, maka itulah trace id baris tersebut. Agen yang menerima error bisa memberikan kepada seseorang satu nilai yang menunjuk panggilan itu.
Apa yang sudah dibangun, dan apa yang belum
Sudah dibangun, saat artikel ini ditulis:
- Satu baris per
tools/calldi server workspace dan setiap server konektor, termasuk panggilan yang ditolak dan yang tidak dikenal. - Id key, server, konektor, profil, tool, efek, hasil, durasi, ukuran hasil, trace id, dan hingga 20 record yang disentuh.
- Argumen dan jawaban yang dibersihkan, masing-masing paling banyak 4 KB.
logs.listdanlogs.get, dibatasi pada workspace, dengan penyimpanan 30 hari.- Persetujuan yang terikat pada digest input, dan penulisan yang diterapkan dicatat dengan digest input dan output di log audit berantai hash.
Belum dibangun, dan perlu Anda ketahui sebelum mengandalkannya:
- Tidak ada skor kesehatan, tidak ada grafik per tool, dan tidak ada peringatan saat tingkat error naik. Ringkasan per tool berisi jumlah panggilan, error, dan durasi paling lambat tersedia untuk operator Tajo, bukan di tampilan mana pun yang bisa Anda buka.
logs.listtidak bisa memfilter berdasarkan nama tool atau trace id. Untuk menemukan baris di balik sebuah id permintaan, persempit berdasarkan waktu dan key.- Baris tidak diekspor ke sistem tracing yang Anda jalankan. Trace id hanya dibaca dari header HTTP, bukan dari field MCP
_metayang dipakai dalam presentasi itu untuk membawa konteks trace. - Setelah 30 hari, baris dihapus. Tidak ada arsip atau ekspor.
- Apa yang sudah disamarkan tidak bisa dipulihkan dari log.
- Penghentian paksa bisa menghilangkan baris dari 100 ms terakhir.
Presentasi itu ditutup dengan pernyataan bahwa observability di MCP “tidak terdistribusi secara merata”. Dasbor di hilir tidak bisa memperbaikinya, begitu juga trace yang berhenti di pintu server. Sync yang gagal memerlukan catatannya sendiri; begitu pula setiap panggilan yang meminta sesuatu.
Server melihat panggilan itu. Tidak ada yang lain. Catatlah di sana.
Pertanyaan yang sering diajukan
Apa yang harus dicatat server MCP untuk setiap panggilan tool?
Satu baris per panggilan, ditulis oleh server: API key mana yang memanggil, server dan konektor mana, nama tool jika tool itu ada, kelas efeknya, ok atau kode error singkat, durasi, ukuran hasil, trace id permintaan, id record yang disebut atau dihasilkan panggilan itu, serta argumen dan jawaban yang sudah dibersihkan dari rahasia dan data pribadi. Server MCP Tajo menulis baris itu untuk setiap tools/call, termasuk panggilan yang ditolak, dan menyimpannya selama 30 hari.
Haruskah log request MCP menyimpan argumen tool?
Ya, setelah dibersihkan. Log tanpa argumen tidak bisa menjelaskan mengapa sebuah panggilan gagal. Tajo tidak menyimpan body sama sekali hingga 18 Oktober 2026 dan kini menyimpan keduanya, setelah satu proses deterministik: rahasia menjadi [secret], teks bebas dan field pribadi menjadi [redacted], email, nomor telepon, kartu, dan IBAN disamarkan, dan setiap body dipotong pada 4 KB. Penyamaran ini permanen, sehingga log menunjuk ke record melalui id alih-alih menyalinnya.
Mengapa log panggilan tool MCP dipisahkan dari log audit?
Karena keduanya menjawab pertanyaan yang berbeda dengan biaya yang berbeda. Log audit Tajo adalah rantai hash dari perubahan status, dan setiap penambahan mengambil lock per workspace untuk memperpanjang rantainya. Menulis setiap pembacaan ke sana akan membuat panggilan sebuah workspace mengantre di belakang lock itu dan mengubur perubahan di antara pembacaan. Panggilan tool masuk ke tabel terpisah tanpa rantai yang disimpan selama 30 hari; penulisan yang disiapkan sebuah panggilan tetap meninggalkan baris audit sendiri.