Skip to main content
Glama
adamabdo-xynora

mcp-capability-guard

mcp-capability-guard

Большинство MCP-серверов вручают модели заряженный пистолет с общим bearer-токеном: один набор учётных данных, каждый инструмент, каждый вызов. Этот сервер заставляет модель спрашивать разрешение на каждую пулю.

Это небольшой, но полный MCP-сервер поверх вымышленной in-memory CRM (Larkspur Supply Co., семь придуманных контактов), который демонстрирует авторизацию записи на основе capability-токенов — паттерн, извлечённый из продакшн-CRM-агента, которого я запускаю на реальной книге контактов (12 000+ записей). Данные здесь вымышлены; поставляется именно механизм принуждения.

Дизайн, в пяти слоях

  1. Многоуровневая поверхность инструментов. Чтения (list_contacts, get_contact) бесплатны. Операции записи не существуют в виде отдельных инструментов — нет ни инструмента add_note, ни инструмента delete_contact. Каждая мутация проходит ровно через два вызова: propose_write, затем execute_write.

  2. Capability-токены (центральный элемент). propose_write выпускает одноразовый warrant с ограничением по TTL, привязанный ровно к одной конкретной мутации — токен встраивает мутацию в себя, а не указывает на неё, так что нет таблицы поиска, которую можно было бы отравить, и нет id, который можно было бы перенацелить. execute_write предъявляет токен вместе с мутацией, и guard проверяет равенство поле за полем. Предъявление warrant с другой мутацией не просто приводит к отказу — оно сжигает токен, унося с собой и легитимную запись, для которой он был выпущен.

  3. Подтверждение человеком для разрушительного уровня. change_stage, remove_tag и delete_contact дополнительно требуют явного «да» оператора через MCP form elicitation — в приглашении, которое одним предложением называет операцию, контакт и payload. Запрос подтверждения выполняется до обращения к guard, так что отказ никогда не расходует warrant — а клиент без канала elicitation получает отказ в разрушительных записях, а не их молчаливое исполнение. Fail closed в обе стороны.

  4. Нижняя граница, которую верхние слои не могут обойти. Контакты в стадии Closed-Lost-DNC (не беспокоить, юридическая блокировка) отклоняют любую запись внутри самого хранилища, которое ничего не знает ни о токенах, ни об MCP. Полностью одобренный поток — действительный warrant, совпадающая мутация, подтвердивший человек — всё равно упирается здесь в тупик. Именно это делает защиту эшелонированной, а не одним шлагбаумом с тремя табличками.

  5. Append-only журнал аудита, из которого не могут утечь warrants. Записывается каждый propose, confirm, execute и отказ. Token id попадают в журнал только в виде 8-символьных отпечатков — и это гарантия на этапе компиляции: поле отпечатка хранит брендированный TypeScript-тип, который может произвести только усекающая функция. Свободный текст также зачищается по значению, потому что собственные сообщения guard об отказе называют токен, которому отказано. (Это та же дисциплина redact-by-value, что и в моём webhook-guard — там для HTTP-учётных данных, здесь для живых warrants.) read_audit — deny-by-default: если сервер не собран с exposeAudit: true, инструмент вообще не регистрируется.

Related MCP server: tenant-scoped-crm

Смотрите, как это работает

npm install
npm run demo

Демо соединяет реальный сервер со скриптовым клиентом через in-memory MCP-транспорт и проходит восемь шагов: две записи, которые проходят (одна обратимая, одна разрушительная и подтверждённая), затем пять атак — replay, bait-and-switch, отклонённое подтверждение, перенос цели и полностью одобренная операция записи против замороженной записи — каждая встречает свой типизированный отказ, а хранилище остаётся побайтово неизменным. В конце читается журнал аудита и проверяется, что нигде в нём не появляется полный token id. Демо проверяет каждое ожидание инлайн и при любом промахе завершается с ненулевым кодом, так что оно работает заодно как смоук-тест и выполняется в CI при каждом пуше.

npm test              # 158 offline tests
npm run typecheck     # strict TypeScript, no emit

Всё офлайн: никаких API-ключей, ни сети, ни переменных окружения — настраивать нечего. Именно поэтому CI запускает весь набор тестов, включая демо, при каждом пуше и без секретов.

Доказательства — в тестовых наборах

Два набора тестов существуют специально для того, чтобы заявления выше оставались честными:

  • test/structural.test.ts читает исходный код как текст и фиксирует архитектуру: src/tools.ts — единственный модуль, импортирующий MCP SDK; хранилище ничего не знает о том, что выше него; модули guard и audit импортируют только то, что заявлено в их заголовках; выпуск токенов ограничен guard; строка tokenId ни разу не появляется в src/audit.ts. Если рефакторинг незаметно перенесёт код SDK в хранилище, этот набор упадёт раньше, чем проявится какое-либо поведение.

  • test/adversarial.test.ts разыгрывает враждебную модель против полностью собранного сервера: пропуск propose, replay, bait-and-switch с проверкой сжигания, перенацеливание warrant на другой контакт, атака с полным одобрением на замороженную запись, просроченный warrant через инъецированные часы, уклонение от подтверждения и проверка целостности аудита с token id, выбранными атакующим. Каждая атака должна встретить свой точный типизированный отказ, а после всех атак хранилище должно остаться неизменным.

