trace-log-mcp
v1.0.9
Published
Standalone MCP service for trace and log tools
Readme
trace-log-mcp
从 log-trace-agent 提取的独立 MCP 服务,提供链路追踪与日志查询工具。
功能特性
- 8 个 MCP 工具:trace.get、trace.search、trace.get_span、trace.aggregate、trace.service_logs、log.get、log.search、log.parse_scope
- 多环境支持:online/offline 环境切换
- SQLite 存储:本地缓存,支持 FTS5 全文检索
- Stdio 传输:与 Claude Desktop 无缝集成
- 灵活配置:分层默认值 + 环境变量覆盖
安装
本地源码环境
npm install
npm run build构建后,如果只是想在当前仓库里调用 CLI,直接用:
npm run cli -- --help
npm run cli -- trace get --input-json '{"trace_id":"<trace-id>","trace_env":"online"}'如果你希望在源码仓库里也能直接敲 trace-log-cli,则在仓库根目录执行一次:
npm link
trace-log-cli --help发布包使用方式
发布到 npm 后,统一使用包名 trace-log-mcp 分发 MCP 和 CLI:
npx trace-log-mcp
npm install -g trace-log-mcp
trace-log-cli --help安装后的命令映射:
trace-log-mcp:MCP 服务入口trace-log-cli:AI 优先 CLI 入口
配置
快速开始(最小配置)
将 .env.example 复制为 .env,配置 3 个必填变量:
cp .env.example .env编辑 .env:
LOG_TRACE_ONLINE_JAEGER_BASE_URL=https://your-jaeger.com
LOG_TRACE_ONLINE_LOKI_BASE_URL=https://your-loki.com
IPS=your-ips-value-here配置层次
服务采用分层配置策略:
- 硬编码常量 — 几乎不变的值
- 合理默认值 — 可能需要调整的值
- 环境变量 — 用户自定义
核心配置(必填 3-4 个变量):
LOG_TRACE_ONLINE_JAEGER_BASE_URL— Jaeger API 地址LOG_TRACE_ONLINE_LOKI_BASE_URL— Loki API 地址IPS— IPS 值(自动拼接ZYBIPSCAS=前缀作为 Grafana Cookie,online/offline 共用)- (可选)Offline 环境对应的同名变量
存储配置(可选,有默认值):
LOG_TRACE_STORAGE_SQLITE_PATH— 默认:~/.trace-log-mcp/data.sqliteLOG_TRACE_STORAGE_TTL_HOURS— 默认:72(3 天)LOG_TRACE_STORAGE_ENABLE_FTS5— 默认:true
高级配置(约 20 个变量,可选):
- Loki 查询参数(datasource 路径、方向、条数、步长)
- Jaeger 配置(API 路径模板、额外请求头)
- HTTP 超时(连接、读取、重试次数)
- 查询设置(cluster 标签操作符、后置管道、过滤命令)
- Span Tags(白名单、最大字符数、最大 key 数量)
完整配置说明见 docs/environment-variables.md。
使用方式
本地开发
npm run dev本地真实调试
可以在本地直接调用日志工具,并复用 MCP 服务相同的环境变量配置,对 online/offline 环境做真实调试。
先构建:
npm run build把 Grafana Explore URL 解析成 log.search 骨架:
npm run debug:log-tool -- \
--tool log.parse_scope \
--grafana-url 'https://log-search-docker.zuoyebang.cc/explore?...'直接从 Grafana URL 执行 log.search,并附带本地覆盖项:
npm run debug:log-tool -- \
--grafana-url 'https://log-search-docker.zuoyebang.cc/explore?...' \
--limit 10 \
--order time_desc使用显式 JSON 参数调用工具:
npm run debug:log-tool -- \
--tool log.get \
--args-json '{"log_hash":"<sha256>","trace_env":"online"}'如果要复现浏览器上下文,可以额外注入请求头,例如 Cookie / Referer:
npm run debug:log-tool -- \
--grafana-url 'https://log-search-docker.zuoyebang.cc/explore?...' \
--headers-file ./debug-headers.jsondebug-headers.json 需要是一个扁平 JSON 对象,例如:
{
"cookie": "k=v; foo=bar",
"referer": "https://log-search-docker.zuoyebang.cc/explore?orgId=4"
}AI 优先 CLI
执行 npm run build 后,使用仓库内 CLI 入口:
npm run cli -- --help
npm run cli -- trace get --input-json '{"trace_id":"<trace-id>","trace_env":"online"}'
node dist/cli/index.js --help
node dist/cli/index.js trace get --input-json '{"trace_id":"<trace-id>","trace_env":"online"}'npm run cli 是源码仓库里最直接的 CLI 入口。dist/index.js 是 MCP 服务入口。发布包场景下,可以直接用 npx trace-log-mcp 启动 MCP;如果执行 npm install -g trace-log-mcp,则可通过 trace-log-cli ... 调用 CLI。若希望在源码仓库里直接使用 trace-log-cli 命令,请先执行一次 npm link。
生产启动
npm start集成到 Claude Desktop
在 claude_desktop_config.json 中添加:
{
"mcpServers": {
"trace-log": {
"command": "node",
"args": ["/absolute/path/to/trace-log-mcp/dist/index.js"],
"env": {
"LOG_TRACE_ONLINE_JAEGER_BASE_URL": "https://jaeger.example.com",
"LOG_TRACE_ONLINE_LOKI_BASE_URL": "https://loki.example.com",
"IPS": "your-ips-value"
}
}
}
}工具说明
trace.get
从 Jaeger 拉取 trace 并返回结构化摘要,包含 services、services_with_request_ids、roots、errors、top_slow_spans、high_call_count 和 time_range_ns,结果会缓存到 SQLite。
参数:
trace_id(必填):Jaeger trace IDtrace_env(必填):指定环境(online或offline)
trace.search
在本地 SQLite 缓存中查询 trace 的 spans,支持按服务、操作、父 span、错误状态、耗时过滤,以及游标分页。返回结果会尽量带上 request_id。
参数:
trace_id(必填):Trace IDservice_name、operation_name、parent_span_id(可选):过滤条件error_only(可选):仅返回错误 spansmin_duration_ms、max_duration_ms(可选):耗时过滤sort_by(可选):start_ns或duration_desccursor_start_ns、cursor_span_id(可选):分页游标limit(可选):返回条数上限(默认 20,最大 100)trace_env(必填):指定环境(online或offline)
trace.get_span
获取单个 span 的详细信息(含 tags),并返回可识别出的 request_id。
参数:
trace_id(必填):Trace IDspan_id(必填):Span IDtrace_env(必填):指定环境(online或offline)
trace.aggregate
对本地缓存 spans 做聚合统计(count/avg/p95/max),支持按 service_name、operation_name、error_flag 分组。
参数:
trace_id(必填):Trace IDgroup_by(必填):service_name、operation_name或error_flag- 过滤:
service_name、operation_name、error_flag、min_duration_ms、max_duration_ms limit(可选):返回条数上限(默认 50,最大 200)trace_env(必填):指定环境(online或offline)
trace.service_logs
按服务维度查看 trace。支持对 service_name 做模糊匹配,返回该服务相关 spans、日志摘要(总数+分级计数)和上下游服务关系。日志优先通过 span 上的 request_id 进行关联。具体日志内容请用 log.search。
参数:
trace_id(必填):Trace IDservice_name(必填):要匹配的服务名limit(可选):spans 返回条数上限(默认 50,最大 100)trace_env(必填):指定环境(online或offline)
log.get
通过 log_hash 从本地 SQLite 取回完整日志行。传入 field_paths 和/或 regex_extractors 时,只返回提取结果,不返回 raw_text。
参数:
log_hash(必填):日志行的 SHA256 hashmax_chars(可选):最大返回字符数(默认 2000)field_paths(可选):从 JSONraw_text中按点路径提取多个字段的数组,例如["params","params.user_id"]。也支持 Loki 文件前缀格式,如/path/app.log:{...}。传入后响应中不再返回raw_textregex_extractors(可选):用于非 JSON 或混合文本日志的提取器数组,形如[{ "name": "request_id", "pattern": "request_id=([^\\s]+)" }]。每个pattern都必须是带捕获组的 JavaScript 正则源码字符串,响应会把首个命中的第 1 个捕获组写入regex_values[name]trace_env(必填):指定环境(online或offline)
返回重点:
total_chars:原始日志总字符数,便于决定是否增大max_charsraw_text:日志内容,按max_chars截断后返回;仅在未传field_paths且未传regex_extractors时返回truncated:是否发生截断;仅在未传field_paths且未传regex_extractors时返回field_values:仅在传入field_paths时返回;每个 key 对应一个请求路径。若路径不存在或raw_text不是可解析 JSON,则该项为nullregex_values:仅在传入regex_extractors时返回;每个 key 对应一个 extractor 的name。若正则未命中,则该项为null
log.search
统一日志调查入口。它接收 log.parse_scope 产出的结构化 scope,在缓存不足时自动补拉,并只返回可供后续 log.get 使用的日志元数据(通过 hits[].log_hash 下钻查看完整日志)。
参数:
scope(必填):主查询范围对象。scope.query:直接日志查询分支。已知requestID时优先填写requestID;否则必须同时提供app、cluster、ns以及scope.start_ms、scope.end_ms;tp、timestamp仅用于进一步收窄范围;与scope.trace互斥。scope.trace:trace 解析分支,需要同时提供service和trace_id,先解析 spans / request IDs / selectors 再查日志;与scope.query互斥。scope.value:Grafana 原始过滤片段,例如grep -P '."level":"WARN"'。只用于远端补拉,不参与本地缓存二次过滤。scope.start_ms、scope.end_ms:绝对毫秒时间戳。query 模式且未提供requestID时必填;空字符串表示未设置。filter(可选):仅用于本地缓存二次精筛,不会缩小远端 query-scope。text:原始日志文本包含指定子串。all_terms:所有词都必须命中。any_terms:任意一个词命中即可。exclude_terms:这些词不能出现。level:按解析后的日志级别过滤,如WARN、ERROR。group_by(可选):none、level、request_id、app;空字符串按none处理。order(可选):time_asc或time_desc;也兼容asc/desc别名。空字符串按time_asc处理。cursor(可选):分页游标;空字符串表示从头开始。limit(可选):返回条数上限;空字符串按默认50处理。trace_env(必填):指定环境(online或offline)
返回重点:
hits[]:日志元数据列表,包含log_hash、ts_ns、app、ns、cluster、pod、level、request_idresolved_scope(可选):scope.trace.service被解析成 request ID / selector 时的解析结果groups(可选):当group_by != none时返回聚合计数next_cursor(可选):下一页游标
log.parse_scope
解析 Grafana/LogSearch 的 Explore 页面 URL,并转换成可直接传给 log.search 的完整参数骨架。如果未显式传入 trace_env,工具会将页面 URL 与配置中的 LOG_TRACE_OFFLINE_LOKI_BASE_URL 对比,自动推断 online 或 offline。
参数:
grafana_url(必填):Grafana/LogSearch Explore 页面 URL
返回重点:
trace_env:最终识别出的环境scope.query:解析出的直接查询分支(app、cluster、ns、requestID)scope.trace:空的 trace 查询骨架(service、trace_id),供调用方按需切换到 trace 模式scope.value:解析出的 Grafana 原始过滤片段scope.start_ms、scope.end_ms:解析出的绝对时间范围;既支持绝对毫秒时间戳,也支持now-1h、now这类简单的 Grafana 相对时间表达式
架构
- 入口:
src/index.ts— MCP 服务,Stdio 传输 - 工具:
src/tools/trace-tools.ts、src/tools/log-tools.ts - 共享:
src/tools/shared.ts— 公共工具函数 - 客户端:
src/jaeger-client.ts、src/loki-client.ts - 存储:
src/store.ts— SQLite + FTS5 - 配置:
src/config.ts— 分层配置系统 - 工具库:
src/utils/— http、limit、redact 辅助模块
故障排查
服务无法启动
- 检查 Node.js 版本:
node --version(需要 >=22.5.0) - 确认依赖已安装:
npm install - 检查
.env中的环境变量
工具返回错误
- 确认 Jaeger/Loki 地址可访问
- 检查 Grafana Cookie 是否有效
- 查看 stderr 日志输出
数据库错误
- 检查 SQLite 路径的文件权限
- 确认磁盘空间充足
- 删除后重建:
rm ~/.trace-log-mcp/data.sqlite
许可证
MIT
