Перейти к содержимому
Guide

Защитите свой сервер MCP: контрольный список для разработчиков из 8 пунктов

| 8 min read

В 2026 году было выпущено 43 агентских платформы со встроенными уязвимостями. Восемь проверок для блокировки вашего сервера MCP, прежде чем ИИ-агент обнаружит бреши.

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

В ноябре 2026 года Barracuda сообщила, что 43 компонента агентской среды поставляются со встроенными уязвимостями. через компромисс в цепочке поставок. Злоумышленники не взламывали серверы. Они отравили инструменты, которыми пользовались агенты ИИ. позвони. В списке 10 лучших агентских приложений OWASP теперь указаны уязвимости цепочки поставок и неправильное использование инструментов. категории.

Серверы MCP (Model Context Protocol) предоставляют ваши API как вызываемые инструменты для помощников искусственного интеллекта: Claude Desktop, Курсор, VS Code Copilot, Виндсерфинг. Каждый зарегистрированный вами инструмент становится поверхностью атаки. И большинство серверов MCP поставляется без аутентификации, проверки ввода и ведения журнала.

Этот пост представляет собой контрольный список из 8 пунктов по обеспечению безопасности вашего сервера MCP. Каждый элемент включает в себя рабочий код, который вы можете адаптироваться. В примерах используется Ботой API для проверки схемы, хеширования, и декодирование JWT, но шаблоны применимы к любому серверу MCP.

Проблема безопасности MCP в одной таблице

Риск Что происходит Пункт контрольного списка
Нет аутентификации на конечной точке MCP Любой клиент в сети вызывает любой инструмент #1 Добавьте аутентификацию
Все инструменты доступны всем клавишам Агент мониторинга, доступный только для чтения, запускает деструктивные операции № 2. Инструменты для каждого ключа
Нет проверки ввода Агенты отправляют неверный формат JSON; инструменты выходят из строя или выполняют непредвиденные операции #3 Подтвердить с Зодом
Отсутствуют аннотации к инструментам Агенты не могут отличить инструменты, доступные только для чтения, от деструктивных. #4 Установите аннотации
Нет ограничений по ставкам Один агент цикла исчерпает вашу квоту API за считанные минуты. #5 Ограничение скорости на агента
Нет контрольного журнала Вы не можете отследить, какой агент вызвал производственную проблему. #6 Журнал вызовов
Подделка манифеста инструмента Злоумышленник изменяет определения инструментов для перенаправления вызовов №7. Манифесты пинов и хэшей
Нет подтверждения записи Агент создает, удаляет или изменяет данные без проверки человеком. #8 Деструктивные операции в песочнице

1. Добавьте аутентификацию в конечную точку MCP.

«Это на локальном хосте» — это не модель безопасности. Расширения браузера, локальные процессы и любой код, работающий на та же машина может достичь localhost:3000. Удаленная MCP быстро растет; Клод Рабочий стол, Курсор, и Windsurf поддерживают подключение к удаленным серверам MCP через HTTPS.

Требовать токен на предъявителя при каждом запросе. Сервер MCP Ботоя по адресу api.botoi.com/mcp принимает API ключи через Authorization заголовок. Без действующего ключа вы получаете 5 запросов в минуту. и 100 в день; с одним лимиты масштабируются в соответствии с вашим планом.

Если ваши агенты передают JWT вместо статических ключей, декодируйте их, чтобы извлечь области и идентификаторы. Вот как чтобы проверить JWT из заголовка запроса 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"
  }
}

The sub утверждение идентифицирует агента. scope утверждает списки, какие инструменты он может доступ. Прежде чем доверять этим значениям, проверьте подпись на стороне сервера.

2. Инструменты для каждого ключа API

Не каждому агенту нужны все инструменты. Агент мониторинга, проверяющий записи DNS, никогда не должен иметь доступ к конечная точка создания вставки. Создавайте белые списки, которые сопоставляют каждый ключ API с определенным набором инструментов.

// 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);
}

Сервер MCP Botoi предоставляет 49 тщательно подобранных инструментов из более чем 150 конечных точек API. Курирование само по себе является формой объема: регистрируются только те инструменты, которые имеют смысл для ИИ-помощников. Ваш сервер должен сделать то же самое.

3. Проверка входных данных инструмента с помощью схем Zod.

Инструменты MCP принимают произвольный JSON от агентов. Агент может отправить где ты ожидать строку или включать поля, которые ваш инструмент не распознает. Проверяйте каждый ввод перед выполнением.

Сервер MCP Botoi преобразует определения путей OpenAPI в схемы Zod при запуске, используя schema-builder.ts. buildZodSchema функция читает вашу спецификацию OpenAPI, отображает каждый тип свойства соответствует типу Zod и отмечает обязательные поля:

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 };
}

Генерация схем Zod на основе образцов входных данных

Если у вас нет спецификации OpenAPI, сгенерируйте схемы Zod на основе входных данных инструмента:

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() })"
  }
}

Проверка входных данных на соответствие схеме JSON во время выполнения.

