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자로 마스킹됩니다.페이지네이션은 도구 호출당 20페이지 / 10만 이벤트로 제한됩니다. 한도에 도달하면 계속하는 데 필요한 커서와 함께 명시적으로 보고됩니다.
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에서 설정 → 내 계정 → 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())"서버를 직접 실행합니다 (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 아래에 다시 반영됩니다:
상수 | 기본값 | 의미 |
|
| 창의 일일 이벤트 수가 기준선 평균의 이 배수를 초과해야 함 |
|
| 급증이 플래그될 수 있는 최소 기준 |
|
| 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 -q페이지네이션/커서 처리, 속도 제한 백오프, API 키와 세션 분류, 마스킹, 모든 이상 징후 임계값을 다루는 105개 테스트. 모든 API 응답은 스텁 전송을 통해 가짜로 처리되므로, 테스트 스위트는 실제 테넌트에 접촉하지 않습니다.
2. 오프라인 종단 간 테스트 (자격 증명 없음, 네트워크 없음)
uv run python scripts/smoke_local.py스크립트로 작성된 가짜 Tenable(조용한 기준선 한 달, 그다음 새 IP에서의 시끄러운 밤)에 대해 여섯 가지 도구를 모두 실행하고 결과를 검증합니다: 플래그된 이상 징후, 심어진 비밀의 마스킹, 잘못된 입력이 예외 대신 구조화된 오류로 반환되는지. 실패 시 0이 아닌 종료 코드를 반환하므로 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 역할 또는 명시적인 audit-log 읽기 권한이 있는 사용자 지정 역할이 필요합니다. 그보다 낮은 권한은 HTTP 403을 반환합니다. 먼저check_permission_prereqs를 실행하세요. 정확히 이 문제를 해결 텍스트와 함께 보고합니다.이상 감지 기능은 이력이 있어야 유용합니다. 새
state.db에 대한 첫detect_anomalies호출은 창 이전 30일의 데이터를 기준으로 기준선을 구축한 다음 이를 비교합니다. 사전 활동이 거의 없거나 전혀 없는 행위자는new_actor로 표시되므로 초기 실행 결과는 이후 실행보다 노이즈가 더 많습니다.역할 확인은 최선 노력입니다.
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을 사용할 수 없으면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.
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.-