Skip to main content
Glama
brendanong95

tenable-activity-mcp

by brendanong95

tenable-activity-mcp

Tests

MCP-сервер, который предоставляет журнал аудита/активности Tenable Vulnerability Management (GET /audit-log/v1/events) в виде небольшого набора инструментов, чтобы любой MCP-клиент мог по запросу получать информацию об активности платформы, использовании API-ключей и аномальном поведении.

Сервер выполняет анализ сам. Подсчёты, группировка, вычисление частот и сравнение с порогами выполняются на Python; инструменты возвращают готовые структурированные результаты (failure_rate_pct, by_actor, findings с пояснениями), а не выгружают сырые события для модели, которая должна их суммировать.

Что он даёт

Инструмент

Назначение

list_activity_events

Лента событий за окно с фильтрами по актору и действию. Пагинация обрабатывается автоматически; возвращается возобновляемый next_token, если достигнут предохранительный предел.

summarize_activity

Детерминированная сводка за окно: подсчёты по актору, действию, типу CRUD и типу доступа, а также частоты отказов и анонимных событий.

get_api_key_usage

Только активность по API-ключам, сгруппированная по актору: разбивка по действиям, уникальные исходные IP-адреса, первое/последнее появление.

detect_anomalies

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

get_actor_profile

Полная картина одного актора: роль (по возможности), разбивка по всем действиям, типы доступа, все виденные исходные IP-адреса.

check_permission_prereqs

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

Полезные свойства безопасности:

  • Ничто, похожее на учётные данные, никогда не возвращается. Значения полей, имена которых указывают на секрет (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+

  • uv

  • 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.json

  • Windows: %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, создаётся автоматически):

  1. Если сохранённые базовые профили старше BASELINE_REFRESH_MAX_AGE_HOURS (12), сервер получает baseline_days, непосредственно предшествующие вашему окну, и пересчитывает средние значения по акторам, известные IP-адреса, известные действия и гистограмму по часам суток.

  2. Ваше окно загружается и сравнивается с этими базовыми профилями.

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

Каждый порог — это именованная константа в начале src/anomaly.py, и она повторяется в каждом результате в разделе thresholds:

Константа

По умолчанию

Значение

SPIKE_MULTIPLIER

3.0

События в окне в день должны превышать это кратное среднего базового

SPIKE_MIN_WINDOW_EVENTS

20

Минимальный порог, прежде чем всплеск вообще может быть отмечен

NEW_IP_LOOKBACK_DAYS

30

Как давно IP должен был быть виден, чтобы считаться «известным»

FAILED_AUTH_BURST_COUNT / FAILED_AUTH_BURST_WINDOW_MINUTES

5 / 10

Триггер кластеризации сбоев

HIGH_FAILURE_RATE_PCT

50.0

Триггер устойчивой частоты отказов (при как минимум 10 событиях)

OFF_HOURS_START_HOUR / OFF_HOURS_END_HOUR

20 / 6 (UTC)

Диапазон нерабочих часов

OFF_HOURS_RATIO_MULTIPLIER

2.0

Доля нерабочих часов должна превышать это кратное базовой доли актора

Базовые профили рассчитываются отдельно для каждого актора, поэтому сервисный аккаунт, который легитимно запускает 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 -q

105 тестов, покрывающих обработку пагинации/курсора, откат при ограничении скорости, классификацию 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, поэтому он также работает на mcp 1.x.

  • Получение событий выполняется через сессию pyTenable TenableIO (audit_log.events(..., return_json=True)), что оставляет обработку аутентификации и подключения в поддерживаемой библиотеке, при этом курсор pagination.next остаётся доступным для нас. Если pyTenable недоступен, используется эквивалентный транспорт на requests с заголовком X-ApiKeys: accessKey=...;secretKey=....

  • Временные метки везде в UTC, включая диапазон нерабочих часов.

  • state.db накапливает историю по каждому субъекту. Удалите его, чтобы сбросить все базовые показатели; следующий вызов detect_anomalies перестроит их.

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

Maintenance

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

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Exposes Azure Log Analytics workspace data with tools for querying AuditLogs and AzureActivity tables, supporting custom KQL queries, time range filters, and pagination.
  • A
    license
    Not graded
    quality
    C
    maintenance
    An 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
  • A
    license
    A
    quality
    C
    maintenance
    MCP 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.
    11
    2
    MIT

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

MCP directory API

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

curl -X GET 'https://glama.ai/api/mcp/v1/servers/brendanong95/tenable-activity-mcp'

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