MCP (Model Context Protocol): Membangun Integrasi Tools untuk AI
Model Context Protocol (MCP) adalah protokol standar terbuka yang dikembangkan oleh Anthropic untuk menghubungkan asisten AI dengan sumber data dan tools eksternal. Bayangkan MCP sebagai "USB-C untuk AI" — satu standar universal yang memungkinkan AI model apapun terhubung dengan tools apapun tanpa perlu integrasi khusus untuk setiap kombinasi.
Dalam tutorial ini, kita akan mempelajari arsitektur MCP secara mendalam, membangun MCP server dan client dari nol, serta membuat contoh praktis berupa database query server yang memungkinkan AI assistant melakukan query PostgreSQL dengan aman.
Mengapa MCP Penting?
Sebelum MCP, setiap integrasi antara AI dan tools eksternal memerlukan implementasi khusus. Jika Anda memiliki 5 AI model dan 10 tools, Anda memerlukan 50 integrasi berbeda. MCP menyelesaikan masalah ini dengan menyediakan satu protokol standar.
Keuntungan utama MCP:
- Standarisasi: Satu protokol untuk semua integrasi AI-tools
- Keamanan: Kontrol akses granular terhadap data dan operasi
- Modularitas: Server dan client dapat dikembangkan secara independen
- Ekosistem: Komunitas yang berkembang dengan banyak server siap pakai
- Vendor-agnostic: Tidak terikat pada satu provider AI tertentu
Arsitektur MCP
MCP menggunakan arsitektur client-server dengan tiga komponen utama:
1. Host
Host adalah aplikasi AI yang digunakan pengguna, seperti Claude Desktop, Claude Code, atau IDE dengan fitur AI. Host mengelola koneksi dan menyediakan antarmuka pengguna.
2. Client
Client adalah komponen di dalam host yang mengelola koneksi ke satu MCP server. Setiap client memiliki koneksi 1:1 dengan satu server. Client menangani negosiasi kapabilitas dan routing pesan.
3. Server
Server adalah program yang mengekspos resources, tools, dan prompts kepada client. Server bisa berjalan secara lokal atau remote dan berkomunikasi melalui transport layer yang didukung.
┌─────────────────────────────────────┐
│ HOST │
│ (Claude Desktop / Claude Code) │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Client 1 │ │ Client 2 │ │
│ └────┬─────┘ └────┬─────┘ │
└───────┼───────────────┼─────────────┘
│ │
┌────▼─────┐ ┌────▼─────┐
│ Server A │ │ Server B │
│ (DB) │ │ (Files) │
└──────────┘ └──────────┘
Primitif Utama MCP
MCP mendefinisikan tiga primitif utama yang dapat diekspos oleh server:
Resources
Resources adalah data yang dapat dibaca oleh AI, seperti file, database record, atau API response. Resources diidentifikasi dengan URI dan bersifat read-only.
Tools
Tools adalah fungsi yang dapat dipanggil oleh AI untuk melakukan aksi. Tools memiliki parameter yang didefinisikan dengan JSON Schema dan mengembalikan hasil dalam format terstruktur.
Prompts
Prompts adalah template yang dapat digunakan ulang untuk interaksi AI. Prompts membantu pengguna melakukan tugas umum dengan cara yang terstruktur.
Instalasi
Python SDK
# Install menggunakan pip
pip install mcp
Atau menggunakan uv (direkomendasikan)
uv add mcp
Untuk development
uv add "mcp[cli]"
TypeScript SDK
# Install menggunakan npm
npm install @modelcontextprotocol/sdk
Atau menggunakan pnpm
pnpm add @modelcontextprotocol/sdk
MCP Inspector (untuk testing)
# Jalankan MCP Inspector
npx @modelcontextprotocol/inspector
Membangun MCP Server dengan Python
Mari kita mulai dengan membangun MCP server sederhana yang mengekspos resources, tools, dan prompts.
Server Dasar
# server.py
from mcp.server.fastmcp import FastMCP
Inisialisasi server
mcp = FastMCP("Demo Server")
Definisikan resource
@mcp.resource("config://app")
def getconfig() -> str:
"""Mengembalikan konfigurasi aplikasi."""
return "App Configuration: debug=true, version=1.0"
Definisikan tool
@mcp.tool()
def calculatebmi(weightkg: float, heightm: float) -> str:
"""Menghitung Body Mass Index (BMI).
Args:
weightkg: Berat badan dalam kilogram
heightm: Tinggi badan dalam meter
"""
bmi = weightkg / (heightm * 2)
category = ""
if bmi < 18.5:
category = "Underweight"
elif bmi < 25:
category = "Normal"
elif bmi < 30:
category = "Overweight"
else:
category = "Obese"
return f"BMI: {bmi:.1f} ({category})"
Definisikan prompt
@mcp.prompt()
def reviewcode(code: str) -> str:
"""Prompt untuk review kode."""
return f"Tolong review kode berikut dan berikan saran perbaikan:\n\n{code}"
if name == "main":
mcp.run()
Menjalankan Server
# Menggunakan stdio transport (default)
python server.py
Menggunakan SSE transport
mcp run server.py --transport sse
Menggunakan streamable HTTP transport
mcp run server.py --transport streamable-http
Definisi Tool dengan Parameter
Tool adalah fitur paling powerful dalam MCP. Berikut cara mendefinisikan tool yang lebih kompleks:
from mcp.server.fastmcp import FastMCP
from typing import Optional
import json
mcp = FastMCP("Advanced Tools Server")
@mcp.tool()
def searchproducts(
query: str,
category: Optional[str] = None,
minprice: Optional[float] = None,
maxprice: Optional[float] = None,
limit: int = 10
) -> str:
"""Mencari produk berdasarkan query dan filter.
Args:
query: Kata kunci pencarian
category: Kategori produk (opsional)
minprice: Harga minimum (opsional)
maxprice: Harga maksimum (opsional)
limit: Jumlah hasil maksimum (default: 10)
"""
# Simulasi pencarian produk
results = {
"query": query,
"filters": {
"category": category,
"minprice": minprice,
"maxprice": maxprice
},
"limit": limit,
"results": [
{"name": "Produk A", "price": 100000, "category": "elektronik"},
{"name": "Produk B", "price": 250000, "category": "fashion"}
]
}
return json.dumps(results, indent=2, ensureascii=False)
@mcp.tool()
def createinvoice(
customername: str,
items: list[dict],
taxrate: float = 0.11
) -> str:
"""Membuat invoice baru.
Args:
customername: Nama pelanggan
items: Daftar item [{name, quantity, price}]
taxrate: Tarif pajak (default 11%)
"""
subtotal = sum(item["price"] item["quantity"] for item in items)
tax = subtotal taxrate
total = subtotal + tax
invoice = {
"customer": customername,
"items": items,
"subtotal": subtotal,
"tax": tax,
"total": total
}
return json.dumps(invoice, indent=2, ensureascii=False)
Membangun MCP Client
Berikut cara membangun MCP client yang terhubung ke server:
# client.py
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdioclient
async def main():
# Konfigurasi koneksi ke server
serverparams = StdioServerParameters(
command="python",
args=["server.py"],
env=None
)
async with stdioclient(serverparams) as (read, write):
async with ClientSession(read, write) as session:
# Inisialisasi koneksi
await session.initialize()
# List semua tools yang tersedia
tools = await session.listtools()
print("Tools tersedia:")
for tool in tools.tools:
print(f" - {tool.name}: {tool.description}")
# List semua resources
resources = await session.listresources()
print("\nResources tersedia:")
for resource in resources.resources:
print(f" - {resource.uri}: {resource.name}")
# Panggil tool
result = await session.calltool(
"calculatebmi",
arguments={"weightkg": 70, "heightm": 1.75}
)
print(f"\nHasil BMI: {result.content[0].text}")
# Baca resource
resourcecontent = await session.readresource("config://app")
print(f"\nConfig: {resourcecontent.contents[0].text}")
if name == "main":
asyncio.run(main())
Transport Types
MCP mendukung beberapa jenis transport untuk komunikasi antara client dan server:
1. Stdio (Standard Input/Output)
Transport default yang paling sederhana. Client menjalankan server sebagai subprocess dan berkomunikasi melalui stdin/stdout.
# Client menggunakan stdio
serverparams = StdioServerParameters(
command="python",
args=["server.py"]
)
Kelebihan: Sederhana, tidak perlu konfigurasi jaringan
Kekurangan: Hanya untuk koneksi lokal
2. SSE (Server-Sent Events)
Transport berbasis HTTP yang memungkinkan koneksi remote.
# Server dengan SSE transport
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("SSE Server")
Jalankan dengan SSE
mcp run server.py --transport sse --port 8080
# Client menggunakan SSE
from mcp.client.sse import sseclient
async with sseclient("http://localhost:8080/sse") as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
3. Streamable HTTP
Transport terbaru yang lebih efisien, mendukung koneksi stateless dan stateful.
# Server dengan streamable HTTP
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("HTTP Server", statelesshttp=True)
Jalankan dengan streamable HTTP
mcp run server.py --transport streamable-http --port 8080
Integrasi dengan Claude Desktop
Untuk menggunakan MCP server dengan Claude Desktop, edit file konfigurasi:
MacOS:~/Library/Application Support/Claude/claudedesktopconfig.json
Windows: %APPDATA%\Claude\claudedesktopconfig.json
Linux: ~/.config/Claude/claudedesktopconfig.json
{
"mcpServers": {
"demo-server": {
"command": "python",
"args": ["/path/to/server.py"],
"env": {
"DATABASEURL": "postgresql://user:pass@localhost/mydb"
}
},
"another-server": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
}
}
}
Setelah menyimpan konfigurasi, restart Claude Desktop. Anda akan melihat ikon tools (palu) di bagian bawah input chat yang menunjukkan tools yang tersedia.
Integrasi dengan Claude Code
Claude Code mendukung MCP server secara native. Anda dapat menambahkan server melalui CLI:
# Menambahkan MCP server ke project scope
claude mcp add db-server -s project -- python /path/to/dbserver.py
Menambahkan dengan environment variables
claude mcp add db-server -s project \
-e DATABASEURL=postgresql://user:pass@localhost/mydb \
-- python /path/to/dbserver.py
Menambahkan server SSE/HTTP remote
claude mcp add remote-server -s user --transport http \
http://api.example.com/mcp
List semua MCP server
claude mcp list
Menghapus MCP server
claude mcp remove db-server
Konfigurasi disimpan di file .mcp.json pada root project:
{
"mcpServers": {
"db-server": {
"command": "python",
"args": ["/path/to/dbserver.py"],
"env": {
"DATABASEURL": "postgresql://user:pass@localhost/mydb"
}
}
}
}
Testing dengan MCP Inspector
MCP Inspector adalah tool visual untuk testing dan debugging MCP server:
# Jalankan Inspector
npx @modelcontextprotocol/inspector
Inspector akan membuka browser di http://localhost:6274
Dengan Inspector, Anda dapat:
- Melihat semua resources, tools, dan prompts yang diekspos server
- Memanggil tools dengan parameter kustom
- Membaca resources
- Memeriksa respons server secara real-time
- Debug masalah koneksi
Anda juga bisa menjalankan Inspector langsung dengan server:
# Langsung test server tertentu
npx @modelcontextprotocol/inspector python server.py
Test server dengan environment variables
DATABASEURL=postgresql://localhost/mydb \
npx @modelcontextprotocol/inspector python server.py
Pertimbangan Keamanan
Keamanan sangat penting saat membangun MCP server. Berikut praktik terbaik:
1. Validasi Input
import re
@mcp.tool()
def querydata(tablename: str, limit: int = 10) -> str:
"""Query data dari tabel tertentu."""
# Validasi nama tabel - hanya alfanumerik dan underscore
if not re.match(r'^[a-zA-Z][a-zA-Z0-9]