tenable-activity-mcp
tenable-activity-mcp
一个 MCP 服务器,将 Tenable 漏洞管理审计/活动日志(GET /audit-log/v1/events)暴露为一小组工具,使任何 MCP 客户端都能按需查询平台活动、API 密钥使用情况和异常行为。
分析由服务器完成。计数、分组、速率计算和阈值比较都在 Python 中完成;工具返回的是已完成的结构化结果(failure_rate_pct、by_actor、带推理的 findings),而不是将原始事件转储给模型去累加。
它提供什么
工具 | 用途 |
| 某个时间窗口的事件流,支持 actor/action 过滤器。自动跟随分页;如果达到安全上限,则返回可续传的 |
| 某个时间窗口的确定性汇总:按 actor、action、CRUD 类型和访问类型计数,以及失败率/匿名率。 |
| 仅 API 密钥驱动的活动,按 actor 分组:action 分解、不同的源 IP、首次/最后出现时间。 |
| 将某个时间窗口与每个 actor 存储的基线进行比较。标记新 actor、流量激增、未见过的源 IP、失败事件突发、持续失败率、非工作时间激增和从未见过的 action——每项都附有证据和一句推理说明。 |
| 单个 actor 的完整画像:角色(尽力而为)、全时段 action 分解、访问类型、见过的每个源 IP。 |
| 检查配置的密钥是否真的能读取审计日志,通过/失败,并附修复说明。 |
值得了解的安全特性:
任何看起来像凭据的内容都不会被返回。 键名暗示秘密的字段值(
secret_key、api_key、token、password……)或看起来像 Tenable 密钥材料的字段值都会被掩码为最后 4 个字符。分页上限为每次工具调用 20 页 / 10 万条事件; 达到上限时会明确报告,并附上继续所需的游标。
429 使用
X-RateLimit-Reset头进行退避(该端点不发送Retry-After),并带指数回退和重试上限。
Related MCP server: Entra Identity Posture MCP
要求
Python 3.11+
所有者能读取审计日志的 Tenable VM API 密钥
Tenable 角色 / 权限
读取 audit-log/v1/events 需要拥有 API 密钥的用户具有 Administrator 角色,或具有明确审计日志读取权限的自定义角色。权限不足会得到 HTTP 403;check_permission_prereqs 会用通俗语言报告这一点。
在 Tenable VM 的 设置 → 我的账户 → API 密钥 下生成密钥。密钥继承创建它们的用户的权限。
get_actor_profile 还会尝试从用户目录解析 actor 的角色。如果密钥无法列出用户,仍然会返回画像——只是没有角色标签。
设置
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 天哪些 API 密钥被用于 Tenable,来自哪些源 IP?"
"对照 30 天基线,查找过去 3 天 Tenable 活动中的异常,并解释你标记的任何内容。"
"显示 actor 00000000-1111-4222-8333-444444444444 做过的所有事情——action、访问类型和 IP。"
异常检测如何工作
detect_anomalies 需要历史数据来比较,这些数据存放在本地 SQLite 文件(state.db,自动创建)中:
如果存储的基线早于
BASELINE_REFRESH_MAX_AGE_HOURS(12 小时),服务器会获取你窗口之前紧邻的baseline_days,并重新计算每个 actor 的平均值、已知 IP、已知 action 和小时分布直方图。获取你的窗口并与这些基线进行比较。
被分析窗口中的事件不会被并入基线,因此重新运行同一窗口会返回相同的发现。
每个阈值都是 src/anomaly.py 顶部的命名常量,并在每个结果的 thresholds 下回显:
常量 | 默认值 | 含义 |
|
| 窗口内每天的事件数必须超过基线平均值的这个倍数 |
|
| 在可以标记激增之前的最低事件数 |
|
| IP 必须在此时间内出现过才能算作"已知" |
|
| 失败聚类触发器 |
|
| 持续失败率触发器(至少 10 条事件) |
|
| 非工作时间段 |
|
| 非工作时间占比必须超过 actor 基线占比的这个倍数 |
基线是按 actor 的,因此一个合法每天运行 500 次扫描的服务账户不会因为这样做而被标记。
布局
src/
server.py MCP entrypoint (FastMCP-style) + the six tool definitions
tenable_client.py Auth, filter building, cursor pagination, 429 backoff, typed errors
classifier.py API-key vs UI/session tagging, IP extraction, redaction, rollups
anomaly.py Thresholds and the individual anomaly checks
state.py SQLite: cursors, accumulated actor history, computed baselines
tests/
test_pagination.py test_classifier.py test_anomaly.py依赖方向是单向的:server → {anomaly, classifier, state} → tenable_client。
测试
三个级别,按你应该运行的顺序。
1. 单元测试(无需凭据,无需网络)
uv run pytest -q105 个测试,涵盖分页/游标处理、速率限制退避、API 密钥与会话分类、脱敏以及每个异常阈值。每个 API 响应都通过桩传输伪造,因此测试套件永远不会接触真实租户。
2. 离线端到端(无需凭据,无需网络)
uv run python scripts/smoke_local.py针对脚本化的假 Tenable(一个安静的基线月份,然后是一个来自新 IP 的嘈杂夜晚)运行全部六个工具,并断言结果:标记的异常、植入的秘密被脱敏、错误输入作为结构化错误而不是异常返回。任何失败都会以非零退出,因此可以用作 pre-commit 或 CI 门禁。
3. 针对你的租户的实时检查(只读)
填入 .env 后:
uv run python scripts/live_check.py 7首先验证审计日志权限,如果权限错误则停止并显示修复说明,然后打印过去 N 天(默认 7 天)的真实摘要、API 密钥使用分解、异常发现和最繁忙 actor 的画像。所有调用都是 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——它会准确报告此问题,并附带修复说明。异常检测需要有历史数据才有意义。 首次对全新的
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时会重新构建基线。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceExposes Azure Log Analytics workspace data with tools for querying AuditLogs and AzureActivity tables, supporting custom KQL queries, time range filters, and pagination.
- AlicenseAqualityBmaintenanceEnables auditing and monitoring of Microsoft Entra ID security posture, Conditional Access policies, and Zero Trust alignment via Microsoft Graph API.5MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server for Tenable Vulnerability Management and the Tenable One platform, enabling LLMs to query assets, vulnerabilities, scans, exposure metrics, attack paths, and more via natural language.MIT
- AlicenseAqualityCmaintenanceMCP server for Tenable.io/One Vulnerability Management that provides read-only tools for querying scans, assets, plugins, and vulnerabilities, plus specialized reporting tools for VPR re-prioritization, CISA KEV/EPSS exposure, and scan delta comparisons.112MIT
Related MCP Connectors
A paid remote MCP for AI SDK data query MCP, built to return verdicts, receipts, usage logs, and aud
Read-only MCP access to sessions, funnels, campaigns, errors, live visitors, and anomalies.
Read-only access to Auralogs production logs: search logs, inspect errors, review AI analyses.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/brendanong95/tenable-activity-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server