[{"data":1,"prerenderedAt":357},["ShallowReactive",2],{"tag-labels":3,"site-header":4,"article-mcp-dibongkar-ulang-kabar-baik-buat-kamu-id":72},{},{"featuredPost":5,"navigations":29},{"id":6,"title":7,"title_en":8,"slug":9,"excerpt":10,"excerpt_en":11,"has_translation":12,"published_at":13,"reading_time":14,"hidden_from_listing":15,"tags":16,"thumbnail_image":21,"og_image":22,"series":23,"authors":28},110,"Ketika Pilih Framework Cuma Biar Kelihatan Beda","When You Pick a Framework Just to Look Different","ketika-pilih-framework-cuma-biar-kelihatan-beda","Terakhir kali kamu milih framework atau library baru, itu karena masalahmu butuh alat itu, atau karena alatnya kedengaran keren dan belum banyak yang pakai? Pertanyaan ini nggak enak dijawab. Soalnya keputusan teknologi sering diambil dengan alasan yang nggak pernah ditulis di dokumen teknis mana pun.","The last time you chose a new framework or library, was it because your problem needed that tool, or because it sounded cool and few people around you were using it? That question is uncomfortable. Technology decisions are often made for reasons that never appear in any technical document.",true,"2026-10-06T15:25:21.000Z",5,false,[17,18,19,20],"karier","framework","opini","pengalaman",null,"\u002Fog\u002Fketika-pilih-framework-cuma-biar-kelihatan-beda.png",{"id":24,"title":25,"title_en":26,"slug":27},9,"Artikel","Articles","all",[],[30,46,67],{"collection":31,"item":32},"series",{"__typename":31,"title":25,"title_en":26,"slug":27,"children_series":33},[34,38,42],{"title":35,"title_en":36,"slug":37},"Kecerdasan Artifisial","Artificial Intelligence","kecerdasan-artifisial",{"title":39,"title_en":40,"slug":41},"Konsep Dasar Pemrograman","Programming Fundamentals","konsep-dasar-pemrograman",{"title":43,"title_en":44,"slug":45},"Algoritma dan Struktur Data","Algorithms and Data Structures","algoritma-struktur-data",{"collection":31,"item":47},{"__typename":31,"title":48,"title_en":48,"slug":49,"children_series":50},"Tutorial","tutorial",[51,55,59,63],{"title":52,"title_en":53,"slug":54},"Belajar Python","Learning Python","belajar-python",{"title":56,"title_en":57,"slug":58},"Belajar Golang","Learning Go","belajar-golang",{"title":60,"title_en":61,"slug":62},"Belajar Java","Learning Java","belajar-java",{"title":64,"title_en":65,"slug":66},"Belajar Pascal","Learning Pascal","belajar-pascal",{"collection":31,"item":68},{"__typename":31,"title":69,"title_en":69,"slug":70,"children_series":71},"Lab","lab",[],{"article":73,"renderedBody":263,"renderedTakeaway":264,"latestArticles":265,"toc":332},{"id":74,"title":75,"title_en":76,"slug":77,"excerpt":78,"excerpt_en":79,"has_translation":12,"published_at":80,"reading_time":81,"hidden_from_listing":15,"tags":82,"thumbnail_image":21,"og_image":89,"series":90,"authors":257,"body_locale":258,"available_locales":259,"body":261,"takeway":262,"prerequisite":21},125,"MCP dibongkar ulang: kabar baik buat kamu yang capek nulis konektor","MCP, Rebuilt: Good News If You're Tired of Writing Connectors","mcp-dibongkar-ulang-kabar-baik-buat-kamu","Kamu punya beberapa API internal dan satu agent AI, tapi kodenya harus ditulis ulang tiap kali modelnya diganti. MCP datang buat mengakhiri itu, dan tahun ini protokolnya dibongkar ulang supaya server-nya bisa jalan seperti web server biasa. Yuk lihat apa yang berubah. 🔧","You have a few internal APIs and one AI agent, but the code has to be rewritten every time the model changes. MCP ends that, and this year the protocol was rebuilt so servers can run like ordinary web servers. Here's what changed. 🔧","2026-10-16T05:00:00.000Z",8,[83,84,85,86,87,88],"mcp","model-context-protocol","ai-agent","llm","backend","python","\u002Fog\u002Fmcp-dibongkar-ulang-kabar-baik-buat-kamu.png",{"id":81,"title":35,"title_en":36,"slug":37,"description":21,"description_en":91,"articles":92,"children_series":249,"parent_series":250},"Notes on AI that go past the demo: how the models work, where they break, and what changes once you put them in production.",[93,110,127,142,156,170,173,190,211,230],{"id":94,"title":95,"title_en":96,"slug":97,"excerpt":98,"excerpt_en":99,"has_translation":12,"published_at":100,"reading_time":101,"hidden_from_listing":15,"tags":102,"thumbnail_image":21,"og_image":107,"series":108,"authors":109},1,"Kenapa AI Suka 'Halu'? Kenalan sama JEPA, Otak AI yang Punya Akal Sehat","Why Does AI Keep Hallucinating? Meet JEPA, the AI Brain With Common Sense","kenapa-ai-suka-halu-kenalan-sama-jepa-otak-ai-yang-punya-akal-sehat","AI generatif sering 'halu' karena cuma jago nebak pola kata. JEPA coba ngerombak itu dengan ngajarin AI cara kerja dunia nyata kayak otak manusia.","Generative AI hallucinates because all it does is guess word patterns. JEPA tries to change that by teaching machines how the real world works, the way a human brain does.","2026-06-02T08:09:05.595Z",4,[103,104,105,106],"jepa","artificial-intelligence","yann-lecun","agi","\u002Fog\u002Fkenapa-ai-suka-halu-kenalan-sama-jepa-otak-ai-yang-punya-akal-sehat.png",{"id":81,"title":35,"title_en":36,"slug":37},[],{"id":111,"title":112,"title_en":113,"slug":114,"excerpt":115,"excerpt_en":116,"has_translation":12,"published_at":117,"reading_time":101,"hidden_from_listing":15,"tags":118,"thumbnail_image":21,"og_image":119,"series":120,"authors":121},2,"LLM Bakal Mentok, Terus Gimana Dong?","LLMs Are Going to Hit a Wall. What Then?","llm-bakal-mentok-terus-gimana-dong","LLM kayak ChatGPT itu jago ngerangkai kata, tapi nggak beneran paham realitas. Yann LeCun bilang arsitektur ini bakal mentok dan butuh solusi baru.","LLMs like ChatGPT are great at stringing words together, but they never really grasp reality. Yann LeCun says this architecture will hit a wall and needs a new answer.","2026-06-03T08:55:33.003Z",[104,86,105,103],"\u002Fog\u002Fllm-bakal-mentok-terus-gimana-dong.png",{"id":81,"title":35,"title_en":36,"slug":37},[122],{"authors_id":123},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},"Daffa Izzuddin","izzudd","Writer",{"id":128,"title":129,"title_en":130,"slug":131,"excerpt":132,"excerpt_en":133,"has_translation":12,"published_at":134,"reading_time":101,"hidden_from_listing":15,"tags":135,"thumbnail_image":21,"og_image":137,"series":138,"authors":139},3,"Mengenal JEPA: Saat AI Mulai Belajar Punya \"Akal Sehat\"","Meet JEPA: Where AI Starts Learning Common Sense","kenapa-ai-suka-halu-dan-gimana-jepa-beresin-masalah-ini","AI sering 'halu' karena cuma nebak probabilitas data tanpa paham realita. Arsitektur JEPA mencoba mengubah itu dengan membangun model dunia di kepalanya.","AI hallucinates because it only guesses data probabilities without understanding reality. The JEPA architecture tries to change that by building a world model in its head.","2026-06-03T09:32:50.446Z",[104,103,136,105],"world-models","\u002Fog\u002Fkenapa-ai-suka-halu-dan-gimana-jepa-beresin-masalah-ini.png",{"id":81,"title":35,"title_en":36,"slug":37},[140],{"authors_id":141},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":101,"title":143,"title_en":144,"slug":145,"excerpt":146,"excerpt_en":147,"has_translation":12,"published_at":148,"reading_time":101,"hidden_from_listing":15,"tags":149,"thumbnail_image":21,"og_image":151,"series":152,"authors":153},"Bukan Sekadar Generative AI, JEPA Coba Kejar Pemahaman Konsep ala Manusia","Beyond Generative AI: JEPA Chases Human-Style Conceptual Understanding","kenapa-ai-masih-gagal-paham-fisika-dasar-mengenal-arsitektur-jepa","AI biasanya cuma jago nebak piksel, tapi JEPA coba belajar lewat konsep abstrak di ruang laten. Ternyata, cara ini bisa sampai dipakai buat baca gelombang otak.","AI usually only guesses pixels, while JEPA tries to learn from abstract concepts in latent space. That approach turns out to reach as far as reading brain waves.","2026-06-03T09:34:14.840Z",[103,105,150,106],"machine-learning","\u002Fog\u002Fkenapa-ai-masih-gagal-paham-fisika-dasar-mengenal-arsitektur-jepa.png",{"id":81,"title":35,"title_en":36,"slug":37},[154],{"authors_id":155},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":14,"title":157,"title_en":158,"slug":159,"excerpt":160,"excerpt_en":161,"has_translation":12,"published_at":162,"reading_time":101,"hidden_from_listing":15,"tags":163,"thumbnail_image":21,"og_image":165,"series":166,"authors":167},"Di Balik Dapur JEPA: Rahasia EMA, VICReg, dan Efisiensi Komputasi","Inside JEPA's Kitchen: The Secrets of EMA, VICReg, and Compute Efficiency","di-balik-dapur-jepa-rahasia-ema-vicreg-dan-efisiensi-komputasi","Bosen sama AI yang cuma jago nebak kata atau ngafalin pixel? Kenalan sama JEPA, arsitektur revolusioner yang ngajarin mesin punya \"akal sehat\" secara super efisien. Yuk intip jeroan teknisnya!","Bored of AI that only guesses words or memorizes pixels? Meet JEPA, an architecture that teaches machines common sense very cheaply. Here is a look at its technical insides.","2026-06-07T16:14:13.723Z",[103,164],"artificial-intelligent","\u002Fog\u002Fdi-balik-dapur-jepa-rahasia-ema-vicreg-dan-efisiensi-komputasi.png",{"id":81,"title":35,"title_en":36,"slug":37},[168],{"authors_id":169},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":74,"title":75,"title_en":76,"slug":77,"excerpt":78,"excerpt_en":79,"has_translation":12,"published_at":80,"reading_time":81,"hidden_from_listing":15,"tags":82,"thumbnail_image":21,"og_image":89,"series":171,"authors":172},{"id":81,"title":35,"title_en":36,"slug":37},[],{"id":174,"title":175,"title_en":176,"slug":177,"excerpt":178,"excerpt_en":179,"has_translation":12,"published_at":180,"reading_time":181,"hidden_from_listing":15,"tags":182,"thumbnail_image":21,"og_image":185,"series":186,"authors":187},126,"Memori AI Agent: dari Vector Store ke Temporal Graph","AI Agent Memory: From Vector Store to Temporal Graph","memori-ai-agent-vector-store-ke-temporal-graph","Dua fakta yang saling bertentangan bikin agent menjawab ngawur. Ini bedanya vector store dan temporal knowledge graph dalam menjaga state jangka panjang.","Two contradictory facts make an agent answer nonsense. Here is how a vector store and a temporal knowledge graph differ at keeping long-term state.","2026-10-18T13:13:29.458Z",7,[183,86,87,184],"ai","system-design","\u002Fog\u002Fmemori-ai-agent-vector-store-ke-temporal-graph.png",{"id":81,"title":35,"title_en":36,"slug":37},[188],{"authors_id":189},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":191,"title":192,"title_en":193,"slug":194,"excerpt":195,"excerpt_en":196,"has_translation":12,"published_at":197,"reading_time":198,"hidden_from_listing":15,"tags":199,"thumbnail_image":21,"og_image":206,"series":207,"authors":208},127,"Kenapa RAG yang cuma andalkan cosine similarity sering nyasar","Why RAG That Leans on Cosine Similarity Alone Keeps Missing","kenapa-rag-cuma-cosine-similarity-sering-nyasar","RAG yang cuma andalkan embedding balikin chunk yang mirip maknanya, bukan yang kamu butuh. Ini penyebabnya, dan dua lapis penambalnya.","RAG that leans only on embeddings returns chunks that look close in meaning, not the ones you need. Here is why, and the two layers that patch it.","2026-10-19T02:04:06.718Z",6,[200,201,202,203,204,205],"rag","vector-search","bm25","hybrid-search","retrieval","embedding","\u002Fog\u002Fkenapa-rag-cuma-cosine-similarity-sering-nyasar.png",{"id":81,"title":35,"title_en":36,"slug":37},[209],{"authors_id":210},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":212,"title":213,"title_en":214,"slug":215,"excerpt":216,"excerpt_en":217,"has_translation":12,"published_at":218,"reading_time":198,"hidden_from_listing":15,"tags":219,"thumbnail_image":21,"og_image":225,"series":226,"authors":227},128,"Linear atau graf: cara mengatur banyak agent tanpa loop abadi","Linear or Graph: How to Run Many Agents Without an Eternal Loop","multi-agen-linear-atau-grafik","Satu agent dengan dua puluh tool gampang kacau. Begitu beberapa agent saling revisi, kamu butuh graf yang mendukung cycle dan angka yang membuatnya berhenti.","One agent with twenty tools gets messy fast. Once several agents revise each other, you need a graph that allows cycles and a number that makes it stop.","2026-10-21T16:05:00.000Z",[220,221,222,223,224,86],"multi-agent","langgraph","autogen","orkestrasi","checkpoint","\u002Fog\u002Fmulti-agen-linear-atau-grafik.png",{"id":81,"title":35,"title_en":36,"slug":37},[228],{"authors_id":229},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":231,"title":232,"title_en":233,"slug":234,"excerpt":235,"excerpt_en":236,"has_translation":12,"published_at":237,"reading_time":14,"hidden_from_listing":15,"tags":238,"thumbnail_image":21,"og_image":244,"series":245,"authors":246},129,"Biar RAG nggak kena 504: pisahin jalur query dan ingestion","So Your RAG Stops Hitting 504: Split the Query Path From Ingestion","rag-pisah-jalur-query-dan-ingestion","Satu service RAG yang merangkap parsing dan menjawab kueri bakal tumbang pas ada yang upload PDF 200 halaman. Obatnya dua jalur dan satu queue.","One RAG service that both parses uploads and answers queries will fall over the moment someone uploads a 200-page PDF. The cure is two paths and one queue.","2026-10-22T01:30:00.000Z",[200,239,240,241,242,243],"cloud-run","cloud-tasks","gcp","serverless","arsitektur","\u002Fog\u002Frag-pisah-jalur-query-dan-ingestion.png",{"id":81,"title":35,"title_en":36,"slug":37},[247],{"authors_id":248},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},[],{"id":24,"title":25,"title_en":26,"slug":27,"parent_series":21,"children_series":251},[252,253,255],{"id":81,"title":35,"title_en":36,"slug":37,"cover_image":21},{"id":254,"title":39,"title_en":40,"slug":41,"cover_image":21},12,{"id":256,"title":43,"title_en":44,"slug":45,"cover_image":21},15,[],"id",[260,258],"en","Kamu punya beberapa endpoint internal: satu buat data artikel, satu buat pengguna, satu lagi buat laporan. Lalu ada satu agent AI yang harus bisa mengakses semuanya. Cara paling cepat adalah menulis konektor per pasangan, yaitu satu kode khusus untuk model A dan sumber data X, satu lagi untuk model A dan sumber Y. Awalnya terasa beres. Semua jalan, demo lancar, dan kamu merasa cukup produktif hari itu.\n\nMasalahnya baru kelihatan begitu modelnya diganti. Format *tool calling* beda, cara mendeskripsikan argumen beda, penanganan *error* pun beda. Setengah kode konektor tadi mendadak jadi sampah, dan kamu harus mengulang dari awal 😅. Kalau dihitung kasar, lima model dikali sepuluh sumber data berarti lima puluh implementasi yang harus dirawat. Angka itu cuma ilustrasi, tapi rasa sakitnya nyata bagi siapa pun yang pernah menjaga kode perekat.\n\n```mermaid\nflowchart LR\n  M1[Model A] --> K1[konektor khusus]\n  M2[Model B] --> K1\n  M3[Model C] --> K1\n  K1 --> S1[(PostgreSQL)]\n  K1 --> S2[(Git)]\n  K1 --> S3[(REST internal)]\n```\n\nNah, di titik inilah **Model Context Protocol** (MCP) masuk. Ide dasarnya sederhana: daripada setiap model bicara dengan setiap sumber lewat jalur khusus, semuanya bicara lewat satu protokol standar. Sumber data cukup ditulis sekali sebagai *server* — dan model apa pun yang paham protokolnya bisa memakainya.\n\n## Kenapa masalah remeh ini mahal?\n\nKode perekat itu jarang dianggap pekerjaan serius. Isinya cuma mengubah format, menyalin skema, dan menempelkan kredensial. Tapi justru bagian itu yang paling rapuh, karena setiap perubahan di salah satu ujung memaksa perubahan di ujung lain. Biayanya nggak kelihatan di *sprint planning*, tapi menumpuk diam-diam sampai satu hari kita sadar separuh waktu habis untuk menambal konektor.\n\nKalau kamu pernah memakai editor modern, kamu sudah merasakan solusi serupa di dunia lain. Spesifikasi MCP sendiri menyebut bahwa protokol ini mengambil inspirasi dari [Language Server Protocol](https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002F2026-07-28). Dulu setiap editor harus mengimplementasikan dukungan untuk setiap bahasa pemrograman. Setelah ada protokol bersama, satu *language server* bisa melayani banyak editor. MCP membawa pola yang sama ke dunia agent AI, jadi kamu menulis konektor sekali dan nggak perlu peduli siapa yang memakainya nanti.\n\n## Siapa yang ngobrol dengan siapa\n\nArsitekturnya punya tiga peran. **Host** adalah aplikasi yang kamu pakai langsung, misalnya aplikasi desktop atau ekstensi editor, dan di dalamnya model AI berjalan. *Client* adalah komponen di dalam host yang mengurus komunikasi. *Server* adalah program yang membuka kemampuan atau data, dan di sinilah kode yang kamu tulis nanti berada.\n\nSatu hal yang perlu diingat: satu *client* berpasangan dengan tepat satu *server*. Kalau host terhubung ke tiga *server*, berarti ada tiga *client* di dalamnya. Pembagian ini bukan kebetulan, karena dari sinilah batas keamanannya terbentuk. Menurut [prinsip arsitektur di spec](https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002F2026-07-28\u002Farchitecture), *server* nggak boleh bisa membaca seluruh percakapan dan nggak boleh bisa melihat ke dalam *server* lain. Riwayat percakapan tetap tinggal di host.\n\nKredensial juga ikut aman. Token *database* atau kunci API tetap berada di sisi *server*, jadi nggak pernah ikut masuk ke *prompt*. Model cuma tahu bahwa ada *tool* bernama sekian dengan argumen sekian, bukan password di belakangnya. Itu keputusan desain yang menenangkan, kan.\n\n## Tiga primitif, dan siapa yang pegang kendali\n\n```mermaid\nsequenceDiagram\n  autonumber\n  participant H as Host\n  participant S as MCP Server\n  Note over H,S: Sebelum 2026-07-28 (stateful)\n  H->>S: initialize\n  S-->>H: Mcp-Session-Id\n  H->>S: tools\u002Fcall + Mcp-Session-Id\n  Note over H,S: Sejak 2026-07-28 (stateless)\n  H->>S: tools\u002Fcall + _meta\n  S-->>H: hasil\n```\n\nServer bisa menawarkan tiga jenis hal, dan perbedaannya terletak pada siapa yang memutuskan kapan dipakai.\n\n- *Tools* dikendalikan model. Model memutuskan sendiri kapan memanggilnya, dan *tool* biasanya punya efek samping seperti menulis data atau mengirim sesuatu.\n- *Resources* dikendalikan aplikasi. Isinya data yang dibaca lewat URI, dan host yang menentukan apa yang masuk ke konteks.\n- *Prompts* dikendalikan user. Bentuknya template alur kerja yang dipilih manusia secara sadar.\n\nBuat kita yang terbiasa bikin web API, ada padanan yang gampang diingat. Resource itu seperti `GET` — cuma membaca dan nggak mengubah apa-apa. *Tool* itu seperti `POST`, karena bisa mengubah keadaan di dunia luar. Dengan cara pikir ini, memutuskan sebuah fungsi harus jadi resource atau *tool* biasanya selesai dalam hitungan detik.\n\n## Kenapa protokolnya dibongkar ulang\n\nIni bagian terpenting, jadi yuk kita bahas pelan-pelan. MCP lahir dengan transport `stdio` untuk aplikasi lokal. Di situ *server* adalah proses anak yang hidup berdampingan dengan host, dan *state* itu wajar. Ada koneksi, ada sesi, dan semuanya berjalan di satu mesin.\n\nMasalah muncul ketika *server* mulai berjalan jauh dari host. *State* tadi ikut terbawa ke HTTP: urusan sesi, stream yang digantung terus, sampai *replay* pesan ketika koneksi putus. [Tulisan Cloudflare](https:\u002F\u002Fblog.cloudflare.com\u002Fmcp-v2) menyebut bahwa kritik utama ke MCP memang koneksi stateful-nya. Bebannya berupa mengatur rute *request* ke *sticky session*, menahan stream terbuka, dan memutar ulang pesan. Siapa sih yang senang mengoperasikan itu semua di produksi?\n\nJawaban dari spesifikasi `2026-07-28` cukup tegas. Handshake `initialize` dan header `Mcp-Session-Id` **dihapus**. Sebagai gantinya, setiap *request* membawa versi protokol, identitas *client*, dan *capability*-nya sendiri. Client yang tetap ingin tahu kemampuan *server* lebih dulu bisa memanggil `server\u002Fdiscover`, tapi itu opsional, bukan syarat. Singkatnya, protokolnya sekarang **stateless di level protokol**.\n\n```mermaid\nflowchart TD\n  H[Host] --> C1[Client]\n  C1 --> SM[MCP Server]\n  SM --> T[Tools - dipanggil model]\n  SM --> R[Resources - dibaca aplikasi]\n  SM --> P[Prompts - dipilih user]\n```\n\nBeberapa detail baru layak dicatat. Pertama, header `Mcp-Method` dan `Mcp-Name` kini wajib ada di *request* Streamable HTTP. Gateway, *rate limiter*, atau WAF jadi bisa memutuskan tanpa membedah body JSON, dan itu kabar bagus buat yang mengurus infrastruktur.\n\nKedua, hasil `tools\u002Flist` dan kawan-kawannya membawa petunjuk cache `ttlMs` dan `cacheScope`, dengan urutan yang deterministik. Artinya katalog *tool* bisa di-*cache* oleh client dengan aman, tanpa khawatir urutannya berubah-ubah.\n\nKetiga, ada **MRTR** (*Multi Round-Trip Request*). Kalau sebuah *tool* butuh konfirmasi, *server* membalas `input_required` beserta permintaan yang dibutuhkan. Client mengumpulkan jawaban dari user, lalu mengulang pemanggilan aslinya. Dulu urusan server-ke-client seperti ini butuh stream terbuka, sekarang cukup putaran *request* biasa.\n\nKonsekuensinya besar: *server* MCP sekarang bisa jadi *workload* HTTP biasa. Nggak ada sesi yang harus dijaga, dan *server* bisa jalan di *serverless*. Menurut Cloudflare, setelah protokolnya stateless, *server* MCP bisa jalan di Worker dan primitif `McpAgent` mereka nggak lagi diperlukan. Emang begitu hasilnya kalau *state* dipindahkan dari koneksi ke *request*.\n\nSatu catatan supaya nggak salah paham: stateless bukan berarti aplikasimu nggak boleh punya *state*. Kalau butuh, buat *handle* eksplisit dari sebuah *tool*, misalnya pengenal keranjang atau sesi kerja, lalu biarkan model membawanya balik sebagai argumen di panggilan berikutnya. *State*-nya pindah ke tempat yang kelihatan, bukan hilang.\n\n## Yang perlu diwaspadai kalau baca tutorial lama\n\nBanyak *tutorial* MCP ditulis sebelum perubahan di atas, jadi ada beberapa jebakan yang gampang kita temui. Kalau kamu menemukan contoh yang kelihatan meyakinkan, cek dulu hal-hal ini:\n\n- `from mcp.server.fastmcp import FastMCP` itu API versi lama. Sekarang yang dipakai `from mcp.server import MCPServer`, dan import lamanya langsung melempar `ModuleNotFoundError`.\n- Transport HTTP+SSE sudah digantikan Streamable HTTP sejak revisi `2025-03-26`. Ia masih hidup demi kompatibilitas, tapi statusnya *deprecated*.\n- Roots, Sampling, dan Logging juga *deprecated*, dengan masa transisi minimal 12 bulan. Sementara itu `ping` sudah dihapus dari protokol.\n\nArtikel ini sendiri punya tanggal kedaluwarsa. Revisi spec datang dengan jarak 3 sampai 8 bulan, dengan urutan `2024-11-05`, `2025-03-26`, `2025-06-18`, `2025-11-25`, lalu `2026-07-28`. Versi yang dipakai di sini adalah `2026-07-28`, jadi kalau kamu membaca ini jauh setelahnya, [cek versi terbaru](https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002Fversioning) sebelum menyalin apa pun.\n\n## Server MCP pertama, sedikit baris\n\nCukup teorinya, sekarang kita lihat kodenya. Server di bawah nih punya satu resource berisi skema tabel dan satu *tool* pencarian. Isinya sengaja dibuat sederhana, dan fungsi pencariannya cuma mengembalikan teks, bukan *query* sungguhan.\n\n```python\n# server.py\nfrom mcp.server import MCPServer\n\nmcp = MCPServer(\"Invasikode Database Server\")\n\n\n@mcp.resource(\"db:\u002F\u002Farticles\u002Fschema\")\ndef get_articles_schema() -> str:\n    \"\"\"Skema DDL tabel artikel, buat konteks LLM.\"\"\"\n    return \"\"\"\n    CREATE TABLE articles (\n        id SERIAL PRIMARY KEY,\n        title VARCHAR(255) NOT NULL,\n        slug VARCHAR(255) UNIQUE NOT NULL,\n        tags VARCHAR(255),\n        status VARCHAR(32) DEFAULT 'draft'\n    );\n    \"\"\"\n\n\n@mcp.tool()\ndef search_articles_by_keyword(keyword: str, limit: int = 5) -> str:\n    \"\"\"Cari artikel berdasarkan kata kunci judul.\n\n    Args:\n        keyword: Kata kunci pencarian.\n        limit: Batas maksimum artikel yang dikembalikan.\n    \"\"\"\n    return f\"Berhasil mengambil {limit} artikel dengan kata kunci '{keyword}'.\"\n```\n\nPerhatikan apa yang nggak ada di kode tuh. Nggak ada JSON Schema yang ditulis tangan, karena *type hint* dan *docstring* sudah otomatis jadi skema. Nggak ada *request handler*, nggak ada deklarasi *capability*. Nama, deskripsi, dan skema argumen semuanya diturunkan dari fungsi Python-nya sendiri. Itulah poinnya — kamu menulis fungsi biasa, dan SDK mengurus sisanya. Kode ini sudah dijalankan pada SDK Python `mcp` 2.0.0, dengan protokol yang dinegosiasikan `2026-07-28`, dan *tool* serta resource-nya terdaftar. Ia belum diuji di *server* produksi, jadi perlakukan sebagai titik awal. Dokumentasi lengkapnya ada di [panduan SDK Python](https:\u002F\u002Fpy.sdk.modelcontextprotocol.io\u002Fget-started\u002Ffirst-steps\u002F).\n\nCara menjalankannya gampang kok: simpan sebagai `server.py`, pasang paketnya, lalu jalankan lewat SDK. Setelah itu kita daftarkan ke host. Di aplikasi desktop, biasanya lewat berkas konfigurasi seperti `claude_desktop_config.json`, dengan menunjuk perintah yang menjalankan servermu. Di editor, biasanya lewat ekstensi atau pengaturan MCP. Setelah terdaftar, coba tanya agent soal skema tabel artikel deh, lalu lihat apakah ia memakai resource yang baru kamu tulis 🙂.\n\n## Kenapa ini penting buat kamu\n\nKeuntungan paling nyata adalah sekali tulis, dipakai di mana-mana. Konektor ke *database* artikel yang tadi kamu tulis bisa dipakai oleh host mana pun yang mendukung MCP, tanpa perubahan di sisi *server*. Ganti model nggak lagi berarti nulis ulang konektor, dan itu menyelesaikan masalah di pembuka tadi.\n\nKredensial juga tetap di sisimu. Server yang menyimpan token dan kunci, model cuma melihat hasil yang sudah kamu izinkan. Dan karena protokolnya kini stateless, men-*deploy* *server* MCP nggak lagi butuh trik khusus. Ia bisa diperlakukan seperti layanan HTTP lain yang sudah biasa kamu urus, lengkap dengan *load balancer* dan *autoscaling*. Itu perubahan yang sebenarnya menarik buat kamu yang kerja di backend, lho!\n\n## Standarisasi dan siapa yang pegang protokolnya\n\nMCP diperkenalkan Anthropic pada 25 November 2024. Pada Desember 2025, protokol ini didonasikan ke Agentic AI Foundation, sebuah dana terarah di bawah Linux Foundation. [Pendirinya](https:\u002F\u002Fwww.anthropic.com\u002Fnews\u002Fdonating-the-model-context-protocol-and-establishing-of-the-agentic-ai-foundation) adalah Anthropic, Block, dan OpenAI, dengan dukungan Google, Microsoft, AWS, Cloudflare, dan Bloomberg. Governance-nya nggak berubah, jadi proses pengambilan keputusan yang sudah berjalan tetap sama.\n\nSoal adopsi, tulisan donasi itu mencatat bahwa per Desember 2025 ada lebih dari 10.000 MCP *server* publik yang aktif. Protokolnya juga sudah diadopsi ChatGPT, Cursor, Gemini, Microsoft Copilot, dan VS Code. Angka itu cukup menjelaskan kenapa banyak *developer* memutuskan belajar MCP sekarang, bukan nanti 🚀.\n\nJadi, kalau endpoint internalmu sudah menunggu ditempelkan ke agent, kamu sudah punya jalan pintasnya. Mulai dari satu fungsi kecil, biarkan type hint jadi skema, dan simpan konektor lima puluh itu sebagai cerita lama. Tinggal pastikan versi spec yang kamu pakai sama dengan yang dipakai host-mu.\n","- Model Context Protocol mengubah integrasi model-ke-sumber-data dari puluhan konektor buatan sendiri jadi satu protokol terbuka yang dipakai bersama.\n- Server MCP membagi peran dengan rapi: tool dipanggil model, resource dibaca aplikasi, dan prompt dipilih user.\n- Kredensial tetap di sisi server dan nggak pernah masuk ke prompt, karena server memang nggak boleh membaca seluruh percakapan.\n- Sejak spec 2026-07-28 protokolnya stateless, jadi server MCP bisa dideploy seperti workload HTTP biasa tanpa sesi yang harus dijaga.\n- Kalau tutorial yang kamu baca masih memakai FastMCP atau transport SSE, itu versi lama: nama API-nya sudah pindah dan transportnya sudah deprecated.","\u003Cp>Kamu punya beberapa endpoint internal: satu buat data artikel, satu buat pengguna, satu lagi buat laporan. Lalu ada satu agent AI yang harus bisa mengakses semuanya. Cara paling cepat adalah menulis konektor per pasangan, yaitu satu kode khusus untuk model A dan sumber data X, satu lagi untuk model A dan sumber Y. Awalnya terasa beres. Semua jalan, demo lancar, dan kamu merasa cukup produktif hari itu.\u003C\u002Fp>\n\u003Cp>Masalahnya baru kelihatan begitu modelnya diganti. Format \u003Cem>tool calling\u003C\u002Fem> beda, cara mendeskripsikan argumen beda, penanganan \u003Cem>error\u003C\u002Fem> pun beda. Setengah kode konektor tadi mendadak jadi sampah, dan kamu harus mengulang dari awal 😅. Kalau dihitung kasar, lima model dikali sepuluh sumber data berarti lima puluh implementasi yang harus dirawat. Angka itu cuma ilustrasi, tapi rasa sakitnya nyata bagi siapa pun yang pernah menjaga kode perekat.\u003C\u002Fp>\n\n\u003Cdiv class=\"mermaid-block my-6 not-prose rounded-xl border-2 border-black dark:border-gray-600 shadow-neo overflow-hidden bg-[#24292e]\" data-mermaid-diagram>\n  \u003Cdiv class=\"mermaid-header flex items-center justify-between px-4 py-2.5 bg-[#1f2428] border-b-2 border-black dark:border-gray-600 font-mono text-xs font-bold text-gray-300 select-none\">\n    \u003Cspan class=\"uppercase tracking-wider\">Diagram\u003C\u002Fspan>\n    \u003Cbutton type=\"button\" class=\"copy-code-btn flex items-center gap-1.5 px-3 py-1 text-xs font-bold bg-[#2f363d] text-gray-200 border-2 border-black dark:border-gray-500 rounded-lg shadow-neo-sm hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-none hover:bg-gray-700 transition-all cursor-pointer\" data-code=\"flowchart%20LR%0A%20%20M1%5BModel%20A%5D%20--%3E%20K1%5Bkonektor%20khusus%5D%0A%20%20M2%5BModel%20B%5D%20--%3E%20K1%0A%20%20M3%5BModel%20C%5D%20--%3E%20K1%0A%20%20K1%20--%3E%20S1%5B(PostgreSQL)%5D%0A%20%20K1%20--%3E%20S2%5B(Git)%5D%0A%20%20K1%20--%3E%20S3%5B(REST%20internal)%5D\" title=\"Salin kode diagram\">\n      \u003Cspan class=\"copy-text\">Copy\u003C\u002Fspan>\n    \u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n  \u003Cdiv class=\"mermaid-canvas p-4 overflow-x-auto\">\n    \u003Cdiv class=\"mermaid-source text-sm font-mono leading-relaxed text-[#e1e4e8]\" data-mermaid-src=\"flowchart%20LR%0A%20%20M1%5BModel%20A%5D%20--%3E%20K1%5Bkonektor%20khusus%5D%0A%20%20M2%5BModel%20B%5D%20--%3E%20K1%0A%20%20M3%5BModel%20C%5D%20--%3E%20K1%0A%20%20K1%20--%3E%20S1%5B(PostgreSQL)%5D%0A%20%20K1%20--%3E%20S2%5B(Git)%5D%0A%20%20K1%20--%3E%20S3%5B(REST%20internal)%5D\">flowchart LR\n  M1[Model A] --&gt; K1[konektor khusus]\n  M2[Model B] --&gt; K1\n  M3[Model C] --&gt; K1\n  K1 --&gt; S1[(PostgreSQL)]\n  K1 --&gt; S2[(Git)]\n  K1 --&gt; S3[(REST internal)]\u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\u003Cp>Nah, di titik inilah \u003Cstrong>Model Context Protocol\u003C\u002Fstrong> (MCP) masuk. Ide dasarnya sederhana: daripada setiap model bicara dengan setiap sumber lewat jalur khusus, semuanya bicara lewat satu protokol standar. Sumber data cukup ditulis sekali sebagai \u003Cem>server\u003C\u002Fem> — dan model apa pun yang paham protokolnya bisa memakainya.\u003C\u002Fp>\n\u003Ch2 id=\"kenapa-masalah-remeh-ini-mahal\">Kenapa masalah remeh ini mahal?\u003C\u002Fh2>\n\u003Cp>Kode perekat itu jarang dianggap pekerjaan serius. Isinya cuma mengubah format, menyalin skema, dan menempelkan kredensial. Tapi justru bagian itu yang paling rapuh, karena setiap perubahan di salah satu ujung memaksa perubahan di ujung lain. Biayanya nggak kelihatan di \u003Cem>sprint planning\u003C\u002Fem>, tapi menumpuk diam-diam sampai satu hari kita sadar separuh waktu habis untuk menambal konektor.\u003C\u002Fp>\n\u003Cp>Kalau kamu pernah memakai editor modern, kamu sudah merasakan solusi serupa di dunia lain. Spesifikasi MCP sendiri menyebut bahwa protokol ini mengambil inspirasi dari \u003Ca href=\"https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002F2026-07-28\">Language Server Protocol\u003C\u002Fa>. Dulu setiap editor harus mengimplementasikan dukungan untuk setiap bahasa pemrograman. Setelah ada protokol bersama, satu \u003Cem>language server\u003C\u002Fem> bisa melayani banyak editor. MCP membawa pola yang sama ke dunia agent AI, jadi kamu menulis konektor sekali dan nggak perlu peduli siapa yang memakainya nanti.\u003C\u002Fp>\n\u003Ch2 id=\"siapa-yang-ngobrol-dengan-siapa\">Siapa yang ngobrol dengan siapa\u003C\u002Fh2>\n\u003Cp>Arsitekturnya punya tiga peran. \u003Cstrong>Host\u003C\u002Fstrong> adalah aplikasi yang kamu pakai langsung, misalnya aplikasi desktop atau ekstensi editor, dan di dalamnya model AI berjalan. \u003Cem>Client\u003C\u002Fem> adalah komponen di dalam host yang mengurus komunikasi. \u003Cem>Server\u003C\u002Fem> adalah program yang membuka kemampuan atau data, dan di sinilah kode yang kamu tulis nanti berada.\u003C\u002Fp>\n\u003Cp>Satu hal yang perlu diingat: satu \u003Cem>client\u003C\u002Fem> berpasangan dengan tepat satu \u003Cem>server\u003C\u002Fem>. Kalau host terhubung ke tiga \u003Cem>server\u003C\u002Fem>, berarti ada tiga \u003Cem>client\u003C\u002Fem> di dalamnya. Pembagian ini bukan kebetulan, karena dari sinilah batas keamanannya terbentuk. Menurut \u003Ca href=\"https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002F2026-07-28\u002Farchitecture\">prinsip arsitektur di spec\u003C\u002Fa>, \u003Cem>server\u003C\u002Fem> nggak boleh bisa membaca seluruh percakapan dan nggak boleh bisa melihat ke dalam \u003Cem>server\u003C\u002Fem> lain. Riwayat percakapan tetap tinggal di host.\u003C\u002Fp>\n\u003Cp>Kredensial juga ikut aman. Token \u003Cem>database\u003C\u002Fem> atau kunci API tetap berada di sisi \u003Cem>server\u003C\u002Fem>, jadi nggak pernah ikut masuk ke \u003Cem>prompt\u003C\u002Fem>. Model cuma tahu bahwa ada \u003Cem>tool\u003C\u002Fem> bernama sekian dengan argumen sekian, bukan password di belakangnya. Itu keputusan desain yang menenangkan, kan.\u003C\u002Fp>\n\u003Ch2 id=\"tiga-primitif-dan-siapa-yang-pegang-kendali\">Tiga primitif, dan siapa yang pegang kendali\u003C\u002Fh2>\n\n\u003Cdiv class=\"mermaid-block my-6 not-prose rounded-xl border-2 border-black dark:border-gray-600 shadow-neo overflow-hidden bg-[#24292e]\" data-mermaid-diagram>\n  \u003Cdiv class=\"mermaid-header flex items-center justify-between px-4 py-2.5 bg-[#1f2428] border-b-2 border-black dark:border-gray-600 font-mono text-xs font-bold text-gray-300 select-none\">\n    \u003Cspan class=\"uppercase tracking-wider\">Diagram\u003C\u002Fspan>\n    \u003Cbutton type=\"button\" class=\"copy-code-btn flex items-center gap-1.5 px-3 py-1 text-xs font-bold bg-[#2f363d] text-gray-200 border-2 border-black dark:border-gray-500 rounded-lg shadow-neo-sm hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-none hover:bg-gray-700 transition-all cursor-pointer\" data-code=\"sequenceDiagram%0A%20%20autonumber%0A%20%20participant%20H%20as%20Host%0A%20%20participant%20S%20as%20MCP%20Server%0A%20%20Note%20over%20H%2CS%3A%20Sebelum%202026-07-28%20(stateful)%0A%20%20H-%3E%3ES%3A%20initialize%0A%20%20S--%3E%3EH%3A%20Mcp-Session-Id%0A%20%20H-%3E%3ES%3A%20tools%2Fcall%20%2B%20Mcp-Session-Id%0A%20%20Note%20over%20H%2CS%3A%20Sejak%202026-07-28%20(stateless)%0A%20%20H-%3E%3ES%3A%20tools%2Fcall%20%2B%20_meta%0A%20%20S--%3E%3EH%3A%20hasil\" title=\"Salin kode diagram\">\n      \u003Cspan class=\"copy-text\">Copy\u003C\u002Fspan>\n    \u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n  \u003Cdiv class=\"mermaid-canvas p-4 overflow-x-auto\">\n    \u003Cdiv class=\"mermaid-source text-sm font-mono leading-relaxed text-[#e1e4e8]\" data-mermaid-src=\"sequenceDiagram%0A%20%20autonumber%0A%20%20participant%20H%20as%20Host%0A%20%20participant%20S%20as%20MCP%20Server%0A%20%20Note%20over%20H%2CS%3A%20Sebelum%202026-07-28%20(stateful)%0A%20%20H-%3E%3ES%3A%20initialize%0A%20%20S--%3E%3EH%3A%20Mcp-Session-Id%0A%20%20H-%3E%3ES%3A%20tools%2Fcall%20%2B%20Mcp-Session-Id%0A%20%20Note%20over%20H%2CS%3A%20Sejak%202026-07-28%20(stateless)%0A%20%20H-%3E%3ES%3A%20tools%2Fcall%20%2B%20_meta%0A%20%20S--%3E%3EH%3A%20hasil\">sequenceDiagram\n  autonumber\n  participant H as Host\n  participant S as MCP Server\n  Note over H,S: Sebelum 2026-07-28 (stateful)\n  H-&gt;&gt;S: initialize\n  S--&gt;&gt;H: Mcp-Session-Id\n  H-&gt;&gt;S: tools\u002Fcall + Mcp-Session-Id\n  Note over H,S: Sejak 2026-07-28 (stateless)\n  H-&gt;&gt;S: tools\u002Fcall + _meta\n  S--&gt;&gt;H: hasil\u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\u003Cp>Server bisa menawarkan tiga jenis hal, dan perbedaannya terletak pada siapa yang memutuskan kapan dipakai.\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cem>Tools\u003C\u002Fem> dikendalikan model. Model memutuskan sendiri kapan memanggilnya, dan \u003Cem>tool\u003C\u002Fem> biasanya punya efek samping seperti menulis data atau mengirim sesuatu.\u003C\u002Fli>\n\u003Cli>\u003Cem>Resources\u003C\u002Fem> dikendalikan aplikasi. Isinya data yang dibaca lewat URI, dan host yang menentukan apa yang masuk ke konteks.\u003C\u002Fli>\n\u003Cli>\u003Cem>Prompts\u003C\u002Fem> dikendalikan user. Bentuknya template alur kerja yang dipilih manusia secara sadar.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Buat kita yang terbiasa bikin web API, ada padanan yang gampang diingat. Resource itu seperti \u003Ccode>GET\u003C\u002Fcode> — cuma membaca dan nggak mengubah apa-apa. \u003Cem>Tool\u003C\u002Fem> itu seperti \u003Ccode>POST\u003C\u002Fcode>, karena bisa mengubah keadaan di dunia luar. Dengan cara pikir ini, memutuskan sebuah fungsi harus jadi resource atau \u003Cem>tool\u003C\u002Fem> biasanya selesai dalam hitungan detik.\u003C\u002Fp>\n\u003Ch2 id=\"kenapa-protokolnya-dibongkar-ulang\">Kenapa protokolnya dibongkar ulang\u003C\u002Fh2>\n\u003Cp>Ini bagian terpenting, jadi yuk kita bahas pelan-pelan. MCP lahir dengan transport \u003Ccode>stdio\u003C\u002Fcode> untuk aplikasi lokal. Di situ \u003Cem>server\u003C\u002Fem> adalah proses anak yang hidup berdampingan dengan host, dan \u003Cem>state\u003C\u002Fem> itu wajar. Ada koneksi, ada sesi, dan semuanya berjalan di satu mesin.\u003C\u002Fp>\n\u003Cp>Masalah muncul ketika \u003Cem>server\u003C\u002Fem> mulai berjalan jauh dari host. \u003Cem>State\u003C\u002Fem> tadi ikut terbawa ke HTTP: urusan sesi, stream yang digantung terus, sampai \u003Cem>replay\u003C\u002Fem> pesan ketika koneksi putus. \u003Ca href=\"https:\u002F\u002Fblog.cloudflare.com\u002Fmcp-v2\">Tulisan Cloudflare\u003C\u002Fa> menyebut bahwa kritik utama ke MCP memang koneksi stateful-nya. Bebannya berupa mengatur rute \u003Cem>request\u003C\u002Fem> ke \u003Cem>sticky session\u003C\u002Fem>, menahan stream terbuka, dan memutar ulang pesan. Siapa sih yang senang mengoperasikan itu semua di produksi?\u003C\u002Fp>\n\u003Cp>Jawaban dari spesifikasi \u003Ccode>2026-07-28\u003C\u002Fcode> cukup tegas. Handshake \u003Ccode>initialize\u003C\u002Fcode> dan header \u003Ccode>Mcp-Session-Id\u003C\u002Fcode> \u003Cstrong>dihapus\u003C\u002Fstrong>. Sebagai gantinya, setiap \u003Cem>request\u003C\u002Fem> membawa versi protokol, identitas \u003Cem>client\u003C\u002Fem>, dan \u003Cem>capability\u003C\u002Fem>-nya sendiri. Client yang tetap ingin tahu kemampuan \u003Cem>server\u003C\u002Fem> lebih dulu bisa memanggil \u003Ccode>server\u002Fdiscover\u003C\u002Fcode>, tapi itu opsional, bukan syarat. Singkatnya, protokolnya sekarang \u003Cstrong>stateless di level protokol\u003C\u002Fstrong>.\u003C\u002Fp>\n\n\u003Cdiv class=\"mermaid-block my-6 not-prose rounded-xl border-2 border-black dark:border-gray-600 shadow-neo overflow-hidden bg-[#24292e]\" data-mermaid-diagram>\n  \u003Cdiv class=\"mermaid-header flex items-center justify-between px-4 py-2.5 bg-[#1f2428] border-b-2 border-black dark:border-gray-600 font-mono text-xs font-bold text-gray-300 select-none\">\n    \u003Cspan class=\"uppercase tracking-wider\">Diagram\u003C\u002Fspan>\n    \u003Cbutton type=\"button\" class=\"copy-code-btn flex items-center gap-1.5 px-3 py-1 text-xs font-bold bg-[#2f363d] text-gray-200 border-2 border-black dark:border-gray-500 rounded-lg shadow-neo-sm hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-none hover:bg-gray-700 transition-all cursor-pointer\" data-code=\"flowchart%20TD%0A%20%20H%5BHost%5D%20--%3E%20C1%5BClient%5D%0A%20%20C1%20--%3E%20SM%5BMCP%20Server%5D%0A%20%20SM%20--%3E%20T%5BTools%20-%20dipanggil%20model%5D%0A%20%20SM%20--%3E%20R%5BResources%20-%20dibaca%20aplikasi%5D%0A%20%20SM%20--%3E%20P%5BPrompts%20-%20dipilih%20user%5D\" title=\"Salin kode diagram\">\n      \u003Cspan class=\"copy-text\">Copy\u003C\u002Fspan>\n    \u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n  \u003Cdiv class=\"mermaid-canvas p-4 overflow-x-auto\">\n    \u003Cdiv class=\"mermaid-source text-sm font-mono leading-relaxed text-[#e1e4e8]\" data-mermaid-src=\"flowchart%20TD%0A%20%20H%5BHost%5D%20--%3E%20C1%5BClient%5D%0A%20%20C1%20--%3E%20SM%5BMCP%20Server%5D%0A%20%20SM%20--%3E%20T%5BTools%20-%20dipanggil%20model%5D%0A%20%20SM%20--%3E%20R%5BResources%20-%20dibaca%20aplikasi%5D%0A%20%20SM%20--%3E%20P%5BPrompts%20-%20dipilih%20user%5D\">flowchart TD\n  H[Host] --&gt; C1[Client]\n  C1 --&gt; SM[MCP Server]\n  SM --&gt; T[Tools - dipanggil model]\n  SM --&gt; R[Resources - dibaca aplikasi]\n  SM --&gt; P[Prompts - dipilih user]\u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\u003Cp>Beberapa detail baru layak dicatat. Pertama, header \u003Ccode>Mcp-Method\u003C\u002Fcode> dan \u003Ccode>Mcp-Name\u003C\u002Fcode> kini wajib ada di \u003Cem>request\u003C\u002Fem> Streamable HTTP. Gateway, \u003Cem>rate limiter\u003C\u002Fem>, atau WAF jadi bisa memutuskan tanpa membedah body JSON, dan itu kabar bagus buat yang mengurus infrastruktur.\u003C\u002Fp>\n\u003Cp>Kedua, hasil \u003Ccode>tools\u002Flist\u003C\u002Fcode> dan kawan-kawannya membawa petunjuk cache \u003Ccode>ttlMs\u003C\u002Fcode> dan \u003Ccode>cacheScope\u003C\u002Fcode>, dengan urutan yang deterministik. Artinya katalog \u003Cem>tool\u003C\u002Fem> bisa di-\u003Cem>cache\u003C\u002Fem> oleh client dengan aman, tanpa khawatir urutannya berubah-ubah.\u003C\u002Fp>\n\u003Cp>Ketiga, ada \u003Cstrong>MRTR\u003C\u002Fstrong> (\u003Cem>Multi Round-Trip Request\u003C\u002Fem>). Kalau sebuah \u003Cem>tool\u003C\u002Fem> butuh konfirmasi, \u003Cem>server\u003C\u002Fem> membalas \u003Ccode>input_required\u003C\u002Fcode> beserta permintaan yang dibutuhkan. Client mengumpulkan jawaban dari user, lalu mengulang pemanggilan aslinya. Dulu urusan server-ke-client seperti ini butuh stream terbuka, sekarang cukup putaran \u003Cem>request\u003C\u002Fem> biasa.\u003C\u002Fp>\n\u003Cp>Konsekuensinya besar: \u003Cem>server\u003C\u002Fem> MCP sekarang bisa jadi \u003Cem>workload\u003C\u002Fem> HTTP biasa. Nggak ada sesi yang harus dijaga, dan \u003Cem>server\u003C\u002Fem> bisa jalan di \u003Cem>serverless\u003C\u002Fem>. Menurut Cloudflare, setelah protokolnya stateless, \u003Cem>server\u003C\u002Fem> MCP bisa jalan di Worker dan primitif \u003Ccode>McpAgent\u003C\u002Fcode> mereka nggak lagi diperlukan. Emang begitu hasilnya kalau \u003Cem>state\u003C\u002Fem> dipindahkan dari koneksi ke \u003Cem>request\u003C\u002Fem>.\u003C\u002Fp>\n\u003Cp>Satu catatan supaya nggak salah paham: stateless bukan berarti aplikasimu nggak boleh punya \u003Cem>state\u003C\u002Fem>. Kalau butuh, buat \u003Cem>handle\u003C\u002Fem> eksplisit dari sebuah \u003Cem>tool\u003C\u002Fem>, misalnya pengenal keranjang atau sesi kerja, lalu biarkan model membawanya balik sebagai argumen di panggilan berikutnya. \u003Cem>State\u003C\u002Fem>-nya pindah ke tempat yang kelihatan, bukan hilang.\u003C\u002Fp>\n\u003Ch2 id=\"yang-perlu-diwaspadai-kalau-baca-tutorial-lama\">Yang perlu diwaspadai kalau baca tutorial lama\u003C\u002Fh2>\n\u003Cp>Banyak \u003Cem>tutorial\u003C\u002Fem> MCP ditulis sebelum perubahan di atas, jadi ada beberapa jebakan yang gampang kita temui. Kalau kamu menemukan contoh yang kelihatan meyakinkan, cek dulu hal-hal ini:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Ccode>from mcp.server.fastmcp import FastMCP\u003C\u002Fcode> itu API versi lama. Sekarang yang dipakai \u003Ccode>from mcp.server import MCPServer\u003C\u002Fcode>, dan import lamanya langsung melempar \u003Ccode>ModuleNotFoundError\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>Transport HTTP+SSE sudah digantikan Streamable HTTP sejak revisi \u003Ccode>2025-03-26\u003C\u002Fcode>. Ia masih hidup demi kompatibilitas, tapi statusnya \u003Cem>deprecated\u003C\u002Fem>.\u003C\u002Fli>\n\u003Cli>Roots, Sampling, dan Logging juga \u003Cem>deprecated\u003C\u002Fem>, dengan masa transisi minimal 12 bulan. Sementara itu \u003Ccode>ping\u003C\u002Fcode> sudah dihapus dari protokol.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Artikel ini sendiri punya tanggal kedaluwarsa. Revisi spec datang dengan jarak 3 sampai 8 bulan, dengan urutan \u003Ccode>2024-11-05\u003C\u002Fcode>, \u003Ccode>2025-03-26\u003C\u002Fcode>, \u003Ccode>2025-06-18\u003C\u002Fcode>, \u003Ccode>2025-11-25\u003C\u002Fcode>, lalu \u003Ccode>2026-07-28\u003C\u002Fcode>. Versi yang dipakai di sini adalah \u003Ccode>2026-07-28\u003C\u002Fcode>, jadi kalau kamu membaca ini jauh setelahnya, \u003Ca href=\"https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002Fversioning\">cek versi terbaru\u003C\u002Fa> sebelum menyalin apa pun.\u003C\u002Fp>\n\u003Ch2 id=\"server-mcp-pertama-sedikit-baris\">Server MCP pertama, sedikit baris\u003C\u002Fh2>\n\u003Cp>Cukup teorinya, sekarang kita lihat kodenya. Server di bawah nih punya satu resource berisi skema tabel dan satu \u003Cem>tool\u003C\u002Fem> pencarian. Isinya sengaja dibuat sederhana, dan fungsi pencariannya cuma mengembalikan teks, bukan \u003Cem>query\u003C\u002Fem> sungguhan.\u003C\u002Fp>\n\n\u003Cdiv class=\"code-block-wrapper my-6 not-prose rounded-xl border-2 border-black dark:border-gray-600 shadow-neo overflow-hidden bg-[#24292e] text-[#e1e4e8] transition-all\">\n  \u003Cdiv class=\"code-block-header flex items-center justify-between px-4 py-2.5 bg-[#1f2428] border-b-2 border-black dark:border-gray-600 font-mono text-xs font-bold text-gray-300 select-none\">\n    \u003Cdiv class=\"flex items-center gap-2\">\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#ff5f56] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#ffbd2e] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#27c93f] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"ml-2 font-mono font-bold text-xs uppercase tracking-wider text-gray-300\">PYTHON\u003C\u002Fspan>\n    \u003C\u002Fdiv>\n    \u003Cbutton type=\"button\" class=\"copy-code-btn flex items-center gap-1.5 px-3 py-1 text-xs font-bold bg-[#2f363d] text-gray-200 border-2 border-black dark:border-gray-500 rounded-lg shadow-neo-sm hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-none hover:bg-gray-700 transition-all cursor-pointer\" data-code=\"%23%20server.py%0Afrom%20mcp.server%20import%20MCPServer%0A%0Amcp%20%3D%20MCPServer(%22Invasikode%20Database%20Server%22)%0A%0A%0A%40mcp.resource(%22db%3A%2F%2Farticles%2Fschema%22)%0Adef%20get_articles_schema()%20-%3E%20str%3A%0A%20%20%20%20%22%22%22Skema%20DDL%20tabel%20artikel%2C%20buat%20konteks%20LLM.%22%22%22%0A%20%20%20%20return%20%22%22%22%0A%20%20%20%20CREATE%20TABLE%20articles%20(%0A%20%20%20%20%20%20%20%20id%20SERIAL%20PRIMARY%20KEY%2C%0A%20%20%20%20%20%20%20%20title%20VARCHAR(255)%20NOT%20NULL%2C%0A%20%20%20%20%20%20%20%20slug%20VARCHAR(255)%20UNIQUE%20NOT%20NULL%2C%0A%20%20%20%20%20%20%20%20tags%20VARCHAR(255)%2C%0A%20%20%20%20%20%20%20%20status%20VARCHAR(32)%20DEFAULT%20'draft'%0A%20%20%20%20)%3B%0A%20%20%20%20%22%22%22%0A%0A%0A%40mcp.tool()%0Adef%20search_articles_by_keyword(keyword%3A%20str%2C%20limit%3A%20int%20%3D%205)%20-%3E%20str%3A%0A%20%20%20%20%22%22%22Cari%20artikel%20berdasarkan%20kata%20kunci%20judul.%0A%0A%20%20%20%20Args%3A%0A%20%20%20%20%20%20%20%20keyword%3A%20Kata%20kunci%20pencarian.%0A%20%20%20%20%20%20%20%20limit%3A%20Batas%20maksimum%20artikel%20yang%20dikembalikan.%0A%20%20%20%20%22%22%22%0A%20%20%20%20return%20f%22Berhasil%20mengambil%20%7Blimit%7D%20artikel%20dengan%20kata%20kunci%20'%7Bkeyword%7D'.%22\" title=\"Salin kode\">\n      \u003Csvg class=\"w-3.5 h-3.5 copy-icon-svg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n        \u003Cpath stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\">\u003C\u002Fpath>\n      \u003C\u002Fsvg>\n      \u003Cspan class=\"copy-text\">Copy\u003C\u002Fspan>\n    \u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n  \u003Cdiv class=\"code-block-content p-4 overflow-x-auto text-sm font-mono leading-relaxed bg-[#24292e]\">\n    \u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\"># server.py\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> mcp.server \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> MCPServer\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">mcp \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> MCPServer(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"Invasikode Database Server\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">@mcp.resource\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"db:\u002F\u002Farticles\u002Fschema\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">def\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> get_articles_schema\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() -> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">str\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">    \"\"\"Skema DDL tabel artikel, buat konteks LLM.\"\"\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\"> \"\"\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">    CREATE TABLE articles (\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">        id SERIAL PRIMARY KEY,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">        title VARCHAR(255) NOT NULL,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">        slug VARCHAR(255) UNIQUE NOT NULL,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">        tags VARCHAR(255),\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">        status VARCHAR(32) DEFAULT 'draft'\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">    );\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">    \"\"\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">@mcp.tool\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">def\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> search_articles_by_keyword\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(keyword: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">str\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, limit: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">int\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> 5\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">) -> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">str\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">    \"\"\"Cari artikel berdasarkan kata kunci judul.\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">    Args:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">        keyword: Kata kunci pencarian.\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">        limit: Batas maksimum artikel yang dikembalikan.\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\">    \"\"\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> f\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"Berhasil mengambil \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">{\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">limit\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">}\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\"> artikel dengan kata kunci '\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">{\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">keyword\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">}\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">'.\"\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\u003Cp>Perhatikan apa yang nggak ada di kode tuh. Nggak ada JSON Schema yang ditulis tangan, karena \u003Cem>type hint\u003C\u002Fem> dan \u003Cem>docstring\u003C\u002Fem> sudah otomatis jadi skema. Nggak ada \u003Cem>request handler\u003C\u002Fem>, nggak ada deklarasi \u003Cem>capability\u003C\u002Fem>. Nama, deskripsi, dan skema argumen semuanya diturunkan dari fungsi Python-nya sendiri. Itulah poinnya — kamu menulis fungsi biasa, dan SDK mengurus sisanya. Kode ini sudah dijalankan pada SDK Python \u003Ccode>mcp\u003C\u002Fcode> 2.0.0, dengan protokol yang dinegosiasikan \u003Ccode>2026-07-28\u003C\u002Fcode>, dan \u003Cem>tool\u003C\u002Fem> serta resource-nya terdaftar. Ia belum diuji di \u003Cem>server\u003C\u002Fem> produksi, jadi perlakukan sebagai titik awal. Dokumentasi lengkapnya ada di \u003Ca href=\"https:\u002F\u002Fpy.sdk.modelcontextprotocol.io\u002Fget-started\u002Ffirst-steps\u002F\">panduan SDK Python\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>Cara menjalankannya gampang kok: simpan sebagai \u003Ccode>server.py\u003C\u002Fcode>, pasang paketnya, lalu jalankan lewat SDK. Setelah itu kita daftarkan ke host. Di aplikasi desktop, biasanya lewat berkas konfigurasi seperti \u003Ccode>claude_desktop_config.json\u003C\u002Fcode>, dengan menunjuk perintah yang menjalankan servermu. Di editor, biasanya lewat ekstensi atau pengaturan MCP. Setelah terdaftar, coba tanya agent soal skema tabel artikel deh, lalu lihat apakah ia memakai resource yang baru kamu tulis 🙂.\u003C\u002Fp>\n\u003Ch2 id=\"kenapa-ini-penting-buat-kamu\">Kenapa ini penting buat kamu\u003C\u002Fh2>\n\u003Cp>Keuntungan paling nyata adalah sekali tulis, dipakai di mana-mana. Konektor ke \u003Cem>database\u003C\u002Fem> artikel yang tadi kamu tulis bisa dipakai oleh host mana pun yang mendukung MCP, tanpa perubahan di sisi \u003Cem>server\u003C\u002Fem>. Ganti model nggak lagi berarti nulis ulang konektor, dan itu menyelesaikan masalah di pembuka tadi.\u003C\u002Fp>\n\u003Cp>Kredensial juga tetap di sisimu. Server yang menyimpan token dan kunci, model cuma melihat hasil yang sudah kamu izinkan. Dan karena protokolnya kini stateless, men-\u003Cem>deploy\u003C\u002Fem> \u003Cem>server\u003C\u002Fem> MCP nggak lagi butuh trik khusus. Ia bisa diperlakukan seperti layanan HTTP lain yang sudah biasa kamu urus, lengkap dengan \u003Cem>load balancer\u003C\u002Fem> dan \u003Cem>autoscaling\u003C\u002Fem>. Itu perubahan yang sebenarnya menarik buat kamu yang kerja di backend, lho!\u003C\u002Fp>\n\u003Ch2 id=\"standarisasi-dan-siapa-yang-pegang-protokolnya\">Standarisasi dan siapa yang pegang protokolnya\u003C\u002Fh2>\n\u003Cp>MCP diperkenalkan Anthropic pada 25 November 2024. Pada Desember 2025, protokol ini didonasikan ke Agentic AI Foundation, sebuah dana terarah di bawah Linux Foundation. \u003Ca href=\"https:\u002F\u002Fwww.anthropic.com\u002Fnews\u002Fdonating-the-model-context-protocol-and-establishing-of-the-agentic-ai-foundation\">Pendirinya\u003C\u002Fa> adalah Anthropic, Block, dan OpenAI, dengan dukungan Google, Microsoft, AWS, Cloudflare, dan Bloomberg. Governance-nya nggak berubah, jadi proses pengambilan keputusan yang sudah berjalan tetap sama.\u003C\u002Fp>\n\u003Cp>Soal adopsi, tulisan donasi itu mencatat bahwa per Desember 2025 ada lebih dari 10.000 MCP \u003Cem>server\u003C\u002Fem> publik yang aktif. Protokolnya juga sudah diadopsi ChatGPT, Cursor, Gemini, Microsoft Copilot, dan VS Code. Angka itu cukup menjelaskan kenapa banyak \u003Cem>developer\u003C\u002Fem> memutuskan belajar MCP sekarang, bukan nanti 🚀.\u003C\u002Fp>\n\u003Cp>Jadi, kalau endpoint internalmu sudah menunggu ditempelkan ke agent, kamu sudah punya jalan pintasnya. Mulai dari satu fungsi kecil, biarkan type hint jadi skema, dan simpan konektor lima puluh itu sebagai cerita lama. Tinggal pastikan versi spec yang kamu pakai sama dengan yang dipakai host-mu.\u003C\u002Fp>\n","\u003Cul>\n\u003Cli>Model Context Protocol mengubah integrasi model-ke-sumber-data dari puluhan konektor buatan sendiri jadi satu protokol terbuka yang dipakai bersama.\u003C\u002Fli>\n\u003Cli>Server MCP membagi peran dengan rapi: tool dipanggil model, resource dibaca aplikasi, dan prompt dipilih user.\u003C\u002Fli>\n\u003Cli>Kredensial tetap di sisi server dan nggak pernah masuk ke prompt, karena server memang nggak boleh membaca seluruh percakapan.\u003C\u002Fli>\n\u003Cli>Sejak spec 2026-07-28 protokolnya stateless, jadi server MCP bisa dideploy seperti workload HTTP biasa tanpa sesi yang harus dijaga.\u003C\u002Fli>\n\u003Cli>Kalau tutorial yang kamu baca masih memakai FastMCP atau transport SSE, itu versi lama: nama API-nya sudah pindah dan transportnya sudah deprecated.\u003C\u002Fli>\n\u003C\u002Ful>\n",[266,283,296,309,322,327],{"id":267,"title":268,"title_en":21,"slug":269,"excerpt":270,"excerpt_en":21,"has_translation":15,"published_at":271,"reading_time":198,"hidden_from_listing":15,"tags":272,"thumbnail_image":21,"og_image":274,"series":275,"authors":280},133,"Python Strings: the Badge That Only Worked for One Name","python-strings","The badge script printed the right name for the person who wrote it and the wrong name for everybody else. Slicing counts characters, and a name is words.","2026-10-28T13:00:00.000Z",[88,273],"string","\u002Fog\u002Fpython-strings.png",{"id":276,"title":277,"title_en":278,"slug":279},30,"Koleksi dan String","Collections and Strings","python-collections",[281],{"authors_id":282},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":284,"title":285,"title_en":21,"slug":286,"excerpt":287,"excerpt_en":21,"has_translation":15,"published_at":288,"reading_time":198,"hidden_from_listing":15,"tags":289,"thumbnail_image":21,"og_image":291,"series":292,"authors":293},132,"Python Tuples: Why All Three Points Are the Same Point","python-tuples","Three points walk into a loop and come out identical. The list was never copied three times; the name was. A tuple makes that bug impossible.","2026-10-28T12:00:00.000Z",[88,290],"tuple","\u002Fog\u002Fpython-tuples.png",{"id":276,"title":277,"title_en":278,"slug":279},[294],{"authors_id":295},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":297,"title":298,"title_en":21,"slug":299,"excerpt":300,"excerpt_en":21,"has_translation":15,"published_at":301,"reading_time":198,"hidden_from_listing":15,"tags":302,"thumbnail_image":21,"og_image":304,"series":305,"authors":306},131,"Python Sets: the Duplicate That Keeps Coming Back","python-sets","A de-duplication loop that works on clean data leaves four tags where there should be two. The bug is case, and the fix is a `set`.","2026-10-28T11:00:00.000Z",[88,303],"set","\u002Fog\u002Fpython-sets.png",{"id":276,"title":277,"title_en":278,"slug":279},[307],{"authors_id":308},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":310,"title":311,"title_en":21,"slug":312,"excerpt":313,"excerpt_en":21,"has_translation":15,"published_at":314,"reading_time":198,"hidden_from_listing":15,"tags":315,"thumbnail_image":21,"og_image":317,"series":318,"authors":319},130,"Python Dictionaries: the Key That Isn't There","python-dictionary","A word counter dies the first time it meets a word twice. The fix is one line; what takes longer is knowing which of a dict's three lookups to reach for.","2026-10-28T10:00:00.000Z",[88,316],"dictionary","\u002Fog\u002Fpython-dictionary.png",{"id":276,"title":277,"title_en":278,"slug":279},[320],{"authors_id":321},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":231,"title":232,"title_en":233,"slug":234,"excerpt":235,"excerpt_en":236,"has_translation":12,"published_at":237,"reading_time":14,"hidden_from_listing":15,"tags":238,"thumbnail_image":21,"og_image":244,"series":323,"authors":324},{"id":81,"title":35,"title_en":36,"slug":37},[325],{"authors_id":326},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},{"id":212,"title":213,"title_en":214,"slug":215,"excerpt":216,"excerpt_en":217,"has_translation":12,"published_at":218,"reading_time":198,"hidden_from_listing":15,"tags":219,"thumbnail_image":21,"og_image":225,"series":328,"authors":329},{"id":81,"title":35,"title_en":36,"slug":37},[330],{"authors_id":331},{"id":94,"name":124,"slug":125,"role":126,"profile_picture":21},[333,336,339,342,345,348,351,354],{"text":334,"depth":111,"id":335},"Kenapa masalah remeh ini mahal?","kenapa-masalah-remeh-ini-mahal",{"text":337,"depth":111,"id":338},"Siapa yang ngobrol dengan siapa","siapa-yang-ngobrol-dengan-siapa",{"text":340,"depth":111,"id":341},"Tiga primitif, dan siapa yang pegang kendali","tiga-primitif-dan-siapa-yang-pegang-kendali",{"text":343,"depth":111,"id":344},"Kenapa protokolnya dibongkar ulang","kenapa-protokolnya-dibongkar-ulang",{"text":346,"depth":111,"id":347},"Yang perlu diwaspadai kalau baca tutorial lama","yang-perlu-diwaspadai-kalau-baca-tutorial-lama",{"text":349,"depth":111,"id":350},"Server MCP pertama, sedikit baris","server-mcp-pertama-sedikit-baris",{"text":352,"depth":111,"id":353},"Kenapa ini penting buat kamu","kenapa-ini-penting-buat-kamu",{"text":355,"depth":111,"id":356},"Standarisasi dan siapa yang pegang protokolnya","standarisasi-dan-siapa-yang-pegang-protokolnya",1793295834459]