Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
mcpsnoop — Wireshark для MCP. Прозрачный прокси, который показывает каждый реальный вызов инструмента между вашим AI-клиентом и вашими MCP-серверами, в реальном времени в вашем терминале. | Kitploit
Инструменты/GitHubGitHub/kerlenton/mcpsnoop
Утилиты общего назначенияДинамический анализ (песочница)Картирование сетиВеб-прокси и перехватСкриптинг и автоматизацияТестирование безопасности APIОтладчикиАнализ Журналов
GitHubkerlenton/mcpsnoop

mcpsnoop

Wireshark для MCP. Прозрачный прокси, который показывает каждый реальный вызов инструмента между вашим AI-клиентом и вашими MCP-серверами, в реальном времени в вашем терминале.

334322013 дней назадПроверено Kitploit
Репозиторий

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

mcpsnoop

Wireshark для MCP. Прозрачный прокси, который показывает каждый реальный вызов инструмента между вашим AI-клиентом и вашими MCP-серверами, в реальном времени в вашем терминале.

CI Go Reference MIT Marketplace

mcpsnoop demo

Проблема

Официальный MCP Inspector подключается как собственный клиент, поэтому он никогда не видит, что ваш клиент (Cursor, Claude Code, Codex) на самом деле отправляет вашему серверу. А всё, что ждёт поступления запроса, не может показать вызов, который модель так и не сделала или сделала с неверными аргументами. Когда инструмент молча не вызывается, возможности не совпадают или вызов просто зависает, вам остаётся копаться в логах и гадать.

mcpsnoop вместо этого находится в реальном пути данных. Оберните им команду вашего сервера и наблюдайте за каждым JSON-RPC кадром в реальном времени, пока ваш реальный клиент и сервер общаются.

В CI

Эта страница также является листингом для mcpsnoop GitHub Action, так что вот всё о нём. Он проверяет захваченную сессию, оформляет каждую находку как code scanning alert и завершает задачу с ошибкой на том, что вы задали в качестве условия.```yaml permissions: security-events: write contents: read

steps:

  • uses: kerlenton/[email protected] with: session: artifacts/session.jsonl
root@kitploit:~
Закрепите нужный вам релиз. Самый новый — на
[странице релизов](https://github.com/kerlenton/mcpsnoop/releases). Каждый вход,
что означают коды выхода и как подключить его без действия, описаны
в разделе [The GitHub Action](#the-github-action) ниже.

## Быстрый старт

Посмотрите сразу, без какой-либо настройки.```bash
mcpsnoop demo

Чтобы использовать это по-настоящему, оберните ваш сервер в MCP-конфиг вашего клиента.```json { "mcpServers": { "my-server": { "command": "mcpsnoop", "args": ["--", "node", "build/index.js"] } } }

root@kitploit:~
Всё, что идёт после `--`, — это команда, которая обычно запускает ваш сервер. Подставьте вместо неё то, что вы уже используете, например `python server.py`, `npx -y @scope/server` или скомпилированный бинарный файл.

В Claude Desktop вам не придётся вносить эту правку вручную.```bash
mcpsnoop wrap my-server     # route my-server through mcpsnoop
mcpsnoop unwrap my-server   # put it back

wrap находит claude_desktop_config.json, копирует его в claude_desktop_config.json.mcpsnoop.bak при первом запуске и перезаписывает только запись этого одного сервера, поэтому ваше форматирование и все остальные серверы остаются нетронутыми. Внутри перезаписанной записи ключи возвращаются в алфавитном порядке. unwrap восстанавливает файл и удаляет резервную копию, как только ни один сервер больше не обёрнут. Перезапустите Claude Desktop после любого из этих действий, поскольку MCP-серверы запускаются один раз при старте.

Затем используйте ваш клиент как обычно и откройте интерфейс.```bash mcpsnoop

root@kitploit:~
No flags, no socket paths, no startup order to remember. The shim and the UI find
each other on their own, and the UI backfills past sessions from disk.

For a streamable-HTTP server, run mcpsnoop as a reverse proxy.```bash
mcpsnoop http --target http://localhost:3000/mcp --listen :7000

Статус HTTP каждого ответа отображается в потоке, поэтому ответ, который не несёт собственного сообщения JSON-RPC, всё равно остаётся видимым кадром, а не пустотой: вызов 401, 403 при отклонённом Origin, 202, подтверждающий уведомление, и 502, когда целевой сервер вообще недоступен. Заголовок WWW-Authenticate ответа 401 сохраняется дословно и показывается в инспекторе, поскольку он указывает схему аутентификации и метаданные ресурса для дальнейших действий. Фильтруйте по статусу с помощью status:401 в TUI или по любой ошибке с помощью status:err. Код 4xx или 5xx считается ошибкой, поэтому обычный запуск mcpsnoop check завершится неудачей.

Нет собственного сервера? Попробуйте вживую против опубликованного тестового сервера, управляемого вашим собственным клиентом. Чтобы просмотреть сеанс после его завершения, см. просмотр прошлых сеансов из журналов.

Файл конфигурации

Если вы используете одни и те же флаги shim в рамках проекта, поместите их в файл .mcpsnoop.toml в текущем рабочем каталоге.```toml label = "filesystem" trace-file = "trace.jsonl" redact-secrets = true redact-key = "token,authorization" redact-value = "sk-[A-Za-z0-9]+" redact-path = "$.params.arguments.password" no-trace = false

root@kitploit:~
Повторите `redact-key`, `redact-value` и `redact-path` на отдельных строках, чтобы добавить
несколько значений каждого типа.

Это все ключи, которые он поддерживает.

Файл ищется только в текущей рабочей директории, а не в родительских
директориях.

Явные флаги командной строки переопределяют значения из файла конфигурации.

## Команды

| Команда | Что она делает |
|---|---|
| `mcpsnoop -- <server>` | обернуть stdio-сервер как прозрачный прокси-слой |
| `mcpsnoop` | открыть интерактивный TUI |
| `mcpsnoop http --target <url>` | проксировать потоковый HTTP-сервер |
| `mcpsnoop export` | отобразить сессию в json, html, text, har или otlp |
| `mcpsnoop check` | завершить CI с ошибкой при ошибках, невалидных фреймах, предупреждениях, несоответствиях маршрутизации, зависших вызовах, поздних результатах или превышении бюджета задержки |
| `mcpsnoop baseline` | просмотреть, принять или сбросить доверенные определения инструментов |
| `mcpsnoop diff` | сравнить инструменты и вызовы между двумя захваченными сессиями |
| `mcpsnoop open` | открыть сохранённую сессию в TUI |
| `mcpsnoop inventory` | вывести список всех серверов, которые запускались через mcpsnoop на этой машине |
| `mcpsnoop stats` | свернуть все сохранённые захваты в одну строку на сервер и инструмент |
| `mcpsnoop prune` | удалить сохранённые журналы сессий старше заданного порога |
| `mcpsnoop wrap <server>` | направить один из серверов Claude Desktop через mcpsnoop |
| `mcpsnoop unwrap <server>` | вернуть запись этого сервера в исходное состояние |
| `mcpsnoop remote <user@host>` | вывести команду SSH-туннеля |
| `mcpsnoop demo` | воспроизвести сценарную сессию |

Выполните `mcpsnoop help` для полного списка или `mcpsnoop help <command>` для флагов конкретной команды.

## Сравнение

| | MCP Inspector | mcpsnoop |
|---|:---:|:---:|
| Видит ваш реальный трафик клиента и сервера | нет | да |
| Отмечает зависшие вызовы и ошибки потока | нет | да |
| Отмечает посторонний вывод, повреждающий поток | нет | да |
| Отмечает некорректные JSON-RPC фреймы | нет | да |
| Обнаруживает расхождение определений инструментов после утверждения | нет | да |
| Интерактивный терминальный интерфейс | нет | да |
| Без конфигурации, без флагов и порядка | нет | да |
| Инспектор возможностей | частично | да |
| Воспроизведение захваченного вызова | нет | да, через stdio и HTTP |
| Экспорт сессии (json / html / text / otlp) | нет | да |
| Один бинарный файл, без зависимостей времени выполнения | нет | да |

## Установка

### npm

Инструментарий Go не требуется. Большинство MCP-серверов написаны на Node или Python, поэтому это
самый короткий путь.```bash
npx mcpsnoop -- node build/index.js

The npm package ships no code of its own. Six platform packages each carry one build, and npm installs the single one that matches your machine, so there is nothing to download at install time and nothing to unblock in a proxy. To keep it around rather than fetching it each run, npm i -g mcpsnoop.

Go```bash

go install github.com/kerlenton/mcpsnoop/cmd/mcpsnoop@latest

root@kitploit:~
### Homebrew```bash
brew install mcpsnoop

Готовые бинарники для всех платформ доступны на странице Releases.

Дополнения для оболочки

mcpsnoop поставляется с дополнениями для bash, zsh, fish и PowerShell. Выполните mcpsnoop completion <shell> --help, чтобы узнать шаги настройки, включая включение дополнений и путь установки для вашей ОС.

Как это работает

mcpsnoop находится в канале между вашим ИИ-клиентом и вашими MCP-серверами, копируя каждый JSON-RPC кадр в живой терминальный интерфейс

mcpsnoop — это две роли в одном бинарнике. mcpsnoop -- <server> — это прозрачный прокси-модуль, который запускает ваш клиент, пересылая байты без изменений и отправляя копию каждого кадра в хаб. mcpsnoop без аргументов — это сам хаб и его живой TUI. Они связываются через известный сокет и журналы на диске, поэтому ни одному из них не нужно запускаться первым.

По умолчанию хаб загружает 100 последних сохранённых сессий, что ограничивает работу при запуске, не удаляя более старые записи. Используйте mcpsnoop --history-limit N, чтобы выбрать другой лимит, или mcpsnoop --history-limit 0, чтобы загрузить всю историю. Более старые сессии остаются доступными через mcpsnoop open <session-id> и mcpsnoop export <session-id>.

