tenable-activity-mcp
tenable-activity-mcp
MCP-сервер, который предоставляет журнал аудита/активности Tenable Vulnerability Management (GET /audit-log/v1/events) в виде небольшого набора инструментов, чтобы любой MCP-клиент мог по запросу получать информацию об активности платформы, использовании API-ключей и аномальном поведении.
Сервер выполняет анализ сам. Подсчёты, группировка, вычисление частот и сравнение с порогами выполняются на Python; инструменты возвращают готовые структурированные результаты (failure_rate_pct, by_actor, findings с пояснениями), а не выгружают сырые события для модели, которая должна их суммировать.
Что он даёт
Инструмент | Назначение |
| Лента событий за окно с фильтрами по актору и действию. Пагинация обрабатывается автоматически; возвращается возобновляемый |
| Детерминированная сводка за окно: подсчёты по актору, действию, типу CRUD и типу доступа, а также частоты отказов и анонимных событий. |
| Только активность по API-ключам, сгруппированная по актору: разбивка по действиям, уникальные исходные IP-адреса, первое/последнее появление. |
| Сравнивает окно с сохранённым базовым профилем каждого актора. Отмечает новых акторов, всплески объёма, ранее не виденные IP-адреса, всплески неудачных событий, устойчивые частоты отказов, всплески в нерабочие часы и ранее не встречавшиеся действия — каждое с доказательствами и поясняющим предложением. |
| Полная картина одного актора: роль (по возможности), разбивка по всем действиям, типы доступа, все виденные исходные IP-адреса. |
| Проходит/не проходит проверку того, могут ли настроенные ключи реально читать журнал аудита, с текстом по устранению проблем. |
Полезные свойства безопасности:
Ничто, похожее на учётные данные, никогда не возвращается. Значения полей, имена которых указывают на секрет (
secret_key,api_key,token,password, ...) или значения которых выглядят как ключевой материал Tenable, маскируются до последних 4 символов.Пагинация ограничена 20 страницами / 100 000 событий на один вызов инструмента; достижение предела явно сообщается вместе с курсором, необходимым для продолжения.
429-е ответы обрабатываются с ожиданием с использованием заголовка
X-RateLimit-Reset(эндпоинт не отправляетRetry-After), с экспоненциальным откатом и пределом повторных попыток.
Related MCP server: Entra Identity Posture MCP
Требования
Python 3.11+
API-ключи Tenable VM, владелец которых может читать журнал аудита
Роль / разрешения Tenable
Чтение audit-log/v1/events требует роли Администратор или пользовательской роли с явным разрешением на чтение журнала аудита у пользователя, которому принадлежат API-ключи. В противном случае возвращается HTTP 403; check_permission_prereqs сообщает об этом простым языком.
Создайте ключи в Tenable VM в разделе Настройки → Моя учётная запись → API-ключи. Ключи наследуют разрешения пользователя, который их создал.
get_actor_profile дополнительно пытается определить роль актора из каталога пользователей. Если ключи не могут получить список пользователей, профиль всё равно возвращается — просто без метки роли.
Настройка
uv sync --extra devЗатем скопируйте .env.example в .env и заполните свои ключи:
cp .env.example .envПроверьте учётные данные и разрешения перед подключением к клиенту:
uv run python -c "from dotenv import load_dotenv; load_dotenv(); from src.server import check_permission_prereqs; print(check_permission_prereqs())"Запустите сервер напрямую (он общается по MCP через stdio, поэтому просто будет ждать клиента — это нормальное поведение):
uv run python -m src.serverПодключение клиента
Используйте абсолютный путь к вашему клону в конфигурации ниже. Чтобы вывести его, выполните pwd из корня репозитория на macOS/Linux или (Get-Location).Path в PowerShell.
Claude Desktop
Отредактируйте claude_desktop_config.json:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"tenable-activity": {
"command": "uv",
"args": [
"--directory",
"C:\\path\\to\\tenable-activity-mcp",
"run",
"python",
"-m",
"src.server"
],
"env": {
"TENABLE_ACCESS_KEY": "your_access_key",
"TENABLE_SECRET_KEY": "your_secret_key",
"TENABLE_MCP_BASE_URL": "https://cloud.tenable.com"
}
}
}
}После этого перезапустите Claude Desktop. На macOS/Linux используйте путь в формате POSIX (/Users/you/tenable-activity-mcp).
Если uv отсутствует в PATH лаунчера, используйте его абсолютный путь (which uv / (Get-Command uv).Source) в качестве command.
Claude Code
claude mcp add tenable-activity --env TENABLE_ACCESS_KEY=your_access_key --env TENABLE_SECRET_KEY=your_secret_key -- uv --directory /absolute/path/to/tenable-activity-mcp run python -m src.serverИли добавьте тот же блок, что и выше, в файл .mcp.json на уровне проекта.
Учётные данные, переданные через env, имеют приоритет над .env; файл .env — это удобство для локальной разработки, и любой из механизмов работает.
Примеры вопросов после подключения
«Проверь, могут ли мои учётные данные Tenable читать журнал аудита.»
«Суммируй активность платформы Tenable за последние 7 дней — кто был наиболее активен, и какова частота отказов?»
«Какие API-ключи использовались против Tenable за последние 30 дней и с каких исходных IP-адресов?»
«Найди аномалии в активности Tenable за последние 3 дня относительно 30-дневного базового профиля и объясни всё, что отметишь.»
«Покажи всё, что когда-либо делал актор 00000000-1111-4222-8333-444444444444 — действия, типы доступа и IP-адреса.»
Как работает обнаружение аномалий
detect_anomalies требует историю для сравнения, которая хранится в локальном файле SQLite (state.db, создаётся автоматически):
Если сохранённые базовые профили старше
BASELINE_REFRESH_MAX_AGE_HOURS(12), сервер получаетbaseline_days, непосредственно предшествующие вашему окну, и пересчитывает средние значения по акторам, известные IP-адреса, известные действия и гистограмму по часам суток.Ваше окно загружается и сравнивается с этими базовыми профилями.
События в анализируемом окне не включаются в базовый профиль, поэтому повторный запуск того же окна даёт те же результаты.
Каждый порог — это именованная константа в начале src/anomaly.py, и она повторяется в каждом результате в разделе thresholds:
Константа | По умолчанию | Значение |
|
| События в окне в день должны превышать это кратное среднего базового |
|
| Минимальный порог, прежде чем всплеск вообще может быть отмечен |
|
| Как давно IP должен был быть виден, чтобы считаться «известным» |
|
| Триггер кластеризации сбоев |
|
| Триггер устойчивой частоты отказов (при как минимум 10 событиях) |
|
| Диапазон нерабочих часов |
|
| Доля нерабочих часов должна превышать это кратное базовой доли актора |
Базовые профили рассчитываются отдельно для каждого актора, поэтому сервисный аккаунт, который легитимно запускает 500 сканирований в день, не будет отмечен за то, что делает именно это.
Структура
src/
server.py MCP entrypoint (FastMCP-style) + the six tool definitions
tenable_client.py Auth, filter building, cursor pagination, 429 backoff, typed errors
classifier.py API-key vs UI/session tagging, IP extraction, redaction, rollups
anomaly.py Thresholds and the individual anomaly checks
state.py SQLite: cursors, accumulated actor history, computed baselines
tests/
test_pagination.py test_classifier.py test_anomaly.pyНаправление зависимостей одностороннее: server → {anomaly, classifier, state} → tenable_client.
Тестирование
Три уровня, в порядке, в котором их следует запускать.
1. Модульные тесты (без учётных данных, без сети)
uv run pytest -q105 тестов, покрывающих обработку пагинации/курсора, откат при ограничении скорости, классификацию API-ключ vs сессия, редактирование и каждый порог аномалий. Каждый ответ API имитируется через заглушку транспорта, поэтому набор тестов никогда не обращается к живому тенанту.
2. Офлайн-сквозное тестирование (без учётных данных, без сети)
uv run python scripts/smoke_local.pyЗапускает все шесть инструментов против сценарного фейкового Tenable (тихий базовый месяц, затем шумная ночь с нового IP) и проверяет результаты: отмеченные аномалии, замаскированные подсаженные секреты, неверный ввод, возвращаемый как структурированная ошибка вместо исключения. Завершается с ненулевым кодом при любой ошибке, поэтому работает как предкоммитный или CI-шлюз.
3. Живая проверка вашего тенанта (только чтение)
С заполненным .env:
uv run python scripts/live_check.py 7Сначала проверяет разрешения на журнал аудита и останавливается с текстом по устранению, если они неверны, затем выводит реальную сводку, разбивку использования API-ключей, результаты обнаружения аномалий и профиль самого активного актора за последние N дней (по умолчанию 7). Все вызовы — GET; ничего не записывается в Tenable.
4. Через MCP-клиент
Подойдёт любой MCP-клиент. Чтобы интерактивно поработать с инструментами без чат-клиента:
npx @modelcontextprotocol/inspector uv --directory . run python -m src.serverИли подключите его к Claude Desktop / Claude Code (см. выше) и задайте один из примеров вопросов. check_permission_prereqs — правильный первый вызов: он подтверждает, что сервер запустился, нашёл свои учётные данные и может получить доступ к журналу аудита.
Просмотр локального состояния
uv run python -c "from src.state import StateStore; print(StateStore().stats())"Удалите state.db, чтобы сбросить базовые профили; следующий вызов detect_anomalies пересоздаст их.
Известные ограничения
Требуется роль администратора. Для чтения
audit-log/v1/eventsнеобходима роль администратора или пользовательская роль с явным разрешением на чтение журнала аудита у пользователя, которому принадлежат ключи API. В противном случае возвращается HTTP 403. Сначала выполнитеcheck_permission_prereqs— он сообщит именно об этом, с текстом по устранению проблемы.Для обнаружения аномалий нужна история, прежде чем оно станет полезным. Первый вызов
detect_anomaliesдля свежегоstate.dbстроит базовые показатели за 30 дней, предшествующих вашему окну, а затем сравнивает с ними. Субъекты (actors) с малой или нулевой предшествующей активностью помечаются какnew_actor, поэтому ранние запуски более шумные, чем последующие.Определение роли выполняется по принципу best effort.
get_actor_profileпытается определить роль субъекта в Tenable из каталога пользователей. Если ключи не могут получить список пользователей, профиль всё равно возвращается — просто без метки роли.Обнаружение нерабочих часов использует фиксированный диапазон UTC. Окно нерабочих часов — 20:00–06:00 UTC и не подстраивается под рабочий часовой пояс тенанта. Распределённые команды будут видеть результаты по нерабочим часам, которые на самом деле являются рабочим утром в другом регионе.
Базовые показатели локальны для машины, на которой запущен сервер.
state.dbне является общим для разных установок, поэтому два оператора, запускающие собственные копии, строят независимые базовые показатели и могут прийти к разным выводам об одном и том же окне.Широкие окна возвращают частичные результаты по замыслу. Один вызов инструмента обрабатывает не более 20 страниц / 100 000 событий. Достижение этого предела явно сообщается вместе с
next_token, необходимым для продолжения, так что это никогда не является молчаливым усечением — но очень большое окно требует нескольких вызовов.Только первые 1 000 событий возвращаются встроенно.
list_activity_eventsограничивает встроенный массивeventsдо 1 000 и устанавливаетinline_truncated, когда это происходит. Блокsummaryпо-прежнему охватывает все полученные события, поэтому агрегированные числа остаются корректными, даже когда встроенный список усечён.get_actor_profileпросматривает максимум 365 дней назад и не может видеть дальше, чем хранит сам журнал аудита.
Примечания
Создано для
mcp==2.0.0, где SDK переименовалFastMCPвMCPServer.server.pyимпортирует то имя, которое предоставляет установленный SDK, поэтому он также работает наmcp1.x.Получение событий выполняется через сессию pyTenable
TenableIO(audit_log.events(..., return_json=True)), что оставляет обработку аутентификации и подключения в поддерживаемой библиотеке, при этом курсорpagination.nextостаётся доступным для нас. Если pyTenable недоступен, используется эквивалентный транспорт наrequestsс заголовкомX-ApiKeys: accessKey=...;secretKey=....Временные метки везде в UTC, включая диапазон нерабочих часов.
state.dbнакапливает историю по каждому субъекту. Удалите его, чтобы сбросить все базовые показатели; следующий вызовdetect_anomaliesперестроит их.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceExposes Azure Log Analytics workspace data with tools for querying AuditLogs and AzureActivity tables, supporting custom KQL queries, time range filters, and pagination.
- AlicenseAqualityBmaintenanceEnables auditing and monitoring of Microsoft Entra ID security posture, Conditional Access policies, and Zero Trust alignment via Microsoft Graph API.5MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server for Tenable Vulnerability Management and the Tenable One platform, enabling LLMs to query assets, vulnerabilities, scans, exposure metrics, attack paths, and more via natural language.MIT
- AlicenseAqualityCmaintenanceMCP server for Tenable.io/One Vulnerability Management that provides read-only tools for querying scans, assets, plugins, and vulnerabilities, plus specialized reporting tools for VPR re-prioritization, CISA KEV/EPSS exposure, and scan delta comparisons.112MIT
Related MCP Connectors
A paid remote MCP for AI SDK data query MCP, built to return verdicts, receipts, usage logs, and aud
Read-only MCP access to sessions, funnels, campaigns, errors, live visitors, and anomalies.
Read-only access to Auralogs production logs: search logs, inspect errors, review AI analyses.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/brendanong95/tenable-activity-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server