LLM kamu pintar tapi terkurung. Dia bisa nulis kode, ngeringkas dokumen, dan jawab pertanyaan, tapi nggak bisa baca file di disk kamu, cek database, atau ambil data live dari API. Function calling ada sih. Tapi tiap provider formatnya beda. OpenAI punya format sendiri. Anthropic juga beda. Ganti model, tulis ulang definisi tool.
Model Context Protocol (MCP) nge-fix masalah ini. Satu standar. LLM apa aja. Tool apa aja.
Apa Itu MCP?
MCP adalah protokol terbuka dari Anthropic, dirilis akhir 2024. Bayangin kayak USB-C buat tool LLM. Daripada wiring tiap tool ke tiap LLM pake kode custom, kamu bikin satu MCP server dan semua client yang kompatibel bisa langsung pakai.
Tiga hal yang bisa diekspos MCP server:
- Tools — fungsi yang dipanggil LLM. Baca file, query database, kirim pesan Slack.
- Resources — data terstruktur yang dibaca LLM. Nilai config, response API, isi file.
- Prompts — template reusable. Checklist code review, instruksi translate, format summarization.
LLM mutusin kapan pakai tool yang mana berdasarkan apa yang kamu tanya. Kamu nggak perlu program workflow-nya. Tinggal definisiin apa yang tool lakukan, model yang cari tahu sisanya.
Prerequisites
- Python 3.10 atau lebih baru (
python --version) - pip atau uv untuk package management
- Node.js 18+ (buat MCP Inspector, alat testing)
- Claude Desktop (opsional, buat testing end-to-end)
Langkah 1: Bikin Project
mkdir mcp-filesystem-server
cd mcp-filesystem-server
python -m venv .venv
source .venv/bin/activate
pip install mcp httpx
Package mcp adalah Python SDK resmi dari Anthropic. httpx buat HTTP async di tool fetch URL.
Langkah 2: Tool Pertama Kamu
Bikin server.py:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Filesystem Tools")
@mcp.tool()
def add(a: float, b: float) -> str:
"""Tambahin dua angka."""
return str(a + b)
if __name__ == "__main__":
mcp.run()
FastMCP cara paling cepet bikin server. Kamu dekorasi fungsi dengan @mcp.tool(), @mcp.resource(), atau @mcp.prompt(). Docstring jadi deskripsi tool yang dibaca LLM. Type hint nentuin skema parameter.
Jalanin:
python server.py
Ini mulai server stdio. Dia nunggu pesan protokol MCP di stdin dan respons di stdout. Belum keliatan apa-apa. Perlu client buat ngomong sama server ini.
Langkah 3: Tool yang Beneran Berguna
Ganti server.py dengan yang beneran ngelakuin sesuatu:
import httpx
import json
from pathlib import Path
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Filesystem Tools")
@mcp.tool()
def read_file(path: str) -> str:
"""Baca isi file di path yang diberikan."""
file_path = Path(path).expanduser().resolve()
if not file_path.exists():
return f"Error: {file_path} tidak ditemukan"
if file_path.is_dir():
return f"Error: {file_path} adalah direktori, bukan file"
if file_path.stat().st_size > 1_000_000:
return f"Error: file terlalu besar ({file_path.stat().st_size} bytes)"
return file_path.read_text()
@mcp.tool()
def list_directory(path: str = ".") -> str:
"""List file dan direktori di path yang diberikan."""
dir_path = Path(path).expanduser().resolve()
if not dir_path.exists():
return f"Error: {dir_path} tidak ditemukan"
if not dir_path.is_dir():
return f"Error: {dir_path} bukan direktori"
items = []
for item in sorted(dir_path.iterdir()):
kind = "dir" if item.is_dir() else "file"
size = item.stat().st_size if item.is_file() else 0
items.append(f"{kind:4s} {size:>10,} {item.name}")
return "\n".join(items)
@mcp.tool()
async def fetch_url(url: str) -> str:
"""Ambil konten dari URL dan kembalikan sebagai teks."""
async with httpx.AsyncClient(timeout=10) as client:
response = await client.get(url, follow_redirects=True)
response.raise_for_status()
return response.text[:5000]
@mcp.tool()
def search_files(directory: str, pattern: str) -> str:
"""Cari file yang cocok dengan pola glob di direktori."""
dir_path = Path(directory).expanduser().resolve()
if not dir_path.is_dir():
return f"Error: {dir_path} bukan direktori"
matches = sorted(dir_path.rglob(pattern))
if not matches:
return f"Tidak ada file yang cocok dengan '{pattern}'"
return "\n".join(str(m) for m in matches[:50])
if __name__ == "__main__":
mcp.run()
Empat tool dalam satu server. LLM sekarang bisa baca file, jelajah direktori, fetch URL, dan cari file berdasarkan pola. Type hint ngasih tahu LLM parameter apa yang diharapkan tiap tool. Docstring ngasih tahu kapan harus dipakai.
Langkah 4: Test dengan MCP Inspector
Nulis server tanpa UI itu nyebelin. MCP Inspector adalah tool browser yang connect ke server kamu dan bikin kamu bisa klik tiap tool:
npx @modelcontextprotocol/inspector python server.py
Buka di http://localhost:5173. Klik Connect, pilih transport (stdio), dan kamu lihat daftar semua tool. Klik tool mana aja, isi parameter, tekan Run. Hasil, error, dan timing muncul di panel.
Ini feedback loop paling cepet buat development. Ubah tool, restart, test. Nggak perlu config Claude Desktop.
Langkah 5: Sambungin ke Claude Desktop
Sekarang sambungin ke LLM beneran.
Cari file config Claude Desktop:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json(kalau pakai build Linux)
{
"mcpServers": {
"filesystem-tools": {
"command": "python",
"args": ["/home/userkamu/mcp-filesystem-server/server.py"]
}
}
}
Path harus absolut. Restart Claude Desktop. Ikon plug kecil muncul dekat input chat. Klik dan kamu lihat server kamu terdaftar dengan jumlah tool-nya.
Coba prompt ini:
Baca file di ~/projects/todo.md dan list 3 prioritas teratas.
Claude panggil read_file, dapet isinya, parse prioritas, dan jawab. Dari sudut pandang Claude, dia baru aja baca file. Dari sudut pandang kamu, kamu baru aja kasih LLM akses filesystem dalam 15 menit.
Kapan Pakai MCP vs Alternatif
MCP nggak selalu jawaban yang tepat.
Pakai MCP kalau:
- Kamu mau tool dipakai di berbagai LLM client (Claude, Cursor, Continue.dev, Zed, agent custom)
- Kamu bangun library tool yang bakal dipakai banyak orang atau tim
- Kamu mau protokol standar yang bisa diadopsi seluruh organisasi
- Kamu butuh resources dan prompts, bukan cuma tools
Pakai function calling langsung (API OpenAI/Anthropic) kalau:
- Kamu bangun satu aplikasi dengan satu provider LLM
- Latency kritis (MCP nambah ~100-200ms buat spawn process)
- Kamu cuma punya 1-2 tool simpel dan nggak butuh overhead protokol
- Kamu prototyping dan pengen sesuatu yang langsung jalan
Pakai LangChain/LangGraph tools kalau:
- Kamu butuh orkestrasi agent multi-step yang kompleks
- Kamu mau built-in memory, streaming, dan observability
- Kamu udah punya codebase LangChain
MCP dan LangChain saling melengkapi. Kamu bisa pakai MCP server sebagai LangChain tools lewat integrasi langchain-mcp.
Kesalahan Umum
Path absolut di config Claude. Selalu. Path relatif gagal tanpa pesan error yang jelas. Aplikasi Claude Desktop jalan dari working directory sendiri.
Nggak handle error di tool. Kalau tool kamu throw exception yang nggak ke-handle, LLM cuma lihat "tool call failed." Return string error daripada nge-raise. LLM baca error dan sering self-correct.
Output terlalu besar. Return 50MB log file bikin protokol crash. Tambahin batas ukuran di tool yang bisa ngasilin hasil gede. Truncate atau paginate.
Izin file. Proses MCP server jalan sebagai user kamu. Tool yang baca file bisa baca apa aja yang user kamu bisa baca. Tool yang nulis file atau ngejalanin command perlu hati-hati. Mulai dari read-only dulu.
Ngebaikan docstring. LLM pakai docstring kamu buat mutusin kapan manggil tool. Docstring yang jelek bikin LLM nggak tahu tool kamu ada. Tulis docstring yang jelasin apa yang tool lakukan dan kapan harus dipakai.
Langkah Selanjutnya
Setelah server kamu jalan, ini langkah natural berikutnya:
- Tambah resources. Resources ngasih LLM akses read-only ke data terstruktur tanpa manggil tool. Nilai config, dokumen API, skema database.
@mcp.resource("config://app")
def get_config() -> str:
return json.dumps({"version": "1.0", "max_file_size": 1_000_000})
- Tambah prompts. Prompts adalah template reusable yang bisa ditarik LLM.
@mcp.prompt()
def code_review(file_path: str, language: str) -> str:
return f"Review {file_path} untuk bug, masalah style, dan performance. Bahasa: {language}."
Jelajahi registry MCP. Komunitas udah bangun server untuk PostgreSQL, SQLite, Google Drive, Slack, GitHub, Brave Search, dan puluhan lainnya. Cek
github.com/modelcontextprotocol/servers.Deploy sebagai HTTP server. Untuk akses remote, ganti ke SSE transport:
mcp.run(transport="sse", port=8080). Client connect lewat HTTP, bukan stdio.
Kesimpulan
LLM kamu sekarang bisa baca file, list direktori, fetch URL, dan cari di filesystem, semua lewat protokol yang dipahami semua client MCP. Nggak ada vendor lock-in. Nggak perlu nulis ulang definisi tool tiap ganti model.
Kekuatan asli MCP keliatan pas kamu chain tool. Minta Claude "cari semua file Python yang dimodifikasi minggu ini, cek TODO comments-nya, dan ringkas apa yang masih harus dikerjain." Dia panggil search_files, lalu read_file di tiap hasil, lalu sintesis jawaban.
Yang kamu bangun selanjutnya terserah. Akses database, integrasi API, otomatisasi deployment. Protokolnya tetap sama. Kamu tinggal nambah tool.