Лимит истории ограничивает количество загружаемых сессий. Внутри сессии живой TUI ограничен дважды, потому что хаб, оставленный наблюдать за болтливым сервером, в противном случае растёт, пока его не убьют. Он хранит не более 64 МиБ тел кадров, освобождая самые старые первыми, и не более 200 000 кадров, полностью отбрасывая самые старые сверх этого. Первый лимит — это то, с чем сталкивается захват больших полезных нагрузок, а второй — то, что делает длинный поток мелких уведомлений.

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

mcpsnoop open <session-id> читает журнал и удерживает его целиком, а экспорт из TUI также читает журнал, поэтому ни один из них не ограничен. check, export и diff намеренно создают неограниченное хранилище, поскольку шлюз, который занижает данные при большом захвате, хуже, чем тот, который использует память.

Лимит истории ограничивает то, что загружается. mcpsnoop prune ограничивает то, что хранится. Он удаляет сохранённые журналы сессий старше определённого порога и никогда не запускается сам по себе.```bash mcpsnoop prune --older-than 30d --dry-run # list what would go, remove nothing mcpsnoop prune --older-than 30d # delete after confirming mcpsnoop prune --older-than 72h --yes # skip the prompt in a script

root@kitploit:~
`--older-than` является обязательным (нет значения по умолчанию, которое удаляло бы что-либо) и
принимает количество дней, например `30d`, или длительность в формате Go, например `72h`. Базовые линии инструментов
не затрагиваются, поскольку базовая линия привязана к метке сервера, а не к сессии.

Поскольку он находится непосредственно в конвейере, а не в стороне, как Inspector, он
видит именно то, что ваш реальный клиент и сервер говорят друг другу, независимо от того, на чём
написан сервер.

## Сочетания клавиш

| Клавиша | Действие | | Клавиша | Действие |
|---|---|---|---|---|
| `enter` | просмотр / углубление | | `/` | фильтр |
| `esc` | назад | | `:` | команда |
| `j` / `k` | перемещение | | `r` / `R` | повтор / редактирование и повтор |
| `g` / `G` | вверх / вниз | | `c` | возможности |
| `ctrl-f` / `ctrl-b` | страница | | `s` | сводка по инструменту |
| `p` | пауза | | `y` | копировать |
| `shift`+`<клавиша>` | сортировка по столбцу | | `e` | экспорт |
| `ctrl-d` | удалить сессию | | `f` | следовать |
| `?` | справка | | | |

Нажмите `?` в приложении для получения полного списка.

## Фильтрация потока

Нажмите `/` в сессии и комбинируйте токены, разделённые пробелами, с логическим И. Обычный текст
соответствует методу, инструменту, идентификатору и полезной нагрузке.

| Токен | Фильтрует по | Пример |
|---|---|---|
| `tool:` | имени инструмента | `tool:search` |
| `method:` | методу JSON-RPC | `method:tools/call` |
| `id:` | идентификатору запроса и любому повтору, продолжающему его | `id:7` |
| `task:` | идентификатору задачи | `task:01J...` |
| `dir:` | направлению (`c2s`, `s2c`) | `dir:s2c` |
| `kind:` | типу кадра (`req`, `resp`, `notify`, `stderr`, `invalid`) | `kind:invalid` |
| `status:` | результату вызова (`ok`, `error`, `cancel`, `late`, `cancelled`, `pending`, `bad`, `warn`, `mismatch` или HTTP-статусу, например `401`) | `status:error` |

Комбинируйте токены для точной настройки.```text
tool:search status:pending        # in-flight calls to one search tool
status:cancel                     # calls the client gave up on (status:cancelled is a cancelled task)
status:late                       # results that arrived after the cancellation
method:tools/call status:error    # tool calls that failed
dir:s2c kind:req                  # server-initiated requests (servers before 2026-07-28)

Последний находит что-либо только на сервере, говорящем на версии 2025-11-25 или более ранней. Редакция от 2026-07-28 убрала запросы, инициируемые сервером, и сервер, которому что-то нужно от клиента, теперь отвечает на собственный запрос клиента с просьбой об этом, после чего клиент повторяет попытку. mcpsnoop связывает эти повторные попытки с запросом, который они продолжают, поэтому обмен читается как один вызов, а не несколько.

Экспорт сеансов

Превратите любой захваченный сеанс в переносимый файл.```bash mcpsnoop export -T json|html|text|har|otlp [-o file|-] [session-id|log.jsonl|-]

root@kitploit:~
| Формат | Что вы получаете |
|---|---|
| `json` | скоррелированные вызовы, количество по каждому инструменту и задержки p50/p95/p99, самые медленные вызовы, возможности и необработанные кадры |
| `html` | автономный браузерный файл с поиском и сворачиваемым JSON |
| `text` | аккуратный текстовый дамп в читаемом виде |
| `har` | по одной записи на каждый скоррелированный вызов, открывается в инструментах разработчика браузера и в любом другом, что читает HAR |
| `otlp` | OTLP JSON с одним span на каждый скоррелированный вызов, с W3C trace context, соединяющим трассы вызывающего кода там, где он присутствует, и одной трассой на сессию в противном случае |

MCP — это не HTTP, поэтому URL, код состояния и тайминги записи HAR являются
намеренным отображением каждого вызова, а не транскрипцией сетевого трафика.

Для OTLP поле `_meta.traceparent` запроса задаёт трассу и идентификаторы родительского
span для этого вызова, а `_meta.tracestate` передаётся вместе со span. Когда traceparent
отсутствует или недействителен, mcpsnoop сохраняет трассу, производную от сессии, и не несёт
никакого состояния. mcpsnoop наблюдает, а не участвует, поэтому он не добавляет собственной
записи поставщика и передаёт состояние вызывающего кода без изменений.```bash
mcpsnoop export -T html -o out.html                    # an HTML file to open in a browser
mcpsnoop export -T text server.py-48213-7f3a1c9e2b04   # a specific session, as text
mcpsnoop export -T json | jq                           # the newest session, piped to jq
mcpsnoop export -T har -o session.har                  # a HAR file to open in browser devtools
mcpsnoop export -T otlp -o trace.json                  # import into an OTLP-compatible tracing backend

Опустите -o, чтобы записать в stdout, и опустите сессию, чтобы взять самую новую, или передайте -, чтобы читать JSONL из stdin. В TUI нажмите e, чтобы экспортировать выбранную сессию как HTML, или выполните :export json|html|text|har|otlp [path] из командного режима.

Редактирование

Чтобы очистить существующую запись перед просмотром или передачей, передайте те же флаги редактирования, которые использовались при захвате, команде export или open:```bash mcpsnoop export session.jsonl --redact-secrets --redact-key project_token -o shared.json mcpsnoop open session.jsonl --redact-path '$.params.arguments.password'

root@kitploit:~
Эти флаги перезаписывают экспортированный файл или представление TUI в памяти, но никогда не изменяют исходный JSONL. `export` отказывается записывать вывод в файл с тем же именем, что и входной, и записывает через временный файл, который затем переименовывается на место, поэтому при сбое выполнения предыдущий файл остаётся нетронутым.

`inputSchema` и `outputSchema` инструмента, как они объявлены в результате `tools/list`, не затрагиваются `--redact-key` и `--redact-secrets` по трём причинам.

- Имя внутри схемы — это объявление типа, а не значение.
- Само имя в любом случае остаётся в журнале.
- Очистка подсхемы под свойством с именем `token` удалила бы и собственные проверки инструмента.

Исключение действует только для этой позиции, поэтому аргумент, который случайно называется `inputSchema`, очищается как и любой другой, и очистка останавливается на `default`, `const`, `examples` и `enum`, которые содержат данные, а не структуру. Используйте `--redact-path`, чтобы указать что-то внутри схемы, или `--redact-value`, который сопоставляет текст в любом месте, кроме двух ключевых слов, которые анализирует mcpsnoop: `type` и `x-mcp-header`.

Действие каждого флага различается, поэтому проверяйте результат, а не предполагайте. Все четыре очищают полезные нагрузки JSON-RPC, и `--redact-key`, `--redact-path` и `--redact-secrets` затрагивают только их. Только `--redact-value` также очищает stderr, другой не-JSON текст и содержимое строк. Заголовок `Mcp-Param-*` очищается вместе со значением тела, которое он отражает. Остальные метаданные конверта, метки сервера, `Mcp-Name`, `Mcp-Method` и HTTP-статус остаются в том виде, в котором были записаны. Очистка выполняется по принципу «лучшее усилие», поэтому используйте отдельный путь вывода и прочитайте результат перед тем, как делиться им.

### Потоковая передача завершённых вызовов в коллектор OTLP

Отправляйте спаны во время работы прокси, указав ему конечную точку трассировок OTLP/HTTP JSON. Повторяйте `--otlp-header` для аутентификации коллектора или заголовков тенанта.```bash
mcpsnoop \
  --otlp-endpoint http://localhost:4318/v1/traces \
  --otlp-header "Authorization=Bearer $OTLP_TOKEN" \
  -- node build/index.js

mcpsnoop http \
  --target http://localhost:3000/mcp \
  --otlp-endpoint http://localhost:4318/v1/traces

Доставка выполняется по принципу best-effort и никогда не блокирует проксируемый MCP-трафик. Если коллектор недоступен, mcpsnoop повторяет попытки в фоновом режиме и отбрасывает новые кадры трассировки, когда его ограниченная очередь заполнена. Обычный JSONL-журнал сеанса остается надежной записью.

Сравнение сеансов

