tenable-activity-mcp
tenable-activity-mcp
Tenable Vulnerability Management の監査/アクティビティログ(GET /audit-log/v1/events)を小さなツール群として公開する MCP サーバーです。あらゆる MCP クライアントが、プラットフォームのアクティビティ、API キーの使用状況、異常な挙動についてオンデマンドで問い合わせることができます。
分析はサーバー側で行われます。カウント、グループ化、レート計算、しきい値の比較はすべて Python 内で実行され、ツールはモデルが集計するための生イベントをそのまま返すのではなく、完成された構造化結果(failure_rate_pct、by_actor、推論付きの findings)を返します。
提供される機能
ツール | 目的 |
| 期間を指定したイベントフィード。アクター/アクションのフィルターに対応。ページネーションは自動的に追跡され、安全上限に達した場合は再開可能な |
| 期間に対する決定論的なロールアップ。アクター、アクション、CRUD タイプ、アクセスタイプ別のカウントに加え、失敗率・匿名率を返します。 |
| API キーによるアクティビティのみをアクター別にグループ化。アクションの内訳、ユニークな送信元 IP、初回・最終の確認時刻を返します。 |
| 指定期間を各アクターの保存済みベースラインと比較します。新しいアクター、イベント数の急増、未知の送信元 IP、失敗イベントのバースト、持続的な失敗率、時間外の急増、前例のないアクションをフラグ付けし、それぞれに証拠と推論文を添えます。 |
| 単一アクターの全体像。ロール(ベストエフォート)、全期間のアクション内訳、アクセスタイプ、これまでに確認されたすべての送信元 IP を返します。 |
| 設定されたキーが実際に監査ログを読み取れるかを合格/不合格で判定し、対処方法のテキストも返します。 |
知っておくべき安全上の特性:
資格情報らしきものは決して返されません。 キー名が秘密情報を示すフィールド(
secret_key、api_key、token、passwordなど)、または値が Tenable のキーらしいフィールドは、最後の 4 文字のみを残してマスクされます。ページネーションは上限付きで、ツール呼び出し 1 回につき 20 ページ/100k イベントまで。上限に達した場合は、続行に必要なカーソルとともに明示的に報告されます。
429 応答時はバックオフします。
X-RateLimit-Resetヘッダーを使用し(このエンドポイントはRetry-Afterを送信しません)、指数関数的バックオフと再試行上限を備えています。
Related MCP server: tenable-mcp-server
要件
Python 3.11+
監査ログを読み取れる権限を持つユーザーの 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.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 の資格情報で監査ログを読み取れるか確認して。」
「過去 7 日間の Tenable プラットフォームのアクティビティを要約して。誰が最もアクティブだったか、失敗率はどのくらい?」
「過去 30 日間に Tenable に対して使用された API キーと、その送信元 IP を教えて。」
「過去 3 日間の Tenable のアクティビティを 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 にそのまま反映されます:
定数 | デフォルト値 | 意味 |
|
| 期間の 1 日あたりイベント数がベースライン平均のこの倍数を超えた場合にフラグ付け |
|
| スパイクをフラグ付けできる最低イベント数 |
|
| IP が「既知」とみなされるために、どの程度最近に確認されている必要があるか |
|
| 失敗の集中を検出するトリガー |
|
| 持続的な失敗率のトリガー(10 イベント以上) |
|
| 時間外の時間帯 |
|
| 時間外の割合がアクターのベースライン上の割合のこの倍数を超えた場合にフラグ付け |
ベースラインはアクターごとなので、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 がFastMCPをMCPServerに改名しました。server.pyはインストールされている SDK が提供する方の名前をインポートするため、mcp1.x でも動作します。イベントの取得は pyTenable の
TenableIOセッション(audit_log.events(..., return_json=True))を経由します。これにより、認証と接続処理はメンテナンスされたライブラリに任せつつ、pagination.nextカーソルは私たちから見える状態が保たれます。pyTenable が利用できない場合は、X-ApiKeys: accessKey=...;secretKey=...ヘッダーを使用する同等のrequestsトランスポートが引き継ぎます。タイムスタンプは時間外帯を含め、すべて UTC です。
state.dbはアクターごとの履歴を蓄積します。削除するとすべてのベースラインがリセットされ、次のdetect_anomalies呼び出しで再構築されます。
Available Tools
6 toolscheck_permission_prereqsA
Verify the configured API keys can actually read the audit log.
Makes one minimal audit-log request and reports pass/fail with a plain explanation and remediation steps. Run this first when another tool returns an authentication or permission error. No secret material is echoed - the access key is shown with only its last 4 characters.
Returns:
A dict with ok, a human-readable message, remediation when
failing, plus configuration and local-state diagnostics.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully discloses behavior: it makes exactly one minimal audit-log request, reports pass/fail with a plain explanation plus remediation steps, and never echoes secret material (the access key shows only the last 4 characters). This goes well beyond a bare operation statement and gives the agent confidence about side effects and output safety.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first sentence, and the remaining sentences carry useful information about behavior, triggering, and secret handling. The 'Returns' section slightly overlaps with the provided output schema, but it only lists the key dictionary fields and is not padded. Overall it is tightly written for the information it needs to convey.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no parameters and a full output schema, the description covers everything an agent needs: what is checked, when to run it, what side effects occur (one request, no secret disclosure), and what the result looks like. There are no missing pieces that would cause an agent to misuses the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description does not need to explain parameter meaning, and the empty input schema leaves nothing ambiguous; the description instead focuses on the output, which is appropriate here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Verify the configured API keys can actually read the audit log,' which clearly states what the tool does. It also distinguishes itself from the sibling data-retrieval tools (list_activity_events, summarize_activity, etc.) by positioning this as a diagnostic preflight check rather than an analytics operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit trigger condition: 'Run this first when another tool returns an authentication or permission error.' This is clear contextual guidance, but it does not mention when not to use it or name alternative tools—though no sibling performs the same diagnostic role, so exclusions are not necessary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
detect_anomaliesA
Compare a window against each actor's stored baseline and flag outliers.
Checks run: previously unseen actor, event volume above SPIKE_MULTIPLIER x
the actor's historical daily average, source IPs absent from the baseline
lookback, failed-event bursts, sustained high failure rate, off-hours
activity spikes, and never-before-seen action types. Every finding includes
the observed value, the threshold crossed, and a reasoning sentence.
Baselines live in the local SQLite state file and are refreshed from the period immediately preceding the window when they are stale. Events in the analysed window itself are not folded into the baseline, so re-running the same window yields the same findings.
Args: date_from: Start of the window under investigation, ISO-8601. date_to: End of the window under investigation, ISO-8601. baseline_days: Days of history preceding the window to baseline against.
Returns:
A dict with findings (severity-ordered, each with evidence and
reasoning), findings_by_type/findings_by_severity counts, and
the active thresholds.
| Name | Required | Description | Default |
|---|---|---|---|
| date_to | Yes | ||
| date_from | Yes | ||
| baseline_days | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden and covers side effects (baseline refresh from local SQLite when stale), idempotence (analyzed window not folded into baseline), and output guarantees (evidence, reasoning, severity ordering). This exceeds what schema alone could convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is dense but every sentence adds necessary operational detail; purpose is front-loaded, checks are grouped, and Args/Returns are clearly structured. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no annotations and moderate input complexity, it explains inputs, output shape, baseline mechanics, staleness handling, and idempotence. An agent has enough to select and call it correctly without further discovery.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the Args section documents all three parameters with semantic meaning: ISO-8601 window bounds and baseline history days. This fully compensates for the absent schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb-resource pair ('Compare a window against each actor's stored baseline') and an enumerated list of anomaly checks that distinguishes this from sibling event-listing/summary tools. The resource and behavior are unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended investigation scenario is clear: detect baseline deviations in a date window using prior history. It does not explicitly name alternatives or when-not-to-use, but the detailed scope leaves little ambiguity about when this tool applies.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_actor_profileA
Full historical view of one actor: roles, actions, access types, IPs.
Combines a fresh audit-log fetch for the actor with everything previously persisted in the local state database, so IPs and actions seen in earlier sessions still show up. The Tenable role is resolved on a best-effort basis from the user directory and is omitted when the API keys cannot list users.
Args:
actor_id: The actor UUID (as it appears in actor.id on events).
lookback_days: How far back to fetch fresh events for this actor.
Returns:
A dict with identity, recent_activity (rollup over the lookback
window), lifetime (accumulated state: all IPs, all actions, all
access types, first/last seen) and pagination.
| Name | Required | Description | Default |
|---|---|---|---|
| actor_id | Yes | ||
| lookback_days | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations available, the description carries the behavioral burden and does so well. It discloses that data combines a fresh audit-log fetch with persisted local state, explains best-effort role resolution, and notes when role data is omitted. This is substantive behavioral context beyond a simple summary.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well structured with a one-sentence summary, a clear behavioral explanation, and separate Args/Returns sections. It is appropriately detailed for the tool's complexity without padding, and each sentence adds useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity, zero annotation coverage, and 0% schema description coverage, the description supplies everything needed: what the profile contains, how data is combined, parameter semantics, and return structure. The output schema also exists, but the description goes beyond it by explaining the lifetime/recent_activity distinction.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully compensates. actor_id is explained as the actor UUID as seen in actor.id, and lookback_days is defined as how far back to fetch fresh events. Both parameters receive meaningful semantic detail not present in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Full historical view of one actor: roles, actions, access types, IPs', which names a specific resource and scope. It clearly distinguishes this from siblings like list_activity_events or summarize_activity by emphasizing the per-actor, history-combining nature.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is implied rather than explicit: the tool is for obtaining a comprehensive actor profile that merges fresh data with persisted state. It does not explicitly state when to prefer this over sibling tools or provide exclusions, so an agent must infer the right selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_api_key_usageA
Report API-key-driven activity per actor (UI/session activity excluded).
Events are classified as API-key driven using the audit event's access/auth-method field, falling back to user-agent shape (scripted client vs browser). Each actor gets an action breakdown, distinct source IPs, and first/last seen timestamps - all pre-aggregated.
Args: actor_id: Optional actor UUID. Omit to cover every actor with API-key activity in the window. date_from: Start of the window, ISO-8601. Defaults to 30 days ago. date_to: End of the window, ISO-8601. Defaults to now.
Returns:
A dict with actors (per-actor API-key usage profiles), an
access_type_totals breakdown for context, and coverage metadata.
| Name | Required | Description | Default |
|---|---|---|---|
| date_to | No | ||
| actor_id | No | ||
| date_from | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of explaining behavior, and it does so well: it discloses the classification method (audit access/auth-method with user-agent fallback), that results are pre-aggregated, and what per-actor fields are returned. It does not mention permissions or rate limits, but 'Report' and 'Returns' strongly imply a safe, read-only operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear one-sentence summary, followed by a concise classification note and clearly labeled Args and Returns sections. Every sentence adds useful information and there is no filler or redundant restating of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a report tool with three optional parameters and an output schema, the description covers the core behavior, defaults, and return shape sufficiently. Minor gaps remain, such as date-boundary inclusivity and explicit guidance about which sibling tools to use instead, but nothing essential is missing for invoking it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does. All three parameters are explained with semantics beyond the bare schema: actor_id is an optional UUID, date_from defaults to 30 days ago, and date_to defaults to now, with ISO-8601 format specified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Report API-key-driven activity per actor' and explicitly excludes UI/session activity. It further clarifies the output (per-actor action breakdown, distinct source IPs, first/last seen timestamps), which distinguishes this tool from the sibling activity tools even without naming them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is clear: this tool is for API-key-driven activity reporting, and the description explicitly notes that UI/session activity is excluded. It also explains the effect of omitting actor_id, but it does not explicitly name alternative sibling tools for when this tool should not be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_activity_eventsA
List Tenable audit-log events for a date range, with optional filters.
Pagination is handled internally (the next cursor is followed
automatically) up to a safety cap of 20 pages / 100k events per call; if the
cap is hit, pagination.next_token is returned so the next call resumes
exactly where this one stopped. Every event is normalised, tagged with an
access type (API key vs UI session), and has credential-looking field values
redacted to their last 4 characters.
Args:
date_from: Start of the window, ISO-8601 (e.g. "2024-01-01" or
"2024-01-01T00:00:00Z"). Inclusive.
date_to: End of the window, ISO-8601. Inclusive.
actor_id: Optional actor UUID to filter on (actor_id.eq).
action: Optional exact action name, e.g. "user.create" (action.eq).
limit: Page size sent to the API (1-5000).
next_token: Opaque cursor from a previous call, to resume pagination.
Returns:
A dict with events (classified, redacted), a summary rollup of
those events, and a pagination block.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| action | No | ||
| date_to | Yes | ||
| actor_id | No | ||
| date_from | Yes | ||
| next_token | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden and does so exceptionally well. It discloses internal pagination with a 20-page/100k-event cap, resume behavior via next_token, normalization of events, access-type tagging, and redaction of credential-looking fields. This is far beyond what a minimal description would provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is information-dense yet well-structured: purpose first, then behavioral caveats, then parameter breakdown, then return structure. Every sentence adds value, and the length is justified by the number of parameters and the pagination/redaction behaviors that need explanation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter tool with no annotations, the description covers use case, filtering, pagination limits, resume semantics, data normalization, redaction, and return shape. The optional filters and cap behavior are fully explained, leaving no critical gap for an agent attempting to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates completely by explaining every parameter: date format and inclusivity, optional filters with their eq semantics, the exact action example, limit range, and the opaque next_token cursor. An agent can correctly populate all six arguments without needing extra documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific verb ('List') and resource ('Tenable audit-log events'), and states the scope ('for a date range') with optional filters. This clearly distinguishes it from sibling tools like summarize_activity and detect_anomalies, so an agent knows exactly what this tool retrieves.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the core use case clear: retrieve audit-log events within a date range, optionally filtered by actor or action. It does not explicitly name sibling alternatives or provide when-not-to-use guidance, but the event-listing purpose is unambiguous and the filter details help an agent choose appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summarize_activityA
Summarise all audit-log activity in a window (counts computed in Python).
Returns event counts by actor, by action, by CRUD type and by access type, plus failure and anonymous rates - all pre-computed. Use these numbers directly; do not re-derive them from raw events.
Args: date_from: Start of the window, ISO-8601. Inclusive. date_to: End of the window, ISO-8601. Inclusive.
Returns:
A dict with a summary block (total_events, by_actor,
by_action, by_crud, by_access_type, failure_rate_pct,
top_failed_actions) and a pagination block describing coverage.
| Name | Required | Description | Default |
|---|---|---|---|
| date_to | Yes | ||
| date_from | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses that counts are pre-computed in Python, that date boundaries are inclusive, and it exposes the exact return structure with summary and pagination blocks. It does not mention permissions, error behavior, or timezone assumptions, but for a read-only aggregation these are not critical.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with a concise purpose line, a usage warning, and clear Args/Returns sections. There is slight redundancy where the prose mention of 'Returns event counts...' is later repeated as a structured returns block, but the text is otherwise efficient and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter aggregation tool with an output schema present, the description covers purpose, parameter semantics, and return keys sufficiently. It lacks an explicit when-to-use-versus-siblings statement and has no annotation safety profile, but the core invocation details are complete enough for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides only bare string properties with 0% coverage. The description compensates fully by defining date_from as 'Start of the window, ISO-8601. Inclusive' and date_to as 'End of the window, ISO-8601. Inclusive', adding format, semantic role, and boundary inclusivity to both parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Summarise all audit-log activity in a window', and enumerates the output dimensions (by actor, action, CRUD, access type, failure and anonymous rates). This clearly frames the tool as an aggregation over raw events and distinguishes it from siblings like list_activity_events or get_actor_profile.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a strong usage directive: 'Use these numbers directly; do not re-derive them from raw events.' This tells the agent to rely on pre-computed counts rather than computing from raw event lists, which is clear contextual guidance. It does not explicitly name alternative tools or exclusion conditions, but the implied comparison to raw event access is present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.1.0- First observed
check_permission_prereqs - First observed
detect_anomalies - First observed
get_actor_profile - First observed
get_api_key_usage - First observed
list_activity_events - First observed
summarize_activity
TDQS
Scored across 6 tools
Each tool targets a clearly different concern: raw event listing, summary rollups, API-key-specific usage, anomaly detection, actor profiling, and prerequisite checks. Even the two aggregation tools (summarize_activity and get_api_key_usage) are separated by access-type scope, and their descriptions reinforce the distinction.
All tool names follow a consistent snake_case verb_noun pattern: list_activity_events, summarize_activity, get_api_key_usage, detect_anomalies, get_actor_profile, check_permission_prereqs. The verbs clearly signal the action and the objects clearly signal the resource or concern, making the set predictable and easy to navigate.
Six tools is well-scoped for an audit-log activity server: two raw/aggregate views, two analysis-focused tools, one deep-dive tool, and one operational prerequisite check. Each tool earns its place without redundancy or bloat.
The tool surface covers the full audit-monitoring lifecycle: listing raw events, summarizing them, isolating API-key usage, detecting anomalies, profiling individual actors, and verifying access prerequisites. The automatic pagination and baseline handling close potential dead ends, so an agent can move from raw data to insight without missing critical operations.
Maintenance
Related MCP Connectors
A paid remote MCP for AI SDK data query MCP, built to return verdicts, receipts, usage logs, and aud
Access New Relic observability data through MCP - query metrics, logs, traces, entities, and more
Read-only access to your Auditon vulnerability scans: findings, endpoints, reports and changes.
Search log events, investigate anomalies, and manage cases in your Knowledge Grid tenant.
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.-
- AlicenseNot gradedqualityDmaintenanceAn 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.1MIT
- AlicenseAqualityBmaintenanceEnables read-only querying of Azure Log Analytics and Azure Resource Graph through MCP, supporting KQL queries, workspace discovery, and resource inventory exploration with Azure RBAC authentication.1191 npm2MIT
- FlicenseNot gradedqualityCmaintenanceRead-only MCP server for querying Microsoft Purview unified audit logs across M365 workloads, wrapping the Graph API's asynchronous audit log search.-