Оставшиеся ~140 тестов покрывают хранилище, guard, audit и поверхность инструментов покомпонентно, включая инвариант порядка: подтверждение выполняется до того, как warrant может быть потрачен.

Версионирование и область применения

Собрано на @modelcontextprotocol/sdk 1.30.0, который нацелен на ревизию MCP 2025-11-25. Ревизия 2026-07-28 делает выпущенные сервером хэндлы, передаваемые как обычные аргументы инструментов, каноническим механизмом состояния между вызовами (SEP-2567) — capability-токен в этом репозитории — ровно этот паттерн, использованный как примитив авторизации, так что дизайн без изменений переносится в протокол без состояния.

Две рантайм-зависимости: сам SDK и zod — язык схем, являющийся peer-dependency самого SDK; схемы входных данных инструментов по дизайну SDK являются zod-схемами, так что это не столько добавленная зависимость, сколько вторая половина SDK. Больше в дерево зависимостей ничего не попадает. Модули хранилища, guard и audit — чистый TypeScript с нулём импортов, кроме node:crypto и типов друг друга, — и именно это позволяет 158 тестам работать офлайн меньше чем за полсекунды.

Чем это не является. Этот репозиторий не реализует OAuth и не реализует роль resource-server из спецификации авторизации MCP. Они решают другую задачу: доказательство того, кем является клиент, на границе транспорта. Capability-токены определяют то, что аутентифицированная сессия может делать, по одной записи за раз — эти два механизма дополняют, а не конкурируют друг с другом, и именно их смешение приводит к тому, что у серверов оказывается один bearer-токен, авторизующий всё. Транспортная идентичность здесь намеренно вынесена за скобки, чтобы паттерн авторизации оставался читаемым.

Ограничения, без прикрас

  • CRM вымышленная и живёт в памяти. Персистентность, конкурентность и многопользовательские сессии — реальные проблемы, которых у этой демки нет.

  • Токены живут в памяти сервера; перезапуск забывает их. В продакшене тот же паттерн работает поверх персистентного хранилища с той же семантикой одноразового использования.

  • Подтверждение через elicitation настолько же надёжно, насколько хорошо клиент его отображает. Клиент, показывающий пользователю голое «Allow?» вместо предложения сервера, ослабляет гарантию — а это аргумент за то, чтобы класть полное предложение в запрос, как делает этот сервер, а не за то, чтобы пропускать запрос.

  • Временные метки заметок в хранилище используют настенные часы, поэтому одна строка вывода демо меняется от запуска к запуску. Guard и журнал аудита используют инъецированные часы и детерминированы.

Адаптация

Паттерн переносится на любой MCP-сервер, чьи операции записи имеют последствия: замените хранилище своей системой, сохраните разделение propose/execute, определите собственные уровни и держите правило нижней границы в слое данных, а не в слое инструментов. Модули guard и audit не импортируют ничего из MCP и могут быть вынесены целиком.

Лицензия MIT.

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Security-enforcing MCP proxy that sits between an AI agent and any number of downstream MCP servers, intercepting every tool call through a capability-token policy gateway that can allow, deny, or escalate to human approval before the call reaches any real tool. It also exposes built-in operator tools for approval workflows, audit trail queries, token management, voice/HUD output, and hierarchical
    21
    12
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    A reference MCP server demonstrating safe agent access to multi-tenant CRM data with tenant isolation enforced in the data layer, role-based permissions, and human confirmation on writes.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    A secure MCP server for CRM operations (contacts and deals) with Auth0 OIDC authentication, role-based access control (sales-rep read-only vs sales-manager full access), and on-behalf-of token exchange.
  • A
    license
    B
    quality
    A
    maintenance
    A secure MCP server enabling tool calls (kb_search, read_doc, publish_report) through a zero-trust CapabilityBroker with OWASP LLM Top-10 guardrails and human-in-the-loop approval.
    3
    Apache 2.0

View all related MCP servers

Related MCP Connectors

  • An authenticated remote MCP server for user-owned devices and one-shot capability invocation.

  • Personal MCP server for humans who create. Proof of authorship, license control.

  • Viridis Verified: wrap any MCP server with tamper-evident delivery receipts + metered fees.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/adamabdo-xynora/mcp-capability-guard'

If you have feedback or need assistance with the MCP directory API, please join our Discord server