Langsung ke konten
Guide

Amankan server MCP Anda: daftar periksa pengembang 8 poin

| 8 min read

43 kerangka kerja agen dikirimkan dengan kerentanan yang tertanam pada tahun 2026. Delapan pemeriksaan untuk mengunci server MCP Anda sebelum agen AI menemukan celahnya.

Server room with colorful network cables representing MCP server infrastructure
Photo by Taylor Vick on Unsplash

Pada bulan November 2026, Barracuda melaporkan bahwa 43 komponen kerangka agen dikirimkan dengan kerentanan yang tertanam melalui kompromi rantai pasokan. Penyerang tidak membobol server. Mereka meracuni alat-alat yang dimiliki agen AI panggilan. 10 Teratas Aplikasi Agen OWASP sekarang mencantumkan Kerentanan Rantai Pasokan dan Penyalahgunaan Alat sebagai khusus kategori.

Server MCP (Model Context Protocol) mengekspos API Anda sebagai alat yang dapat dipanggil untuk asisten AI: Claude Desktop, Kursor, VS Code Copilot, Selancar Angin. Setiap alat yang Anda daftarkan menjadi permukaan serangan. Dan sebagian besar server MCP dikirimkan tanpa autentikasi, tanpa validasi input, dan tanpa pencatatan.

Posting ini adalah daftar periksa 8 poin untuk mengamankan server MCP Anda. Setiap item menyertakan kode kerja yang Anda bisa beradaptasi. Contohnya menggunakan API Botoi untuk validasi skema, hashing, dan decoding JWT, tetapi polanya berlaku untuk server MCP mana pun.

Masalah keamanan MCP dalam satu tabel

Mempertaruhkan Apa yang terjadi Barang daftar periksa
Tidak ada autentikasi pada titik akhir MCP Setiap klien di jaringan memanggil alat apa pun #1 Tambahkan otentikasi
Semua alat terkena semua kunci Agen pemantauan read-only memicu operasi yang merusak #2 Alat cakupan per kunci
Tidak ada validasi masukan Agen mengirim JSON dalam format yang salah; alat mogok atau menjalankan operasi yang tidak diinginkan #3 Validasi dengan Zod
Anotasi alat tidak ada Agen tidak dapat membedakan alat baca-saja dari alat destruktif #4 Tetapkan anotasi
Tidak ada batasan tarif Satu agen perulangan menghabiskan kuota API Anda dalam hitungan menit #5 Batas tarif per agen
Tidak ada jejak audit Anda tidak dapat melacak agen mana yang menyebabkan masalah produksi #6 Catat pemanggilan
Gangguan nyata pada alat Penyerang memodifikasi definisi alat untuk mengalihkan panggilan #7 Pin dan manifes hash
Tidak ada konfirmasi untuk penulisan Agen membuat, menghapus, atau memodifikasi data tanpa tinjauan manusia #8 Operasi destruktif Sandbox

1. Tambahkan autentikasi ke titik akhir MCP Anda

"Ada di localhost" bukan model keamanan. Ekstensi browser, proses lokal, dan kode apa pun yang berjalan mesin yang sama dapat mencapainya localhost:3000. MCP jarak jauh berkembang pesat; Claude Desktop, Kursor, dan Windsurf semuanya mendukung koneksi ke server MCP jarak jauh melalui HTTPS.

Memerlukan token Pembawa pada setiap permintaan. Server MCP Botoi di api.botoi.com/mcp menerima API kunci melalui Authorization tajuk. Tanpa kunci yang valid, Anda mendapatkan 5 permintaan per menit dan 100 per hari; dengan satu, batasannya sesuai dengan rencana Anda.

Jika agen Anda meneruskan JWT dan bukan kunci statis, dekodekan kode tersebut untuk mengekstrak cakupan dan identitas. Begini caranya untuk memeriksa JWT dari header permintaan MCP:

curl -s -X POST https://api.botoi.com/v1/jwt/decode \\
  -H "Content-Type: application/json" \\
  -d '{
    "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZ2VudC1jdXJzb3ItNDIiLCJzY29wZSI6InJlYWQ6ZG5zIHJlYWQ6c3NsIiwiaWF0IjoxNzE3MDAwMDAwfQ.signature"
  }'
{
  "success": true,
  "data": {
    "header": { "alg": "RS256", "typ": "JWT" },
    "payload": {
      "sub": "agent-cursor-42",
      "scope": "read:dns read:ssl",
      "iat": 1717000000
    },
    "signature": "signature"
  }
}

Itu sub klaim mengidentifikasi agen. Itu scope klaim mencantumkan alat apa yang bisa digunakan akses. Verifikasi sisi server tanda tangan sebelum memercayai nilai-nilai ini.

2. Alat cakupan per kunci API

Tidak semua agen membutuhkan semua alat. Agen pemantauan yang memeriksa catatan DNS tidak boleh mengakses a titik akhir pembuatan tempel. Buat daftar yang diizinkan yang memetakan setiap kunci API ke serangkaian alat tertentu.

// Scope tools per API key using an allowlist
interface AgentPermissions {
  allowedTools: Set<string>;
  maxBurst: number;
  dailyLimit: number;
}

const AGENT_PERMISSIONS: Record<string, AgentPermissions> = {
  "key_readonly_monitor": {
    allowedTools: new Set(["lookup_dns", "lookup_ssl", "lookup_ip"]),
    maxBurst: 10,
    dailyLimit: 500,
  },
  "key_full_access": {
    allowedTools: new Set(["*"]),  // wildcard for all tools
    maxBurst: 30,
    dailyLimit: 5000,
  },
};

function canUseTool(apiKey: string, toolName: string): boolean {
  const perms = AGENT_PERMISSIONS[apiKey];
  if (!perms) return false;
  if (perms.allowedTools.has("*")) return true;
  return perms.allowedTools.has(toolName);
}

Server MCP Botoi menampilkan 49 alat yang dikurasi dari 150+ titik akhir API. Kurasi itu sendiri adalah sebuah bentuk pelingkupan: hanya alat yang masuk akal untuk asisten AI yang terdaftar. Server Anda harus melakukan hal yang sama.

3. Validasi input alat dengan skema Zod

Alat MCP menerima JSON sewenang-wenang dari agen. Agen dapat mengirim dimana kamu mengharapkan string, atau menyertakan bidang yang tidak dikenali alat Anda. Validasi setiap input sebelum mengeksekusi.

Server MCP Botoi mengubah definisi jalur OpenAPI menjadi skema Zod saat startup menggunakan schema-builder.ts. Itu buildZodSchema fungsi membaca spesifikasi OpenAPI Anda, peta setiap tipe properti ke tipe Zod, dan menandai bidang yang wajib diisi:

import { z } from "zod";
import { buildZodSchema } from "./schema-builder";

// Build a Zod schema from your OpenAPI spec for each tool
const dnsSchema = z.object(buildZodSchema("/v1/dns/lookup", "post"));