Для проверки времени выполнения без Zod используйте схему JSON. Отправьте схему и входные данные агента в /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" }
  }'

Допустимые входные данные:

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

Если агент проходит "record_type": "INVALID", вы получите ошибки, требующие принятия мер, до запуска инструмента:

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

4. Установите аннотации к инструменту

Протокол MCP определяет четыре подсказки аннотации: readOnlyHint, destructiveHint, idempotentHint, и openWorldHint. Они сообщают агентам, считывает ли инструмент данные, изменяет состояние, можно безопасно повторить попытку или обращается к внешним службам. Большинство серверов MCP игнорируют их.

Сервер MCP Botoi аннотирует все 49 инструментов. Вот как это выглядит на практике:

// 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
    },
  },
};

Агенты, уважающие аннотации, будут избегать вызова деструктивных инструментов без подтверждения и предпочитают идемпотентные инструменты при повторных неудачных запросах. Установите их на каждый инструмент.

Аннотация Значение Пример
readOnlyHint: true Инструмент читает данные, ничего не меняет Поиск DNS, проверка SSL, геолокация IP
destructiveHint: true Инструмент создает, обновляет или удаляет данные Создать вставку, создать короткий URL-адрес, отправить вебхук
idempotentHint: true Безопасно звонить несколько раз с одним и тем же вводом Генерация хеша, форматирование JSON, преобразование единиц измерения
openWorldHint: true Инструмент связывается с внешними службами DNS через HTTPS, WHOIS, извлечение метаданных URL-адресов

5. Ограничение скорости на личность агента

Один мошеннический агент, застрявший в цикле повторных попыток, не должен исчерпать всю квоту API. Стандартное ограничение скорости по IP-адресу недостаточно; несколько агентов могут использовать один и тот же IP-адрес, а один агент может менять IP-адреса.

Извлеките идентификатор агента из ключа API или JWT, а затем примените ограничения для каждого идентификатора с помощью скользящего окна. или корзина токенов, хранящаяся в 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\

Промежуточное программное обеспечение аутентификации Botoi обеспечивает два уровня: пакетный лимит (5 запросов в минуту) и дневной лимит. (100 запросов в день) для анонимного доступа. Аутентифицированные ключи имеют более высокие ограничения в зависимости от их Уровень подписки Stripe. Примените тот же двухуровневый шаблон к вашему серверу MCP.

6. Регистрируйте каждый вызов инструмента с указанием агента.

Когда на производстве что-то идет не так, нужно ответить на три вопроса: какой агент какой звонил инструмент, когда и с каким входом. Без журналов вызовов вы выполняете отладку вслепую.

Хешируйте входные данные вместо хранения необработанных аргументов. Это дает вам достаточно для корреляции и дедупликации без регистрации конфиденциальных данных:

// 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));
}

Отправьте эти структурированные журналы в существующий конвейер (Datadog, Grafana Loki, Cloudflare Logpush). Создавайте оповещения о необычных закономерностях: один оператор совершает в 10 раз больше обычного объема вызовов, либо агент, доступный только для чтения. агент пытается вызвать деструктивные инструменты.

7. Закрепите определения инструмента и проверьте целостность.

В отчете Barracuda обнаружено, что злоумышленники внедряют определения вредоносных инструментов в структуры агентов через нарушенные зависимости. Если кто-то изменяет манифест вашего инструмента MCP (имена, описания или параметры схемы), агенты будут вызывать инструменты с другим поведением, чем вы предполагали.

Хешируйте манифест инструмента во время сборки. При запуске пересчитайте хэш и сравните:

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.");
  }
}

Сгенерируйте хеш с помощью Botoi API

Для сред CI или периферийных сред без 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"
  }
}

Сохраните ожидаемый хеш как переменную среды. Сравните его во время развертывания. Если хеши расходятся, заблокировать развертывание.

8. Деструктивные операции в песочнице

Инструментам, которые записывают данные, вызывают побочные эффекты или обращаются к внешним службам, необходим поток подтверждения. Не позволяйте агенту создавать 1000 вставок или запускать веб-перехватчики без проверки человеком.

// 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);
}

Схема проста: деструктивные инструменты возвращают предварительный просмотр при первом вызове. Агент показывает предварительный просмотр пользователю. Только после того, как пользователь подтвердит, агент отправляет второй звонок с "confirmed": true.

Для инструментов, которые обращаются к внешним службам (openWorldHint: true), рассмотрите возможность добавления тайм-аут и автоматический выключатель. Если внешний API работает медленно или не работает, ваш сервер MCP не должен висеть вечно, ожидая ответа.

Как сервер MCP Botoi применяет эти проверки

Сервер MCP Ботоя по адресу api.botoi.com/mcp служит рабочей ссылкой для этого контрольный список. Вот как отображается каждый элемент:

