内容
# 侦察员MCP
> 한국어文档请参考 [README.ko.md](README.ko.md)。
一个直接连接到Scouter Collector的stdio MCP服务器,通过TCP查询XLogs、计数器和对象。其目的是让AI快速探索Scouter指标并诊断根本原因。每个结果都带有`txid` / `gxid` / `objName` / `endTimeIso`,您可以用这些作为键与OpenSearch或Datadog等其他可观察性工具进行交叉分析。
## 架构
Java 17。它重用了`scouter-common`并将`scouter.webapp`的net/server类移植到了`scouter.mcp.client`包中。MCP使用Java SDK 2.0.0的stdio传输。所有对Collector的操作都是只读的。
## 构建
```bash
./gradlew shadowJar
# 输出:build/libs/scouter-mcp-<version>-all.jar
```
`.mcpb`包仅由发布CI(它封装了此jar)生成;本地构建只生成jar。
## 注册(Claude Code,Claude Desktop,...)
对于单个Collector,从 [GitHub Release](../../releases) 安装`.mcpb`包以进行一键设置 - 或者复制`.mcp.json.example`,指向fat jar(从发布或本地构建下载),并填写凭证。对于多个Collector,请参阅[多个Collector](#多个Collector)。
| 环境变量 | 描述 |
|---|---|
| `SCOUTER_COLLECTOR_HOST` | Collector主机 |
| `SCOUTER_COLLECTOR_PORT` | Collector TCP端口(默认为6100) |
| `SCOUTER_USER` | 登录用户 |
| `SCOUTER_PASSWORD` | 登录密码 |
| `SCOUTER_TZ` | 时区(例如`Asia/Seoul`) |
| `SCOUTER_LOCALE` | 面向用户的消息区域:`en`或`ko`。如果未设置,则根据JVM默认设置(仅当JVM语言为韩语时为韩语,否则为英语) |
| `SCOUTER_INCLUDE_BIND_PARAMS` | `get_xlog_detail`中SQL绑定参数的运算符杀死开关(默认为`true`)。设置为`false`以在服务器端剥离绑定参数,无论每个调用的参数如何 - 不允许LLM重新启用它们。在绑定值可能包含PII时使用。 |
### 多个Collector
官方发布版附带**一个**`.mcpb`包(一次性安装,一个Collector)以及独立的fat jar。`.mcpb`定义了具有一组凭证的服务器,因此它不能一次注册两个Collector。对于多个Collector(通常具有不同的连接集(主机/端口**和**用户/密码)),直接使用jar并为每个Collector添加一个条目:
1. 从 [GitHub Release](../../releases) 下载`scouter-mcp-<version>-all.jar`。
2. 为客户端配置文件(`.mcp.json` / `claude_desktop_config.json`)添加每个Collector的`mcpServers`条目,全部指向同一个jar,每个条目都有自己的环境变量集。这样可以隔离每个凭证:
```json
{
"mcpServers": {
"scouter-prod": {
"command": "java",
"args": ["-jar", "/ABSOLUTE/PATH/scouter-mcp-<version>-all.jar"],
"env": {
"SCOUTER_COLLECTOR_HOST": "prod-collector", "SCOUTER_COLLECTOR_PORT": "6100",
"SCOUTER_USER": "prod-user", "SCOUTER_PASSWORD": "***", "SCOUTER_TZ": "Asia/Seoul"
}
},
"scouter-stg": {
"command": "java",
"args": ["-jar", "/ABSOLUTE/PATH/scouter-mcp-<version>-all.jar"],
"env": {
"SCOUTER_COLLECTOR_HOST": "stg-collector", "SCOUTER_COLLECTOR_PORT": "6100",
"SCOUTER_USER": "stg-user", "SCOUTER_PASSWORD": "***", "SCOUTER_TZ": "Asia/Seoul"
}
}
}
}
```
然后,AI会跨Collector进行协调。
## 工具(14)
| 名称 | 目的 | 关键输入 |
|---|---|---|
| `list_objects` | 列出对象/代理 | `objType?`,`nameLike?`(不区分大小写) |
| `search_xlog` | 搜索XLogs(延迟/错误) | `from`,`to`,`objNameLike?`,`objHash?`,`service?`,`login?`,`ip?`,`desc?`,`minElapsedMs?`,`onlyError?`,`limit?`(默认为20,最大200) |
| `get_service_summary` | 按服务聚合(计数/平均值/最大值/ p95/错误率),前50名 | `from`,`to`,与`search_xlog`相同的过滤器 |
| `get_summary` | Collector的每日预聚合统计(前50名SQL/服务/错误/... - 无扫描) | `category`(服务/SQL/API调用/IP/用户代理/错误/警报),`from`,`to`(最多31天),`objType?`,`objNameLike?`,`objHash?` |
| `get_xlog_detail` | XLog详情(SQL/绑定参数) | `txid`,`date?`/`at?`,`includeBindParams?`(默认为true) |
| `get_xlog_by_gxid` | 分布式事务组 | `gxid`,`date?`/`at?` |
| `get_counter` | 计数器时间序列(当天,全分辨率) | `objNameLike`\|`objHashes`\|`objType`,`counter`,`from`,`to` |
| `get_counter_stat` | 长期计数器统计(5分钟分辨率,最多31天) | `objNameLike`\|`objHashes`\|`objType`,`counter`,`from`,`to` |
| `list_counters` | 对象类型可用的计数器 | `objType` |
| `list_alerts` | 过去的Collector警报 | `from`,`to`,`level?`,`object?`,`key?`,`limit?` |
| `get_active_services` | 当前正在运行的服务 | `objNameLike`\|`objType`\|`objHash` |
| `list_threads` | JVM线程列表(状态直方图 + 按CPU前50名) | `objNameLike`\|`objHash`(最多5个活动实例) |
| `get_thread_detail` | 活动事务的实时线程(堆栈/锁所有者/当前SQL) | `txid`(必需,活动),`id?`,`objNameLike`\|`objHash` |
| `get_object_env` | 代理JVM系统属性(屏蔽秘密) | `objNameLike`\|`objHash`,`keyLike?` |
### 模糊定位(`objNameLike`)
用户说应用程序名称片段(“shop-order-api”),但实际的objNames嵌入了k8s pod名称(`/shop-order-api-deployment-5f4b8c7d9-abcde/shop-order-api1`),因此objHash在每次部署时都会更改,并且应用程序跨多个实例运行。`objNameLike`解决了这个问题:不区分大小写的片段解析为**所有**匹配实例(首先是活动实例,最高20个),并跨实例查询 - 不需要objHash。 对于XLog搜索/摘要,解析还联合了Collector的每日对象DB,因此在查询窗口期间被部署替换的pod仍然可以找到。 如果没有匹配,则错误为`NOT_FOUND`,并带有`candidates`提示,列出实际的objNames,以便调用者可以一步纠正。
### 粗略的服务查询
Scouter服务名称类似于`/api/order/.../search-order-info-grade<POST>`,但用户输入“GET orderDetail”或“order info grade”。 `service`过滤器标准化了此类输入:从任何位置提取HTTP方法(`GET x`,`x POST`,粘贴的`<POST>`),空格分隔的单词默认为最长的令牌服务器端,显式`*`模式不修改。 服务器端匹配仍然区分大小写 - 因此当模式不匹配任何内容时,将在没有服务过滤器的情况下重新扫描(有界)窗口,并返回与查询令牌不区分大小写匹配的实际服务名称作为`serviceCandidates`,按流量排序。一次重试使用确切的名称来解决它。
`service`/`login`/`ip`/`desc`默认情况下使用子字符串匹配(服务器端`StrMatch`),因此像`search-order-info-grade`这样的短令牌与`/api/order/ext/order-info/search-order-info-grade<POST>`相匹配。 `objNameLike`/`login`/`ip`/`desc`被视为服务器端过滤器,因此它们放松了5分钟无过滤窗口上限。 `list_counters`还接受`objNameLike`并派生对象类型,因此用户永远不需要了解Scouter的类型分类。
所有工具都带有`readOnlyHint`广告。 `diagnose_root_cause` MCP提示公开了延迟/错误调查的推荐工具顺序。
## 资源/令牌安全策略
生产Scouter可以在五分钟内生成数十万个XLogs,因此`search_xlog`强制实施了防护措施(参见`scouter.mcp.policy.Limits`):
- 在流式传输过程中,如果达到`limit`或扫描上限(5,000个检查包),则停止并关闭套接字,这也停止了Collector的扫描/传输 - 绑定服务器负载,网络和MCP堆。
- 没有`service`或`objHash`过滤器,仅允许最多5分钟的窗口;绝对窗口上限为24小时。
- `limit`默认为20,最高可达200。 结果包含`truncated`/`scanCapReached`和一个`hint`,以便调用者可以缩小过滤器而不是重新获取。
- `get_service_summary`不保留行(仅服务计数器),因此它使用更高的扫描上限(200,000)来廉价地覆盖更广泛的窗口;它还报告`scanCapReached`/`examined`。
- `get_counter`限制每个`objType`的扇出数量为20个实例,并使用min/max方案压缩长序列以保留峰值/下降(汇总`min`/`max`/`avg`从完整序列中计算)。
- 跨越午夜的窗口按日历日分隔(Collector按日分区XLogs/计数器/警报),因此在边界两侧不会丢失任何数据。
- 响应文本预算:SQL文本在1,500个字符处剪切,错误消息在500个字符处剪切,线程堆栈跟踪在4,000个字符处剪切,环境值在500个字符处剪切 - 每个都带有截断标记,显示原始长度。 `get_xlog_detail`配置文件步骤在150处被限制,通过`totalSteps`/`stepsTruncated`发出信号。
- 单个请求最多可扩展到40个Collector往返(实例x天段)。 当客户端过滤器(`minElapsedMs`/`onlyError`)丢弃超过99%的扫描行时,低选择性提示会引导模型转向服务器端过滤器或`get_summary`。
- `get_summary`/`get_counter_stat`读取Collector的每日预聚合数据(无扫描),最高可达31天;摘要返回每个类别的前50行。 `list_threads`限制为5个活动实例和每个实例50个线程行(状态直方图始终涵盖所有线程)。
- 每个请求的遥测(通过/检查/保留/耗时毫秒)以结构化的`key=value`行记录到stderr中,以进行事后负载分析。
## 国际化
仅动态的面向用户的输出(工具错误消息,结果提示,注释)通过`messages.properties` / `messages_ko.properties`本地化为英语和韩语。 静态模式/工具描述和结构化的stderr日志(`key=value`)仍为英语,以确保稳定的合同和日志解析。
## 安全注意事项
- 对Collector只读(无写入命令暴露)。
- 凭证仅通过环境变量注入(从不以纯文本形式写入文件或参数)。 优先使用最小特权/只读Scouter帐户。
- **传输是纯文本TCP**(Scouter协议无TLS):SHA-256密码摘要,会话令牌和所有XLog/计数器数据在传输过程中未加密。 只在受信任的网络中运行,或通过SSH/VPN隧道传输。 不要通过公共互联网暴露Collector端口。
- `get_xlog_detail`绑定参数可能包含PII。 设置`SCOUTER_INCLUDE_BIND_PARAMS=false`以在服务器端剥离它们(LLM无法重新启用它们)。 查看上面的环境变量表。 `get_thread_detail`的实时绑定值(`SQLActiveBindVar`)服从相同的开关。
- `get_object_env`**无条件**屏蔽与password/secret/token/credential/private匹配的键值 - 这是LLM无法选择退出的服务器端策略。
- 标准输出保留用于JSON-RPC,因此所有日志仅输出到stderr。
## 许可证/通知
`scouter.mcp.client`包移植自Scouter v2.20.0客户端代码(Apache License 2.0)。 有关详细信息,请参见[NOTICE](NOTICE)。
## 已知限制
1. `search_xlog`/`get_service_summary` `minElapsedMs`/`onlyError`/`limit`在客户端应用,因为Collector没有这些参数的原生参数。 `truncated=true`是一个启发式方法(返回计数==限制)并且可能导致假阳性。
2. 在会话过期(`INVALID_SESSION`)时,客户端会重新登录一次并重试请求;第二次失败会以`SCOUTER_AUTH_FAILED`的形式出现(无限重试循环不会出现)。 上游2秒时间增量刷新守护进程尚未移植,因此长时间运行的进程可能会略微漂移以进行实时相对查询。 绝对纪元(历史)查询不受影响。
3. `list_alerts`/`get_active_services`从上游协议移植并通过烟雾测试(`SmokeIT`)针对Collector验证;根据Collector版本,字段覆盖范围可能会有所不同。