Сравните два сохраненных сеанса по идентификатору или пути к JSONL-файлу.```bash mcpsnoop diff before-session after-session mcpsnoop diff old.jsonl new.jsonl

root@kitploit:~
Отчёт показывает инструменты, которые были добавлены или удалены, изменения описания и `inputSchema`,
изменения статуса соответствующих вызовов инструментов, а также заметные сдвиги длительности. Вызовы
сопоставляются по имени инструмента и аргументам, поэтому переупорядоченные вызовы всё равно корректно сравниваются.
По умолчанию изменения длительности должны отличаться как минимум на 100 мс и в 2 раза. Используйте
`--duration-threshold` и `--duration-ratio`, чтобы настроить эти пороговые значения.

Передайте `--exit-code`, чтобы ограничить CI по регрессиям. Он завершается с ненулевым кодом, когда сессия
после:

- удаляет инструмент
- изменяет описание инструмента, заголовок, входную схему, выходную схему или аннотации
- имеет вызов, чей статус ухудшился
- замедляется

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

## Проверка сессий в CI

Ограничьте записанный запуск агента по ошибкам, повреждению потока, предупреждениям протокола,
несоответствиям заголовков маршрутизации, вызовам, которые так и не получили ответа, отброшенным кадрам, которые
оставляют захват неполным, дрейфу определений инструментов или использованию устаревших
функций протокола.```bash
mcpsnoop check [--format text|junit|sarif] [--fail-on error,invalid,warn,mismatch,pending,late-result,drift,deprecated,incomplete,schema] [session-id|log.jsonl|-]

error, invalid и warn завершают проверку сами по себе. Остальные — опциональные. Передайте подмножество через запятую, чтобы ограничиться только тем, что важно для конкретной задачи, опустите сессию, чтобы проверить самую свежую запись, или используйте - для чтения JSONL из stdin.

СигналПриводит к сбою при
errorвызове, на который получен ответ с ошибкой JSON-RPC, результате с пометкой isError, или задаче, завершившейся сбоем
invalidкадре на канале протокола, который не является корректным JSON-RPC, обычно когда сервер пишет в stdout
warnкадре, нарушающем ожидание, заданное спецификацией MCP или JSON-RPC
mismatchзаголовке маршрутизации, противоречащем телу, входящем в пакетную передачу, или отсутствующем там, где этого требует ревизия
pendingзапросе, всё ещё открытом на момент завершения записи, из-за чего вызывающая сторона осталась в ожидании
late-resultответе, пришедшем после отмены его запроса
driftизменении объявленного определения инструмента после утверждения базовой версии
deprecatedфункции, объявленной устаревшей спецификацией
incompleteкадрах, отброшенных выше по потоку, из-за чего каждый остальной счётчик является нижней границей, а не итогом
schemaобъявленной схеме, использующей конструкцию или диалект, которые плохо переносятся между клиентами

Каждый сигнал подсчитывается независимо от того, является ли он блокирующим, поэтому запуск показывает, что было обнаружено, прежде чем вы решите, что должно приводить к сбою.``` session build-agent: errors=1 invalid=0 warnings=0 mismatches=0 pending=0 late_results=0 deprecated=0 missing_frames=0 schema_findings=1 schema findings: oneOf: search check failed: error

root@kitploit:~
Количество пропущенных кадров также передаётся вместе с артефактами, поэтому запись, которая занижает свои показатели, сообщает об этом в любом месте, где её открывают:

- `missing_frames` в JSON-экспорте
- `log.comment` в HAR
- атрибут ресурса `mcpsnoop.session.missing_frames` в OTLP```bash
mcpsnoop check build-agent
mcpsnoop check --fail-on error,invalid artifacts/session.jsonl
mcpsnoop check --fail-on mismatch gateway-run.jsonl

Код выхода сообщает, какое из двух событий произошло, и CI-обёртке нужно это различие. 1 означает, что проверка выполнилась и что-то не прошло гейт, поэтому находки реальны и их стоит публиковать. 2 означает, что проверка так и не состоялась: путь, которого нет, файл, который не является журналом сеанса, каталог состояния, в котором ничего нет, флаг, который не разбирается. При коде 2 в stdout ничего не выводится, поэтому конвейер никогда не загрузит пустой отчёт так, будто это вердикт.

Утверждайте, что должно и не должно происходить

Помимо подсчёта сигналов, утверждайте форму выполнения. Эти флаги сочетаются друг с другом и с --fail-on, и любой сбой завершается кодом 1 — кодом, означающим, что проверка выполнилась и что-то нашла.

ФлагЗавершается ошибкой, когда
--max-duration <dur>один или несколько завершённых вызовов инструментов превысили бюджет, с указанием их количества и худшего вызова
--expect-tool <name>указанный инструмент ни разу не вызывался (повторяемый)
--forbid-tool <name>указанный инструмент был вызван (повторяемый)

a contract for the run: search must run, delete must not, nothing over 2s

mcpsnoop check --expect-tool search --forbid-tool delete --max-duration 2s run.jsonl

root@kitploit:~
### Сообщайте об этом там, где CI уже ищет

`--format junit` записывает один `<testcase>` на сигнал и сессию, а его сбои
следуют тому же выбору `--fail-on`, что и текстовый вывод.```yaml
- name: Check captured MCP session
  run: |
    mkdir -p test-results
    mcpsnoop check --format junit artifacts/session.jsonl > test-results/mcpsnoop.xml
- name: Upload mcpsnoop JUnit report
  if: always()
  uses: actions/upload-artifact@v4
  with:
    name: mcpsnoop-junit
    path: test-results/mcpsnoop.xml

--format sarif записывает журнал SARIF 2.1.0 вместо этого. Там, где junit сообщает об одном агрегате на сигнал, SARIF сообщает об одном результате на находку, неся сессию, Seq кадра и собственный текст предупреждения или дрейфа кадра, и указывая на строку журнала, из которой был декодирован кадр. Сигнал, указанный в --fail-on, сообщается на уровне error, а сигнал вне него — на уровне note, поэтому отчёт и шлюз никогда не расходятся.

Результат указывает на журнал, из которого пришла находка, и то, как именно, зависит от того, откуда был прочитан журнал.

  • Путь внутри рабочего каталога становится относительным, который code scanning разрешает относительно корня репозитория.
  • Путь в другом месте на диске или идентификатор сессии, разрешённый из каталога состояния, становится абсолютным URI file://.
  • Чтение из stdin даёт результату вообще без местоположения, поскольку нет файла, на который можно указать.

Оповещение отображается с окружающими его строками только тогда, когда этот путь является файлом в анализируемом коммите, поэтому захват, который рабочий процесс сгенерировал в artifacts/, открывает оповещение с сообщением, правилом и номером строки, но без просмотра исходного кода. Фиксация захвата, который вы хотите отобразить полностью, — единственный способ получить такой просмотр.

Code scanning отклоняет файл, в прогоне которого более 25 000 результатов, и отображает только первые 5 000 из принятых, поэтому отчёт ограничен 5 000: сначала находки, на которых шлюз завершился с ошибкой, затем результат mcpsnoop/report-truncated, сообщающий, сколько было пропущено. Текстовый и junit форматы остаются полными.

GitHub Action

Всё ниже — это то, что действие делает за вас. Оно устанавливает mcpsnoop, проверяет захват, регистрирует находки на вкладке Security и завершает задание с ошибкой на том, что вы указали в шлюзе.```yaml permissions: security-events: write contents: read

steps:

  • uses: kerlenton/[email protected] with: session: artifacts/session.jsonl
