Belajar MCP - Server SDK (TypeScript & Python)
Episode 6 of 23

Belajar MCP - Server SDK (TypeScript & Python)

Di episode ini kita bangun server MCP nyata dengan dua bahasa: TypeScript lewat McpServer high-level dan Server low-level, serta Python lewat FastMCP dan Server low-level, lengkap dengan contoh tool server sederhana end-to-end.

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

Pendahuluan

Di episode 5 kemarin kalian sudah memahami dua primitives penting: Resources untuk menyediakan data kontekstual lewat resources/list dan resources/read, serta Prompts sebagai template reusable lewat prompts/list dan prompts/get. Sekarang saatnya berpindah dari teori ke praktik murni: kita akan membangun server MCP nyata yang siap dijalankan di mesin kalian.

Episode ini fokus ke Server SDK dalam dua ekosistem utama: TypeScript dan Python. Kita bedah dua level abstraksi di masing-masing bahasa — yang high-level untuk produktivitas, dan yang low-level untuk kontrol penuh atas pesan JSON-RPC. Di akhir episode, kalian punya satu server tool lengkap yang bisa langsung dicolokkan ke MCP Inspector maupun aplikasi host.

Dua Level Abstraksi SDK

Sebelum menulis kode, pahami dulu peta SDK. Setiap ekosistem resmi menyediakan dua gaya:

  • High-level API — TypeScript memakai McpServer dari paket @modelcontextprotocol/sdk, Python memakai FastMCP dari paket mcp. Kalian cukup mendaftarkan tool lewat satu fungsi atau satu dekorator; serialisasi JSON-RPC, skema, dan lifecycle diurus SDK.
  • Low-level Server — kelas yang memberi akses langsung ke request handler JSON-RPC seperti tools/list dan tools/call. Cocok untuk transport custom, tool dinamis, atau saat kalian butuh menyelipkan logika di setiap pesan.

Info

Pilih high-level untuk memulai dan untuk mayoritas kasus produksi. Turun ke low-level hanya jika kalian butuh menangani request di luar tools, resources, dan prompts — misalnya interaksi mid-call yang akan kita bahas di episode 8 soal Multi-Round-Trip Requests.

Pemasangannya satu baris per ekosistem: npm install @modelcontextprotocol/sdk untuk TypeScript, atau pip install mcp untuk Python. Sisanya tinggal menulis kode.

TypeScript: High-Level McpServer

High-level server paling cocok untuk tool-based server. Contoh berikut membuat server mata uang dengan satu tool konversi, lalu terhubung ke transport stdio — protokol standar untuk server lokal yang dipanggil sebagai subprocess oleh host seperti editor atau CLI agent.

server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 
const server = new McpServer({
  name: "currency-tools",
  version: "1.0.0",
});
 
server.registerTool(
  "convert-currency",
  {
    description: "Konversi nilai antar mata uang",
    inputSchema: {
      type: "object",
      properties: {
        from: { type: "string" },
        to: { type: "string" },
        amount: { type: "number" },
      },
      required: ["from", "to", "amount"],
    },
  },
  async ({ from, to, amount }) => ({
    content: [
      { type: "text", text: `${amount} ${from} = ${amount * 15000} ${to}` },
    ],
  })
);
 
const transport = new StdioServerTransport();
await server.connect(transport);

Perhatikan struktur registerTool: argumen pertama nama tool, kedua deskripsi plus skema input JSON Schema, ketiga fungsi eksekusi yang menerima parameter hasil parsing skema. Nilai baliknya objek content bertipe array — inilah structured output yang kalian kenal dari episode 4. Tanpa dekorasi apa pun, McpServer otomatis mengimplementasikan tools/list dan tools/call di belakang layar. Untuk menjalankannya, build dengan npm run build lalu panggil node dist/server.js. Sekadar catatan, ada juga pustaka fastmcp untuk TypeScript yang meniru gaya dekorator Python — tapi McpServer tetap API utama SDK.

TypeScript: Low-Level Server

Kalau kalian butuh kontrol penuh — misalnya menambahkan log per request atau mengubah respons sebelum dikirim — turun ke kelas Server dari @modelcontextprotocol/sdk/server/index.js. Di sini setiap method JSON-RPC didaftarkan manual lewat setRequestHandler.

server-low-level.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
 
const server = new Server({ name: "low-level-server", version: "1.0.0" });
 
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    { name: "ping", description: "Balas pong", inputSchema: { type: "object", properties: {} } },
  ],
}));
 
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "ping") {
    return { content: [{ type: "text", text: "pong" }] };
  }
  throw new Error(`Tool tidak dikenal: ${request.params.name}`);
});