function validateToolInput(toolName: string, input: unknown) {
  const schemas: Record<string, z.ZodTypeAny> = {
    lookup_dns: dnsSchema,
    // ... one schema per tool
  };

  const schema = schemas[toolName];
  if (!schema) {
    throw new Error(\`Unknown tool: \${toolName}\`);
  }

  const result = schema.safeParse(input);
  if (!result.success) {
    return {
      error: "Invalid input",
      issues: result.error.issues.map((i) => ({
        path: i.path.join("."),
        message: i.message,
      })),
    };
  }

  return { data: result.data };
}

Hasilkan skema Zod dari input sampel

Jika Anda tidak memiliki spesifikasi OpenAPI, buat skema Zod dari contoh input alat:

curl -s -X POST https://api.botoi.com/v1/schema/json-to-zod \\
  -H "Content-Type: application/json" \\
  -d '{
    "json": {
      "domain": "github.com",
      "check_mx": true,
      "timeout_ms": 5000
    }
  }'
{
  "success": true,
  "data": {
    "schema": "z.object({ domain: z.string(), check_mx: z.boolean(), timeout_ms: z.number() })"
  }
}

Validasi input terhadap Skema JSON saat runtime

Untuk validasi runtime tanpa Zod, gunakan Skema JSON. Kirim skema dan masukan agen ke /v1/schema/validate:

curl -s -X POST https://api.botoi.com/v1/schema/validate \\
  -H "Content-Type: application/json" \\
  -d '{
    "schema": {
      "type": "object",
      "required": ["domain"],
      "properties": {
        "domain": { "type": "string", "minLength": 1 },
        "record_type": { "type": "string", "enum": ["A", "AAAA", "MX", "TXT", "CNAME", "NS"] }
      },
      "additionalProperties": false
    },
    "data": { "domain": "stripe.com", "record_type": "MX" }
  }'

Pengembalian masukan yang valid:

{
  "success": true,
  "data": {
    "valid": true,
    "errors": []
  }
}

Jika ada agen yang lewat "record_type": "INVALID", Anda mendapatkan kesalahan yang dapat ditindaklanjuti sebelum alat Anda berjalan:

{
  "success": true,
  "data": {
    "valid": false,
    "errors": [
      {
        "path": "/record_type",
        "message": "must be equal to one of the allowed values"
      }
    ]
  }
}

4. Atur anotasi alat

Protokol MCP mendefinisikan empat petunjuk anotasi: readOnlyHint, destructiveHint, idempotentHint, Dan openWorldHint. Ini memberi tahu agen apakah suatu alat membaca data, mengubah status, aman untuk mencoba lagi, atau menghubungi layanan eksternal. Kebanyakan server MCP mengabaikannya.

Server MCP Botoi memberi anotasi pada seluruh 49 alat. Berikut tampilan praktiknya:

// curated-tools.ts (from Botoi's MCP server)
export const CURATED_TOOLS: Record<string, CuratedTool> = {
  lookup_dns: {
    path: "/v1/dns/lookup",
    method: "post",
    title: "DNS Lookup",
    description: "Query DNS records for a domain.",
    annotations: {
      readOnlyHint: true,   // reads data, changes nothing
      openWorldHint: true,  // contacts external DNS servers
    },
  },
  storage_paste_create: {
    path: "/v1/paste/create",
    method: "post",
    title: "Create Paste",
    description: "Store text content and return a short URL.",
    annotations: {
      destructiveHint: true,  // creates new data
      idempotentHint: false,  // each call creates a new paste
    },
  },
};

Agen yang menghormati anotasi akan menghindari memanggil alat yang merusak tanpa konfirmasi dan lebih memilih alat idempoten ketika mencoba kembali permintaan yang gagal. Atur di setiap alat.

Anotasi Arti Contoh
readOnlyHint: true Alat membaca data, tidak mengubah apa pun Pencarian DNS, pemeriksaan SSL, geolokasi IP
destructiveHint: true Alat membuat, memperbarui, atau menghapus data Buat tempel, buat URL pendek, kirim webhook
idempotentHint: true Aman untuk menelepon berkali-kali dengan masukan yang sama Pembuatan hash, pemformatan JSON, konversi unit
openWorldHint: true Alat menghubungi layanan eksternal DNS melalui HTTPS, WHOIS, ekstraksi metadata URL

5. Batas tarif per identitas agen

Satu agen nakal yang terjebak dalam putaran percobaan ulang tidak akan menghabiskan seluruh kuota API Anda. Pembatasan tarif standar berdasarkan alamat IP saja tidak cukup; beberapa agen dapat berbagi IP yang sama, dan satu agen dapat merotasi IP.

Ekstrak identitas agen dari kunci API atau JWT, lalu terapkan batas per identitas menggunakan jendela geser atau ember token yang disimpan di KV:

// Hono middleware for per-agent rate limiting
import type { Context, Next } from "hono";

const BURST_LIMIT = 5;   // requests per minute
const DAILY_LIMIT = 100;  // requests per day

async function rateLimitAgent(c: Context, next: Next) {
  // Extract agent identity from API key or JWT
  const apiKey = c.req.header("Authorization")?.replace("Bearer ", "");
  const agentId = apiKey || c.req.header("X-Forwarded-For") || "anonymous";

  // Check burst limit (sliding window in KV)
  const burstKey = \`rate:\${agentId}:burst\

Middleware autentikasi Botoi menerapkan dua lapisan: batas burst (5 permintaan per menit) dan batas harian (100 permintaan per hari) untuk akses anonim. Kunci yang diautentikasi mendapatkan batas yang lebih tinggi berdasarkan kuncinya Tingkat berlangganan Stripe. Terapkan pola dua lapis yang sama ke server MCP Anda.

6. Catat setiap pemanggilan alat dengan atribusi agen

Ketika terjadi kesalahan dalam produksi, Anda perlu menjawab tiga pertanyaan: agen mana yang menelepon alat, kapan, dan dengan masukan apa. Tanpa log pemanggilan, Anda melakukan debug secara buta.

Hash masukan alih-alih menyimpan argumen mentah. Ini memberi Anda cukup untuk mengkorelasikan dan menghapus duplikat tanpa mencatat data sensitif:

// Log every tool invocation with agent identity
interface ToolInvocationLog {
  timestamp: string;
  agent_id: string;
  tool_name: string;
  input_hash: string;   // SHA-256 of the input (not the raw input)
  duration_ms: number;
  status: "success" | "error";
}

async function logToolInvocation(
  agentId: string,
  toolName: string,
  input: unknown,
  startTime: number,
  status: "success" | "error"
) {
  const inputStr = JSON.stringify(input);
  const inputHash = await crypto.subtle.digest(
    "SHA-256",
    new TextEncoder().encode(inputStr)
  );
  const hashHex = Array.from(new Uint8Array(inputHash))
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");

  const log: ToolInvocationLog = {
    timestamp: new Date().toISOString(),
    agent_id: agentId,
    tool_name: toolName,
    input_hash: hashHex,
    duration_ms: Date.now() - startTime,
    status,
  };

  // Send to your logging pipeline (Datadog, Loki, Cloudflare Logpush)
  console.log(JSON.stringify(log));
}

Kirim log terstruktur ini ke pipeline Anda yang ada (Datadog, Grafana Loki, Cloudflare Logpush). Buat peringatan untuk pola yang tidak biasa: agen tunggal melakukan 10x volume panggilan normal, atau hanya baca agen mencoba memanggil alat destruktif.

7. Sematkan definisi alat dan periksa integritasnya

Laporan Barracuda menemukan penyerang memasukkan definisi alat berbahaya ke dalam kerangka agen melalui ketergantungan yang dikompromikan. Jika seseorang mengubah manifes alat MCP Anda (nama, deskripsi, atau parameter skema), agen akan memanggil alat dengan perilaku berbeda dari yang Anda inginkan.

Hash manifes alat Anda pada waktu pembuatan. Saat memulai, hitung ulang hash dan bandingkan:

import crypto from "node:crypto";
import Botoi from "@botoi/sdk";

const botoi = new Botoi();

// Your tool manifest (the source of truth)
const tools = [
  { name: "dns_lookup", path: "/v1/dns/lookup" },
  { name: "ip_lookup", path: "/v1/ip/lookup" },
  { name: "email_validate", path: "/v1/email/validate" },
  // ... all your tools
];

const manifest = JSON.stringify(tools);

// Hash it at build time and store the expected hash
const EXPECTED_HASH = "a3f2b8c1d4e5f6..."; // from your CI build

// At startup, verify integrity
function verifyManifestIntegrity() {
  const currentHash = crypto
    .createHash("sha256")
    .update(manifest)
    .digest("hex");

  if (currentHash !== EXPECTED_HASH) {
    throw new Error(
      \`Tool manifest tampered. Expected \${EXPECTED_HASH}, got \${currentHash}\`
    );
  }

  console.log("Tool manifest integrity verified.");
}

// Or use the Botoi API for environments without Node crypto
async function verifyWithApi() {
  const result = await botoi.hash.sha256({ input: manifest });
  if (result.data.hash !== EXPECTED_HASH) {
    throw new Error("Tool manifest tampered.");
  }
}

Hasilkan hash dengan Botoi API

Untuk lingkungan CI atau runtime edge tanpa node:crypto:

curl -s -X POST https://api.botoi.com/v1/hash \\
  -H "Content-Type: application/json" \\
  -d '{
    "text": "[{\\"name\\":\\"dns_lookup\\",\\"path\\":\\"/v1/dns/lookup\\"},{\\"name\\":\\"ip_lookup\\",\\"path\\":\\"/v1/ip/lookup\\"}]",
    "algorithm": "sha256"
  }'
{
  "success": true,
  "data": {
    "hash": "a3f2b8c1d4e5f67890abcdef1234567890abcdef1234567890abcdef12345678",
    "algorithm": "sha256"
  }
}

Simpan hash yang diharapkan sebagai variabel lingkungan. Bandingkan pada waktu penerapan. Jika hashnya berbeda, memblokir penerapan.

8. Operasi destruktif sandbox

Alat yang menulis data, memicu efek samping, atau menghubungi layanan eksternal memerlukan alur konfirmasi. Jangan biarkan agen membuat 1.000 pasta atau mengaktifkan webhook tanpa peninjauan manusia.

// Confirmation flow for destructive MCP tools
interface ToolResult {
  content: Array<{ type: string; text: string }>;
  isError?: boolean;
}

function handleDestructiveTool(
  toolName: string,
  input: Record<string, unknown>,
  confirmed: boolean
): ToolResult {
  const destructiveTools = new Set([
    "paste_create",
    "short_url_create",
    "webhook_inbox_create",
  ]);

  if (!destructiveTools.has(toolName)) {
    // Non-destructive: execute immediately
    return executeTool(toolName, input);
  }

  if (!confirmed) {
    // Return a preview instead of executing
    return {
      content: [{
        type: "text",
        text: JSON.stringify({
          action: "confirmation_required",
          tool: toolName,
          input,
          message: \`This tool will create new data. Pass "confirmed": true to proceed.\`,
        }),
      }],
    };
  }

  // Confirmed: execute the destructive operation
  return executeTool(toolName, input);
}

Polanya jelas: alat destruktif mengembalikan pratinjau pada panggilan pertama. Agen itu menunjukkan pratinjau kepada pengguna. Hanya setelah pengguna mengonfirmasi, agen mengirim panggilan kedua "confirmed": true.

Untuk alat yang menghubungi layanan eksternal (openWorldHint: true), pertimbangkan untuk menambahkan batas waktu dan pemutus sirkuit. Jika API eksternal lambat atau tidak berfungsi, server MCP Anda tidak akan berfungsi bertahan selamanya menunggu jawaban.

Bagaimana server MCP Botoi menerapkan pemeriksaan ini

Server MCP Botoi di api.botoi.com/mcp berfungsi sebagai referensi kerja untuk ini daftar periksa. Berikut cara setiap item dipetakan:

Barang daftar periksa Bagaimana Botoi melakukannya
Otentikasi Kunci API melalui Authorization tajuk; akses anonim dengan batasan tarif yang ketat
Pelingkupan alat 49 alat yang dikurasi dari 150+ titik akhir; hanya alat yang sesuai dengan agen yang terdaftar
Validasi masukan schema-builder.ts mengubah skema OpenAPI menjadi Zod; memvalidasi sebelum dieksekusi
Anotasi alat Setiap alat masuk curated-tools.ts memiliki readOnlyHint, destructiveHint, dll.
Pembatasan tarif 5 permintaan/mnt burst + 100 permintaan/hari batas anonim melalui KV; batas yang lebih tinggi per tingkat kunci API
Pencatatan Log observasi Cloudflare Workers untuk setiap permintaan dengan atribusi agen
Tunjukkan integritas Definisi alat menggunakan TypeScript yang dikontrol versi; disebarkan melalui CI tanpa mutasi runtime
Kotak pasir yang merusak Alat penyimpanan (tempel, url pendek, webhook) terpisah dari alat pencarian baca-saja; anotasi menandakan risiko

Anda dapat terhubung ke server MCP Botoi dari Claude Desktop, Claude Code, Cursor, VS Code, atau Windsurf. Itu halaman pengaturan MCP memiliki konfigurasi untuk setiap klien.

Daftar periksa keamanan server MCP Anda

Berikut daftar periksa selengkapnya, ringkas. Cetak, sematkan, atau tempelkan ke runbook tim Anda:

  • Memerlukan autentikasi pada setiap titik akhir MCP (Token pembawa, kunci API, atau JWT)
  • Petakan setiap kunci API ke daftar alat yang diizinkan
  • Validasi setiap input alat dengan skema Zod atau Skema JSON sebelum dieksekusi
  • Beri anotasi pada setiap alat dengan readOnlyHint, destructiveHint, idempotentHint, Dan openWorldHint
  • Batas tarif per identitas agen, bukan per IP; gunakan batas burst dan harian
  • Catat setiap pemanggilan alat dengan ID agen, nama alat, hash masukan, durasi, dan status
  • Hash manifes alat Anda pada waktu pembuatan; verifikasi saat startup dan blokir penerapan yang dirusak
  • Kembalikan pratinjau dari alat perusak; memerlukan konfirmasi eksplisit sebelum mengeksekusi

43 kerangka kerja agen dikirimkan dengan kerentanan yang tertanam pada tahun 2026. Server MCP adalah target berikutnya. Kedelapan pemeriksaan di atas tidak akan membuat server Anda kebal, namun akan menutup celah dari penyerang eksploitasi terlebih dahulu: titik akhir terbuka, masukan yang tidak divalidasi, dan pemanggilan yang tidak terlihat.

FAQ

Apakah server MCP memerlukan otentikasi?
Ya. Kebanyakan server MCP dikirimkan tanpa autentikasi, artinya klien mana pun yang mencapai titik akhir dapat memanggil alat apa pun. Seiring berkembangnya adopsi MCP jarak jauh, Anda memerlukan kunci API atau autentikasi berbasis JWT di setiap titik akhir. Hanya localhost bukanlah jaminan keamanan; proses lokal dan ekstensi browser juga dapat menjangkau localhost.
Apa yang dimaksud dengan anotasi alat MCP dan mengapa itu penting?
Anotasi alat adalah petunjuk metadata yang ditentukan dalam protokol MCP: readOnlyHint, destruktifHint, idempotentHint, dan openWorldHint. Mereka memberi tahu agen AI apakah suatu alat membaca data, mengubah status, aman untuk dicoba ulang, atau menghubungi layanan eksternal. Agen menggunakan petunjuk ini untuk membuat keputusan yang lebih aman tentang alat mana yang harus dipanggil dan dalam urutan apa.
Bagaimana cara saya membatasi tarif agen AI yang menelepon server MCP saya?
Tetapkan identitas kepada setiap agen (atau kunci API) dan terapkan batas tingkat per identitas. Gunakan algoritma token bucket atau jendela geser. Lacak permintaan di toko KV atau Redis. Server MCP milik Botoi menerapkan 5 permintaan per menit burst dan 100 permintaan per hari untuk akses anonim, dengan batas lebih tinggi untuk kunci yang diautentikasi.
Bisakah saya memvalidasi input alat MCP dengan Zod?
Ya. Alat MCP menerima JSON sewenang-wenang dari agen. Tentukan skema Zod untuk bentuk masukan yang diharapkan dari setiap alat dan validasi sebelum mengeksekusi. Anda dapat membuat skema Zod dari sampel JSON menggunakan titik akhir Botoi /v1/schema/json-to-zod, atau mengonversi definisi jalur OpenAPI ke objek Zod seperti yang dilakukan oleh Schema-builder.ts Botoi.
Bagaimana cara mendeteksi gangguan pada manifes alat MCP saya?
Hash manifes alat Anda dengan SHA-256 dan simpan hashnya. Sebelum setiap server dimulai atau diterapkan, hitung ulang hashnya dan bandingkan. Jika hashnya berbeda, seseorang (atau sesuatu) mengubah definisi alat Anda. Anda dapat menghitung hash SHA-256 melalui titik akhir Botoi /v1/hash atau dengan pustaka kripto asli.

Mulai membangun dengan botoi

150+ endpoint API untuk pencarian, pemrosesan teks, pembuatan gambar, dan utilitas developer. Paket gratis, tanpa kartu kredit.