root@kitploit:~
Закрепите релиз — любой, какой хотите. Самый свежий — на
[странице релизов](https://github.com/kerlenton/mcpsnoop/releases). Плавающего
`v1` намеренно нет. Закреплённый релиз — это также бинарник, который
устанавливает действие, так что они никогда не могут разойтись, и нет версии
по умолчанию, которая могла бы устареть.

| Вход | |
|---|---|
| `session` | захват `.jsonl` для проверки, относительно корня репозитория. Обязательно |
| `fail-on` | как `--fail-on`, по умолчанию — то же, что и у CLI |
| `args` | любые другие флаги `check`, в кавычках, как в командной строке. `--format` отклоняется, так как действие читает отчёт |
| `upload-sarif` | отправить отчёт в code scanning. `true` |
| `category` | пространство имён code scanning. `mcpsnoop`. Меняйте его для каждой ветви матрицы, иначе ветви перезапишут друг друга |
| `fail-on-findings` | завершить задачу ошибкой при наличии находки. `true`. Установите `false`, чтобы оформить алерты и позволить обязательной проверке code scanning решить |
| `version` | какой mcpsnoop установить. По умолчанию — релиз, который вы закрепили |
| `install` | `false`, когда mcpsnoop уже в PATH, — так делается на платформе, для которой нет собранного релиза |

Выходные данные — `outcome`, `sarif` и `exit-code`. `outcome` принимает значения
`passed`, `findings` или `error`, и третье стоит обрабатывать отдельно. Оно
означает, что ничего не было проверено, а это не то же самое, что ничего не
найдено. **Запуск, который не смог проверить, завершает задачу ошибкой, что бы
ни говорил `fail-on-findings`**, потому что пайплайн, который становится зелёным,
ничего не проверив, хуже того, который падает.

Задаче нужно право `security-events: write`, иначе загрузка ответит 403.
Установите `upload-sarif: false` в репозитории без code scanning.

### Или подключите сами

Действие — это четыре шага и никакой магии. Делая это вручную, нужно проявить
ту же осторожность. Загрузка должна выполняться на запусках, у которых есть
отчёт, — это те, что завершились с кодом 0 или 1, а не те, что с кодом 2, и шаг,
который завершает задачу ошибкой, должен идти после неё, иначе находки никогда
не попадут на вкладку, ради которой они существуют.```yaml
permissions:
  # required for all workflows
  security-events: write
  # only required for workflows in private repositories
  actions: read
  contents: read

steps:
- name: Check captured MCP session
  id: check
  run: |
    code=0
    mcpsnoop check --format sarif artifacts/session.jsonl > mcpsnoop.sarif || code=$?
    echo "exit-code=$code" >> "$GITHUB_OUTPUT"
    # 2 means the check never happened, so there is no report to publish and
    # nothing was verified. Stop here rather than uploading an empty file.
    [ "$code" -le 1 ] || exit 1
- name: Upload mcpsnoop SARIF report
  if: ${{ !cancelled() }}
  uses: github/codeql-action/upload-sarif@v4
  with:
    sarif_file: mcpsnoop.sarif
    category: mcpsnoop
- name: Fail on findings
  # Separate, and after the upload, so the findings reach the Security tab on
  # exactly the runs that have some.
  if: ${{ !cancelled() && steps.check.outputs.exit-code == '1' }}
  run: exit 1

Перехват маршрутизирующего заголовка, не совпадающего с телом запроса

В транспортном протоколе streamable-HTTP шлюз маршрутизирует запросы по заголовкам Mcp-Method и Mcp-Name, в то время как сервер читает тело запроса, поэтому заголовок, не совпадающий с телом, означает, что они обрабатывают два разных запроса. Сигнал mismatch покрывает этот случай, заголовок, прикреплённый к пакету, который он не может адресовать, и полностью отсутствующий обязательный заголовок.

В версии от 2026-07-28 отсутствующий маршрутизирующий заголовок является ошибкой валидации, и соответствующий требованиям сервер отклоняет запрос с кодом 400 и ошибкой -32020. mcpsnoop поднимает этот сигнал только после того, как сессия подтверждает поддержку этой ревизии или более поздней, поскольку более ранние ревизии вообще не определяют эти заголовки, и их отсутствие там корректно. Собственное отклонение сервером с ошибкой -32020 считается тем же сигналом.

Имя или URI ресурса, которые не помещаются в значение поля HTTP, передаются в Base64 с маркером =?base64?…?=, который декодируется перед сравнением, поэтому клиент, выполняющий корректное кодирование, никогда не помечается.

Для HTTP-запросов tools/call mcpsnoop также показывает каждый заголовок Mcp-Param-{Name} и, когда известно соответствующее объявленное определение инструмента, сравнивает его с аннотированным путём аргумента. Вложенные свойства, маркер Base64, логические значения и численно эквивалентные безопасные целые числа обрабатываются без ложных срабатываний при строковом сравнении. Неизвестные заголовки параметров и сессии без соответствующего определения инструмента остаются наблюдательными. Редактирование на основе ключей и значений применяется к захваченным значениям заголовков параметров до того, как они попадут в приёмник, и значение, которое mcpsnoop зачистил самостоятельно, никогда не сообщается как расхождение.

Проверка обязательных транспортных заголовков, определённых спецификацией

Маршрутизирующие заголовки выше были единственными, которые переносились в кадре, поэтому остальные обязательные заголовки транспортного протокола Streamable HTTP не достигали ничего, что могло бы их проверить. Content-Type был самым острым случаем. Ответная сторона уже читала его, чтобы отличить SSE-поток от JSON-тела, а затем отбрасывала его.

Теперь HTTP-кадр переносит заголовки, для которых транспорт определяет правила, и два из этих правил можно проверить.

ПравилоСообщается как
клиент ОБЯЗАН отправить Accept со списком, содержащим как application/json, так и text/event-streamwarn на запросе
сервер, отвечающий на JSON-RPC-запрос, ОБЯЗАН вернуть Content-Type: application/json или text/event-streamwarn на ответе

Оба предложения читаются одинаково в версиях от 2025-11-25 и 2026-07-28, поэтому, в отличие от проверок расхождений и расширений, им не требуется шлюз ревизий. Origin также записывается, поскольку серверы ОБЯЗАНЫ проверять его и ОБЯЗАНЫ отвечать кодом 403, когда он недействителен, но mcpsnoop не может знать ваши разрешённые источники, поэтому он показывает значение, а не оценивает его.

Подстановочные знаки учитываются. Клиент, отправляющий */*, предложил оба типа и никогда не сообщается, а параметр charset в Content-Type игнорируется. Журнал, захваченный до того, как mcpsnoop записал эти заголовки, остаётся молчаливым, а не сообщает о каждом кадре в нём для заголовка, который никто не записал, а stdio вообще их не имеет.

Authorization намеренно не захватывается. Превращение вызова в факты о токенах — это отдельная проблема, и запись bearer-токена на диск — не ответ на неё. Mcp-Session-Id и Last-Event-ID также не захватываются. Ревизия от 2026-07-28 удалила оба и предписывает серверу игнорировать их, поэтому проверять больше нечего.

Обнаружение расхождений в определениях инструментов

Первое полное tools/list, наблюдаемое для метки сервера, становится его доверенным базовым определением. Более поздние сессии сравнивают это базовое определение поле за полем:

  • описание
  • название
  • схемы ввода и вывода
  • аннотации и иконки

Инструменты, которые были добавлены или удалены, также сравниваются, что является сравнением множеств, а не полей.

Аннотации важнее всего, поскольку инструмент, одобренный с readOnlyHint, который позже объявляет себя разрушительным, — это тот самый обман, для обнаружения которого существует эта проверка, а спецификация предписывает клиентам относиться к аннотациям как к ненадёжным. Название и иконки отслеживаются, потому что именно их видит пользователь, а спецификация ставит title инструмента выше annotations.title и его имени. Таблица сессий и сводка инструментов помечают расхождения, не блокируя и не изменяя MCP-трафик.

Аннотации сравниваются через их значения по умолчанию из спецификации, поэтому сервер, который начинает явно указывать подсказку, на которую он уже полагался, не сообщается. Базовое определение, записанное до того, как mcpsnoop начал отслеживать поле, продолжает работать для полей, которые он записывает, и указывает, на какие из них он не может ответить. Повторно запишите с помощью mcpsnoop baseline --accept, как только вы доверитесь текущим определениям.

Изменение того, что записывает редактирование, изменяет то, что сравнивает проверка расхождений. Базовое определение, снятое без --redact-value, а затем проверенное по захвату, сделанному с ним, сообщает о зачищенных полях как об изменённых, что корректно, поскольку записанное определение действительно изменилось. Повторно запишите с --accept после изменения настроек редактирования.

Используйте стабильную уникальную --label для каждого сервера, чьё имя команды или целевой хост в противном случае конфликтовали бы. Базовые определения хранятся в обычном каталоге состояния mcpsnoop, поэтому применяются MCPSNOOP_HOME и XDG_STATE_HOME.```bash mcpsnoop check --fail-on drift session.jsonl mcpsnoop baseline session.jsonl mcpsnoop baseline --accept session.jsonl # trust a legitimate definition change mcpsnoop baseline --reset session.jsonl # trust the next complete tools/list

root@kitploit:~
В эфемерном CI каталог состояния изначально пуст, поэтому запуску не с чем сравнивать, и он записывает базовую линию вместо её проверки. **Запуск, который должен был завершиться ошибкой при расхождении, но ничего не проверил, не считается успешным**, и в сообщении указывается, какой каталог нужно сохранять. Это единственный случай, когда запись базовой линии считается ошибкой. Без `drift` в `--fail-on` запись базовой линии — обычное дело и не меняет код завершения.

Таким образом, базовая линия должна сохраняться между запусками, чтобы проверка расхождений имела смысл. Укажите `--baseline` на каталог, включённый в репозиторий или кэшируемый, либо задайте `MCPSNOOP_HOME` как путь к сохраняемому расположению.```
recorded first-seen tool baseline (trusted, not verified)
check failed: drift

Установка

Требования

  • Python 3.8+
  • pip

Установка из PyPI

root@kitploit:~
pip install kitploit

Установка из исходного кода

root@kitploit:~
git clone https://github.com/kitploit/kitploit.git
cd kitploit
pip install -r requirements.txt
python setup.py install

Проверка установки

root@kitploit:~
kitploit --version

Если вы видите номер версии, установка прошла успешно.```bash mcpsnoop check --fail-on drift --baseline .mcpsnoop/baselines session.jsonl

root@kitploit:~
`drift` является опциональным для `check`. Стандартный фильтр `error,invalid,warn` не изменён.

### Обнаружение функции, которую ни одна из сторон не согласовала

SEP-2133 вынесло опциональные функции из основного протокола в расширения,
анонсируемые в карте `extensions` возможностей каждой стороны. Tasks — одна из
них, поэтому начиная с 2026-07-28 `tasks/get`, `notifications/tasks` или `tools/call`
с ответом, содержащим дескриптор задачи, имеет смысл только тогда, когда другая сторона заявила, что поддерживает Tasks.

Когда это не так, спецификация явна: поддерживающая сторона ОБЯЗАНА либо
откатиться к базовому поведению, либо отклонить запрос. Игнорирование этого — причина того, почему функция выглядит подключённой, а затем тихо ничего не делает, и что читатель получает вместо этого `-32601` или `-32021` спустя несколько кадров, либо задачу, которая никогда не продвигается. mcpsnoop предупреждает о кадре, который обратился к расширению, и указывает, какая сторона его никогда не анонсировала.```
tool "slow" answered with a task handle uses the io.modelcontextprotocol/tasks
extension, which the client never advertised

Это warn, поэтому обычный прогон check завершается с ошибкой на нём. Он остаётся незаметным всякий раз, когда захват не может показать, что было согласовано, — это захват, начинающийся после рукопожатия, или тот, чьи возможности были вычищены вашей собственной редакцией, — а также на ревизиях до 2026-07-28, где tasks/* являются базовым протоколом и их использование корректно.

Помечать устаревшие функции протокола

Ревизия от 2026-07-28 объявляет устаревшими Roots, Sampling и Logging. Они продолжают работать как минимум год, поэтому mcpsnoop помечает их, а не обрабатывает как ошибки. Поток, инспектор возможностей и экспорт — все помечают их, и каждая метка называет замену.

Две из трёх теперь доступны только через запрос с несколькими циклами обмена, где имя метода находится внутри карты inputRequests сервера, а не в самом кадре. Они тоже помечаются, поэтому сервер, перешедший на новый шаблон, не перестаёт молча сообщать о них.```bash mcpsnoop check --fail-on deprecated session.jsonl

root@kitploit:~
Как и `drift`, `deprecated` включается явно. При запуске по умолчанию выводится количество и статус остаётся зелёным, поэтому сеанс, использующий всё ещё допустимую устаревшую функцию, сам по себе никогда не переведёт CI в красный статус.

### Конструкции схемы флагов, которые клиенты обрабатывают некорректно

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

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

| Показано | Значение |
|---|---|
| `no root` | `inputSchema` отсутствует, не является JSON-объектом или имеет корневой тип, отличный от `"object"` |
| `dialect` | `$schema`, указывающий на диалект, отличный от 2020-12, который используется по умолчанию в ревизии |
| `ext ref` | `$ref`, указывающий за пределы документа, — это также случай, когда спецификация предупреждает разработчиков не следовать ссылке вслепую |
| `oneOf`, `anyOf`, `allOf`, `not` | ключевое слово композиции, обрабатываемое клиентами непоследовательно |
| `ref` | `$ref`, указывающий внутри того же документа |
| `untyped` | свойство, которое не объявляет тип и не предоставляет иного способа указать, что оно принимает |

Все пункты, кроме первого, являются наблюдениями, а не вердиктами. Схема, использующая `oneOf`, не является ошибочной — просто разные клиенты, скорее всего, прочитают её по-разному, и схема может объявлять любой диалект, какой пожелает. Исключением является `no root`: определение `Tool` требует `inputSchema` и фиксирует его корневой тип как `"object"`, поэтому клиент, проверяющий список, отклоняет такой инструмент полностью, и он никогда не становится вызываемым, при этом в передаваемых данных нет ничего, что объясняло бы причину. Именно поэтому `no root` возглавляет колонку, а схема, вычищенная собственной редакцией mcpsnoop, никогда не сообщается, поскольку нечитаемая схема — это не ошибочная схема.

Это разделение определяет, что `check` делает с ними. `no root` — это предупреждение на кадре `tools/list`, поэтому оно не проходит стандартный фильтр `error,invalid,warn` вообще без каких-либо флагов, и в этом суть: сервер, поставляющий непригодный инструмент, нормально отвечает на каждое рукопожатие и просто никогда не получает `tools/call`. Наблюдения учитываются как `schema_findings` и сообщаются в разделе `schema findings:`, и приводят к сбою запуска только при добавлении `schema` в `--fail-on`. Оба варианта попадают в `--format junit` и `--format sarif`, а `export` переносит поинструментальный список в `summary.definitions.per_tool[].findings`.```bash
mcpsnoop check session.jsonl                     # a non-object root already fails this
mcpsnoop check --fail-on schema session.jsonl    # and now so do the observations

Колонка несёт предупреждающий цвет и никогда не красный цвет колонки ERR, а mcpsnoop по-прежнему ничего не меняет в трафике, который он пересылает.

Ничего не разрешается и не извлекается. Внешний $ref распознаётся только по своей форме, а схема, на которую он указывает, никогда не читается.

Повтор вызова, захваченного по HTTP

r повторно отправляет захваченный вызов на живой сервер. Для захвата через stdio команда находится в журнале, поэтому mcpsnoop запускает изолированную копию и отправляет запрос на неё. У HTTP-захвата нет команды для запуска, а конечная точка, которую он записывает, лишается своей информации о пользователе и всех значений запроса, поэтому она называет сервер, не являясь адресом для набора.

Итак, вы указываете, куда направляется повтор, и mcpsnoop никогда не набирает производственную конечную точку только потому, что кто-то нажал клавишу.```bash mcpsnoop open --replay-target https://api.example.com/mcp session.jsonl mcpsnoop open --replay-target https://api.example.com/mcp
--replay-header 'Authorization: Bearer sk-…' session.jsonl

root@kitploit:~
Без `--replay-target` HTTP-сессия сообщает об этом, а не предлагает ключ, который
не может работать. С ним `r` по-прежнему спрашивает перед первой отправкой сессии,
точно так же, как записанная команда подтверждается перед её выполнением.

Учётные данные достигают сервера через `--replay-header` и нигде больше.
mcpsnoop не записывает заголовок `Authorization` и не воспроизводит ни одного, так что
нечего перехватывать для утечки при воспроизведении.

Повторно отправленный POST несёт то, что делает обязательным транспорт, чего не делает POST
с голым захваченным телом: `MCP-Protocol-Version`, `Accept` со списком как
`application/json`, так и `text/event-stream`, `Mcp-Method`, `Mcp-Name` там, где это
требует спецификация, и каждый захваченный `Mcp-Param-*`. Они повторно отправляются дословно
из захвата, включая sentinel в base64, поэтому не могут расходиться с телом
так, как могло бы повторное вычисление. Единственный заголовок, который не копируется, — это версия
протокола, потому что повторно отправленное тело объявляет ревизию, на которой говорит mcpsnoop, а
заголовок должен соответствовать телу.

`Mcp-Name` вычисляется из отправляемого тела, а не копируется, потому что
спецификация берёт его из `params.name` или `params.uri` и требует, чтобы сервер
отклонял заголовок, который расходится с телом, поэтому правка, переименовывающая инструмент,
иначе отправила бы старое имя. Заголовки `Mcp-Param-*` отражают захваченные
аргументы, поэтому при отредактированном воспроизведении ни один из них не отправляется, а не утверждается
что-то о теле, которое кто-то переписал. Захват может задавать заголовки только в этом
одном семействе. Журнал — это файл, который люди передают друг другу, и разрешение ему называть любой
заголовок позволило бы перезаписать обязательные или добавить учётные данные, которые никто не передавал.

`Mcp-Param-*`, который вычистило правило редактирования, останавливает воспроизведение с указанием причины. Отправка
заглушки поместила бы собственные байты mcpsnoop на живой сервер, как будто их
ввёл пользователь.

Перенаправление отклоняется, а не выполняется. Адрес — это тот, который вы назвали и
подтвердили, и следование за 307 передало бы этот выбор удалённой стороне, повторно отправив
тело и, на переходе, меняющем только порт, также учётные данные. mcpsnoop
сообщает, куда сервер хотел его отправить, и позволяет вам решить, не назвать ли
именно этот адрес вместо этого.

Ответ, приходящий как единый JSON-объект, и ответ, приходящий как поток событий,
оба читаются, и сбой называется по имени, а не по номеру:

- `401` сообщает схему, которую потребовал сервер
- `-32020` сообщает, на что он возражал
- не-JSON-RPC `400` или `404` говорит, что адрес не является конечной точкой Streamable HTTP
  этой ревизии

### Отличайте задержку сервера от задержки пользователя

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

В цепочке `book_flight`, где сервер работал 1,2 секунды, а пользователь потратил
37, `check --max-duration 5s` обвиняет инструмент за 38,2 секунды. Он по-прежнему так делает,
потому что изменение значения этого флага ослабило бы каждый конвейер, который уже
его задаёт. Два родственных флага называют то, что они измеряют, вместо этого.```bash
mcpsnoop check --max-server-duration 1s session.jsonl   # the server's share alone
mcpsnoop check --max-round-trips 2 session.jsonl        # how chatty a tool is

Установка

Требования

  • Python 3.8+
  • pip

Установка из PyPI

root@kitploit:~
pip install kitploit

Установка из исходного кода

root@kitploit:~
git clone https://github.com/kitploit/kitploit.git
cd kitploit
pip install -r requirements.txt
python setup.py install

Проверка установки

После установки вы можете проверить, что инструмент установлен корректно, выполнив:

root@kitploit:~
kitploit --version

Вы должны увидеть вывод, похожий на:

root@kitploit:~
Kitploit v1.0.0

Быстрый старт

Базовое использование

Чтобы начать использовать Kitploit, просто выполните:

root@kitploit:~
kitploit search nmap

Это позволит найти все инструменты, связанные с nmap, в каталоге Kitploit.

Поиск инструментов

Вы можете искать инструменты по имени, описанию или ключевым словам:

root@kitploit:~
kitploit search "sql injection"
kitploit search --category web
kitploit search --tag exploit

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

Чтобы установить инструмент из каталога:

root@kitploit:~
kitploit install metasploit

Обновление инструмента

Чтобы обновить установленный инструмент до последней версии:

root@kitploit:~
kitploit update metasploit

Удаление инструмента

Чтобы удалить инструмент:

root@kitploit:~
kitploit remove metasploit

Команды

КомандаОписание
searchПоиск инструментов в каталоге
installУстановка инструмента
updateОбновление инструмента
removeУдаление инструмента
listСписок всех доступных инструментов
infoПоказать подробную информацию об инструменте
versionПоказать версию Kitploit
helpПоказать справочную информацию

Параметры

ПараметрОписание
--categoryФильтр по категории
--tagФильтр по тегу
--verboseПодробный вывод
--quietТихий режим (только ошибки)
--jsonВывод в формате JSON
--no-colorОтключить цветной вывод

Примеры

Поиск инструментов по категории

root@kitploit:~
kitploit search --category network

Поиск инструментов по нескольким тегам

root@kitploit:~
kitploit search --tag exploit --tag remote

Просмотр подробной информации об инструменте

root@kitploit:~
kitploit info burpsuite

Вывод результатов в формате JSON

root@kitploit:~
kitploit search nmap --json

Установка нескольких инструментов одновременно

root@kitploit:~
kitploit install nmap metasploit burpsuite

Конфигурация

Файл конфигурации

Kitploit использует файл конфигурации, расположенный по адресу ~/.kitploit/config.yaml. Вы можете изменить настройки по умолчанию, отредактировав этот файл.

Пример конфигурации

root@kitploit:~
# Конфигурация Kitploit
settings:
  default_category: all
  color_output: true
  verbose: false
  cache_enabled: true
  cache_ttl: 3600

paths:
  install_dir: ~/tools
  data_dir: ~/.kitploit/data
  cache_dir: ~/.kitploit/cache

api:
  base_url: https://api.kitploit.com
  timeout: 30
  retries: 3

Переменные окружения

Вы также можете настроить Kitploit с помощью переменных окружения:

ПеременнаяОписание
KITPLOIT_CONFIGПуть к файлу конфигурации
KITPLOIT_INSTALL_DIRКаталог установки инструментов
KITPLOIT_DATA_DIRКаталог данных
KITPLOIT_CACHE_DIRКаталог кэша
KITPLOIT_API_URLБазовый URL API
KITPLOIT_TIMEOUTТайм-аут API в секундах
KITPLOIT_RETRIESКоличество повторных попыток API
KITPLOIT_NO_COLORОтключить цветной вывод (true/false)
KITPLOIT_VERBOSEВключить подробный вывод (true/false)

Каталог инструментов

Категории

Kitploit организует инструменты по следующим категориям:

  • Network — Сетевые инструменты и сканеры
  • Web — Инструменты для веб-приложений
  • Exploit — Инструменты для эксплуатации уязвимостей
  • Forensics — Инструменты для криминалистики
  • Reverse Engineering — Инструменты для реверс-инжиниринга
  • Password — Инструменты для работы с паролями
  • Wireless — Инструменты для беспроводных сетей
  • Social Engineering — Инструменты для социальной инженерии
  • OSINT — Инструменты для разведки по открытым источникам
  • Malware — Инструменты для анализа вредоносного ПО

Популярные инструменты

Вот некоторые из самых популярных инструментов, доступных в Kitploit:

ИнструментКатегорияОписание
NmapNetworkСканер сети и безопасности
MetasploitExploitФреймворк для эксплуатации уязвимостей
Burp SuiteWebПлатформа для тестирования безопасности веб-приложений
WiresharkNetworkАнализатор сетевых протоколов
John the RipperPasswordИнструмент для взлома паролей
Aircrack-ngWirelessНабор инструментов для аудита беспроводных сетей
SQLMapWebИнструмент для автоматизации обнаружения и эксплуатации SQL-инъекций
HydraPasswordИнструмент для подбора паролей
NiktoWebСканер уязвимостей веб-серверов
HashcatPasswordИнструмент для восстановления паролей

API

Обзор

Kitploit предоставляет REST API для программного доступа к каталогу инструментов. API доступен по адресу https://api.kitploit.com.

Аутентификация

Для использования API вам потребуется ключ API. Вы можете получить ключ, зарегистрировавшись на kitploit.com.

Конечные точки

МетодКонечная точкаОписание
GET/api/v1/toolsСписок всех инструментов
GET/api/v1/tools/{id}Получить информацию об инструменте
GET/api/v1/searchПоиск инструментов
GET/api/v1/categoriesСписок категорий
GET/api/v1/tagsСписок тегов

Пример запроса

root@kitploit:~
curl -H "Authorization: Bearer YOUR_API_KEY" \
     https://api.kitploit.com/api/v1/tools

Пример ответа

root@kitploit:~
{
  "status": "success",
  "data": {
    "tools": [
      {
        "id": "nmap",
        "name": "Nmap",
        "category": "network",
        "description": "Сканер сети и безопасности",
        "version": "7.94",
        "url": "https://github.com/nmap/nmap"
      }
    ],
    "total": 1
  }
}

Устранение неполадок

Общие проблемы

Ошибка подключения к API

Если вы получаете ошибки подключения при использовании Kitploit, проверьте:

  1. Ваше интернет-соединение
  2. Настройки прокси (если применимо)
  3. Переменную окружения KITPLOIT_API_URL
  4. Файл конфигурации ~/.kitploit/config.yaml

Ошибка установки инструмента

Если установка инструмента завершается с ошибкой:

  1. Убедитесь, что у вас есть права на запись в каталог установки
  2. Проверьте зависимости инструмента
  3. Попробуйте установить с подробным выводом: kitploit install <tool> --verbose

Проблемы с кэшем

Если вы подозреваете проблемы с кэшем:

root@kitploit:~
kitploit cache clear

Получение поддержки

Если у вас возникли проблемы, которые вы не можете решить:

  • Посетите GitHub Issues
  • Присоединяйтесь к нашему Discord-серверу
  • Отправьте электронное письмо на адрес [email protected]

Часто задаваемые вопросы

Что такое Kitploit?

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

Совместим ли Kitploit с моей операционной системой?

Kitploit поддерживает Linux, macOS и Windows. Однако некоторые инструменты в каталоге могут быть доступны только для определенных операционных систем.

Как часто обновляется каталог?

Каталог обновляется ежедневно. Вы можете проверить наличие обновлений с помощью команды kitploit update.

Могу ли я внести свой вклад в Kitploit?

Да! Мы приветствуем вклад сообщества. Посетите наш GitHub-репозиторий, чтобы узнать, как вы можете помочь.

Лицензия

Kitploit распространяется под лицензией MIT. См. файл LICENSE для получения подробной информации.

Благодарности

Мы хотели бы поблагодарить всех участников и пользователей, которые помогли сделать Kitploit тем, чем он является сегодня. Ваш вклад и отзывы неоценимы.

Связаться с нами

  • Веб-сайт: kitploit.com
  • GitHub: github.com/kitploit
  • Twitter: @kitploit
  • Discord: discord.gg/kitploit
  • Электронная почта: [email protected]

Сделано с ❤️ сообществом Kitploit``` assertion failed: 1 tool call exceeded the 1s server budget (worst: tool "book_flight" held for 1.2s) assertion failed: 1 tool call exceeded the 2 round trip budget (worst: tool "book_flight" took 3)

root@kitploit:~
Оба параметра по умолчанию выключены, поэтому стандартный запуск `check` не затрагивается, и оба считываются из временных меток кадров и связи, которую mcpsnoop уже вывел, так что ни один из них не угадывает намерения.

Нажмите `i` в TUI для разбивки или прочитайте `interactions` в экспортах json, text и html. Каждая запись — это одна логическая операция с количеством её циклов, её общим временем, долей, которую сервер удерживал её, и долей, которую она ждала клиента, плюс строка на каждый хоп с указанием того, что запрашивал каждый ответ. Сводка по каждому инструменту получает столбец `TRIPS`, чтобы болтливый инструмент был виден без открытия чего-либо.

`export --format har` помещает долю сервера в `wait`, а остальное — в `blocked`, что и предназначено для этого поля, чтобы просмотрщик перестал рисовать 38-секундное ожидание сервера, которого никогда не было.

Счётчики и две доли накапливаются по мере поступления кадров, а не вычисляются по запросу, потому что живое хранилище освобождает старые кадры, чтобы оставаться в рамках своего бюджета, и производный ответ тихо оказался бы окном, а не цепочкой. Разбивка по хопам считывается из ещё удерживаемых кадров и явно указывает, когда она охватывает лишь часть цепочки. `ServerTime + ClientTurnaround` равно общему времени по построению, а не по арифметике, которой кому-то приходится доверять.

`--max-round-trips` оценивает цепочку, которая всё ещё выполняется, потому что каждый уже сделанный ею запрос поддаётся подсчёту, а сервер, спрашивающий снова и снова, порождает ровно ту операцию, которую никто никогда не завершает. `--max-server-duration` ждёт завершения, что является правилом, которое уже применяет `--max-duration`, поскольку у всё ещё открытой операции нет задержки для оценки.

Операция, которую mcpsnoop не смог связать, остаётся собственной записью с одним хопом. `matchRetry` намеренно отказывается от неоднозначной связи, и это представление не заполняет этот пробел.

Операция, занявшая один запрос, не несёт разбивки по хопам, потому что один хоп дословно повторяет итоги выше. Цепочка сообщает по одному хопу на запрос и явно указывает, когда хранилище больше не удерживает каждый кадр или когда работа осела вне пары запрос-ответ, из которой состоит хоп, как это делает дескриптор задачи.

### Посмотреть, что сервер запросил у вашего пользователя

Элиситация — это единственный путь в MCP, где человек вводит данные в сервер, и при MRTR вопрос и ответ больше не являются двумя половинами одного обмена. Вопрос погребён в `InputRequiredResult`, ответ возвращается внутри `inputResponses` при повторной попытке под другим id, и единственное, что их связывает, — это связь, которую mcpsnoop уже выводит.

Без этого сопоставления отклонённый запрос пароля читается как обычная ошибка инструмента.```
tools/call login_legacy [form] creds: decline after 3s
  password string

Нажмите l в TUI или прочитайте elicitations в экспортах json, text и html. Каждая строка называет операцию, которую вопрос прервал, режим, сообщение, что было запрошено, что сделал пользователь и сколько времени он потратил. Вопрос, на который ни одна повторная попытка так и не ответила, отображается как ожидающий, что MRTR делает обычным исходом, а не ошибкой, поскольку спецификация предписывает серверам не предполагать, что клиент вообще повторит попытку.

Строки форм перечисляют имена свойств requestedSchema и их объявленные типы. Свойство, подсхему которого заменило правило редактирования, показывает неизвестный тип, а не заполнитель, потому что заполнитель — это не то, что объявил сервер. Строки URL несут адрес целиком, который, согласно спецификации, клиент должен показывать перед согласием, и называют хост отдельно, который, как сказано, следует выделять против подмены поддоменов.

Реестр никогда не содержит отправленное значение. То, что ввёл пользователь, остаётся в захвате для того, кому это нужно, и исключение этого из сводной поверхности, созданной для экспорта и вставки куда угодно, — это то, что полностью убирает это из истории редактирования. Это важнее всего в режиме url, где спецификация намеренно помещает учётные данные.

Повторная попытка отвечает на тот раунд, из которого она была выдана, и ни на какой другой. MRTR сообщает серверу, что когда клиент опускает часть запрошенного, следует спросить снова в новом раунде, поэтому более ранний раунд, содержащий один безответный ключ рядом с отвеченным, — это обычный трафик, и безответная половина остаётся ожидающей, а не заимствует ответ более позднего раунда.

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

Здесь ничто не предупреждает и ничто не меняет код выхода check. Реестр записывает, что произошло. Он не выносит суждений.

Найдите инструмент, который выходит из строя один раз из четырёх

check читает одну сессию, а diff читает ровно две, поэтому инструмент, который иногда выходит из строя, остаётся невидимым, пока кто-то не откроет захваты вручную. За шестнадцать захватов сервера, чей run_query отвечает isError примерно в четверти случаев, check честно сообщает о самом новом как о чистом.```bash mcpsnoop stats mcpsnoop stats --since 7d --label prod mcpsnoop stats --limit 20 --format json

root@kitploit:~
No Markdown content was provided in the input. Please paste the chunk you want translated.```
read 16 logs of 16 in ~/.local/state/mcpsnoop/sessions

SERVER       TOOL          CALLS   ERR  PROTO    FAIL%       SESS       p50      p95      p99      DEF
flaky-demo   run_query        13     3      0    23.1%       3/13     434ms    519ms    519ms     195B
docs-mirror  run_query         3     1      0    33.3%        1/3     357ms    434ms    434ms     195B
docs-mirror  search_docs      12     0      0     0.0%        0/3     377ms    386ms    386ms     200B
flaky-demo   search_docs      52     0      0     0.0%       0/13      42ms     58ms      59ms    200B

ERR и PROTO — это отдельные столбцы, потому что спецификация делает их отдельными сущностями. Инструмент, отвечающий isError, сообщает о том, на что модель может отреагировать и повторить попытку. Ошибка JSON-RPC означает, что неверен запрос или сервер. SESS — это количество сеансов, в которых наблюдался сбой, по отношению к сеансам, вызвавшим инструмент; это тот самый вопрос «один запуск из десяти», на который доля от числа вызовов ответить не может.

Строки привязаны к серверу и метке вместе. Сервер — это записанная команда и рабочая директория для stdio и конечная точка для HTTP, та же идентичность, которую использует inventory. Любая половина по отдельности объединяет то, что объединять не следует: одна лишь метка сливает два сервера, производящих одно имя, что случается всякий раз, когда два чекаута проекта запускают одну и ту же точку входа, а одна лишь идентичность сливает одну команду, намеренно запущенную как prod, а затем как staging. Обе ошибки размазывают два чистых распределения в одно, которое не описывает ни одно из них.

Когда две строки действительно разделяют метку, ячейка SERVER несёт рабочую директорию или конечную точку, по которым их различают, а JSON несёт command, cwd и endpoint в каждой строке. Имя, которое никогда не было неоднозначным, остаётся без изменений, так что обычная таблица не меняется.

Каждый сеанс в журнале сворачивается, а не только первый, поэтому файл, созданный конкатенацией захватов, учитывает их все.

Процентили объединяются по сырым длительностям. Медиана медиан — это медиана ничего. Одна операция с несколькими круговыми обменами — это один вызов с одной длительностью, сколько бы запросов она ни заняла, а всё ещё открытый вызов учитывается в CALLS, не внося вклад в задержку.

Один захват находится в памяти за раз. Журнал загружается, сворачивается в текущие счётчики и отбрасывается до открытия следующего, поэтому директория из сотен файлов стоит столько же, сколько самый крупный отдельный захват, а не их сумма.

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

Посмотреть, какие серверы здесь действительно запускались

Вывод, который люди постоянно повторяют о Shadow MCP, заключается в том, что организации обнаруживают в несколько раз больше запущенных MCP-серверов, чем кто-либо одобрил, потому что сервер часто — это просто зависимость, которую кто-то добавил в плагин IDE. То же самое происходит в миниатюре на одном ноутбуке, и mcpsnoop всё это время записывал ответ, так и не показывая его.```bash mcpsnoop inventory mcpsnoop inventory --tools # also count what each server last advertised mcpsnoop inventory --format json # for something else to read

root@kitploit:~
Одна строка на сервер, а не на сессию. Ключом строки являются записанная команда
и рабочая директория, а не метка, потому что метка берётся из
последнего элемента пути команды, и `node ~/one/build/index.js` и
`node ~/two/build/index.js` оба дают `index.js`. HTTP-сессия вместо этого ключуется по
эндпоинту, который она проксировала, поскольку mcpsnoop там ничего не запускал.

Чтение — это один конверт на лог, мета-кадр, который прокси записывает первым, так что
это остаётся дешёвым для каталога с большими захватами. `--tools` — исключение и
читает один лог на сервер, самый последний запуск каждого, поэтому это флаг, а не
колонка. Даже тогда чтение ограничено, потому что инвентарь инструментов — это
состояние сессии, которое хранилище сворачивает по ходу дела, так что захват на сотню
мегабайт читается через фиксированное окно, а не удерживается целиком, чтобы получить одно целое число.

Когда счётчика нет, строка сообщает, что из трёх вещей произошло, потому что
лог, который не удалось прочитать, — это не сервер, который ничего не анонсировал, и одно
предложение для обоих заставило бы mcpsnoop утверждать что-то ложное.

Команда, переписанная правилом `--redact`, печатается как записанная и помеченная, а
не выдаётся за команду, которая выполнялась. Два запуска одного сервера, один
очищенный, а другой нет, — это две строки. mcpsnoop не может знать, что заменил
плейсхолдер, и их слияние означало бы предположение, что скрытые половины совпали. Один сервер, запущенный
под двумя значениями `--label`, — это одна строка с обоими именами, поскольку ключом является
команда, а не имя.

Ничего в строке не записывается mcpsnoop. Команда приходит от того, кто установил
сервер, рабочая директория берётся из файловой системы, а производная метка
берётся из команды. Значение, содержащее управляющий символ, заключается в кавычки, а
не печатается как есть, чтобы директория, имя которой содержит перевод строки, не могла закрыть
поле, в котором она печатается, и заставить следующие строки читаться как серверы, которые никогда
не запускались. Аргумент, содержащий пробел, тоже заключается в кавычки, потому что `node "~/My Project/
build/index.js"` иначе неотличим от двух аргументов.

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

Вывод сортируется по имени, а не по давности, чтобы два запуска по одному каталогу
давали одинаковые байты, что и делает его пригодным в качестве базовой линии для сравнения
с более поздними версиями.

Два пробела присутствуют по построению, а не по недосмотру. Запуск с
`--trace-file` писал вне каталога сессий и не появится, а
`prune` удаляет логи, так что «впервые замечен» никогда не старше того, что ещё есть на
диске. mcpsnoop сообщает, что запускалось на этой машине через него. Он не сканирует сеть,
не читает конфигурацию клиента, на которую не был указан, и ничего не оценивает.

### Отличить сломанный сервер от инструмента, который говорит «нет»

Инструмент, отвечающий `result.isError`, работает. Он посмотрел и ничего не нашёл, или он
отклонил ввод. Сервер, отвечающий ошибкой JSON-RPC, сломан. Оба были одним
числом в сводке инструментов, что означало, что корректно работающий инструмент, сообщающий о доменных
сбоях, выглядел точно так же, как сломанный сервер, и сортировался выше него.

Колонка `ERR` разделяет их. Красный — это сторона сервера, то есть ошибка JSON-RPC
или задача, завершившаяся неудачей без объяснения причин. Предупреждающий цвет — это собственный
`isError` инструмента. Инструмент с обоими показывает объединённые счётчики, красный первым, и
строка под таблицей называет две суммы всякий раз, когда есть число предупреждений, которое нужно
объяснить. Экспорт несёт то же разделение как `protocol_errors` и
`tool_errors` рядом с итогом `errors`, которому они всегда в сумме равны.

`check --fail-on error` не изменился и по-прежнему срабатывает на любом из них, поскольку
шлюз, игнорирующий один из них, был бы шлюзом, который сервер мог бы отключить, вернув
другой.```bash
mcpsnoop export -T json | jq '.summary.tools[] | {name, errors, protocol_errors, tool_errors}'

Посмотрите, во что сервер вам обходится в контексте

Определения инструментов попадают в контекст модели при каждом разговоре, а результаты инструментов — при каждом вызове. Сводка по инструментам (s) учитывает и то, и другое из той сессии, которую вы фактически захватили.

Строка definitions — это фиксированная стоимость: сколько весит tools/list этого сервера ещё до первого вызова. Столбец DEF разбивает это по каждому инструменту, а RESULT показывает, во сколько обошлись ответы каждого инструмента на данный момент. Таблица отсортирована по ошибкам и задержке, поэтому просматривайте DEF, чтобы найти дорогие определения. В экспорте они перечислены от самых тяжёлых к самым лёгким. Строка под таблицей называет единственный самый тяжёлый результат, который общая сумма скрывает.

Показатели определений — это JSON без незначимых пробелов, поэтому сервер, который красиво форматирует свой tools/list, не считается более дорогим, чем тот, который этого не делает, и один и тот же сервер даёт одинаковые показатели при разных захватах. RESULT — это байты в том виде, в котором они поступили: результат — это разовый полезный груз, а не контракт, который стоит нормализовывать.```bash mcpsnoop export -T json | jq '.summary.definitions'

root@kitploit:~
Экспорт содержит те же показатели — по каждому инструменту и с разбивкой на байты описания и байты схемы, так что «толстое» описание и «толстая» схема остаются разделимыми, и за каждой из них можно следить между снимками. `mcpsnoop diff` сообщает, изменилось ли описание или схема между двумя сеансами. Экспорт — это то место, где живёт размер этого изменения.

**Это байты, а не токены.** Количество токенов зависит от модели, поэтому для его измерения пришлось бы встраивать токенизатор и выбирать, чей именно. Байты точны, и вы можете применить собственное соотношение. Незавершённый `tools/list` сообщает то, что увидел, как нижнюю границу, и прямо об этом говорит, а не выдаёт частичную сумму за общий итог.

### Обнаружение клиента, который портит состояние сервера

В рамках многораундового шаблона сервер передаёт клиенту непрозрачный `requestState`, и клиент обязан вернуть его без изменений при повторной попытке. Серверу предписано считать эти данные вводом, контролируемым атакующим, потому что клиент, который их подделывает, может попытаться изменить поведение сервера или обойти проверку авторизации.

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

| Сообщение | Значение |
|---|---|
| `MRTR retry changed requestState` | клиент вернул что-то иное, чем выдал сервер |
| `MRTR retry is missing requestState` | сервер выдал значение, а повторная попытка его опустила |
| `MRTR retry invented requestState` | повторная попытка несла значение, которое сервер никогда не выдавал |

Это нарушения протокола со стороны клиента, а не наши наблюдения, поэтому они идут по обычному сигналу предупреждения, и **запуск `check` по умолчанию завершается ошибкой при таком нарушении**. Это сделано намеренно. Клиент, портящий состояние сервера, — достаточный повод остановить сборку.

Само значение никогда не отображается и не записывается в журнал, и ничто его не декодирует и не разбирает. Это может быть зашифрованный блок, несущий субъект и токен, и сравнение непрозрачных байтов — вся проверка.

Один случай остаётся вне досягаемости. Когда сервер отвечает `requestState` без `inputRequests`, подделанная повторная попытка не совпадает ни с чем и не даёт ответа ни на один ключ, поэтому её не с чем связать с исходным запросом, и она читается как несвязанный вызов, а не как нарушение.

Брошенный обмен не мешает следующему и не хранится вечно. Шестьдесят четыре открытых обмена — это гораздо больше, чем есть у любого клиента одновременно, поэтому сеанс, удерживающий больше, держит те, которые никто не завершит, и самые старые выводятся из обращения, потому что спецификация предписывает серверам давать такому состоянию короткий срок действия и отклонять его после. Вывод из обращения учитывается, а не происходит молча. В нижнем колонтитуле потока показывается `N unlinked`, а экспорт несёт `session.retired_exchanges`, потому что повторная попытка, которая всё же приходит для выведенной из обращения операции, читается как собственный вызов, и читателю, сравнивающему счётчики, следует об этом сообщить.

Вывод одной операции из обращения также позволяет живому хранилищу освободить её. Приостановленная операция остаётся ожидающей намеренно, поэтому её длительность охватывает весь обмен, и хранилище отказывается забывать ожидающий вызов, потому что ответ всё ещё может прийти. Как только предел вывел операцию из обращения, ничто не может на неё ответить, поэтому её удержание поддерживает вызов, до которого ни один читатель не может добраться. То, что сообщает сеанс, не меняется. Операция по-прежнему считается ожидающей и по-прежнему учитывается в `N unlinked`, потому что то, сколько памяти занимает запись, и то, что говорит запись, — разные вопросы.

Брошенный обмен не мешает следующему. MRTR предписывает серверам не предполагать, что клиент когда-либо повторит попытку, поэтому пользователь, отклоняющий запрос-уточнение, оставляет операцию, которую ни один последующий кадр никогда не урегулирует. mcpsnoop сначала ищет среди операций, чьё наличие `requestState` согласуется с повторной попыткой, что спецификация делает правилом в обоих направлениях, поэтому соответствующая повторная попытка всё равно находит ту единственную операцию, которую она продолжает, даже если рядом сидит брошенный обмен по тому же инструменту. Проверка, сообщающая о трёх нарушениях выше, запускается только тогда, когда ничто не согласуется, поэтому по-настоящему несоответствующая повторная попытка всё равно называется.

## Наблюдение с другой машины

Держите захват локально на машине, где происходит трафик, и используйте SSH для сетевого перехода, чтобы mcpsnoop никогда не нуждался в собственном удалённом транспорте.

### Живой просмотр

Запустите TUI на своей рабочей станции и пробросьте сокет mcpsnoop удалённой машины обратно к ней. Живой туннель использует пересылку Unix-сокетов через SSH, поэтому оба конца должны работать под Linux или macOS. На Windows используйте посмертную копию журнала ниже.```bash
# on your workstation, start the TUI
mcpsnoop

# create the remote socket directory once
ssh remote-user@remote-host 'mkdir -p ~/.local/state/mcpsnoop'

# print the tunnel command, then run the printed ssh -R line
mcpsnoop remote remote-user@remote-host

# on the remote host, wrap your server as usual
mcpsnoop -- node build/index.js

Сокет находится в каталоге состояния удалённой системы, который определяется как MCPSNOOP_HOME, иначе XDG_STATE_HOME/mcpsnoop, иначе ~/.local/state/mcpsnoop. По умолчанию mcpsnoop предполагает домашний каталог Linux /home/<user> из вашего user@host и выводит напоминание в stderr всякий раз, когда прибегает к этому предположению. Если удалённая система разрешается в другое место, укажите этот единственный нестандартный элемент.```bash

a non-Linux or custom home, macOS is /Users/ and root is /root

mcpsnoop remote --remote-home /Users/remote-user remote-user@remote-host

an explicit MCPSNOOP_HOME on the remote

mcpsnoop remote --remote-mcpsnoop-home /srv/mcpsnoop remote-user@remote-host

an explicit XDG_STATE_HOME on the remote

mcpsnoop remote --remote-xdg-state-home /var/lib/state remote-user@remote-host

root@kitploit:~
### Посмертный анализ

Транслируйте удалённую сессию прямо в TUI через SSH, без необходимости локальной копии.```bash
ssh remote-user@remote-host 'cat ~/.local/state/mcpsnoop/sessions/session.jsonl' | mcpsnoop open -

Чтобы сохранить локальную копию, вместо этого скопируйте логи через scp в каталог вашей сессии и запустите TUI как обычно.```bash

copy the remote logs into your local sessions directory

mkdir -p /.local/state/mcpsnoop/sessions scp remote-user@remote-host:'/.local/state/mcpsnoop/sessions/*.jsonl'
~/.local/state/mcpsnoop/sessions/

open the TUI, it backfills the copied sessions

mcpsnoop

root@kitploit:~
## Security

mcpsnoop запускает команду сервера, которую вы оборачиваете, поэтому оборачивайте только те серверы, которым доверяете, а недоверенные запускайте в контейнере. Он никогда не выполняет ничего, что вы не указали в конфигурации своего клиента.

Для удалённых рабочих процессов используйте SSH-туннелирование или передачу файлов по SSH, чтобы аутентификация транспорта, шифрование, проверка хоста, ротация ключей и политика аудита оставались в вашей существующей SSH-настройке.

### Редактирование того, что вы захватываете

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

Редактирование на основе ключей заменяет целые значения под соответствующими ключами JSON-объектов, и тот же набор ключей применяется по мере возможности к аргументам командной строки обёрнутого сервера, поэтому `--api-key=sk-x` и `--token sk-x` очищаются при `--redact-secrets`. Аргумент, содержащий секрет без узнаваемого имени флага, обнаружить невозможно.

HTTP-конечная точка не входит в это, поскольку это не полезная нагрузка, которую вы выбрали отправить. `--target` — это флаг, который необходимо передать, чтобы вообще запустить прокси, поэтому его URL попадёт в журнал сеанса независимо от ваших настроек редактирования. mcpsnoop записывает его с уже удалёнными userinfo, каждым значением запроса и фрагментом — всегда, по построению, а не по шаблону. Ключи запроса сохраняются, поскольку именно они отличают две конечные точки одного хоста, а фрагмент отбрасывается, потому что он изначально не достигал сервера. Записанное идентифицирует сервер и не является адресом для соединения.

Редактирование на основе пути заменяет только значения, выбранные выражением JSONPath, что полезно, когда распространённое имя ключа чувствительно в одном месте, но безопасно в другом. Повторите `--redact-path`, чтобы очистить более одного места.

Редактирование на основе значений применяет регулярные выражения к наблюдаемым строковым значениям, тексту stderr и не-JSON текстовым кадрам.

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

Редактирование никогда не превращается в обвинение. Каждая проверка, которая сравнивает одно наблюдаемое значение с другим — заголовок маршрутизации с телом, значение `Mcp-Param` с аргументом, который оно отражает, схему инструмента с тем, что требует от него ревизия, — знает, когда именно mcpsnoop был стороной, переписавшей байты, и остаётся молчаливой, а не сообщает о сервере из-за настройки конфиденциальности самого пользователя. Дрейф определения инструмента является исключением, и намеренно, поскольку включение редактирования меняет то, что записывается, а следовательно, и то, что содержит базовый уровень. См. [Обнаружение дрейфа определения инструмента](#detect-tool-definition-drift).```bash
# built-in preset of common secret keys
mcpsnoop --redact-secrets -- node build/index.js

# or name your own keys
mcpsnoop --redact-key token,api_key,password -- node build/index.js

# scrub one location without redacting every field named password
mcpsnoop --redact-path '$.params.arguments.password' -- node build/index.js

# wildcards scrub every matching array element
mcpsnoop --redact-path '$.params.arguments.accounts[*].password' -- node build/index.js

# scrub obvious token-shaped values outside known keys
mcpsnoop --redact-value 'sk-[A-Za-z0-9]+' -- node build/index.js

# combine the layers in http mode
mcpsnoop http --target http://localhost:3000/mcp --redact-secrets --redact-value 'Bearer\s+\S+'

Вклад


Read more

Скачать инструмент