MCP di Produksi: Mengatasi Tantangan Transport, Auth, dan Scaling
Engineering Team
Dari Prototipe ke Produksi: Apa yang Berubah
Membangun MCP server yang berfungsi di laptop Anda cukup mudah. Menjalankannya untuk menangani ribuan sesi AI agent secara bersamaan di seluruh infrastruktur terdistribusi adalah tantangan engineering yang sangat berbeda. Deployment MCP di produksi harus menangani lima masalah yang dapat diabaikan oleh prototipe: skalabilitas transport, autentikasi dan otorisasi, manajemen sesi dalam skala besar, jejak audit, dan orkestrasi multi-server.
Artikel ini adalah panduan teknis untuk tim engineering yang memindahkan MCP server dari development ke produksi. Kami mengasumsikan Anda telah membangun setidaknya satu MCP server dan memahami dasar-dasar protokol. Jika belum, mulailah dengan artikel pendamping kami tentang membangun MCP server pertama Anda.
Skalabilitas Transport: stdio vs SSE vs Streamable HTTP
MCP mendefinisikan tiga mekanisme transport. Memilih yang tepat untuk produksi adalah keputusan arsitektur pertama Anda.
Transport stdio
Transport stdio berkomunikasi melalui stream input/output standar. Aplikasi host menjalankan MCP server sebagai proses anak dan bertukar pesan JSON-RPC melalui stdin/stdout.
Kelebihan:
- Nol konfigurasi jaringan
- Isolasi tingkat proses
- Tidak ada konflik port
- Latensi terendah (tanpa stack jaringan)
Keterbatasan:
- Server harus berjalan di mesin yang sama dengan host
- Satu proses server per sesi client
- Tidak dapat di-load balance
- Tidak ada horizontal scaling
Terbaik untuk: Tool development lokal, ekstensi IDE, aplikasi desktop pengguna tunggal.
Transport SSE (Server-Sent Events)
Transport SSE menggunakan HTTP untuk pesan client-ke-server dan Server-Sent Events untuk pesan server-ke-client. Server berjalan sebagai layanan HTTP.
Kelebihan:
- Dapat diakses melalui jaringan (server remote)
- Kompatibel dengan infrastruktur HTTP yang ada
- Mendukung beberapa client bersamaan
- Bekerja melalui firewall dan proxy
Keterbatasan:
- Streaming unidirectional (server-ke-client saja via SSE)
- Memerlukan session affinity (koneksi stateful)
- Beberapa load balancer kesulitan dengan koneksi SSE yang berumur panjang
- Tidak ada semantik reconnection bawaan dalam protokol
Terbaik untuk: Deployment kecil hingga menengah, tool internal, tim dengan infrastruktur HTTP yang ada.
Transport Streamable HTTP
Streamable HTTP adalah transport terbaru, dirancang khusus untuk deployment produksi. Menggunakan HTTP POST standar untuk semua pesan, dengan SSE streaming opsional untuk operasi yang berjalan lama.
Kelebihan:
- Model request/response sepenuhnya stateless
- Bekerja dengan HTTP load balancer mana pun
- Manajemen sesi bawaan melalui header
Mcp-Session-Id - Mendukung respons streaming dan non-streaming
- Kompatibel dengan CDN dan proxy
Keterbatasan:
- Memerlukan penyimpanan sesi sisi server (Redis, database)
- Overhead per-pesan sedikit lebih tinggi dari stdio
- Transport lebih baru — tooling ekosistem lebih sedikit
Terbaik untuk: Deployment cloud produksi, platform multi-tenant, lingkungan enterprise.
Matriks Perbandingan Transport
| Fitur | stdio | SSE | Streamable HTTP |
|---|---|---|---|
| Akses jaringan | Lokal saja | Remote | Remote |
| Load balancing | Tidak memungkinkan | Session-sticky | HTTP LB standar |
| Horizontal scaling | Tidak | Terbatas | Ya |
| Firewall-friendly | N/A | Ya | Ya |
| Reconnection | N/A | Manual | Bawaan |
| Client bersamaan | 1 | Banyak | Banyak |
| Latensi | Terendah | Rendah | Rendah |
| Statelessness | Stateful | Stateful | Stateless memungkinkan |
| Kesiapan produksi | Dev saja | Menengah | Tinggi |
Autentikasi: Integrasi SSO, API Key, dan OAuth
MCP server di produksi harus mengautentikasi baik aplikasi AI host maupun pengguna akhir atas nama siapa AI bertindak.
OAuth 2.0 untuk Server Remote
Spesifikasi MCP mencakup alur OAuth 2.0 bawaan untuk server remote (berbasis HTTP). Alurnya bekerja sebagai berikut:
- MCP client mengirim permintaan
initializetanpa kredensial. - Server merespons dengan HTTP 401 dan header
WWW-Authenticateyang mengarah ke endpoint otorisasi OAuth-nya. - Aplikasi host membuka browser untuk autentikasi pengguna.
- Setelah autentikasi berhasil, host menerima access token.
- Permintaan MCP berikutnya menyertakan token di header
Authorization: Bearer.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import express from "express";
const app = express();
app.use("/mcp", async (req, res, next) => {
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token) {
res.status(401).json({
error: "unauthorized",
oauth_url: "https://auth.example.com/oauth/authorize",
});
return;
}
const user = await validateToken(token);
if (!user) {
res.status(403).json({ error: "invalid_token" });
return;
}
req.mcpUser = user;
next();
});
Autentikasi API Key
Untuk komunikasi MCP service-to-service (di mana tidak ada pengguna manusia yang terlibat), API key lebih sederhana:
const API_KEYS = new Map([
["sk-prod-abc123", { name: "analytics-service", scopes: ["read"] }],
["sk-prod-def456", { name: "admin-service", scopes: ["read", "write"] }],
]);
function authenticateApiKey(key: string) {
return API_KEYS.get(key) || null;
}
Pola Integrasi SSO
Untuk deployment enterprise, integrasikan dengan SSO yang ada (SAML, OIDC):
User -> AI Host -> MCP Client -> MCP Server -> SSO Provider
|
v
Validasi OIDC token
Ekstrak peran pengguna
Terapkan RBAC tingkat tool
Setiap MCP tool dapat memeriksa peran pengguna yang terautentikasi sebelum mengeksekusi:
server.tool(
"delete_record",
"Hapus record database berdasarkan ID",
{ table: z.string(), id: z.string() },
async ({ table, id }, { authContext }) => {
if (!authContext.roles.includes("admin")) {
return {
content: [{ type: "text", text: "Terlarang: diperlukan peran admin" }],
isError: true,
};
}
// Lanjutkan penghapusan
}
);
Scaling: Sesi Stateful vs Load Balancer
Sesi MCP pada dasarnya stateful: handshake initialize menegosiasikan kemampuan, dan server mungkin mempertahankan konteks di seluruh panggilan tool dalam satu sesi. Ini menciptakan ketegangan dengan horizontal scaling.
Arsitektur Session Store
Ekstrak state sesi dari proses server ke penyimpanan eksternal:
interface McpSession {
id: string;
userId: string;
capabilities: ServerCapabilities;
createdAt: Date;
lastActivityAt: Date;
metadata: Record<string, unknown>;
}
class RedisSessionStore {
constructor(private redis: Redis) {}
async create(session: McpSession): Promise<void> {
await this.redis.set(
`mcp:session:${session.id}`,
JSON.stringify(session),
"EX", 3600
);
}
async get(sessionId: string): Promise<McpSession | null> {
const data = await this.redis.get(`mcp:session:${sessionId}`);
return data ? JSON.parse(data) : null;
}
}
Horizontal Scaling dengan Streamable HTTP
Dengan sesi yang dieksternalisasi dan transport Streamable HTTP, Anda dapat menjalankan beberapa instance MCP server di belakang load balancer standar. Tidak diperlukan routing session-sticky. Instance server mana pun dapat menangani permintaan apa pun dengan memuat sesi dari Redis.
Konfigurasi Auto-Scaling
Contoh Kubernetes HPA untuk MCP server:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mcp-server
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: mcp-server
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Pods
pods:
metric:
name: mcp_active_sessions
target:
type: AverageValue
averageValue: "100"
Jejak Audit dan Logging
Setiap pemanggilan MCP tool di produksi harus dicatat untuk keamanan, kepatuhan, dan debugging.
Skema Structured Logging
interface McpAuditLog {
timestamp: string;
sessionId: string;
userId: string;
toolName: string;
toolInput: Record<string, unknown>;
toolOutput: string;
durationMs: number;
success: boolean;
errorMessage?: string;
ipAddress: string;
userAgent: string;
}
Pertimbangan Kepatuhan
| Persyaratan | Implementasi |
|---|---|
| Akses data GDPR | Catat data pengguna mana yang diakses AI melalui MCP tools |
| Jejak audit SOC 2 | Log immutable dari semua pemanggilan tool dengan timestamp |
| Perlindungan PII | Redaksi field sensitif dalam input tool sebelum logging |
| Retensi data | Tetapkan TTL log sesuai persyaratan kepatuhan Anda |
| Review akses | Catat event autentikasi dan pemeriksaan izin |
Pola Gateway untuk Deployment Multi-Server
Lingkungan enterprise sering memerlukan lusinan MCP server — satu untuk setiap sistem internal. MCP Gateway memusatkan manajemen:
Gateway menyediakan:
- Autentikasi terpadu: Satu alur auth untuk semua server backend.
- Routing namespace tool: Tool diberi prefix dengan nama server (
jira.create_issue,slack.send_message). - Rate limiting terpusat: Batas per-pengguna, per-tool, dan per-server.
- Routing permintaan: Arahkan panggilan tool ke server backend yang sesuai.
- Circuit breaking: Jika server backend tidak sehat, gateway mengembalikan error yang graceful alih-alih menggantung.
FAQ
T: Haruskah saya menggunakan transport stdio atau HTTP di produksi? J: Gunakan Streamable HTTP untuk deployment apa pun yang perlu di-scale melebihi satu mesin. Gunakan stdio hanya untuk integrasi desktop lokal di mana AI host dan MCP server berjalan di mesin yang sama.
T: Berapa banyak sesi bersamaan yang dapat ditangani satu MCP server? J: Dengan Streamable HTTP dan sesi yang dieksternalisasi, satu instance server Node.js biasanya menangani 500-1.000 sesi bersamaan. Dengan server Rust atau Go, 5.000-10.000 dapat dicapai. Scale secara horizontal melebihi itu.
T: Bagaimana cara menangani downtime MCP server?
J: Implementasikan health check (endpoint /health), gunakan Kubernetes liveness/readiness probes, dan konfigurasi gateway Anda dengan circuit breaker. MCP client akan menerima error koneksi yang dapat ditampilkan oleh AI host sebagai “tool sementara tidak tersedia.”
T: Bisakah MCP server memanggil MCP server lain? J: Ya. MCP server juga dapat menjadi MCP client, membuat rantai. Ini adalah dasar komunikasi agent-to-agent. Gunakan pola ini dengan hati-hati — rantai yang dalam meningkatkan latensi dan probabilitas kegagalan.
T: Bagaimana cara mengelola versi API MCP server saya?
J: Gunakan field versi server dalam respons initialize. Untuk perubahan breaking (menghapus tools, mengubah skema), naikkan versi major dan dukung versi lama dan baru selama periode migrasi.
T: Berapa ukuran pesan maksimum untuk MCP? J: Protokol tidak mendefinisikan maksimum, tetapi batas praktis tergantung pada transport. Untuk Streamable HTTP, jaga respons di bawah 10 MB. Untuk stdio, buffer pipe sistem (biasanya 64 KB) mungkin memerlukan chunking untuk respons besar.