Пункт контрольного списка Как это делает Ботой
Аутентификация Ключи API через Authorization заголовок; анонимный доступ со строгими ограничениями скорости
Обзор инструмента 49 тщательно подобранных инструментов из более чем 150 конечных точек; регистрируются только инструменты, подходящие для агента
Проверка ввода schema-builder.ts преобразует схемы OpenAPI в Zod; проверяет перед выполнением
Аннотации к инструментам Каждый инструмент в curated-tools.ts имеет readOnlyHint, destructiveHint, и т. д.
Ограничение скорости 5 запросов в минуту в пакетном режиме + 100 запросов в день анонимно через KV; более высокие ограничения на уровень ключей API
Ведение журнала Журналы наблюдения Cloudflare Workers для каждого запроса с атрибуцией агента
Проявите целостность Определения инструментов написаны на языке TypeScript с контролем версий; развертывается через CI без мутаций во время выполнения
Деструктивная песочница Storage tools (paste, short-url, webhook) are separate from read-only lookup tools; аннотации сигнализируют о риске

Вы можете подключиться к серверу MCP Botoi из Claude Desktop, Claude Code, Cursor, VS Code или Windsurf. Страница настройки MCP имеет конфигурацию для каждого клиента.

Контрольный список безопасности вашего сервера MCP

Вот полный контрольный список в сокращенном виде. Распечатайте его, прикрепите или вставьте в Runbook вашей команды:

  • Требовать аутентификацию на каждой конечной точке MCP (токен носителя, ключ API или JWT).
  • Сопоставьте каждый ключ API с разрешенным списком разрешенных инструментов.
  • Перед выполнением проверяйте каждый ввод инструмента с помощью схем Zod или схемы JSON.
  • Аннотируйте каждый инструмент с помощью readOnlyHint, destructiveHint, idempotentHint, и openWorldHint
  • Ограничение скорости для каждого идентификатора агента, а не для каждого IP-адреса; используйте как взрывные, так и ежедневные ограничения
  • Регистрируйте каждый вызов инструмента с указанием идентификатора агента, имени инструмента, входного хеша, продолжительности и статуса.
  • Хешируйте манифест вашего инструмента во время сборки; проверять при запуске и блокировать несанкционированные развертывания
  • Return previews from destructive tools; требовать явного подтверждения перед выполнением

В 2026 году было выпущено 43 агентских платформы со встроенными уязвимостями. Следующей целью станут серверы MCP. Восемь вышеописанных проверок не сделают ваш сервер неуязвимым, но закроют бреши, которые злоумышленники могут сначала эксплуатируйте: открытые конечные точки, непроверенные входные данные и невидимые вызовы.

FAQ

Нужна ли аутентификация серверам MCP?
Да. Большинство серверов MCP поставляются без аутентификации, а это означает, что любой клиент, достигший конечной точки, может вызвать любой инструмент. По мере роста внедрения удаленного MCP вам понадобится ключ API или аутентификация на основе JWT на каждой конечной точке. Использование только локального хоста не является гарантией безопасности; локальные процессы и расширения браузера также могут достигать локального хоста.
Что такое аннотации инструмента MCP и почему они имеют значение?
Аннотации инструментов — это подсказки метаданных, определенные в протоколе MCP: readOnlyHint, DestructiveHint, IdempotentHint и openWorldHint. Они сообщают агентам ИИ, считывает ли инструмент данные, изменяет состояние, безопасно ли повторять попытку или связывается с внешними службами. Агенты используют эти подсказки, чтобы принимать более безопасные решения о том, какие инструменты вызывать и в каком порядке.
Как мне ограничить скорость агентов ИИ, звонящих на мой сервер MCP?
Назначьте каждому агенту (или ключу API) идентификатор и примените ограничения скорости для каждого идентификатора. Используйте сегмент токенов или алгоритм скользящего окна. Отслеживайте запросы в магазине KV или Redis. Собственный MCP-сервер Botoi обеспечивает пакетную обработку 5 запросов в минуту и ​​100 запросов в день для анонимного доступа с более высокими ограничениями для аутентифицированных ключей.
Могу ли я проверить входные данные инструмента MCP с помощью Zod?
Да. Инструменты MCP получают произвольный JSON от агентов. Определите схему Zod для ожидаемой формы ввода каждого инструмента и проверьте ее перед выполнением. Вы можете генерировать схемы Zod из образца JSON, используя конечную точку Botoi /v1/schema/json-to-zod, или конвертировать определения путей OpenAPI в объекты Zod, как это делает Schema-builder.ts Botoi.
Как обнаружить вмешательство в манифест моего инструмента MCP?
Хэшируйте манифест инструмента с помощью SHA-256 и сохраните хэш. Перед каждым запуском или развертыванием сервера пересчитывайте хэш и сравнивайте его. Если хеши различаются, значит кто-то (или что-то) изменил определения вашего инструмента. Вы можете вычислять хеши SHA-256 через конечную точку Botoi /v1/hash или с помощью собственных криптографических библиотек.

Начните разработку с botoi

150+ API-эндпоинтов для поиска, обработки текста, генерации изображений и утилит для разработчиков. Бесплатный тариф, без банковской карты.