Tutorial Membangun MCP Server dengan Python: Hubungkan Internal API ke LLM
AP
Adrian Prat

Dipublikasikan 20 Juni 2026

Tutorial Membangun MCP Server dengan Python: Hubungkan Internal API ke LLM

Model Context Protocol (MCP) sedang mengubah cara developer menghubungkan AI dengan sistem internal. Alih-alih menyalin data manual ke chatbot, MCP memungkinkan LLM seperti Claude berkomunikasi langsung dengan API, database, dan service yang kamu miliki. Artikel ini adalah panduan praktis membangun MCP server dengan Python menggunakan library FastMCP.

Berdasarkan tutorial dari DevClubhouse, kita akan membuat server yang mengekspos tiga tool utama: pencarian customer, fetch order, dan pembuatan support ticket. Hasil akhirnya adalah AI agent yang bisa mengakses internal API-mu dengan type safety penuh tanpa pernah melihat credential langsung.

Apa itu MCP dan Mengapa Developer Perlu Memahaminya

MCP adalah protokol terbuka dari Anthropic yang menyediakan cara standar untuk menghubungkan AI dengan sumber data eksternal. Bayangkan seperti USB-C untuk integrasi AI: satu konektor yang bisa dipakai untuk database, API, file system, atau tool lainnya. Dengan MCP, Claude Desktop, Cursor, atau agent custom bisa memanggil function yang kamu definisikan dengan schema yang jelas.

Prasyarat dan Setup Proyek

Sebelum mulai, pastikan environment-mu sudah siap:

  • Python 3.10 atau lebih baru

  • pip atau uv untuk manajemen paket

  • Node.js 18+ (dibutuhkan oleh mcp dev)

  • Claude Desktop terbaru (untuk end-to-end testing)

Buat direktori proyek baru dan aktifkan virtual environment:

mkdir mcp-internal-api && cd mcp-internal-api
python -m venv .venv
source .venv/bin/activate
pip install "mcp[cli]" httpx python-dotenv

Library mcp[cli] menyediakan command line inspector, sementara httpx menangani HTTP request async ke backend. Buat file .env dan pastikan masuk ke .gitignore:

API_BASE_URL=https://api.corp.example.com
API_KEY=sk-your-real-token-here

Langkah 1: Inisialisasi Server dengan FastMCP

Buat file server.py dengan struktur dasar berikut:

import os
import httpx
from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP

load_dotenv()

mcp = FastMCP("internal-api")

_BASE = os.environ["API_BASE_URL"]
_KEY  = os.environ["API_KEY"]

def _auth_headers() -> dict[str, str]:
    return {"Authorization": f"Bearer {_KEY}", "Accept": "application/json"}

Objek FastMCP adalah entry point server-mu. Semua tool yang didaftarkan dengan decorator @mcp.tool() akan otomatis terekspos ke client dengan JSON Schema yang digenerate dari type annotation Python.

Langkah 2: Menambahkan Tool search_customers

Tool pertama adalah pencarian customer. Perhatikan penggunaan type annotation dan docstring yang jelas:

@mcp.tool()
async def search_customers(query: str, limit: int = 10) -> list[dict]:
    """Search customers by name or email. Returns a list of customer records."""
    async with httpx.AsyncClient() as client:
        r = await client.get(
            f"{_BASE}/customers",
            headers=_auth_headers(),
            params={"q": query, "limit": limit},
            timeout=10.0,
        )
        r.raise_for_status()
        return r.json()

Type annotation list[dict] dan docstring akan dikonversi FastMCP menjadi JSON Schema. LLM membaca schema ini sebelum memanggil tool, sehingga parameter selalu terstruktur dengan benar.

Langkah 3: Menambahkan Tool get_order dan create_support_ticket

Lanjutkan dengan dua tool tambahan. Tool get_order mengambil detail order berdasarkan ID:

@mcp.tool()
async def get_order(order_id: str) -> dict:
    """Fetch a single order by its ID."""
    async with httpx.AsyncClient() as client:
        r = await client.get(
            f"{_BASE}/orders/{order_id}",
            headers=_auth_headers(),
            timeout=10.0,
        )
        r.raise_for_status()
        return r.json()

Untuk create_support_ticket, tambahkan validasi enum pada priority:

@mcp.tool()
async def create_support_ticket(
    customer_id: str,
    subject: str,
    body: str,
    priority: str = "normal",
) -> dict:
    """Open a support ticket for a customer."""
    if priority not in {"low", "normal", "high"}:
        raise ValueError(f"priority must be low/normal/high, got '{priority}'")
    async with httpx.AsyncClient() as client:
        r = await client.post(
            f"{_BASE}/tickets",
            headers=_auth_headers(),
            json={
                "customer_id": customer_id,
                "subject": subject,
                "body": body,
                "priority": priority,
            },
            timeout=10.0,
        )
        r.raise_for_status()
        return r.json()

Langkah 4: Menjalankan Server dan Inspeksi Lokal

Tutup file dengan blok berikut:

if __name__ == "__main__":
    mcp.run()

Jalankan inspector untuk memverifikasi schema tanpa membuka Claude Desktop:

mcp dev server.py

Perintah ini akan membuka browser dengan daftar tool yang terekspos. Kamu bisa mencoba memanggil search_customers dengan query alice dan memastikan response JSON muncul tanpa error import.

Langkah 5: Integrasi ke Claude Desktop

Tambahkan konfigurasi server ke Claude Desktop. Gunakan absolute path karena Claude Desktop menjalankan clean shell:

{
  "mcpServers": {
    "internal-api": {
      "command": "/absolute/path/to/.venv/bin/python",
      "args": ["/absolute/path/to/server.py"],
      "env": {
        "API_BASE_URL": "https://api.corp.example.com",
        "API_KEY": "sk-your-real-token-here"
      }
    }
  }
}

Path file konfigurasi bervariasi berdasarkan OS:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Restart Claude Desktop, buka conversation baru, dan coba prompt: Search for customers named smith, then open a high-priority support ticket for the first result. Claude akan otomatis memanggil search_customers dan create_support_ticket secara berurutan.

Kesimpulan dan Best Practices

Membangun MCP server dengan Python dan FastMCP memberikan keuntungan signifikan: type safety otomatis, schema generation, dan isolasi credential dari model. Pastikan selalu menyimpan API key di environment variable, menggunakan raise_for_status() untuk error handling, dan menulis docstring yang jelas karena itu menjadi instruksi yang dibaca LLM.

Untuk referensi lebih lanjut, kunjungi tutorial asli di DevClubhouse dan dokumentasi resmi Model Context Protocol.