Тестируйте, отлаживайте и выпускайте MCP-server
Проверка MCP-сервера складывается из четырёх слоёв, и пропуск любого оставляет дыру. Сначала - pure domain tests, где бизнес-логика проверяется без протокола. Затем protocol contract tests. Затем настоящий транспорт - реально запущенный процесс, а не вызовы в памяти. И наконец security- и failure-тесты, где вы намеренно ломаете систему. Inspector помогает исследовать сервер руками, но не заменяет автоматический suite.
Integration-тест обязан действительно поднимать stdio-сервер - иначе вы не проверяете framing и shutdown.
import assert from "node:assert/strict";
import test from "node:test";
import { runMcpDemo } from "../src/mcp/client.js";
test("MCP client и server договариваются о современной редакции", async () => {
const result = await runMcpDemo();
assert.equal(result.era, "modern");
});
test("MCP discovery возвращает tools, resources и prompts", async () => {
const result = await runMcpDemo();
assert.deepEqual(result.tools, ["search_runbooks", "review_release"]);
assert.ok(result.resources.includes("runbook://release-policy"));
assert.ok(result.prompts.includes("prepare-release-review"));
});
test("MCP tool возвращает валидированный structured output", async () => {
const result = await runMcpDemo();
assert.equal(result.decision, "ready");
assert.equal(result.policyTitle, "Политика выпуска");
});Локальный review перед выпуском - это несколько команд, включая ручную инспекцию.
npm run typecheck
npm test
npm run demo:mcp
# Ручная protocol inspection
npx @modelcontextprotocol/inspector <server command>Главная ценность - в негативных тестах: важно не то, что счастливый путь работает, а то, что ломается предсказуемо. Таблица показывает, что стоит сломать намеренно и какое доказательство вы ждёте.
Слой · Что сломать намеренно · Ожидаемое доказательство
- Schema - Пустой service, неверная semver; Invalid params до домена
- Authorization - Чужой tenant/object; Одинаковый безопасный deny
- Transport - Мусор stdout, abort, half-close; Чистое завершение без зависшего process
- Retry - Timeout после side effect; Idempotency предотвращает дубль
- Cache - Смена token/list_changed; Private data не переиспользуется
- Compatibility - Modern и поддержанный legacy peer; Negotiated era совпадает с ожиданием
За каждой строкой - конкретный класс багов. Пустой service или неверный semver должны отсеиваться до домена. Чужой tenant - давать одинаковый безопасный deny. Мусор на stdout, abort или half-close - завершаться чисто, без зависшего процесса. Timeout после side effect - не приводить к дублю благодаря idempotency.
Выпуск стоит сопровождать release manifest: protocol version, SDK lockfile, name/version сервера, схемы capabilities, authorization scopes, golden requests, лимиты таймаутов и changelog. Публикация в registry улучшает discovery, но не является сертификатом доверия.
Inspector показывает возможность, не безопасность. Успешный ручной tools/call не доказывает object authorization, поведение под нагрузкой, корректную отмену или отсутствие утечки секретов. Это доказывают только автоматические тесты.На этом сторона MCP собрана целиком - от границы до выпуска. Дальше мы переходим ко второй границе системы, где работа делегируется независимому агенту. Это A2A.