Last9
官方无缝地将实时生产环境上下文——日志、指标和追踪——引入本地环境,从而更快地自动修复代码。
你可以用 Last9 MCP 做什么?
- 调查生产事故 — 让你的助手为某项服务提取日志、追踪、指标、异常和触发的告警,以便诊断故障原因。
- 关联变更与影响 — 检查部署和配置变更,然后比较变更前后某项服务及其调用方的情况,判断变更是否导致了回归。
- 查询 Prometheus 指标 — 运行 PromQL 范围查询或即时查询,并列出标签值,以探索数据源中的任意指标。
- 检查数据库性能 — 发现数据库、查找执行缓慢的查询,并通过 OTel spans 查看查询模式和服务器端指标。
- 分析追踪和性能剖析 — 按 ID 获取追踪瀑布图,比较不同群组间的属性偏差并排序,或提取某项服务的火焰图和热门函数。
- 管理告警和仪表板 — 检查告警覆盖范围和规范性,创建或修改告警规则,并列出、验证或编辑自定义仪表板。
文档
Last9 MCP Server

你的 AI 代理不知道生产环境出了什么问题。这个服务器可以解决这个问题。
Last9 MCP Server 可将 Claude、Cursor、Windsurf 以及任何其他支持 MCP 的 AI 助手直接连接到你的生产环境可观测性数据——日志、指标、追踪、异常、数据库查询、告警和部署。代理不再靠猜测,而是开始读取实际信号。
30 秒内启动(托管版)
无需安装二进制文件。无需管理令牌。只需一个 URL,在浏览器中完成 OAuth,即可使用。
在你的 Last9 URL 中找到组织标识:app.last9.io/<org_slug>/...
Claude Code
claude mcp add --transport http last9 https://app.last9.io/api/v4/organizations/<org_slug>/mcp
输入 /mcp,选择 last9,然后进行身份验证。就这么简单。
Cursor
Settings > MCP > Add New MCP Server:
{
"mcpServers": {
"last9": {
"type": "http",
"url": "https://app.last9.io/api/v4/organizations/<org_slug>/mcp"
}
}
}
点击 Connect,完成 OAuth。
VS Code
需要 v1.99+。打开命令面板 → MCP: Add Server,粘贴 URL 并进行身份验证。
或者直接在 settings.json 中配置:
{
"mcp": {
"servers": {
"last9": {
"type": "http",
"url": "https://app.last9.io/api/v4/organizations/<org_slug>/mcp"
}
}
}
}
Windsurf
Settings > Cascade > Open MCP Marketplace > 齿轮图标 (mcp_config.json):
{
"mcpServers": {
"last9": {
"serverUrl": "https://app.last9.io/api/v4/organizations/<org_slug>/mcp"
}
}
}
Claude Web/Desktop
**Settings > Connectors > Add custom connector。**将其命名为 last9,粘贴 URL 并进行身份验证。
需要拥有 Claude 组织的管理员权限。
自托管(STDIO)
当你的 MCP 客户端不支持 HTTP 传输,或需要在本地运行服务器时,请使用此方式。
安装
Homebrew:
brew install last9/tap/last9-mcp
NPM:
需要 Node.js 22.23.4+、24.22.1+ 或 26.12.1+:较早版本在安装程序下载二进制文件时,会接受来自已泄露的 eMudhra 中间证书的 TLS 证书。
npm install -g @last9/mcp-server@latest
# or directly:
npx -y @last9/mcp-server@latest
二进制版本(Windows / 手动安装):
从 GitHub Releases 下载:
| 平台 | 压缩包 |
|---|---|
| Windows (x64) | last9-mcp-server_Windows_x86_64.zip |
| Windows (ARM64) | last9-mcp-server_Windows_arm64.zip |
| Linux (x64) | last9-mcp-server_Linux_x86_64.tar.gz |
| Linux (ARM64) | last9-mcp-server_Linux_arm64.tar.gz |
| macOS (x64) | last9-mcp-server_Darwin_x86_64.tar.gz |
| macOS (ARM64) | last9-mcp-server_Darwin_arm64.tar.gz |
获取刷新令牌
只有管理员可以创建令牌。
- 前往 API Access
- 点击 Generate Token 并授予写入权限
- 复制令牌
客户端配置
Homebrew:
{
"mcpServers": {
"last9": {
"command": "/opt/homebrew/bin/last9-mcp",
"env": {
"LAST9_REFRESH_TOKEN": "<your_refresh_token>"
}
}
}
}
NPM:
{
"mcpServers": {
"last9": {
"command": "npx",
"args": ["-y", "@last9/mcp-server@latest"],
"env": {
"LAST9_REFRESH_TOKEN": "<your_refresh_token>"
}
}
}
}
粘贴位置:
| 客户端 | 位置 |
|---|---|
| Claude Web/Desktop | Settings > Developer > Edit Config (claude_desktop_config.json) |
| Cursor | Settings > Cursor Settings > MCP > Add New Global MCP Server |
| Windsurf | Settings > Cascade > MCP Marketplace > 齿轮图标 (mcp_config.json) |
| VS Code | 在 settings.json 中将其包装在 { "mcp": { "servers": { ... } } } 内 — 详情 |
VS Code STDIO 配置
{
"mcp": {
"servers": {
"last9": {
"type": "stdio",
"command": "/opt/homebrew/bin/last9-mcp",
"env": {
"LAST9_REFRESH_TOKEN": "<your_refresh_token>"
}
}
}
}
}
对于 NPM:使用 "command": "npx" 并添加 "args": ["-y", "@last9/mcp-server@latest"]。
Windows
从 GitHub Releases 下载后,解压并指定完整路径:
{
"mcpServers": {
"last9": {
"command": "C:\\Users\\<user>\\AppData\\Local\\Programs\\last9-mcp-server.exe",
"env": {
"LAST9_REFRESH_TOKEN": "<your_refresh_token>"
}
}
}
}
在 Windows 上使用 NPM 更简单——无需管理路径。
环境变量
| 变量 | 默认值 | 说明 |
|---|---|---|
LAST9_REFRESH_TOKEN | (必填) | 从 API Access 获取的刷新令牌 |
LAST9_DATASOURCE | 组织默认值 | 数据源/集群名称——拥有多个 Levitate 集群时很有用 |
LAST9_FAKE_NOW_ISO | (未设置) | **仅用于评估/回放;切勿在生产环境中设置。**RFC3339 时间点(例如 2026-01-02T15:04:05Z),用于替代解析相对时间窗口(如 lookback_minutes)时的当前时间,以确保运行结果可复现。无效值会导致启动错误。超时、缓存和令牌过期仍使用实际时间 |
LAST9_API_HOST | app.last9.io | 覆盖 API 主机 |
LAST9_TOOLSETS | 所有工具 | 以逗号分隔要公开的工具集(logs、traces、metrics、alerts、dashboards、profiles、grafana、investigate、all)。别名:LAST9_MCP_TOOLSETS |
LAST9_MCP_READ_ONLY | false | 将 true 设为仅提供只读工具;参见只读模式。非布尔值会导致启动错误。别名:LAST9_READ_ONLY |
LAST9_MCP_ALLOW_WRITE_TOOLS | — | 只读模式下仍提供的、以逗号分隔的写入工具。别名:LAST9_ALLOW_WRITE_TOOLS |
LAST9_MAX_GET_LOGS_ENTRIES | 5000 | 分块 get_logs 请求的最大条目数 |
LAST9_USE_LOG_SEARCH_API | false | 将 true 设为通过一次服务器端搜索调用响应 get_logs 和 get_service_logs,而不是由客户端分块。每次调用最多等待 90 秒,之后会返回缩小时间窗口的建议;502 或 503 会在此时间内重试一次 |
LAST9_DEBUG_CHUNKING | false | 将 true 设为记录 get_logs、get_service_logs、get_traces 的分块规划详情 |
LAST9_DISABLE_TELEMETRY | true | 将 false 设为启用内部 OTel 追踪 |
OTEL_SDK_DISABLED | — | 标准 OTel 环境变量。覆盖 LAST9_DISABLE_TELEMETRY |
OTEL_EXPORTER_OTLP_ENDPOINT | — | OTLP 收集器端点(仅在启用遥测时使用) |
OTEL_EXPORTER_OTLP_HEADERS | — | OTLP 身份验证标头(仅在启用遥测时使用) |
工具阶段耗时
启用内部遥测后,工具 span 会携带 last9.phase.<phase>.duration_ms
(实际经过的毫秒数)和 last9.phase.<phase>.failed(该阶段是否
返回错误)。当配置的日志记录器接受调试级别记录时,同样的字段也会作为 tool phase completed 调试
日志输出,并包含 tool 和 phase。这些计时信息不会添加输入、查询文本、凭据或错误正文。
| 工具 | 阶段 |
|---|---|
get_log_patterns | sample:获取并解码样本;mine:模式挖掘;deep_link:解析可选索引并构建链接 |
get_logs | fetch:获取、解码并合并结果,包括重试和可选的计数合理性检查;count_sanity:嵌套的可选检查;post_process:生成指导信息、摘要并格式化 JSON;deep_link:解析索引并构建链接 |
get_service_profile | request:通过共享 API 客户端准备并发送请求,然后读取完整响应,之后再进行简要格式化 |
只记录实际执行的阶段,包括失败的获取操作。会抑制错误的可选辅助程序仍保持原有行为;failed: false 并不能证明可选链接或计数检查可用。嵌套的 count_sanity 耗时已包含在 fetch 中;不要重复相加。获取耗时包含客户端工作,因此并非仅测量后端执行时间。在调整采样或缓存之前,请先比较等效时间窗口和搜索路径下的这些阶段。
调查延迟时,请在基线版本和候选版本上,使用相同的服务、数据源、索引、时间窗口和限制进行回放。记录构建 SHA、工具总耗时、阶段耗时、last9.logs.search_path、存在时的重试属性,以及覆盖标志。除了典型调用,也要比较慢调用。获取或性能分析请求耗时较长,说明应调查网络/API 阶段;在将长尾延迟归因于后端之前,需要有独立且相关的证据证明后端执行情况。仅凭这些诊断信息无法确认延迟有所改善。
只读模式
--read-only(或 LAST9_MCP_READ_ONLY=true)仅提供标注为 readOnlyHint: true 的工具,因此没有任何工具可以创建、更改或删除告警规则、通知渠道、仪表板或丢弃规则,也无法确认或重新分配告警,或静默告警组。没有注解的工具会被视为写入工具并隐藏。
若要保留少数写入工具,请通过 --allow-write-tools(或 LAST9_MCP_ALLOW_WRITE_TOOLS)列出它们:
last9-mcp --read-only --allow-write-tools=acknowledge_alert,mute_alert_group
- 如果允许的名称不是写入工具(例如拼写错误,或填写了读取工具的名称),服务器会拒绝启动;错误信息会列出有效的写入工具。
- 不带
--read-only的--allow-write-tools会导致启动错误,因为此时所有写入工具都已提供。 - 只读模式与
--toolsets组合使用:工具必须同时满足两者的条件才会提供。--toolsets=alerts --read-only --allow-write-tools=mute_alert_group会提供告警读取工具以及mute_alert_group;不属于所选工具集的允许写入工具仍会被隐藏。 --http模式和dump-tools使用相同的标志和环境变量:go run . dump-tools --read-only会打印只读接口,以及服务器在instructions中提供的指令。- 读取工具的说明、架构和结果,以及服务器指令,都不会提及隐藏的写入工具。允许的写入工具仍可能提及其被隐藏的同类工具(
create_alert会创建一个由patch_alert启用的禁用规则),因此应将这类工具配对一并允许。
功能介绍
概览
get_workspace_overview— 当请求未指定服务或工具时,建议首先调用此工具(指定了服务或工具的请求会直接调用相应工具):通过一次低成本调用获取环境信息、过去一小时内检测到的信号(日志、追踪、指标)、服务和告警组数量、正在触发的告警以及当前时间。某个信号在这一小时内未出现,并不代表它没有更早的数据,因此仍可查询。如果某个子调用失败,其字段会标记为null,并添加一条errors[]条目。所有工具集均提供此工具get_current_time— 当前时间,以及last 2h、yesterday或since yesterday 9am IST的绝对边界;支持任意 IANA 时区或常见缩写。所有工具集均提供此工具
服务健康状况
get_service_summary— 按排名排列的全体服务(service, env)行:时间间隔内的 request_count、throughput_rpm、HTTP 4xx/5xx 计数和 gRPC 错误计数get_service_environments— 服务可用的环境。请先运行此工具——其他 APM 工具需要此处提供的envget_service_performance_details— 完整细分数据:吞吐量、错误率、p50/p90/p95/平均值/最大值、apdex、可用性(默认提供摘要;使用include_series可获取完整序列)get_service_operations_summary— 按 HTTP 端点、数据库调用、消息传递和 HTTP 客户端分组的操作get_service_dependency_graph— 上游/下游/基础设施的依赖关系图,包含吞吐量、延迟和错误率get_apm_service_deviations— 将当前时间窗口与等时长的基线进行比较:回归/改进、Apdex 对账以及最终结果(全体服务或单个服务)get_exceptions— 可按服务和 span 筛选的服务器端异常
数据库可观测性
这四种工具可直接分析数据库性能,数据来源于 OpenTelemetry trace span;如果没有追踪数据,则使用 CloudWatch 等基础设施指标。如果你已经在使用 OTel,则无需额外埋点。
get_databases— 发现基础设施中的所有数据库:数据库类型、主机、吞吐量(查询/分钟)、p95 延迟、错误率、依赖服务数量。还会发现来自 CloudWatch 等基础设施指标的数据库,无需进行跟踪插桩——这些行会显示活动值,而不是跟踪指标get_database_slow_queries— 按持续时间排序的实际最慢查询执行记录,并附带用于深入查看完整跟踪的跟踪 IDget_database_queries— 查询模式和聚合数据:查询运行频率、平均/p95 持续时间、错误率get_database_server_metrics— 来自数据库主机本身的服务器端指标(CPU、连接数、缓冲区命中率——取决于数据库系统)
支持 PostgreSQL、MySQL、MongoDB、Redis、Aerospike,以及任何带有 db_system 属性的 OTel 跟踪中的其他数据库;还支持从 CloudWatch 等基础设施指标中发现的数据库,这些数据库的行会显示活动值,而不是跟踪指标。
Prometheus / PromQL
prometheus_range_query— 对任意指标执行 PromQL 范围查询prometheus_instant_query— 即时查询;使用avg_over_time、sum_over_time等汇总函数prometheus_label_values— 获取给定序列的标签值prometheus_labels— 获取序列的所有可用标签
设置 LAST9_DATASOURCE,或在单次调用中设置 datasource,即可将这些查询指向默认数据源/集群以外的目标。省略 datasource 时使用默认值;如果匹配器认为某个唯一的近似匹配是安全的(例如大小写变体),则使用最接近的匹配项。缺少、多出或调换字母时,不保证能自动解析:即使只有一个候选项,如果修改可能影响区域或环境代码,也可能需要确认。较宽松或有歧义的匹配会返回候选项且不会运行查询(不算错误);未知名称则会返回错误。只要数据源名称不是完全匹配,额外的内容块就会指出所用的数据源。get_metric_status、get_service_profile 和 get_apm_service_deviations 以相同方式解析 datasource。
日志
get_logs— 完整的 JSON 管道日志查询(聚合、筛选、字段提取)get_service_logs— 服务的日志行,可按严重性和正文内容筛选;除非response_mode为raw,否则会将结果汇总为 20 行get_log_patterns— 将某个时间窗口内服务的日志行聚类为消息模板,并显示数量、首次/最后出现时间、严重性分布和示例get_emerging_log_patterns— 与基线时间窗口相比新增、增加、减少或消失的日志模板,并显示两个窗口的数量get_log_attributes— 指定时间窗口内日志架构中属性的全局目录get_log_attributes_for_pipeline— 正在进行的管道中实际存在的日志字段(范围限定的发现),每个字段都附带其精确的filter_fieldget_drop_rules— 来自 Last9 Control Plane 的日志丢弃规则add_drop_rule— 创建新的丢弃规则,从源头减少日志量get_remapping_rules— 来自 Last9 Control Plane 的重映射规则(logs_extract、logs_map、traces_map)add_remapping_rule— 创建重映射规则,在摄取时提取或映射日志和跟踪属性
跟踪
get_traces— 用于广泛搜索和聚合的 JSON 管道跟踪查询get_service_traces— 按精确跟踪 ID 或服务名称查询跟踪。已有跟踪 ID 时使用此项,速度更快get_trace_attributes— 跟踪架构中属性的全局目录get_trace_attributes_for_pipeline— 正在进行的管道中实际存在的属性(范围限定的发现),每个属性都附带其精确的filter_fieldget_trace_attribute_values— 跟踪属性的不同值,可选择限定到某个管道get_trace_attribute_deviations— 对两个有界 span 群组(慢与快、错误与非错误,或两个时间窗口)中不同的属性值进行排名。表示相关性,而非因果关系get_trace_waterfall— 将一条精确跟踪显示为父子瀑布图,并提供区间并集自耗时、最慢 span 和图结构警告
变更事件与告警
get_change_events— 部署、配置变更、回滚。将事故与变更内容关联起来analyze_change_impact— 变更是否造成了问题?比较变更前后某个服务及其直接调用方的黄金信号、APM 和跟踪属性偏差、新触发的告警,以及判定结果(regression likely/no significant change/insufficient data)get_alert_groups— 已配置的 Compass 告警组,包含元数据标签、团队、层级和规则数量——包括规则数为零且未触发的组get_alert_operations_summary— 指定时间窗口内的值班健康状况:触发与已确认的告警数、积压、投递情况;使用include_rules时,还会显示最嘈杂、反复触发和未路由的规则。每个计数都附带其status(available/partial/unavailable)get_alert_coverage— 尚未设置告警的内容:未覆盖的黄金信号、完全禁用或未路由的告警组,以及静默时间过长的规则;每项都附带建议的修复工具。只读。get_alert_config— 告警规则配置——可按名称、严重性、类型和标签搜索get_entity_kpis— 某个告警组中的所有 KPI(id、名称、PromQL、单位),包括尚未被任何规则使用的 KPI——create_alert和validate_alert_expression需要这些信息create_kpi— 当现有 KPI 都不适用时,在告警组中创建 KPI(PromQL + 单位)。只创建一次,并保留返回的 idget_alerts— 指定时间窗口内当前正在触发的告警get_alert_rule_state— 按rule_id分组,显示时间范围内每条告警规则的历史触发状态(1/0)。可按告警组、规则名称、标签筛选条件和状态筛选。get_alert_hygiene— 过去 7 或 30 天内嘈杂、反复触发、过时和未路由的告警规则,按排名列出,并为每项提供判定依据和建议的修复方法。只读。get_notification_channels— 已配置的通知渠道(Slack、PagerDuty、电子邮件等)。scope=channels列出渠道本身(用于关联的 id);默认的attached则列出每个告警组的关联渠道recommend_alert_config— 创建告警规则前提供只读设计指导(生命周期、验证关卡、响应人员上下文)validate_alert_expression— 对告警组的 KPI 试运行告警表达式,不保存任何内容describe_alert_chart— Discover 图表上可用于告警的信号(key、单位),只读(discover-service、discover-exceptions)create_alert— 在现有告警组中创建告警规则(静态规则,或通过adaptive_std_cmp创建自适应规则);始终以禁用的草稿状态创建。只创建一次;使用update_alert/patch_alert进行调整create_alert_from_chart— 一次调用即可从 Discover 图表创建静态阈值告警规则。与create_alert一样,规则会以禁用的草稿状态创建update_alert— 完整替换规则的评估配置(可能会返回替换后的规则 ID)patch_alert— 部分修改规则:启用/暂停、mute_until、响应人员properties、每周recurring_mute_schedule(或clear_recurring_mute_schedule)delete_alert— 永久删除告警规则mute_alert_group— 将告警组中的所有规则静默(或取消静默)至指定截止时间acknowledge_alert— 接管正在触发的告警,或释放该告警reassign_alert— 将已确认的告警转交给其他用户create_notification_channel— 创建 Slack、PagerDuty、Opsgenie、电子邮件或通用 webhook 渠道attach_notification_channel— 将现有渠道路由到告警组,以用于breach、threat或两者detach_notification_channel— 移除一个渠道与告警组之间的关联delete_notification_channel— 永久删除没有任何关联的渠道
告警写入工具(create_kpi、create_alert、update_alert、patch_alert、delete_alert、create_alert_from_chart、mute_alert_group、acknowledge_alert、reassign_alert、create_notification_channel、attach_notification_channel、detach_notification_channel、delete_notification_channel)需要具有写入范围的令牌;delete_alert、detach_notification_channel 和 delete_notification_channel 则需要删除范围。它们仅在 alerts 工具集中提供。
这些工具创建的规则、渠道和关联会标记为 created_via: last9-mcp,并附带 MCP 客户端的名称和版本(对于规则,还会添加 _l9_created_via_ 和 _l9_created_via_client_ 注释;patch_alert 和 update_alert 会保留这些注释,调用方无法设置)。get_entity_alert_rules 和 get_notification_channels 会显示该标记;delete_alert、detach_notification_channel 和 delete_notification_channel 会指示代理仅清理带标记的资源,除非用户明确指定某个资源。
自定义仪表板
list_dashboards— 按名称筛选并分页列出自定义仪表板,结果不超过 32 KB:包括 ID、名称、最后更新时间、作者和锁定状态get_dashboard— 按 ID 获取完整仪表板定义,包括面板和查询preview_dashboard— 对未保存的仪表板或补丁进行只读预览:解析查询、限制每个面板的结果,并显示面板差异;绝不保存validate_dashboard— 对已保存的仪表板 id 或内联dashboard_definition执行只读 lint、查询和分类,时间窗口不超过 24 小时。绝不创建或更新仪表板create_dashboard— 一次性创建全新的自定义仪表板(面板、查询、元数据)。返回 id 后,使用patch_dashboard编辑面板。update_dashboard— 按 ID 大幅重构现有仪表板(完整替换;只读系统仪表板会返回错误)。如需编辑单个面板,请使用patch_dashboardpatch_dashboard— 按 ID 对现有仪表板进行定向编辑(添加/更新/移除/移动面板、设置标题、设置变量);返回精简差异,而非完整仪表板delete_dashboard— 按 ID 删除自定义仪表板set_dashboard_lock— 按 ID 锁定或解锁自定义仪表板(仅作者或组织管理员可操作);锁定的仪表板无法更新、打补丁或删除list_dashboard_snapshots— 仪表板的冻结时间点快照(仅元数据)get_dashboard_snapshot— 包含面板数据的完整冻结快照,用于 RCA / 可分享视图delete_dashboard_snapshot— 按 ID 删除冻结快照
无需安装 skill,即可通过 MCP prompts/list 和 prompts/get 创建仪表板。以下三个提示均不接受参数:
create_dashboard_guide— 发现、布局和面板选择;在审批前验证完整候选方案并运行每个面板的查询,只创建一次,使用补丁进行定向编辑,然后读取结果。dashboard_examples— 完整示例,涵盖服务 RED、端点延迟、状态类别、主机健康状况、日志计数和跟踪面板,并包含依赖变量。query_guide— 计数器/仪表/直方图和派生跟踪指标语义、即时查询与范围查询、速率窗口、百分比边界,以及 logjson/tracejson 规则。
相同内容也可通过 last9://reference/create_dashboard_guide、last9://reference/dashboard_examples 和 last9://reference/query_guide 阅读。所有工具集下都可以发现提示和资源;执行工作流需要相关工具(对于混合信号创作,请使用 --toolsets=dashboards,investigate,它也适用于 list_datasources)。只读会话可以准备和验证,但无法保存。执行步骤前请检查工具是否可用。
面板检查目前会将 prometheus_range_query、prometheus_instant_query、get_logs 和 get_traces 与 validate_dashboard 配合使用。验证器不支持的查询类型和简化默认值并不能证明渲染结果一致。#475 合并后,独立的查询检查步骤将切换到 query_panel。
持续剖析
需要为组织启用持续剖析。先使用 get_profile_services 发现服务,然后获取火焰图或排名函数。
get_profile_services— 在时间窗口内有性能分析数据的服务(查询前索引)get_flamegraph— 单个服务的嵌套火焰图树(默认cpu;也支持alloc、wall)get_top_functions— 单个服务中最热门函数的自身采样排名get_profile_summary— 对单个服务的性能分析进行简短的自然语言排查
Grafana 仪表板
针对组织 Grafana 实例的只读工具(通过 Last9 的 Grafana 代理)。凭据字段绝不会返回给模型。使用 LAST9_TOOLSETS=grafana 启用(或不设置工具集以启用所有工具)。
grafana_search_dashboards— 按标题子字符串搜索仪表板(分页;达到上限时为truncated: true)grafana_get_dashboard— 按 uid 获取仪表板摘要(面板、变量、PromQL 目标);原始 Grafana JSON 使用full_json=truegrafana_list_folders— 文件夹树grafana_list_folder_dashboards— 单个文件夹中的仪表板(分页)grafana_list_datasources— 不含凭据的数据源清单
模糊名称解析
did_you_mean— 当代理不确定实体名称时,此工具会从目录中返回最接近的匹配项(服务、环境、主机、数据库、K8s 部署/命名空间、作业)。最多提供 3 个建议及相似度分数。大多数工具在名称查询无结果时,服务器会自动调用此工具。
服务概况
get_service_profile— 在查询服务之前,了解其遥测数据的实际情况:有哪些信号、语言和运行时、部署环境、日志的结构,以及适用时建议的采集修复方案。这样代理可以在服务没有跟踪数据时跳过跟踪工具;当SeverityText为空时,也可以从日志正文解析严重性,而不是按其筛选却一无所获。
工作原理
每个响应都包含深层链接。 每个工具都会返回一个 deep_link 字段,其中包含指向 Last9 仪表板的直接 URL,精确对应相应查询和时间范围。代理可以把链接发给你;点击即可打开对应页面。
工具集。 默认情况下,服务器会公开所有工具。只需要进行调查(日志/跟踪/指标/性能分析)的自动化主机可以设置 LAST9_TOOLSETS=investigate(或传入 --toolsets=investigate),这样无需在客户端批量禁用工具,也能让 tools/list 保持精简。命名工具包:logs、traces、metrics、alerts、dashboards、profiles、grafana、investigate、all。未知名称会立即报错。所有工具集都会提供 get_current_time 和 get_workspace_overview。在 HTTP 模式下,请求可以通过 X-Last9-Toolsets 标头进一步缩小范围(参见按请求设置工具集)。alerts 工具包还提供只读的 prometheus_range_query 和 get_dashboard,由 author-alert 提示调用。仅使用 metrics 工具包不包含 list_datasources 或 did_you_mean — 需要这些发现辅助工具时,请使用 investigate(或组合多个工具集)。
工具参考资源。 较长的 logjson/tracejson/service-logs/metrics 手册是 MCP 资源(last9://reference/logjson、last9://reference/tracejson、last9://reference/service_logs、last9://reference/metrics、last9://reference/investigation、last9://reference/alerting),而不是始终显示的工具描述文本。告警手册涵盖告警表达式语法、静态字段与自适应字段、单位、validate_alert_expression 的检查内容,以及延迟/错误率/饱和度规则模板。关键查询规则仍保留在工具描述中,因此即使代理从不调用 resources/read,也能正确构造查询。使用 get_log_attributes / get_log_attributes_for_pipeline(以及对应的跟踪工具)发现组织专属字段——这些字段不会注入描述中。
分块处理大型结果。 get_logs 和 get_traces 通过分块处理大型结果集,而不是截断结果。日志的默认上限为 5000 条;可通过 LAST9_MAX_GET_LOGS_ENTRIES 配置。
开发
HTTP 模式、curl 测试、从源代码构建
在 HTTP 模式下运行
export LAST9_REFRESH_TOKEN="your_refresh_token"
export LAST9_HTTP=true
export LAST9_PORT=8080
./last9-mcp-server
服务器启动于 http://localhost:8080/mcp。
使用 curl 测试
Streamable HTTP 处理程序以无状态模式运行,因此每个请求都会独立处理。initialize 握手和 Mcp-Session-Id 标头均为可选项——发送这些内容的客户端仍可正常工作(标头会被接受并忽略),客户端也可以直接跳过,转而发送 tools/list / tools/call。每个工具都是独立的请求/响应查询;服务器不会发送服务器→客户端通知,因此 GET /mcp(SSE 流)会返回 405。
# List tools — a session handshake is optional in stateless mode
curl -s -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}'
# Call a tool
curl -s -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_service_logs",
"arguments": {
"service_name": "your-service-name",
"lookback_minutes": 30,
"limit": 10
}
}
}'
按请求设置工具集
在 HTTP 模式下,请求可以通过 X-Last9-Toolsets 标头缩小可用工具范围;无法设置标头的客户端可以使用 toolsets 查询参数(/mcp?toolsets=logs,traces)。如果两者都提供,则非空白标头优先。其值使用与 --toolsets 相同的逗号分隔名称。请求可见的工具集是其与启动时 --toolsets 的交集:只能缩小范围,不能扩大;all 或空值会保留启动时的工具集。未知名称会返回指出该名称的 400。tools/list、tools/call 和 initialize 指令都会遵循生效的工具集;get_current_time 和 get_workspace_overview 则始终包含在所有工具集中。
curl -s -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "X-Last9-Toolsets: logs,alerts" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}'
每个不同的生效工具集都由独立服务器提供服务,该服务器会在首次请求时构建(耗时数十毫秒),并一直保留到关闭;如果请求指定的工具集与启动时相同,则会复用启动服务器。不会进行淘汰:只接受命名工具集,因此缓存中每种组合最多保留一个服务器(目前共 135 种组合,实时堆内存合计约 75 MB;测试中完整缓存稳定后常驻内存接近 230 MB)。
从源代码构建
git clone https://github.com/last9/last9-mcp-server.git
cd last9-mcp-server
go build -o last9-mcp-server
LAST9_HTTP=true ./last9-mcp-server
LAST9_HTTP=true适用于本地开发。实际使用时,托管 HTTP 端点更方便。
工具参考
所有参数、时间输入规范和详细信息
时间输入
- 绝对时间(
start_time_iso/end_time_iso,或time_iso)优先于lookback_minutes。 - 对于相对时间窗口:使用
lookback_minutes。 - 对于绝对时间窗口:使用 RFC3339/ISO8601 —
2026-02-09T15:04:05Z。 - 旧版
YYYY-MM-DD HH:MM:SS仅为兼容性而接受。 - 将
since yesterday 9am IST等短语解析为 RFC3339 边界,并使用get_current_time。
get_workspace_overview
无参数。并发探测最近 60 分钟的数据,每个子调用都设有较短超时,并返回 current_time、lookback_minutes、environments、telemetry(logs/traces/metrics 布尔值)、service_count(不同服务的 get_service_summary 排名,涵盖所有环境)、alert_group_count、firing_alert_count 和 errors([{field, error}])。子调用失败的字段为 null(未知),绝不会是 0 或 false。这些探测不会受 --toolsets 限制:工具集决定提供哪些工具,而 API 令牌决定服务器可以读取哪些内容。
get_current_time
range(字符串,可选):last 2h、past 30 minutes、last 7d(s、m、h、d = 24h、w = 7d;最多 366d);today;yesterday;since <point>;<point> to <point>。时间点可以是 RFC3339,也可以是today/yesterday/ 星期几(monday、mon:最近一次出现的日期,包括今天)/YYYY-MM-DD,并可选带有9am、9:30pm或14:30。末尾的时区会覆盖两个边界的timezone;其他位置出现时区则会报错。若只需要now,请省略。timezone(字符串,可选):IANA 名称或缩写(IST = Asia/Kolkata、PST/PDT、EST/EDT、UTC、GMT)。默认值为 UTC。未知时区会报错;含义不明确的CST也会报错(请传入America/Chicago或Asia/Shanghai)。
返回 now(以及在 range 下的 start/end),格式为 {iso, epoch_seconds, local};仅当时区非 UTC 时才会出现 local。
get_exceptions
limit(整数,可选):异常数量上限。默认值:20。lookback_minutes(整数,可选):默认值:60。start_time_iso/end_time_iso(字符串,可选):绝对时间范围。service_name(字符串,可选):按服务筛选。span_name(字符串,可选):按 span 名称筛选。env(字符串,可选):按环境筛选。
get_service_summary
start_time_iso/end_time_iso(字符串,可选)env(字符串,可选):PromQL 正则表达式。默认值为.*。精确匹配需要锚点(例如^prod$)。sort_by(字符串,可选):request_count(默认值)、throughput_rpm、http_4xx_count、http_5xx_count或grpc_error_count。limit(整数,可选):排名行数上限。省略或设为 0 表示 10;大于 100 的值会限制为 100。
get_service_environments
start_time_iso/end_time_iso(字符串,可选)
所有其他 APM 工具都需要
env值。如果此处返回空值,请使用""。
get_service_performance_details
默认返回每个序列的摘要:points、missing_points(无流量的可用性时间段,不计入统计)、min、p50、p90、p99(最近秩)、max、mean、last、baseline_mean(有效数据点前半部分的均值,而非整个时间窗口的均值)、delta_pct(有效数据点后半部分相对于基线的变化;基线为 0 时不显示),以及最多 3 个 change_points(timestamp、before_mean、after_mean);每项指标和每个响应时间分位数最多包含 4 个序列(按均值从高到低排列;series_omitted 统计其余序列)。带有 points: 0 的序列不包含统计数据;baseline_mean/delta_pct 至少需要 6 个数据点(每半部分 3 个)。full_series 表示可通过 include_series 获取原始数据点。
service_name(字符串,必填)lookback_minutes(整数,可选):默认值:60。start_time_iso/end_time_iso(字符串,可选)env(字符串,可选):默认值为prod。top_n(整数,可选):top-operations/top-errors 列表的条目上限。默认值:5;使用include_series=true时为 10。最大值为 100。include_series(布尔值,可选):返回每个序列的所有数据点,而非摘要。默认值:false。
get_service_operations_summary
service_name(字符串,必填)lookback_minutes(整数,可选):默认值:60。start_time_iso/end_time_iso(字符串,可选)env(字符串,可选):默认值为prod。
get_service_dependency_graph
service_name(字符串,可选)lookback_minutes(整数,可选):默认值:60。start_time_iso/end_time_iso(字符串,可选)env(字符串,可选):默认值为prod。
get_apm_service_deviations
service_name(字符串,可选):省略表示整个集群范围;提供此参数可指定单个服务及其操作关联。lookback_minutes(整数,可选):当前时间窗口。默认值:60。start_time_iso/end_time_iso(字符串,可选):显式指定当前时间窗口。baseline_start_time_iso/baseline_end_time_iso(字符串,可选):显式指定基线。默认使用紧邻当前窗口之前、时长相同的窗口。datasource(字符串,可选):省略则使用默认值;近似名称的解析方式与 Prometheus 工具相同。响应会指出使用的默认项或最接近的匹配项;名称有歧义时会返回候选项,不会执行查询。env(字符串,可选):默认值为prod。max_services/max_operations(整数,可选):默认值为 10,每项最大值为 10。
get_databases
env(字符串,可选):按环境筛选。接受正则表达式。默认值:全部。lookback_minutes(整数,可选):默认值:60。时间窗口不得超过 7 天。start_time_iso/end_time_iso(字符串,可选)
get_database_slow_queries
db_system(字符串,可选):例如postgresql、mysql、mongodb、redis。host(字符串,可选):数据库主机(net_peer_name)。service_name(字符串,可选):调用方服务名称。env(字符串,可选)min_duration_ms(浮点数,可选):查询时长下限,单位为 ms。lookback_minutes(整数,可选):默认值:60。start_time_iso/end_time_iso(字符串,可选)limit(整数,可选):默认值:20。
get_database_queries
db_system(字符串,可选)host(字符串,可选)service_name(字符串,可选)env(字符串,可选)lookback_minutes(整数,可选):默认值:60。start_time_iso/end_time_iso(字符串,可选)limit(整数,可选):默认值:20。
get_database_server_metrics
db_system(字符串,必需):例如postgresql、mysql、mongodb、redis、aerospike。host(字符串,可选)lookback_minutes(整数,可选):默认值:60。start_time_iso/end_time_iso(字符串,可选)
prometheus_range_query
query(字符串,必需):PromQL 查询。start_time_iso/end_time_iso(字符串,可选):默认查询最近 60 分钟。lookback_minutes(浮点数,可选):默认值:60。
prometheus_instant_query
query(字符串,必需)time_iso(字符串,可选):默认值为当前时间。lookback_minutes(浮点数,可选)
prometheus_label_values
match_query(字符串,可选):PromQL 筛选条件。label(字符串,必需):标签名称。lookback_minutes(浮点数,可选):默认值:60。start_time_iso/end_time_iso(字符串,可选)
未指定时间窗口且 match_query 指定了一个指标(metric{...} 或 {__name__="metric"})时,如果 60 分钟的结果为空,则会在 4 天的时间范围内重试一次;第二个文本块会说明结果涵盖的时间窗口。
prometheus_labels
match_query(字符串,可选):PromQL 筛选条件。lookback_minutes(浮点数,可选):默认值:60。start_time_iso/end_time_iso(字符串,可选)
与 prometheus_label_values 类似,单指标查询结果为空时会在 4 天的时间范围内重试。
get_logs
logjson_query(数组,必需):JSON 管道查询。lookback_minutes(整数,可选):默认值:5。start_time_iso/end_time_iso(字符串,可选)limit(整数,可选):服务器默认值:5000。index(字符串,可选):physical_index:<name>或rehydration_index:<block_name>。response_mode(字符串,可选):summary(默认值;也适用于null)或raw。原始行结果超过 20 行时,会以summary返回:lines_summarized、severity_counts(前六个标签,其余放在other_severities中)、first_timestamp/last_timestamp、覆盖查询时间窗口的 10 桶histogram(基于返回的行;如果结果被限制截断,则包含truncated: true),以及排名靠前的patterns(template、count,最多两个samples),其余汇总到other中;总长度最多为 4000 个字符。仍然无法放入的顶层元数据会被丢弃,并在dropped_fields中列出。raw会返回这些行。聚合结果不会被汇总。
对于基于日志的服务清单,先查询 physical_index_service_count:
sum by (name, service_name, env) (physical_index_service_count{destination="logs"})
将 service_name 用作 ServiceName,存在时将 env 用作环境,并将 name 用作物理索引名称。如果 name="default",则省略 index;如果用户选择了非默认物理索引,则传入 index: "physical_index:<name>"。如果后端拒绝显式物理索引筛选,则不带 index 重试,并说明该后端不支持显式物理索引筛选。
get_service_logs
service_name(字符串,必需)lookback_minutes(整数,可选):默认值:60。limit(整数,可选):默认值:100;使用response_mode: "raw"时为 20。env(字符串,可选)severity_filters(数组,可选):例如["error", "warn"]。使用 OR 逻辑。body_filters(数组,可选):例如["timeout", "failed"]。使用 OR 逻辑。start_time_iso/end_time_iso(字符串,可选)index(字符串,可选)response_mode(字符串,可选):summary(默认值;也适用于null)或raw。超过 20 行时,logs会替换为与get_logs相同的summary,其他字段保持不变;raw会返回这些条目。
多种筛选类型之间使用 AND 逻辑。每个数组内部使用 OR 逻辑。
先使用 get_logs 获取宽泛的聚合计数;只有在将范围缩小到服务/环境/索引和少量样本集后,才使用 get_service_logs。
get_log_patterns
service_name(字符串,必需)env(字符串,可选)start_time_iso/end_time_iso(字符串,可选)lookback_minutes(整数,可选):默认值:60。severity_filters/body_filters(数组,可选):使用 OR 逻辑,与get_service_logs中相同。仅当get_service_profile报告severity_setall时才设置severity_filters;使用none或partial时,它会丢弃正文中严重性符合条件的行。index(字符串,可选)sample_size(整数,可选):从时间窗口中采样的行数,按最新优先。默认值:1000,最大值:5000。top_n(整数,可选):按计数返回的模板数。默认值:20,最大值:100。其余模板的计数汇总到other中。
聚类在 MCP 服务器中对采样行执行,因此计数、first_seen 和 last_seen 均基于样本;当样本可能遗漏匹配行时,window.sample_limit_reached 会说明这一点(样本包含 sample_size 行,且 API 未报告与此相等的精确 total_matching_lines,或者搜索已被 logs_truncated),此时样本仅包含该时间窗口中最新的行。每个 template 和 sample 最多截取 500 个字符,并以 … 结尾,因此无法聚类的正文(例如不含 message 字段的 JSON)不会占满响应。搜索中有分块失败时会返回工具错误;搜索被截断或达到上限时仍会返回模式,并通过 sample_limit_reached 标记。只有在 sample_limit_reached 为 false 时,空的 patterns 列表才表示没有匹配项;如果为 true,则表示搜索提前停止,可能遗漏匹配行。
get_emerging_log_patterns
接受所有 get_log_patterns 参数(时间范围为当前窗口),并额外接受:
baseline_start_time_iso/baseline_end_time_iso(字符串,可选):必须同时设置或都不设置。默认值:紧邻当前窗口之前、时长相同的窗口。min_count(整数,可选):变化模式在其数量较多的窗口中所需的行数:对于new/increased,使用当前窗口;对于decreased/disappeared,使用基线窗口。默认值:3(如果sample_size更小,则使用该值),最大值:sample_size。change_factor(数字,可选):频率比,必须大于 1;在两个窗口中都出现的模式必须达到该比值(increased),或降至其倒数(decreased)。默认值:2。
两个阈值都必须满足,因此频率未变化达到 change_factor 的高频模板绝不会被报告。仅返回发生变化的模板(new、increased、decreased、disappeared),并附带 current 和 baseline 计数;unchanged_patterns 统计两个窗口中都出现、但变化幅度小于 change_factor 的模板;below_min_count_patterns 统计因行数少于 min_count 而被丢弃的变化。当两个样本都包含所有匹配行时,按每分钟频率进行比较;对于达到上限的样本,则根据精确的 total_matching_lines 估算每分钟频率;其他情况下,按样本占比比较,此时 increased/decreased 描述的是组成而非速率(comparison_basis)。空的 patterns 列表表示没有变化超过两个阈值,并不表示日志没有变化:较少见的变化会计入 below_min_count_patterns;如果某个窗口包含 sample_limit_reached,则比较的是样本,而非整个窗口。
get_log_attributes
lookback_minutes(整数,可选):默认值:15。start_time_iso/end_time_iso(字符串,可选)region(字符串,可选)index(字符串,可选)
get_log_attributes_for_pipeline
pipeline(数组,必需):用于限定属性发现范围的前置筛选阶段,例如[{"type":"filter","query":{"$eq":["ServiceName","<service>"]}}]。lookback_minutes(整数,可选):默认值:15。start_time_iso/end_time_iso(字符串,可选)region(字符串,可选)index(字符串,可选)
get_drop_rules
无参数。通过 GET /otel_settings/drop?region=... 列出丢弃规则。
add_drop_rule
name(字符串,必需)filters(数组,必需):每个筛选条件包含:key、value、operator(equals/not_equals)、conjunction(and)。- 筛选键必须使用
attributes["key_name"]或resource.attributes["key_name"](Last9 API 要求)。 - 通过
POST /otel_settings/drop?region=...&cluster_id=...创建规则。
get_remapping_rules
rule_type(字符串,必需):logs_extract、logs_map或traces_map。region(字符串,可选):默认值:已配置的数据源区域。- 通过
GET /otel_settings/remapping/{rule_type}?region=...列出规则。
add_remapping_rule
每次调用创建一条规则;映射规则需要针对每个 target_attribute 单独调用。
rule_type(字符串,必填):logs_extract、logs_map或traces_map。name(字符串,必填)remap_keys(数组,必填):源字段。logs_extract配合json使用时:正文中的字段名;配合pattern使用时:恰好一个带命名捕获组的正则表达式。映射规则:属性路径,优先采用第一个非空值。target_attribute(字符串,必填):logs_extract:log_attributes或resource_attributes。logs_map:service、severity或resource_deployment.environment。traces_map:service。extract_type(字符串,仅限logs_extract,且在该模式下必填):json或pattern。action(字符串,仅限logs_extract):upsert(默认值)或insert。prefix(字符串,仅限logs_extract)preconditions(数组,仅限logs_extract):最多一个{key, value, operator};operator为equals(默认值)、not_equals或like(正则表达式)。region(字符串,可选):默认值:已配置的数据源区域。- 通过
POST /otel_settings/remapping/{rule_type}?region=...创建规则。不会重试;超时后,请使用get_remapping_rules检查。
get_traces
用于广泛搜索和聚合。若要精确查找 trace ID,请使用 get_service_traces。
tracejson_query(数组,必填)start_time_iso/end_time_iso(字符串,可选)lookback_minutes(整数,可选):默认值:60。limit(整数,可选):默认值:5000。
get_service_traces
必须且只能提供 trace_id 或 service_name 其中之一。
trace_id(字符串,可选):默认回溯时间:72 小时。service_name(字符串,可选):默认回溯时间:60 分钟。lookback_minutes(整数,可选)start_time_iso/end_time_iso(字符串,可选)limit(整数,可选):默认值:10。env(字符串,可选)
get_trace_attributes
lookback_minutes(整数,可选):默认值:15。start_time_iso/end_time_iso(字符串,可选)region(字符串,可选)
get_trace_attributes_for_pipeline
pipeline(数组,必填):用于限定发现范围的前置筛选阶段,例如[{"type":"filter","query":{"$eq":["ServiceName","<service>"]}}]。lookback_minutes(整数,可选):默认值:15。start_time_iso/end_time_iso(字符串,可选)region(字符串,可选)
get_trace_attribute_values
tag_name(字符串,必填):来自get_trace_attributes的属性名称(例如resource_department或attributes['http.method'])。pipeline(数组,可选):用于限定值范围的前置筛选阶段;省略则返回全局值。lookback_minutes(整数,可选):默认值:15。start_time_iso/end_time_iso(字符串,可选):历史 RFC3339 时间边界;优先于lookback_minutes。region(字符串,可选)
get_trace_attribute_deviations
comparison_mode(字符串,必填):latency、errors或time。service_name(字符串,必填)environment(字符串,必填):精确的deployment.environment值。operation(字符串,可选)filters(数组,可选):Trace JSON 筛选条件。candidate_attributes(数组,可选):最多 8 个;省略则执行有界发现。latency_threshold_ms(数字,可选):latency模式必填;其他模式不接受。start_time_iso/end_time_iso(字符串,可选)lookback_minutes(整数,可选):默认值:15。最大值:15。baseline_start_time_iso/baseline_end_time_iso(字符串,可选):time模式必填;时间范围不得重叠,且时长须与目标窗口相同。minimum_cohort_size(整数,可选):默认值:100。最小值:20。minimum_value_support(整数,可选):默认值:20。最小值:10。limit(整数,可选):默认值:10。最大值:10。
需要启用配套的后端功能。
get_trace_waterfall
trace_id(字符串,必填)environment(字符串,可选)start_time_iso/end_time_iso(字符串,可选)lookback_minutes(整数,可选):默认值:4320(72 小时)。selected_span_id(字符串,可选):仅返回该 span 的属性、事件和链接。max_spans(整数,可选):默认值:500。最大值:1000;组织的脱敏策略可能会将上限设得更低。
原样返回 trace 服务的 investigation-evidence/v1 信封;瀑布图位于 data 下。服务会生成瀑布图,并在数据离开后端前,按照每个组织各自的策略对值进行脱敏(凭据、查询字面值、URL、电子邮件、IP、用户标识符):sanitizer 指明所执行的策略,evidence.sanitization 统计被脱敏或截断的内容。如果所需内容被脱敏,请让组织管理员调整策略,而不要尝试绕过策略。如果响应没有 sanitizer 块、sanitizer.version 不是 trace-evidence-sanitizer/v1、正文中重复出现 JSON 键,或正文超过 512 KiB(降低 max_spans),该工具将拒绝响应。需要启用配套的后端功能。
get_change_events
start_time_iso/end_time_iso(字符串,可选)lookback_minutes(整数,可选):默认值:60。service_name(字符串,可选)env(字符串,可选)event_name(字符串,可选):首次调用时不传此参数,以获取available_event_names。
analyze_change_impact
恰好传入 change_event 或 service + timestamp 其中一种。
change_event(对象,可选):get_change_eventschange_events[]中的一个元素,保持原样。使用metric.service、metric.deployment_environment和最早的values[].timestamp。service(字符串,可选):省略change_event时,必须与timestamp一起提供。timestamp(字符串,可选):RFC3339 或 Unix 秒数,向下取整到分钟。env(字符串,可选):精确环境。默认值:事件所属环境;否则为全部环境。baseline_minutes(整数,可选):默认值:60。限制在 30..120。after_minutes(整数,可选):默认值:baseline_minutes。限制在 30..120,且不晚于当前时间。
满足以下任一条件时,regression likely:服务或其吞吐量排名前 10 的调用方之一,错误率至少上升 1 个百分点、p95 至少上升 40%,或吞吐量(rpm)至少下降 50%;排名依据两个窗口合计的吞吐量(变更前至少有 100 个请求;对于吞吐量,还要求变更后至少有 100 个请求;p95 仅统计 latency_env 的请求);某个告警在变更后开始触发,并在变更后窗口结束时仍处于触发状态(按告警组名称或 service、service_name 或 service.name 标签进行不区分大小写的匹配;若无匹配,则检查注释,绝不匹配摘要等自由文本);提供 env 时,带有其他环境标签的告警(忽略大小写)会被排除,未标注环境的告警则标记为 env_match: unlabelled;或者发现来自 get_apm_service_deviations 的回归。若变更后窗口不足 5 分钟(包括变更发生在未来)、服务请求数过少,或黄金信号、直接调用方查询、告警或 get_apm_service_deviations 失败(全部失败或 deviations.apm.unavailable 中列出的任一查询失败),则为 insufficient data:证据缺失绝不会得出 no significant change;即使仍发现回归,也会注明失败项。no significant change 是有效结论,并非失败。仅当设置了 env 时才会运行 Trace 属性偏差分析,每侧最多覆盖 15 分钟;该分析用于解释结论,但不会决定结论,因此跳过或获取失败都不会改变结论。每个列表最多保留 10 项,并报告丢弃的数量;上游调用失败时,只会在对应部分留下一个 error。黄金信号延迟在两个窗口中均取自同一环境,该环境会在 latency_env 中注明:未提供 env 时,使用流量最大的环境。黄金信号错误率统计 5xx 和 gRPC 错误;deviations.apm 还会统计错误状态的 span 和 429。调用方信号取自其自身的服务器 span,因此仅有客户端 span 的调用方会显示 0 rpm。
regressions 会按 reason 的顺序,为 regression likely 背后的每个触发条件列出一项;对于其他结论则为 []。每项包含 service、role(changed 或 dependent)、env、metric(恰好为 error_rate_pct、latency_p95_ms、throughput_rpm、alert、apm_deviation 之一),以及以指标单位(%、ms、rpm 或 APM 信号自身的值;对于 alert 则为 null)表示的 baseline/after。alert 项还会添加 rule_id 和 state,表示该实例在变更后窗口中最新的、列出该实例的告警监控切片中的状态,始终为 firing:变更后开始触发、但在变更后窗口结束前已恢复的告警不算回归,因此不会创建工单;它仍会保留在 alerts.started 中,并带有其 state,而 reason 会统计它。env 表示测量指标所用的环境:若指定了 env,则使用该环境;否则,错误率和吞吐量汇总所有环境(env: ""),而 p95 使用流量最大的环境(latency_env);告警使用其自身的环境标签,APM 偏差则使用其自身的环境。所有回归都针对整个服务,因此不会指向任何端点。
get_alert_groups
用于 changeboard / 标签覆盖率审计的已配置 Compass 告警组清单。包括规则数为零的组和当前未触发的组。不返回 PromQL。
alert_group_name/alert_group_type/data_source_name(字符串,可选):不区分大小写的子字符串匹配。team/tier(字符串,可选):对已配置元数据进行不区分大小写的精确匹配。label_key+label_value(字符串,可选):必须同时设置。对一个metadata.labels键值对进行不区分大小写的精确匹配,键和值均须匹配。
返回精简 JSON {"count":N,"groups":[...]},包含 id、name、type、entity_class、team、tier、metadata.labels 和规则计数。空的 team / labels 表示未设置。
get_alert_operations_summary
start_time_iso/end_time_iso(字符串,必填):RFC3339 时间窗口,最长 31 天。timezone(字符串,可选):用于划分日期边界的 IANA 名称。默认值:UTC。severities/services(数组,可选):缩小摘要范围。include_rules(布尔值,可选):同时返回每条规则的健康状况(按fire_count排名前 20 的规则、频繁抖动和未路由规则;若 API 限制了规则列表,则包含truncated)。默认值:false。
返回包含 alerts_raised、acknowledged、unacknowledged、current_backlog、delivered、notification_outcomes、top_rules、needs_attention 和 coverage 的 JSON。每项指标均为 {status, count?, reason?};partial 计数仅覆盖窗口的一部分,并非下限。
get_alert_coverage
针对某个服务、环境、告警组,或在未指定范围时针对整个组织,回答“我有哪些内容尚未配置告警?”。只读:不会创建、修改或取消静默任何内容。也可通过 investigate 工具集调用。
service(字符串,可选):服务名称。environment(字符串,可选):部署环境(例如prod)。entity_id(字符串,可选):告警组(实体)UUID,由get_alert_groups返回。muted_days(整数,可选):整天数,范围为 1 到 3650。默认值:7;0 表示使用默认值。规则静默时间超过此值时,会被视为muted_too_long缺口。 数值会被去除首尾空白;空字符串会被忽略。缺口类型:uncovered_signal(latency、error_rate、throughput 或 saturation 上没有启用的规则;会指出一个可覆盖该信号的已禁用规则)、all_rules_disabled(规则全部已禁用的告警组)、no_notification_channel(其严重级别没有任何告警组路由渠道的规则)、muted_too_long(无限期静音或静音时间超过muted_days;muted_since是规则的最后更新时间;无限期静音时省略mute_until)。
返回精简 JSON {scope, generated_at, complete, summary, counts, groups}。groups 对每种存在的类型包含一个 {kind, count, gaps, omitted} 条目,每种类型最多列出 10 个缺口(其余数量由 omitted 统计;缩小范围以查看这些缺口);每个缺口包含 suggested_tool(create_alert、create_alert_from_chart、attach_notification_channel 或 patch_alert)和 suggested_args,其中仅包含该工具接受的输入(patch_alert:entity_id、id 和 is_disabled=false 或 mute_until=0;attach_notification_channel:alert_group_id 和一个 breach/threat severity;create_alert:entity_id;create_alert_from_chart:service_name);缺口自身的 entity_id、rule_id 和 signal 会列在旁边。仅当建议的工具在当前会话中可用且用户确认后,才调用该工具。只有当 API 未列出任何缺口、所有计数均为 0,且至少有一个告警组与范围匹配时,complete 才为 true(精确的 service_name / env 标签,根据 get_alert_groups 的列表进行检查);范围未匹配任何对象、查询失败或存在计数但未列出缺口,都不算完成;summary 会说明原因。
get_alert_config
search_term(string,可选):按名称、组、数据源和标签进行全文搜索。rule_name(string,可选)severity(string,可选)rule_type(string,可选):static或anomaly。alert_group_name/alert_group_type/data_source_name(string,可选)tags(array,可选):必须全部匹配(AND 逻辑)。
每条规则都会列出 Recent Evaluations:5 个一分钟采样点,按时间从新到旧排列,每个采样点标注其结束时的 UTC 分钟;最新采样点的结束时间比调用时间早 1–2 分钟,因为监控器会延迟填充最新的一分钟。firing;ok = 监控器报告该规则未触发(正常、已解决、待处理或空状态,如 is_firing=0 在 get_alert_rule_state 中所示);unknown = 没有该规则的监控器行(尚未评估,或该分钟的查询失败,响应顶部会注明),或者该行的状态不属于 firing、normal、resolved、pending 或 empty(例如 no_data、silenced)。已禁用的规则显示 none。匹配的已启用规则超过 25 条时,所有这些规则的历史记录都会省略,并且响应会说明这一点。
get_entity_kpis
只读;仅适用于 alerts 和 investigate 工具集。列出一个告警组中的所有 KPI,包括尚未被任何告警规则使用的 KPI。在 expression_args / indicators_used 中使用返回的 ID;切勿自行编造。
entity_id(string,必填):告警组/实体 UUID,来自get_alert_groups或get_alert_config。
返回按名称排序的 JSON {"entity_id","count","kpis":[{"id","name","description","query","unit"}]}。unit 是显示标签:阈值会与原始查询值进行比较。没有合适的 KPI 时,使用 create_kpi 创建一个。仅当会话提供该功能时,空组的结果才会列出 create_kpi;使用 --read-only(除非是 --allow-write-tools=create_kpi)或 investigate 工具集时,结果会说明 KPI 创建需要可写的 alerts 会话。
create_kpi
在现有告警组中创建 KPI;仅适用于 alerts 工具集。仅当 get_entity_kpis 中没有所需查询的 KPI 时才使用。先用 prometheus_range_query 检查查询是否返回数据:API 只会拒绝无法解析的查询,并会保存语法有效但对应指标不存在的查询。
entity_id(string,必填):告警组/实体 UUID。name(string,必填):在告警组内唯一;使用相同名称再次创建会因冲突而被拒绝。query(string,必填):PromQL。若要对仪表板面板设置告警,请从get_dashboard获取该面板的 PromQL。unit(string,必填):查询原始值的单位,例如seconds、ms、percent、ratio、count、req/s。它只是标签,不会进行任何转换,因此阈值会与原始值进行比较。description(string,可选)data_source_id(string,可选):默认为告警组的数据源。
没有 MCP 工具可以删除或编辑 KPI(请使用 Last9 UI),因此创建前请确认名称、查询和单位。只创建一次,并保留返回的 ID 以供 expression_args / indicators_used 使用;名称冲突时,请从 get_entity_kpis 复用现有 KPI 的 ID。发生超时或连接错误时,创建操作可能已生效,也可能未生效:重试前先用 get_entity_kpis 按名称检查。返回 {"id","name","query","unit"}。
get_alerts
time_iso(string,可选):RFC3339 格式的评估时间。window(integer,可选):回溯秒数。默认值:900。范围:60–86400。lookback_minutes(integer,可选):范围:1–1440。
get_alert_rule_state
start_time(integer 或 string,必填):范围起点(包含):Unix 纪元秒数(1718000000)或 RFC3339(2024-06-10T06:13:20Z)。Unix 纪元毫秒、微秒和纳秒会转换为秒;早于 2000-01-01 的值会被拒绝。end_time(integer 或 string,必填):范围终点(包含),格式相同。step(integer,必填):采样间隔秒数。采样数((end_time - start_time) / step + 1)上限为 100。每个采样点都是一次上游调用,覆盖以其时间戳为终点的min(step, 3600)秒;每次获取 5 个采样点,如果耗时超过 60s,工具会返回错误并提供重试指引。alert_group_id(string,可选):按告警组 ID 筛选。rule_name(string,可选):按规则名称进行正则表达式筛选。alert_group_name(string,可选):按告警组名称进行正则表达式筛选。label_filters(string,可选):以逗号分隔的key=value标签筛选条件。state(string,可选):按状态筛选(例如firing)。
返回 rule_id -> [{timestamp, is_firing}] 的 JSON 映射。上游响应中缺少某条规则的时间戳会报告为 is_firing=0 ——这表示“未观察到正在触发”,而非已确认处于正常状态。
get_alert_hygiene
对已启用告警规则进行只读审计。不会更改任何内容:每项建议修复都只是提案,只有用户明确确认后,才会通过 update_alert(调整)、patch_alert(is_disabled)、delete_alert 或 attach_notification_channel 应用(前提是这些工具可用)。
window(string,可选):7d或30d。默认值:7d。limit(integer,可选):返回的标记规则数量上限,按问题严重程度从高到低排列。默认值:20。范围:1–100。
时间窗口截至当前。类别(同一规则可能属于多个类别):noisy(每天触发 ≥ 5 次,且 < 20% acked; with an unavailable ack_rate it is judged on fire rate alone and the reason says so; mute time is not reported), flapping (> 每天抖动 4 次)、stale(上次触发时间早于窗口且窗口内没有触发时间;或者已启用的已配置规则在窗口内没有事件,且生命周期 coverage 已完成、API 返回的列表未被截断)、unrouted(窗口内没有任何触发到达渠道,且告警组当前未关联任何渠道;无法读取关联信息时,该规则会归入 unavailable.routed)。每项统计值为 {status, count|value, reason} 或 null:不可用的值绝不会被视为 0,且只会跳过依赖该值的检查;unavailable 会统计每种缺失值对应的已启用规则数量(fire_count、flap_count、ack_rate、routed、rule_config 表示规则未出现在告警规则列表中,因此其修复建议不包含当前值;activity 表示已配置但没有事件的规则,其静默状态无法通过历史记录证实,因此不会进行评估)。coverage 说明告警历史覆盖了多长的窗口;速率按已覆盖时长计算,且至少为一天。若 API 仅返回最响亮的 200 条规则,则 upstream_truncated 为 true,因此较安静的规则不会被评估。修复建议基于告警规则列表中的各规则配置生成:提高 bad_minutes(count_true(result) >= N 中的 N)或延长 eval_window(最长 60 分钟);对于嘈杂的静态阈值,将阈值调整到 condition(expr > 100),或将表达式切换为 adaptive_std_cmp(metric, sensitivity, window);关联通知渠道;禁用或删除过时规则。
返回精简 JSON {window, from, to, coverage, upstream_truncated, rules_evaluated, flagged_rules, truncated, omitted_for_size, unavailable, rules},目标大小为 32 KB:当标记规则数量超过 limit 或该大小目标时,truncated 为 true;omitted_for_size 统计因大小限制而从 limit 中删去的规则数量(始终保留问题最严重的规则,因此单条规则超过 32 KB 时会单独返回,并超出目标大小);每条规则包含 findings(category、reason、suggested_fix、可选的 alternative_fix)以及原始的 stats。
get_notification_channels
scope(string,可选):attached(默认)会为每个告警组关联项返回一行;id是关联项 ID,由detach_notification_channel使用。channels会返回组织的渠道(id、name、type、send_resolved、created_via);id是渠道 ID,由attach_notification_channel使用。绝不会返回目标地址、标头或证书。
以 TSV 表格形式返回已配置的通知渠道(Slack、PagerDuty、电子邮件、webhook 等)。关联项行(已设置 service_fqid)会显示 global 为 false,且 services 为 -;services 仅列出旧版服务绑定。在关联项行中,send_resolved 是该行存储的默认值,而非实际投递所用的值;解决通知遵循渠道自身的 send_resolved(scope=channels)。两个范围都包含 created_via(由 MCP 代理创建的行显示 last9-mcp,否则显示 -)。
recommend_alert_config
只读。返回生命周期指导、验证门槛和响应人员上下文要求;这些内容本身并非证据,因此应使用遥测工具来确定阈值。
signal(string,必填):指标或用户影响信号,包括单位和维度。objective(string,必填):要检测的症状或用户影响。rule_type(string,可选):static(默认)或anomaly。severity(string,可选):breach(默认)或threat。environment(string,可选):环境和流量特征。
validate_alert_expression
对表达式进行试运行,不会保存。请在 create_alert / update_alert 之前使用。
entity_id(string,必填):告警组/实体 UUID。expression(string,必填):对以 KPI 精确名称命名的指标进行算术运算,例如errors / requests。最多 3 个指标。名称中包含空格、点或连字符时,按原样书写(Test Alert / errors),与create_alert保存的名称完全一致。indicators_used(object,必填,非空):指标名称到 KPI UUID 的映射;这些 KPI 归属于entity_id;使用get_entity_kpis列出该组的 KPI ID 和名称。使用每个 KPI 的精确名称:此试运行接受任意名称,但create_alert和update_alert会拒绝键名不是所绑定 KPI 名称的expression_args。 仅检查算术表达式(传入内部指标表达式,而不是adaptive_std_cmp(...)包装器);不检查condition/alert_condition。仅当使用多个指标时,才会执行至少一个时间序列检查。
返回 {"valid":true} 或 {"valid":false,"reason":"..."};无效表达式是正常结果,不是工具错误。
describe_alert_chart
只读。列出受支持的 Discover 图表上的可告警信号(key、unit、eval_query、query_kind)。拒绝查看者角色令牌。
surface(字符串,必填):discover-service或discover-exceptions;包括自定义仪表板在内的任何其他界面都会在调用 API 前被拒绝(改用create_alert并指定 KPI)。chart_key(字符串,必填):例如apdex、error_rate、response_time、exception_count。service_name(字符串,必填)env(字符串,可选)attributes(对象,可选):额外的身份维度,使用此工具报告的键名。
create_alert
在现有告警组中创建规则,始终处于禁用状态(草稿,即使传入 is_disabled=false 也是如此)。先调用 recommend_alert_config,仅在用户确认后再通过 patch_alert is_disabled=false 启用。只创建一次并保留返回的规则 ID。如果告警组已使用 rule_name(不区分大小写),则拒绝创建任何内容,并指出现有规则的 id。
entity_id(字符串,必填):告警组/实体 UUID。alert_rule(对象,必填):完整的类型化规则正文,包括绑定到实体真实 KPI 的primary_indicator和expression_args。每个expression_args键都必须是其绑定 KPI 的确切名称(不能是x之类的占位符),并且primary_indicator和expression使用这些名称。静态规则需要condition、alert_condition和eval_window(0–60 分钟)。自适应规则使用expression=adaptive_std_cmp(<primary_indicator>, sensitivity, window);此时这三个字段均为可选项(默认值为expr > 0、count_true(result) >= 1、1)。不能设置algorithm。响应者上下文放在properties中(描述、运行手册、注释、query_mode)。
通知路由配置在告警组上,而不是规则上。
create_alert_from_chart
根据 describe_alert_chart 描述的图表创建静态阈值规则。与 create_alert 一样,规则创建后会处于禁用状态,作为草稿且不会触发;仅在用户确认后通过 patch_alert is_disabled=false 启用。图表 API 创建的规则默认启用,因此此工具会在创建后立即禁用规则;如果禁用失败,结果会报错并指出规则 id,该规则可能仍处于启用状态。
surface/chart_key/service_name/signal_key/name(字符串,必填)env(字符串,可选)attributes(对象,可选)threshold(数字,可选):使用信号的单位;必须大于或等于 0。Apdex 等评分单位信号需要显式指定值。threshold_operator(字符串,可选):>(默认值)、<、>=、<=、==、!=。eval_window(整数,可选):分钟,1–60。默认值:5。bad_minutes(整数,可选):1–eval_window。默认值:3。severity(字符串,可选):breach或threat。description(字符串,可选)group_id(字符串,可选):通常省略。
update_alert
完整替换规则的评估配置。先通过 get_alert_config 或 get_entity_alert_rules 获取规则。如果规则不存在或属于其他告警组,则拒绝操作且不做任何更改。此操作可能会软删除并重新创建规则,因此之后请使用返回的替换规则 ID。
entity_id(字符串,必填)id(字符串,必填):告警规则 UUID。alert_rule(对象,必填):完整配置;结构与create_alert相同。
patch_alert
部分更改,保留规则 ID。至少需要进行一项更改。如果规则不存在或属于其他告警组,则拒绝操作且不做任何更改。
entity_id(字符串,必填)id(字符串,必填):告警规则 UUID。is_disabled(布尔值,可选):false会启用规则,true会暂停规则。mute_until(整数,可选):Unix 纪元截止时间;0会取消静音。properties(对象,可选):description、runbook、annotations、query_mode。每个已发送字段都会替换已存储的对应字段;省略或留空的字段保留其已存储值。annotations会替换整个映射,因此要保留现有内容,请发送所有键;{}会清除该映射。recurring_mute_schedule(对象,可选):替换每周计划:enabled(默认值为 false)、timezone(IANA 名称,必填)以及windows(weekdays中的 1–20 个时间段,格式为sun..sat,start_time/end_time使用 24 小时制的HH:MM)。结束时间早于或等于开始时间时,结束时间视为次日。要保留所有时间段,请全部发送。clear_recurring_mute_schedule(布尔值,可选):完全移除计划;不能与recurring_mute_schedule同时使用。与enabled=false不同,后者会保留已存储的时间段。
查看者角色用户只能更改 mute_until。当组或实体处于静音状态时,拒绝更改规则级静音设置。使用 get_entity_alert_rules 读取更改后的状态,其中会显示 mute_until、recurring_mute_schedule 和 properties。
delete_alert
永久删除规则。先通过 get_alert_config 验证,并取得用户的明确确认。如果规则不存在或属于其他告警组,则拒绝删除任何内容。
entity_id(字符串,必填)id(字符串,必填):告警规则 UUID。
mute_alert_group
将组中所有当前规则和未来规则设为静音;若要将单条规则设为静音,请使用带有 mute_until 的 patch_alert。需要编辑者权限。
entity_id(字符串,必填):告警组/实体 UUID。until(整数,必填):静音结束时的 Unix 纪元秒数。0会取消静音;负值(例如-1)表示无限期静音。
acknowledge_alert
接管正在触发的告警,或释放该告警。不会解决或静音告警。确认自己已拥有的告警是安全的空操作。除非 get_alerts 在过去一小时内列出了该确切告警(全部三个 ID),否则 ack 会拒绝操作且不记录任何内容。
alert_group_id/rule_id/rule_type(字符串,必填):从get_alerts中的告警复制。action(字符串,可选):ack(默认值)或unack。只有所有者或组织管理员可以取消确认。mute_until(整数,可选):仅限ack。记录你已通过mute_alert_group或patch_alert应用的静音;不会执行静音操作。
reassign_alert
将已有所有者的告警转交给另一位用户;如果告警没有所有者,请先确认该告警。如果告警没有所有者而未能转交,工具会说明 get_alerts 是否在过去一小时内列出过该告警。Last9 不会通知新所有者。
alert_group_id/rule_id/rule_type(字符串,必填):从get_alerts中的告警复制。owner_email(字符串,可选):优先使用;与活跃组织用户进行不区分大小写的匹配。owner_user_id(字符串,可选):必须且只能提供owner_email或owner_user_id之一。
create_notification_channel
创建通知渠道;在通过 attach_notification_channel 关联之前,该渠道不会路由任何通知。只创建一次并保留 ID;没有更新工具。仅返回 id、name、type 和 send_resolved。
name(字符串,必填):在同一类型中必须唯一;不能包含冒号。type(字符串,必填):slack、pagerduty、opsgenie、email或generic_webhook。destination(字符串,必填):Slack Incoming Webhook URL(或使用slack_app_mode时的频道 ID)、PagerDuty 路由密钥、Opsgenie API 密钥、以逗号分隔的工作邮箱地址(可使用任何域名,不限于组织的域名;API 会拒绝 Gmail 等个人邮箱服务提供商的地址,而使用个人账号登录的组织只接受其管理员的地址),或 HTTPS webhook URL。slack_app_mode(布尔值,可选):仅限 Slack。默认值:false。mention_handles(字符串,可选):以逗号分隔,例如user|U123ABC|name、special|here、special|channel。webhook_headers(对象,可选):仅限generic_webhook。webhook_ca_certificate(字符串,可选):仅限generic_webhook;一个 PEM CA 证书,最大 64 KiB。send_resolved(布尔值,可选):默认值:true。
attach_notification_channel
将现有渠道路由到一个告警组。此操作具有幂等性。关联项会在关联时复制渠道的投递设置(标头、证书、提及);如果之后更改了渠道设置,请重新关联。
channel_id(整数,必填):渠道 ID(使用scope=channels时的get_notification_channels),而不是关联 ID。alert_group_id(字符串,必填):来自get_alert_groups。severity(字符串,必填):breach、threat或both。both会创建两个关联;如果第二个失败,第一个仍会保留,错误会指出需要重试的严重级别。
detach_notification_channel
移除一个关联。需要具有删除范围的令牌;写入范围的令牌无法解除关联。
attachment_id(整数,必填):使用scope=attached时,来自get_notification_channels的id。拒绝渠道 ID。alert_group_id(字符串,可选):如果该关联属于其他组,则拒绝操作。
delete_notification_channel
永久删除没有任何关联的渠道;请先解除其关联。需要具有删除范围的令牌。通过重新列出渠道来确认删除。
channel_id(整数,必填):使用scope=channels时,来自get_notification_channels的id。拒绝关联 ID。
did_you_mean
query(字符串,必填):要搜索的名称——可以是不完整、拼写错误或缩写形式。type(字符串,可选):按实体类型筛选:service、environment、host、database、k8s_deployment、k8s_namespace、job。
最多返回 3 个最接近的匹配项及其相似度分数。实体名称不确定时,在调用任何工具前使用此工具。如果之前的调用返回空结果,请在重试前使用此工具。
get_service_profile
service_name(字符串,必填):要为其推导遥测配置文件的服务。datasource(字符串,可选):数据源名称。默认数据源可省略;近似名称的解析方式与 Prometheus 工具相同。 返回简短的调查摘要,后接原始 JSON 格式的完整配置文件:信号是否存在(logs/traces/metrics,分别表示present、absent或unknown)、语言和运行时、部署环境、日志signal_shape(log_format、severity_set、level_field、trace_context_in_logs),以及适用时建议的摄取修复方案。当后端报告freshness时,摘要会添加一行last seen,其中包含freshness.logs.last_seen和freshness.traces.last_seen(RFC3339;为 null 时使用none);当freshness.traces_stale为true时,还会添加traces stale警告:跨度已停止而日志仍在继续,因此应调查freshness.traces.last_seen附近的回归问题,而不是缺少配置。数据源自上游并经过缓存,TTL 约为 15 分钟。
在进行任何特定服务的调查之前调用此工具,以便工具选择与服务的实际遥测数据相匹配——当 traces 为 absent 时跳过跟踪工具;当 severity_set 为 none 或 partial 时,从日志正文中的 level_field 解析严重性,而不要使用 severity_filters。metrics 始终为 unknown,且 v1 中不会填充 dependencies。当 logs 和 traces 均为 absent 时,请先通过 did_you_mean 确认名称,再断定该服务未受监控。
list_dashboards
name(字符串,可选):仪表板名称中不区分大小写的子字符串。用于缩小列表范围并total。limit(整数,可选):每页仪表板数,1–200。默认值:100。cursor(字符串,可选):上一页的next_cursor;传入时需同时传入相同的name。
返回 {"dashboards": [{"id", "name", "updated_at", "created_by", "locked"}], "total", "next_cursor"},按最近更新时间从新到旧排列。为空时省略 created_by;API 未报告 readonly 时省略 locked。updated_at 是以字符串表示的 Unix 纪元秒数。为保持在 32 KB 以内,页面可能提前结束;最后一页不包含 next_cursor。
get_dashboard
id(字符串,必填):仪表板 UUID。region(字符串,可选):用于填充面板查询的区域。默认为已配置的数据源区域。
结果会添加顶层字段 locked(API 未提供时为 false)和 created_by(作者的用户 ID)。
如需为面板设置告警,请参阅 last9://reference/alerting。
validate_dashboard
只读。绝不会创建或更新仪表板。必须且只能提供 dashboard_id 或 dashboard_definition 其中之一。
dashboard_id(字符串,可选):要验证的已保存仪表板 UUID。dashboard_definition(对象,可选):内联的未保存仪表板正文(真正的试运行)。如果传入{dashboard, metadata}创建封装对象,则会解包其dashboard对象。start_time_iso/end_time_iso(字符串,可选):验证时间范围(RFC3339)。必须 ≤ 24h。region(字符串,可选):执行面板查询的区域。
返回 dashboard_validation/v1:逐面板的 lint + 执行分类(data / no_data / invalid / error)。首日的空结果会分类为 valid_no_data,不会执行诊断探测。没有面板的仪表板会返回 success: false 和 error: "no_panels"。其他格式中的面板字段(Grafana 的 gridPos、title、type,以及需要查询的面板上的 targets)和类型错误的字段会按面板列在 shape_problems 中,在 summary.panels_invalid_shape 中计数,并使 overall 变为 fail。
preview_dashboard
只读的客户端预览。传入 dashboard(创建请求中的未保存仪表板对象),或传入 id 和 ops(与 patch_dashboard 相同顺序的操作)。必填的 start_time_iso 和 end_time_iso 是 RFC3339 时间戳,跨度最多为 24 小时。可选的 variables 包含标量覆盖值;否则使用仪表板值和内置默认值。
{
"id": "dashboard-id",
"ops": [{"op": "update_panel", "panel_id": "panel-id", "fields": {"name": "Request latency"}}],
"start_time_iso": "2026-10-01T08:00:00Z",
"end_time_iso": "2026-10-01T09:00:00Z"
}
返回 saved: false、定义/查询 validation 摘要(包括创建架构不匹配时的 definition_error),以及包含 ok / empty / error 状态、已解析查询和目标诊断信息的 panels。PromQL 和 LogJSON 会执行;不支持的查询类型和无法解析的变量会使面板报错。有效的非查询面板为 ok;无效的面板定义为 error。补丁 diff 包含净 panels_added、panels_changed(包括移动)和 panels_removed,以及按顺序排列的操作变更。ID 和从零开始的索引用于标识面板;已移除面板的索引指向原始仪表板。已保存的面板必须具有互不相同且非空的 ID。
限制:50 个面板、100 个查询、100 个操作;输入和候选仪表板的 JSON 字节数各不超过 65536;执行时限为 60 秒。超过 65536 个 JSON 字节的已解析查询会在执行前被拒绝。每个目标最多保留三个样本和 1024 个 JSON 字节;省略样本时会包含 truncated: true。超过 262144 字节的 JSON 报告会失败,并提示缩减输入。
不会创建或更新任何仪表板。此操作会根据创建架构检查候选内容,并使用现有验证器执行查询;但不能保证后端接受或正确渲染。后端分配的 ID、默认值、被丢弃的字段或并发编辑都可能改变保存结果。预览使用与写入相同的本地补丁操作和面板版本默认值。
create_dashboard
仅用于新建。此调用返回 dashboard.id 后,请使用 patch_dashboard 编辑面板(或使用 update_dashboard 调整结构)——不要再次创建仪表板来添加、精简或修复面板。
dashboard(对象,必填):包含name和panels[]的仪表板定义。每个面板都必须包含name、version、layout(x、y、w、h)、visualization.type和queries[]。metadata(对象,可选):仪表板元数据字段——_category和_type(例如{"_category":"custom","_type":"metrics"})。
update_dashboard
仅用于重构仪表板的大部分内容;如需添加、编辑、移除或移动单个面板,请使用 patch_dashboard。按 ID 完整替换(正文与创建时相同):必须重新发送每个面板。
id(字符串,必填):要更新的仪表板 UUID。dashboard(对象,必填):完整替换用的仪表板正文(结构与创建时相同)。metadata(对象,可选):替换用的元数据。只读系统仪表板会返回可恢复的工具错误。
patch_dashboard
小幅调整时优先使用此工具,而不是 update_dashboard:不会重新发送未更改的面板。读取仪表板,按顺序应用 ops,然后写回;因此,在读取和写入之间由其他位置进行的编辑会被覆盖。返回 {dashboard_id, changes[]};仪表板已满足的操作会被省略,如果没有任何变更,则不会写入。写入后会通过重新读取来检查差异:面板 fields 显示已存储的值,not_stored 列出 API 丢弃的键,not_removed 列出 API 在收到 null 后仍保留的键。超过 200 个字符的差异值会原地缩短,同时保留其 JSON 类型。
id(字符串,必填):要修补的仪表板 UUID。ops(数组,必填):按顺序应用的操作;如果任何操作无效,则不会写入,并会在错误中将其标记为ops[i]。add_panel:panel(完整面板对象;version默认为 1),可选的index(从零开始的插入位置,默认追加)。update_panel:panel_id、fields(要替换的顶层面板键;null会移除键;id不可更改)。remove_panel:panel_id。move_panel:panel_id、index(移动后的从零开始的位置)。set_title:title(仪表板名称)。set_variable:variable;替换具有相同target的变量,否则追加。
delete_dashboard
id(字符串,必填):要删除的仪表板 UUID。无法删除只读系统仪表板。
set_dashboard_lock
id(字符串,必填):仪表板 UUID。locked(布尔值,必填):true会锁定仪表板,false会解锁仪表板。
写入工具;仅在用户明确提出要求时调用。只有仪表板作者或组织管理员可以锁定或解锁仪表板,内置仪表板始终为只读。返回包含最终状态的 {"id", "locked"}。锁定期间,update_dashboard、patch_dashboard 和 delete_dashboard 不会发送写入请求,并会返回可恢复的工具错误;错误以 dashboard is locked 开头,指出作者,并建议解锁或使用 create_dashboard 复制仪表板。
list_dashboard_snapshots
dashboard_id(字符串,必填):要列出快照的仪表板 UUID。
仅返回元数据(id、name、expires_at 等)。如需获取冻结的面板数据,请使用 get_dashboard_snapshot。
get_dashboard_snapshot
id(字符串,必填):快照 UUID。
返回完整的冻结快照,包括 dashboard_definition、panel_data、time_range 和 variables。
delete_dashboard_snapshot
id(字符串,必填):要删除的快照 UUID。
get_profile_services
lookback_minutes/start_time_iso/end_time_iso(可选):时间范围;优先使用回溯时长或明确的 ISO 边界(默认 60m)。region(字符串,可选):区域覆盖值。
返回在该时间范围内有性能分析数据的服务。在调用 get_flamegraph / get_top_functions / get_profile_summary 之前先调用此工具。
get_flamegraph
service(字符串,必填):来自get_profile_services的服务名称。profile_type(字符串,可选):cpu(默认值)、alloc或wall。比较不同时间范围时请固定类型。env/cluster/namespace/runtime(字符串,可选):范围筛选条件。limit(数字,可选):聚合堆栈行数上限(默认 1000,最大 10000)。lookback_minutes/start_time_iso/end_time_iso/region(可选)。
返回嵌套的火焰图树(name / value / self / children)。truncated: true 表示已达到 API 行数上限。
get_top_functions
筛选条件与 get_flamegraph 相同。返回按自身采样数排序的热点函数。结果可能被截断;请检查 truncated。
get_profile_summary
筛选条件与 get_flamegraph 相同。返回针对该服务性能分析数据的简短自然语言分诊摘要。
grafana_search_dashboards
query(字符串,可选):标题子字符串。为空时会广泛列出(受 5,000 行上限约束)。
返回包含 uid、title、uri、url、type、tags 的 {"dashboards":[…], "truncated":bool}。请将 uid 与 grafana_get_dashboard 配合使用。
grafana_get_dashboard
uid(字符串,必填):Grafana 仪表板 uid。full_json(布尔值,可选):为 true 时,返回原始 Grafana JSON,而不是经过筛选的摘要。
默认摘要:版本、标签、模板变量,以及每个面板的类型/数据源/gridPos/promQL 目标。未知的插件面板类型会显示在 unsupportedPanelTypes 中。
grafana_list_folders
无参数。返回文件夹树。
grafana_list_folder_dashboards
folder_uid(string, required): Grafana 文件夹 uid。
返回该文件夹中仪表板的 {"dashboards":[…], "truncated":bool}(分页,最多 5,000 个)。
grafana_list_datasources
无参数。返回数据源的安全投影(不包含凭据字段)。
测试
运行测试 goroutine 分析器,但不执行应用程序测试:
make lint-test
这会对所有软件包运行 Go 的 testinggoroutine 分析器,包括其
*_test.go 文件,并使用不安全和安全的测试样例进行检查。两个 CI 测试
工作流都会将 go vet -testinggoroutine ./... 作为单独步骤运行,因此缓存的
软件包测试结果无法绕过 lint 检查。
根软件包也会将该分析器作为测试运行。使用 go test -count=1 ./...
运行完整测试套件并禁用该检查的缓存:Go 的测试缓存不会跟踪分析器子进程读取的
内部软件包源文件。修改这些文件后,普通的
go test ./... 可能会复用根测试之前通过的结果。
Fatal、Fatalf 和 FailNow 在 testing.T 或 testing.B 上必须在
父测试 goroutine 中运行。工作线程应将错误发送回父线程,以便父线程进行断言:
errs := make(chan error, 1)
go func() { errs <- doWork() }()
if err := <-errs; err != nil {
t.Fatal(err)
}
该分析器会捕获 go func 闭包中的直接调用;它不是通用的跨过程检查,无法检测隐藏在任意辅助函数调用后的断言。
除非设置了 TEST_REFRESH_TOKEN,否则集成测试会跳过。
