Veil
Veil
ИИ-агент может управлять размещением учетных данных, никогда не получая их значение, в то время как доверенный интерфейс, управляемый человеком, независимо авторизует, куда этим учетным данным разрешено попасть.
В этом предложении — вся суть. Veil — это MCP-сервер плюс защищенный брокер ввода: агент говорит «поместить продакшн-ключ Stripe в Google Secret Manager», человек видит, в какой именно проект и секрет будет произведена запись, и вводит значение в собственное окно Veil, после чего значение отправляется напрямую в пункт назначения. Модель никогда не получает его.
Реализовано на основе SPEC.md.
Установка
Veil — это stdio MCP-сервер, поэтому вы не запускаете его сами — его запускает ваш MCP-клиент. Применяется обычный шаблон Python-MCP: uvx загружает и запускает его в одноразовом окружении, точно так же, как npx -y делает для TypeScript-серверов. Требуется uv и Python 3.11+.
Claude Code
claude mcp add veil -e VEIL_ENV_ALLOWED_ROOTS="$PWD" -- \
uvx --from git+https://github.com/rosostolato/veil-mcp veil-mcp serveДобавьте -s project, чтобы записать его в .mcp.json репозитория вместо вашей собственной конфигурации.
Любой другой клиент (Claude Desktop, Cursor, Windsurf, VS Code, Zed…)
Вставьте это в файл конфигурации MCP клиента — блок mcpServers везде имеет одинаковую форму:
{
"mcpServers": {
"veil": {
"command": "uvx",
"args": [
"--from", "git+https://github.com/rosostolato/veil-mcp",
"veil-mcp", "serve"
],
"env": {
"VEIL_ENV_ALLOWED_ROOTS": "/absolute/path/to/your/project"
}
}
}
}Как только Veil появится на PyPI, пара --from git+… исчезнет, и вызов станет uvx veil-mcp serve. Облачным назначениям нужны их дополнительные пакеты — veil-mcp[gcp], veil-mcp[firestore] или оба — добавьте их к любой используемой спецификации.
Предпочитаете постоянную установку временной:
uv tool install "veil-mcp[gcp] @ git+https://github.com/rosostolato/veil-mcp"
# then use `veil-mcp serve` as the command, with no uvxУстановите VEIL_ENV_ALLOWED_ROOTS. Адаптер .env отказывается записывать за пределами этих каталогов, и по умолчанию он ограничен только рабочей директорией сервера. Все остальное необязательно — см. Конфигурация.
Первый запуск
Попросите вашего агента о чем-то вроде «сохрани мой тестовый ключ Stripe в .env». Что произойдет:
Агент вызывает
secret.store, описывая куда попадут учетные данные. Он не отправляет никакого значения, потому что у инструмента нет поля, которое могло бы его нести.Veil открывает собственное окно на вашей машине, показывая имя учетных данных, назначение, проект, окружение, операцию и риск. Агент не получает эту ссылку.
Вы вводите значение в замаскированное поле. Операции среднего и высокого риска запрашивают второе подтверждение — после ввода и перед записью.
Veil записывает его и сообщает агенту
STOREDплюс ссылку на назначение — но никогда не значение.
Собственный stderr Veil несет структурированный аудиторский JSON. Больше от вас в терминале ничего не требуется.
Related MCP server: Janee
Что решает Veil
Он устраняет целый класс сбоев, вызванных тем, что агент знает секрет. С Veil в цикле учетные данные не проходят через:
Промпты LLM или историю разговора
Аргументы инструментов MCP или результаты инструментов
Память агента или сгенерированный код
Аргументы команд оболочки или argv процесса
Журналы, трассировки отладки или телеметрию
URL-адреса
Видимый модели вывод команд
Что Veil не решает
Veil не делает ИИ-агента заслуживающим доверия, и это не «безопасный ИИ». Он не гарантирует, что агент выбрал правильное назначение, что он вас понял, что он свободен от промпт-инъекций, что само назначение безопасно, что ваша машина не скомпрометирована или что учетные данные не могут быть использованы впоследствии во зло программным обеспечением, которое легитимно их получает.
Здесь две отдельные проблемы:
Вопрос | Ответ Veil |
Должен ли агент знать секрет? | Нет. |
Должен ли агент решать в одиночку, куда пойдет секрет? | Не без авторизации человека. |
Veil отвечает на эти два вопроса. Он не претендует на ответы на остальные.
Модель доверия
Trusted with the credential value:
The human at the keyboard
Veil's secure input UI (loopback only, in your control)
Veil's secure input broker (this process)
The selected destination adapter
The destination provider (e.g. Google Secret Manager)
NOT trusted with the credential value:
The LLM
The agent / MCP client
The conversation
The prompt and any repository content it read
Generated code
Logs, telemetry, crash reportsЭта диаграмма не утверждает, что доверенные компоненты неуязвимы. Она говорит, где учетным данным разрешено существовать. Veil — это чувствительное к безопасности программное обеспечение: если сам Veil вредоносен или скомпрометирован, граница исчезает. Его исходный код, зависимости и релизы заслуживают такого же внимания, какое вы уделили бы любому инструменту обработки учетных данных.
Два потока
Поток секрета — путь человека, который модель не может наблюдать:
Human ─▶ Veil secure UI (127.0.0.1) ─▶ Broker ─▶ Adapter ─▶ DestinationПоток агента — все, что видит модель:
LLM ─▶ MCP client ─▶ Veil MCP server ─▶ non-sensitive result metadataСхема инструмента MCP не имеет свойства, способного нести учетные данные. Это структурно, а не инструкция в промпте: здесь нет поля value, secret_value, password, token, content или raw_secret, которое можно было бы использовать во зло, закрытые схемы отклоняют неизвестные свойства, а аргументы проверяются на наличие значений в форме учетных данных до их разбора.
Что вызывает агент
{
"destination": "gcp-secret-manager",
"name": "STRIPE_SECRET_KEY",
"target": { "project": "my-production-project", "secret": "STRIPE_SECRET_KEY" },
"write_mode": "new-version",
"environment": "production",
"description": "Stripe production API key"
}Veil отвечает request_id, классификацией риска и нормализованным назначением — и открывает собственное окно авторизации на вашей машине. Агент опрашивает secret.status.
Агент не получает ссылку на авторизацию. Эта ссылка — возможность: все, что ею владеет, может завершить человеческую половину потока, а агент с оболочкой или HTTP-инструментом — именно та модель угрозы. Veil передает ее вашему браузеру и печатает в собственную консоль. Установите VEIL_DISCLOSE_AUTHORIZATION_URL=true, если вашей настройке нужно, чтобы агент передавал ссылку (например, для удаленной или безголовой сессии) — и понимайте, что это позволяет скомпрометированному агенту авторизовать собственный запрос.
Инструмент | Назначение |
| Создать запрос на учетные данные. Возвращает нечувствительные метаданные и идентификатор запроса. |
| Опрашивать запрос. Никогда не возвращает материал учетных данных. |
| Отменить ожидающий запрос; любое введенное значение уничтожается. |
| Аннулировать авторизацию и начать новую. Ничего не редактируется на месте. |
| Перечислить назначения и целевые поля, которые ожидает каждое из них. |
Что видит человек
Этап A показывает имя учетных данных, провайдера назначения, проект/аккаунт, ресурс, операцию и риск до ввода значения. Операции высокого риска (перезапись продакшена, хранение в открытом виде, базы данных приложений, замена учетных данных) требуют второго подтверждения на Этапе B — после ввода и перед записью. Значение никогда не отображается обратно.
Страница, которую читает человек, и операция, которую выполняет исполнитель, — это один и тот же неизменяемый объект — нет отдельного «отображаемого назначения». Любое изменение назначения, проекта, имени секрета, операции, режима записи или адаптера аннулирует авторизацию и требует новой.
Поддерживаемые адаптеры
Адаптер | Класс | Примечания |
|
| Предпочтительный. Требуется |
|
| Ограниченный по путям, отказывающийся от символических ссылок, атомарная запись |
|
| Требуется |
Назначения arbitrary-network (универсальный HTTP POST, вебхуки) не реализованы, и реестр адаптеров отказывается регистрировать такой.
Предположения о безопасности и ограничения
Сформулировано прямо, потому что инструмент безопасности, который себя переоценивает, хуже, чем никакой:
Процесс брокера видит секрет. В этом и смысл: кто-то должен, иначе хранение невозможно. Гарантия в том, что это делают только минимальные доверенные компоненты транспорта и назначения.
CPython не может надежно стирать память.
SecretBufferзатирает изменяемый буфер, которым владеет, но процентное декодирование, преобразованияstr/bytesи SDK провайдеров создают неизменяемые копии, которые интерпретатор может хранить до сборки мусора. Veil минимизирует и не фабрикует эту гарантию.UI — это loopback HTTP. Любой процесс, работающий от вашего имени на вашей машине, может до него добраться, и любой такой процесс также может его имитировать. Каждый процесс Veil печатает случайную фразу идентичности, которую отображают его страницы (помощь против спуфинга, а не криптографический контроль). Сокрытие ссылки от агента поднимает планку; это не останавливает процесс, который может читать вывод консоли Veil, перечислять argv браузера или сканировать loopback-порты.
Veil не аудитирует назначение. Если вы авторизуете учетные данные в документ Firestore, Veil записывает их туда и сообщает вам, что это плохая идея; он вас не останавливает.
Таймауты на уровне провайдера. Veil не может отменить блокирующий вызов SDK извне, поэтому каждый адаптер передает явный таймаут провайдеру. SDK назначения, игнорирующий собственный таймаут, может по-прежнему удерживать запрос — и его секрет — открытым.
Предварительная проверка — по возможности. Провайдер, недоступный при предварительной проверке, сообщается как недоступный, а не угадывается.
Семантика сбоя. Сбой между записью у провайдера и ответом может оставить учетные данные записанными без локальной записи об успехе. Veil сообщает о запросе как о неудачном; назначение — источник истины.
Локальная разработка
git clone https://github.com/rosostolato/veil-mcp && cd veil-mcp
uv venv
uv pip install -e ".[dev,gcp,firestore]"
# drive it the way a client would
uv run veil serveЧтобы указать клиенту на ваш локальный код, используйте /path/to/veil-mcp/.venv/bin/veil-mcp в качестве команды вместо uvx.
Конфигурация
Конфигурация читается из собственного окружения Veil — никогда из аргументов инструмента, поэтому агент не может ослабить политику:
Переменная | По умолчанию | Значение |
|
| Срок действия запроса. |
|
| Верхняя граница одной записи в назначение. |
|
| Требовать подтверждение для операций среднего риска. |
|
| Безопасный адрес привязки UI. |
|
| Автоматически открывать окно авторизации. |
|
| Возвращать ссылку на авторизацию агенту. |
| текущий каталог | Корни, внутри которых адаптер |
|
| Разрешить запись в файл env, отслеживаемый git. |
| все | Разделенный запятыми список разрешенных. |
Тесты
uv run pytest # everything
uv run pytest tests/security # the adversarial suite only
uv run ruff check .
uv run mypyНабор тестов безопасности — это требование к продукту, а не приятный бонус. Он содержит обнаружение утечек канареечных значений по каждому наблюдаемому каналу, тесты вредоносных агентов, фикстуры промпт-инъекций, тесты TOCTOU и повторного воспроизведения, стресс-тест конкурентности на 100 потоков, гонки, пути сбоев, симуляцию отказа провайдера, проверки UI и фаззинг. Релиз блокируется, если утекает любое канареечное значение, удается любой обход авторизации, удается любая мутация после одобрения, любой завершенный запрос можно воспроизвести, любой секрет пересекает границу запроса, любая необработанная ошибка провайдера достигает MCP или любая операция высокого риска пропускает подтверждение.
См. docs/SECURITY_MODEL.md для карты инвариантов к тестам.
Статус проекта
Версия 0.1.0, построенная в соответствии с SPEC.md, который остаётся в репозитории как авторитетное описание предполагаемого поведения. Каждый значимый модуль и тест ссылаются на раздел, который они реализуют, так что рецензент может проверить код на соответствие требованию, а не его краткому изложению.
MVP завершён, и полный набор тестов — включая состязательные — проходит. Что остаётся, прежде чем кто-либо сможет на него положиться в серьёзной работе: независимая проверка, тестирование человеческого фактора интерфейса подтверждения (SPEC.md §35) и подписанные релизные артефакты (§43).
Участие в разработке
Безопасность здесь — это продукт, поэтому планка для изменений скорее конкретна, чем бюрократична:
Изменение, затрагивающее обработку учётных данных, авторизацию или поверхность MCP, требует теста, который пытается нарушить затрагиваемый инвариант, а не только тот, который показывает его работу.
Никогда не ослабляйте тест безопасности, чтобы пройти набор. Если тест выявляет архитектурный недостаток, меняется архитектура.
Новые зависимости времени выполнения в ядре по умолчанию отвергаются. Брокер является доверенной вычислительной базой для учётных данных; SDK провайдеров должны быть за опциональным дополнением.
Запустите
ruff check .,ruff format --check .,mypyиpytestперед открытием pull request.
Нашли уязвимость? Пожалуйста, сообщите о ней приватно через уведомления о безопасности GitHub, а не открывая публичный issue.
Лицензия
Лицензия Apache 2.0 © 2026 Eduardo Rosostolato.
Available Tools
5 toolssecret.cancelCancel a credential requestA
Cancel a pending request. Any credential already entered is destroyed.
| Name | Required | Description | Default |
|---|---|---|---|
| reason | No | ||
| request_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It explicitly discloses a critical side effect: 'Any credential already entered is destroyed.' This is valuable transparency for a destructive mutation. However, it doesn't mention other effects like whether cancellation is reversible or requires special permissions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences long, highly concise, and front-loaded with the core action ('Cancel a pending request') followed by a key consequence. There is no fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description doesn't explain return values or error conditions. While it covers the key destructive behavior, it lacks guidance on when to use the reason parameter, potential side effects beyond credential destruction, and any prerequisites. For a security-related tool, more context would be helpful, but the essential purpose is clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, and the description does not explain the parameters at all. It doesn't mention that request_id is required or that reason is optional. The schema itself provides clear names, but the description adds no additional meaning, leaving the agent to infer that request_id identifies the request and reason is for audit context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Cancel a pending request' which is a specific verb (cancel) and resource (request). It distinguishes from siblings like secret.store and secret.revise, as it focuses on cancellation and the destruction of already-entered credentials.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for pending requests ('Cancel a pending request') but gives no explicit guidance on when to use it versus alternatives, nor exclusions. It lacks context like 'use secret.revise to modify instead' or 'do not use for completed requests'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
secret.destinationsList available destinationsARead-only
List the destinations this Veil instance can write to, with the target fields each one expects.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations include readOnlyHint: true, and the description does not contradict it. It adds context about the content (target fields) which is useful for the agent. Given the annotation already covers safety, the description provides adequate extra behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, front-loaded with the verb and resource, no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with no parameters and no output schema, the description fully explains what it does and includes the key detail about target fields, which is likely sufficient for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameterswing schema coverage is 100% (vacuously). Baseline for 0 params is 4, and the description clarifies that the output includes target fields per destination, which adds contextual meaning beyond the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (List) and the specific resource (destinations this Veil instance can write to), and adds the detail about target fields. It distinguishes itself from sibling tools like store, cancel, revise, which involve mutations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use it (to discover available destinations and their required fields), but does not explicitly contrast with alternatives. Since it's a simple listing tool, the purpose clarity implicitly covers usage, though no exclusions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
secret.reviseReplace a credential request with a corrected oneA
Cancel a pending request and create a new one. The original authorization is invalidated and the human must authorize the new operation from scratch; an authorized operation can never be edited in place.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Logical name of the credential, e.g. STRIPE_SECRET_KEY. This is a label, never the credential value. | |
| target | Yes | Where the credential goes. Fields depend on the destination; call secret.destinations for the exact contract. | |
| request_id | Yes | ||
| write_mode | No | create | |
| description | No | Short human-readable purpose, shown to the user. | |
| destination | Yes | Which destination adapter should receive the credential. | |
| environment | No | Environment you believe this destination belongs to. Advisory only: Veil classifies the destination itself and uses the stricter of the two. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well. It discloses that the original authorization is invalidated, the human must reauthorize from scratch, and authorized operations cannot be edited in place. This covers the key side effects and workflow consequences of a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The first sentence states the core action, and the second provides the key behavioral consequence and an important invariant. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter tool with nested objects and no output schema, the description explains the compound nature and authorization consequences sufficiently. It could additionally mention that all parameters must be resubmitted for the new request, but the schema and existing wording make the required inputs inferable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 71%, so most parameters have descriptions already. The tool description adds context around request_id by referring to 'pending request' and 'new operation from scratch,' but it does not explain parameter interactions or destination-specific requirements beyond what the schema provides. This is adequate but not enhanced.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a compound operation: 'Cancel a pending request and create a new one.' The title, 'Replace a credential request with a corrected one,' further specifies the resource and intent, distinguishing this from sibling tools like secret.cancel and secret.store.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context for when to use the tool: when a pending request must be corrected, and specifically notes that 'an authorized operation can never be edited in place.' It doesn't explicitly contrast with secret.cancel or secret.store, but the described workflow makes the intended use case unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
secret.statusCheck a credential requestARead-only
Return the non-sensitive status of a credential request. Never returns credential material.
| Name | Required | Description | Default |
|---|---|---|---|
| request_id | Yes | ||
| wait_seconds | No | Optionally block until the request reaches a terminal state or this many seconds elapse. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds valuable behavioral context beyond the readOnlyHint annotation by guaranteeing that no credential material is ever returned. This safety guarantee is a key trait not covered by annotations, though it does not disclose blocking behavior or error handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences that front-load the core purpose and add a critical safety note. There is no unnecessary detail or verbosity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with two parameters and a read-only annotation, but the description omits key behavioral details such as the optional blocking behavior via wait_seconds and what the response actually contains (e.g., status list, error scenarios). Without an output schema, the description should describe the return value format more fully.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description provides no explanation of the parameters. request_id is self-explanatory from its name, but wait_seconds is already described in the schema. With only 50% schema description coverage, the description fails to compensate for the missing request_id semantics or clarify how to obtain such an ID.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns the status of a credential request and explicitly mentions it never returns credential material. This distinguishes it from siblings like secret.cancel or secret.store, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for checking status but provides no explicit guidance on when to use it versus alternatives. There is no mention of 'use when you need to check status' or exclusions like 'do not use to cancel requests'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
secret.storeRequest that the user store a credentialADestructive
Ask the human to provide a credential and have Veil write it to the destination described here. The credential value is never passed through this tool, never returned by it, and never becomes visible to the model: the user enters it in Veil's own trusted window. Share the returned authorization_url with the user, then poll secret.status.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Logical name of the credential, e.g. STRIPE_SECRET_KEY. This is a label, never the credential value. | |
| target | Yes | Where the credential goes. Fields depend on the destination; call secret.destinations for the exact contract. | |
| write_mode | No | create | |
| description | No | Short human-readable purpose, shown to the user. | |
| destination | Yes | Which destination adapter should receive the credential. | |
| environment | No | Environment you believe this destination belongs to. Advisory only: Veil classifies the destination itself and uses the stricter of the two. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explicitly discloses that the credential value never passes through the tool, is never returned, and never becomes visible to the model—a key behavioral trait. It also outlines the multi-step process involving an authorization_url and polling. Annotations already signal destructive and open-world behavior, and the description complements these without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core action, and includes essential security and workflow context. Every sentence earns its place, and there is no redundant or extraneous text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (nested target, multiple destinations, write modes, environment), the description covers the critical workflow and security aspects, and points to secret.destinations for detailed contracts. It does not explain write_mode or environment semantics, but those are well-documented in the schema. Overall, it is reasonably complete for a tool of this intricacy.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description does not directly elaborate on any input parameters, but the schema provides extensive descriptions for 83% of fields. It directs users to secret.destinations for the target contract, which covers the remaining nuance. Since the schema already carries the semantic load, the description adds little beyond baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action: asking the human for a credential and having Veil write it to a specified destination. It distinguishes itself from siblings like secret.status and secret.cancel by focusing on the store action and includes critical security context (credential not visible to model) and subsequent steps (share authorization_url, poll status).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear workflow guidance: ask the user, share the authorization_url, and poll secret.status. It implies this tool is for new credentials but does not explicitly contrast with secret.revise or specify when not to use it. The flow is described well, but alternative exclusions are missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
secret.cancel - First observed
secret.destinations - First observed
secret.revise - First observed
secret.status - First observed
secret.store
TDQS
Scored across 5 tools
Each tool has a clearly distinct role: status checks a pending request, store initiates a credential request, cancel aborts it, revise replaces it, and destinations lists available targets. No overlap in purpose, making agent selection unambiguous.
All tool names follow a consistent 'secret.<action>' pattern with clear, concise verbs (status, store, cancel, revise) and one noun (destinations). The pattern is uniform and predictable, though 'destinations' is a noun rather than a verb, it still fits the domain prefix style.
With 5 tools, the server is tightly scoped to credential request management. This is within the ideal range and each tool earns its place; no redundancy or bloat.
The tool surface covers the entire lifecycle of a credential request: create (store), read (status), update/replace (revise), delete (cancel), and context (destinations). There are no evident gaps—even revision gracefully handles invalidation of prior authorizations.
Maintenance
Related MCP Connectors
Give AI agents identity, scoped access, trusted context, and verifiable actions through MCP.
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
- TAPOAuthtech.human
Credential isolation for AI agents: placeholder secrets, policy checks, optional human approval.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server that lets AI agents call APIs without ever seeing the credentials, using a local encrypted vault and per-secret allowlist policies for HTTP requests and subprocess environment variables.1AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceSecrets management MCP server that injects credentials into API requests for AI agents, enforcing policies and logging all activity without exposing raw keys.112 npm30MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for AI-native credential management, enabling agents to securely store, retrieve, and manage API keys with encryption, spending budgets, and audit logging.MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for DemiPass secrets management, enabling AI agents to securely store, rotate, and use credentials without exposing them in context windows.44 npmMIT