Skip to main content
Glama
brendanong95

tenable-activity-mcp

by brendanong95

tenable-activity-mcp

Tests

Tenable Vulnerability Management の監査/アクティビティログ(GET /audit-log/v1/events)を小さなツール群として公開する MCP サーバーです。あらゆる MCP クライアントが、プラットフォームのアクティビティ、API キーの使用状況、異常な挙動についてオンデマンドで問い合わせることができます。

分析はサーバー側で行われます。カウント、グループ化、レート計算、しきい値の比較はすべて Python 内で実行され、ツールはモデルが集計するための生イベントをそのまま返すのではなく、完成された構造化結果(failure_rate_pctby_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_keyapi_keytokenpassword など)、または値が Tenable のキーらしいフィールドは、最後の 4 文字のみを残してマスクされます。

  • ページネーションは上限付きで、ツール呼び出し 1 回につき 20 ページ/100k イベントまで。上限に達した場合は、続行に必要なカーソルとともに明示的に報告されます。

  • 429 応答時はバックオフします。X-RateLimit-Reset ヘッダーを使用し(このエンドポイントは Retry-After を送信しません)、指数関数的バックオフと再試行上限を備えています。

Related MCP server: Entra Identity Posture MCP

要件

  • Python 3.11+

  • uv

  • 監査ログを読み取れる権限を持つユーザーの Tenable VM API キー

Tenable のロール/権限

audit-log/v1/events を読み取るには、API キーを所有するユーザーに Administrator ロール、または明示的な監査ログ読み取り権限を持つカスタムロールが必要です。それ未満の権限では HTTP 403 が返ります。check_permission_prereqs はこれを平易な言葉で報告します。

キーは Tenable VM の Settings → My Account → API Keys で生成します。キーは作成したユーザーの権限を引き継ぎます。

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())"

サーバーを直接実行します(stdio 経由で MCP を話すため、クライアントを待って待機したままになります。これが正しい動作です):

uv run python -m src.server

クライアントの接続

以下の設定では、クローンしたリポジトリへの絶対パスを使用してください。絶対パスを表示するには、macOS/Linux ではリポジトリのルートで pwd を実行し、PowerShell では (Get-Location).Path を実行します。

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 の資格情報で監査ログを読み取れるか確認して。」

  • 「過去 7 日間の Tenable プラットフォームのアクティビティを要約して。誰が最もアクティブだったか、失敗率はどのくらい?」

  • 「過去 30 日間に Tenable に対して使用された API キーと、その送信元 IP を教えて。」

  • 「過去 3 日間の Tenable のアクティビティを 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

期間の 1 日あたりイベント数がベースライン平均のこの倍数を超えた場合にフラグ付け

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

時間外の割合がアクターのベースライン上の割合のこの倍数を超えた場合にフラグ付け

ベースラインはアクターごとなので、1 日 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

テスト

3 つのレベルがあります。実行する順序に従って進めてください。

1. ユニットテスト(資格情報なし、ネットワークなし)

uv run pytest -q

ページネーション/カーソル処理、レート制限のバックオフ、API キーかセッションかの分類、マスキング、すべての異常検知しきい値をカバーする 105 件のテストです。すべての API レスポンスはスタブトランスポートで模擬されるため、このテストスイートが実環境のテナントに触れることはありません。

2. オフラインのエンドツーエンドテスト(資格情報なし、ネットワークなし)

uv run python scripts/smoke_local.py

スクリプト化された偽の Tenable(静かなベースライン月、その後新しい IP からの騒がしい夜)に対して 6 つすべてのツールを実行し、結果を検証します: 異常がフラグ付けされること、仕込まれた秘密情報がマスクされること、不正な入力が例外ではなく構造化エラーとして返されること。失敗時には非ゼロで終了するため、pre-commit や 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 呼び出しで再構築されます

  • Administrator ロールが必要です。 audit-log/v1/events の読み取りには、API キーを所有するユーザーに Administrator ロール、または監査ログの読み取り権限が明示的に付与されたカスタムロールが必要です。それ以外の場合は HTTP 403 が返されます。最初に check_permission_prereqs を実行してください。このツールはまさにこの問題を、修正方法のテキストとともに報告します。

  • 異常検知は履歴が蓄積されてから有用になります。 新しい state.db に対する最初の detect_anomalies 呼び出しは、対象期間の直前 30 日間からベースラインを構築し、それと比較します。過去のアクティビティがほとんどない、またはまったくないアクターは new_actor としてフラグが立つため、初期の実行は後期の実行よりもノイズが多くなります。

  • ロール解決はベストエフォートです。 get_actor_profile は、ユーザーディレクトリからアクターの Tenable ロールを解決しようとします。キーがユーザーを一覧表示できない場合でも、プロファイルは返されます。ただし、ロールラベルは付きません。

  • 時間外検知は固定の UTC 帯を使用します。 時間外ウィンドウは 20:00〜06:00 UTC で、テナントの勤務時間帯に合わせて調整されません。分散チームでは、別の地域の勤務時間の朝にすぎない時間外の検知結果が表示されます。

  • ベースラインはサーバーを実行しているマシンにローカルです。 state.db はインストール間で共有されないため、各自のコピーを実行している 2 人のオペレーターは独立したベースラインを構築し、同じ期間について異なる結論に達する可能性があります。

  • 広い期間は設計上、部分的な結果を返します。 1 回のツール呼び出しは最大 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 が FastMCPMCPServer に改名しました。server.py はインストールされている SDK が提供する方の名前をインポートするため、mcp 1.x でも動作します。

  • イベントの取得は pyTenable の TenableIO セッション(audit_log.events(..., return_json=True))を経由します。これにより、認証と接続処理はメンテナンスされたライブラリに任せつつ、pagination.next カーソルは私たちから見える状態が保たれます。pyTenable が利用できない場合は、X-ApiKeys: accessKey=...;secretKey=... ヘッダーを使用する同等の requests トランスポートが引き継ぎます。

  • タイムスタンプは時間外帯を含め、すべて 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