Skema ListToolsRequestSchema dan CallToolRequestSchema dari @modelcontextprotocol/sdk/types.js adalah definisi JSON-RPC resmi yang di-export SDK. Dengan pola ini kalian juga bisa meregistrasi resources/list, resources/read, prompts/list, dan prompts/get satu per satu — tidak ada yang otomatis.

Python: FastMCP untuk Produktivitas

Di Python, padanan McpServer adalah FastMCP. Registrasi tool cukup lewat dekorator @mcp.tool(), dan type hint pada parameter langsung diterjemahkan menjadi skema JSON Schema — kodenya terasa seperti menulis fungsi biasa.

Pythonserver.py
from mcp.server.fastmcp import FastMCP
 
mcp = FastMCP("currency-tools")
 
 
@mcp.tool()
def convert_currency(from_currency: str, to_currency: str, amount: float) -> str:
    result = amount * 15000
    return f"{amount} {from_currency} = {result} {to_currency}"
 
 
if __name__ == "__main__":
    mcp.run(transport="stdio")

Jalankan dengan satu baris: python server.py. Kelebihan FastMCP: dukungan asinkron, notifikasi progress, dan helper untuk resources serta prompts dalam satu kelas. Untuk server sederhana, ini jalur tercepat dari nol menuju server yang berfungsi.

Python: Low-Level Server

Jika FastMCP terlalu "sihir", Python juga menyediakan Server low-level dengan dekorator yang eksplisit terhadap method JSON-RPC:

Pythonserver_low_level.py
import asyncio
 
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import CallToolRequest
 
server = Server("low-level-server")
 
 
@server.list_tools()
async def list_tools():
    return [{"name": "ping", "description": "Balas pong"}]
 
 
@server.call_tool()
async def call_tool(request: CallToolRequest):
    if request.params.name == "ping":
        return {"content": [{"type": "text", "text": "pong"}]}
    raise ValueError("Tool tidak dikenal")

Dekorator @server.list_tools() dan @server.call_tool() menangkap request JSON-RPC yang masuk. Untuk menjalankannya, bungkus server.run(read, write, server.create_initialization_options()) di dalam async with stdio_server() lalu panggil asyncio.run(main()). Perhatikan create_initialization_options() — di era modern (spesifikasi 2026-07-28) informasi versi dan capability dikirim per-request, jadi server tidak lagi bergantung pada handshake sesi khusus.

Contoh End-to-End: Server Cuaca

Terakhir, rangkai semua menjadi satu server cuaca dengan dua tool, siap dicolokkan ke MCP Inspector dari episode berikutnya:

Pythonweather_server.py
from mcp.server.fastmcp import FastMCP
 
mcp = FastMCP("weather-server")
 
 
@mcp.tool()
def get_weather(city: str) -> str:
    if city.lower() == "jakarta":
        return "Cerah, 32 derajat Celcius"
    return f"Data cuaca untuk {city} belum tersedia"
 
 
@mcp.tool()
def get_forecast(city: str, days: int) -> str:
    return f"Perkiraan {days} hari ke depan untuk {city}: hujan ringan"
 
 
if __name__ == "__main__":
    mcp.run(transport="stdio")

Server ini bisa diuji cepat lewat npx @modelcontextprotocol/inspector — ia membuka UI interaktif di browser; kita bedah semua fiturnya di episode 7.

Penutup

Episode 6 memberi kalian keterampilan membangun server MCP di dua bahasa dengan dua level abstraksi: McpServer dan FastMCP untuk produktivitas, serta Server low-level untuk kontrol penuh atas pesan JSON-RPC. Kalian juga sudah punya satu server cuaca end-to-end yang berfungsi nyata.

Inti yang harus dibawa pulang:

  • High-level untuk produktivitas: registerTool dan @mcp.tool() cukup untuk mayoritas tool server.
  • Low-level untuk kontrol: setRequestHandler dan @server.call_tool() memberi akses langsung ke method JSON-RPC.
  • Structured output: nilai balik tool selalu array content berisi blok teks (dan nanti blok lain).
  • Transport stdio: memadai untuk server lokal; server remote memakai HTTP (episode 9).
  • SDK berbeda, protokol sama: selama pesan JSON-RPC valid, server TypeScript bisa dipakai client Python dan sebaliknya.

Di episode 7 berikutnya kita bangun sisi sebaliknya — Client SDK untuk menghubungi server lewat stdio maupun HTTP, plus MCP Inspector untuk menguji server kalian secara interaktif. Sampai jumpa!

Belajar MCP - Server SDK (TypeScript & Python) | Belajar MCP