qyl-mcp-server 7.6.1 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +89 -89
  2. package/dist/analysis-budget.d.ts +8 -0
  3. package/dist/analysis-budget.js +73 -0
  4. package/dist/analysis-budget.js.map +1 -0
  5. package/dist/analysis-client.d.ts +5 -0
  6. package/dist/analysis-client.js +46 -0
  7. package/dist/analysis-client.js.map +1 -0
  8. package/dist/analysis-summary.d.ts +2 -0
  9. package/dist/analysis-summary.js +54 -0
  10. package/dist/analysis-summary.js.map +1 -0
  11. package/dist/analysis-tools.d.ts +3 -0
  12. package/dist/analysis-tools.js +167 -0
  13. package/dist/analysis-tools.js.map +1 -0
  14. package/dist/authorization.d.ts +2 -0
  15. package/dist/authorization.js +8 -6
  16. package/dist/authorization.js.map +1 -1
  17. package/dist/ci.d.ts +2 -23
  18. package/dist/ci.js +7 -108
  19. package/dist/ci.js.map +1 -1
  20. package/dist/collector-resources.d.ts +17 -25
  21. package/dist/collector-resources.js +33 -147
  22. package/dist/collector-resources.js.map +1 -1
  23. package/dist/collector.d.ts +7 -43
  24. package/dist/collector.js +22 -172
  25. package/dist/collector.js.map +1 -1
  26. package/dist/config.d.ts +2 -2
  27. package/dist/config.js +2 -2
  28. package/dist/contract-handshake.js +0 -6
  29. package/dist/contract-handshake.js.map +1 -1
  30. package/dist/contract-validation.d.ts +0 -1
  31. package/dist/contract-validation.js +0 -1
  32. package/dist/contract-validation.js.map +1 -1
  33. package/dist/data.d.ts +3 -69
  34. package/dist/data.js +6 -182
  35. package/dist/data.js.map +1 -1
  36. package/dist/events-authorization.d.ts +1 -1
  37. package/dist/events.d.ts +3 -2
  38. package/dist/events.js +1 -1
  39. package/dist/events.js.map +1 -1
  40. package/dist/main.d.ts +1 -8
  41. package/dist/main.js +6 -10
  42. package/dist/main.js.map +1 -1
  43. package/dist/mcp-app.html +2 -3
  44. package/dist/mcp-dashboard.html +3 -4
  45. package/dist/mcp-home.html +1 -1
  46. package/dist/metrics-tools.d.ts +0 -14
  47. package/dist/metrics-tools.js +14 -71
  48. package/dist/metrics-tools.js.map +1 -1
  49. package/dist/request-scope.d.ts +3 -0
  50. package/dist/request-scope.js +7 -3
  51. package/dist/request-scope.js.map +1 -1
  52. package/dist/secret-redactor.js +13 -0
  53. package/dist/secret-redactor.js.map +1 -1
  54. package/dist/server.d.ts +3 -16
  55. package/dist/server.js +24 -123
  56. package/dist/server.js.map +1 -1
  57. package/dist/summaries.d.ts +2 -45
  58. package/dist/summaries.js +1 -207
  59. package/dist/summaries.js.map +1 -1
  60. package/dist/tool-scopes.js +2 -14
  61. package/dist/tool-scopes.js.map +1 -1
  62. package/dist/tools.d.ts +0 -4
  63. package/dist/tools.js +18 -170
  64. package/dist/tools.js.map +1 -1
  65. package/dist/write-tools.d.ts +12 -4
  66. package/dist/write-tools.js +21 -75
  67. package/dist/write-tools.js.map +1 -1
  68. package/package.json +13 -8
  69. package/dist/demo.d.ts +0 -41
  70. package/dist/demo.js +0 -941
  71. package/dist/demo.js.map +0 -1
  72. package/dist/metrics.d.ts +0 -35
  73. package/dist/metrics.js +0 -266
  74. package/dist/metrics.js.map +0 -1
  75. package/dist/paging.d.ts +0 -16
  76. package/dist/paging.js +0 -33
  77. package/dist/paging.js.map +0 -1
  78. package/dist/stats.d.ts +0 -18
  79. package/dist/stats.js +0 -144
  80. package/dist/stats.js.map +0 -1
package/README.md CHANGED
@@ -5,8 +5,8 @@ logs, metrics, sessions and CI runs, plus the Trace Explorer and MCP Dashboard
5
5
  viewers for hosts that render MCP Apps.
6
6
 
7
7
  ```bash
8
- npx qyl-mcp-server --stdio # stdio MCP server
9
- npx qyl-mcp-server # Streamable HTTP on 127.0.0.1:3001
8
+ bunx qyl-mcp-server --stdio # stdio MCP server
9
+ bunx qyl-mcp-server # Streamable HTTP on 127.0.0.1:3001
10
10
  ```
11
11
 
12
12
  Use a modern or 2025-era MCP client. Point it at a collector:
@@ -27,7 +27,6 @@ its own.
27
27
  Both use MCP TypeScript SDK v2: Streamable HTTP through `createMcpHandler`
28
28
  and stdio through `serveStdio`, with their documented compatibility defaults.
29
29
  One factory serves revision `2026-07-28` and supported 2025-era requests.
30
- Events require `2026-07-28`.
31
30
  The HTTP server serves a product page at `/`; `/mcp` is the only protocol
32
31
  endpoint.
33
32
 
@@ -39,7 +38,8 @@ with PKCE S256, both `private_key_jwt` and `none` for ChatGPT CIMD compatibility
39
38
  issuance; this server validates resource-bound RFC 9068 access tokens on every
40
39
  MCP request. It rejects malformed/query credentials, invalid tokens and
41
40
  insufficient scopes with distinct 400/401/403 responses. Every request needs
42
- `qyl:read`; a write tool called without `qyl:write` or `qyl:delete` gets a
41
+ `qyl:read`. The initial 401 requests `qyl:read qyl:write qyl:delete` so new
42
+ connections can authorize the complete tool set. A write tool called without `qyl:write` or `qyl:delete` gets a
43
43
  `403` with `error="insufficient_scope"` naming the scopes to request, in both
44
44
  protocol eras, before the handler runs.
45
45
 
@@ -63,81 +63,55 @@ an enabled module proves a client has been provisioned.
63
63
 
64
64
  ## Tools
65
65
 
66
- **Telemetry** — `list_traces`, `get_trace`, `list_sessions`, `search_logs`,
67
- `ci_log`, `display_traces`, `display_mcp_dashboard`.
68
-
69
- `list_traces` filters by a `start_time`/`end_time` window (RFC 3339, start
70
- inclusive, end exclusive), `service_name` (traces with a span from that
71
- service) and `errors_only`. `list_sessions` filters by `active_only` and the
72
- same window on the session start. `search_logs` filters by `trace_id`,
73
- `session_id`, `service_name`, `severity_min`, a body substring `query` and the
74
- window. Every list tool pages the same way: the output carries `has_more` and,
75
- when more exist, `next_cursor`; pass it back as `cursor` with the same filters
76
- for the next page. A cursor is opaque; one that is not ours is refused with
77
- `invalid_argument` rather than answered with the first page again.
78
-
79
- `get_trace` returns every span by default. `errors_only` selects error spans;
80
- `max_spans` (1–1000) caps the result after filtering in Collector order.
81
- `include_attributes=false` omits span, resource, event, link and instrumentation
82
- scope attribute collections, including any returned root-span copy. Trace
83
- totals remain the Collector's totals; the text reports matching and returned
84
- counts. `ci_log.service_prefix` is case-sensitive, defaults to `qyl-ci`, and
85
- filters both recent runs and individual phase spans.
86
-
87
- **Metrics** — `list_metrics`, `get_metric_series`, `query_metric`. Read in that
88
- order: the catalog gives you an exact instrument name and how many attribute
89
- streams it has, series discovery tells you which attribute keys are worth
90
- grouping or filtering on, and the range query answers the actual question —
91
- a window, a bucket width in whole milliseconds (`step_ms`), a reducer (`avg`,
92
- `min`, `max`, `sum`, `count`, `last`, `p50`, `p90`, `p95`, `p99`), optional
93
- `group_by` keys, and optional `matchers`, each `{ key, op, value }` with `op`
94
- `eq` (exact) or `prefix`; the server serializes them to the Collector's
95
- `attr` / `attr_prefix` parameters. One bucket spanning the whole window
96
- collapses the answer to a single number. The catalog and the series list page
97
- with `cursor` like the telemetry lists.
98
-
99
- **App-only** — `fetch_telemetry` is called by the bundled MCP Apps, not by a
100
- model. Its input is one of four shapes selected by `view` (`traces`, `trace`,
101
- `logs`, `mcp_stats`); the `trace` view requires `trace_id` at the schema layer.
102
-
103
- **Writes** — `create_annotation`, `update_annotation`, `create_saved_query`,
104
- `update_saved_query` and `delete` change only objects users create in qyl, in
105
- the caller's Collector project: annotations (plain-text notes of at most 2000
106
- characters on a trace, span or session) and saved queries (named filters for
107
- traces, logs or metrics). `delete` takes `kind` (`annotation` or
108
- `saved_query`; alert rules follow with Contract 11.7.0), `id` and `etag`. No
109
- tool deletes or edits traces, logs or metrics; retention removes telemetry.
110
- Updates and deletes send the `etag` as `If-Match`: a stale one fails with
111
- `precondition_failed`, a duplicate saved-query name with `conflict`.
112
- `list_saved_queries` and `run_saved_query` read saved queries; `get_trace` and
113
- `list_sessions` return the annotations on what they read. Demo mode keeps none
114
- of these objects and refuses these tools.
115
-
116
- **Failures** — every failed call returns `isError: true`, the message as text,
117
- and `structuredContent.error = { code, message, retryable }` with the
118
- contract's `ToolErrorCode`.
119
-
120
- The thirteen read tools carry `readOnlyHint: true` and only query the
121
- configured collector. The create tools carry `destructiveHint: false` and
122
- `idempotentHint: false`; the update tools and `delete` carry
123
- `destructiveHint: true` and `idempotentHint: true`. On the hosted server
124
- `qyl:read` covers the read tools, `qyl:write` adds the create and update tools,
125
- and `qyl:delete` adds `delete`.
126
-
127
- The `display_*` tools return MCP Apps UI resources as single-file viewers.
128
-
129
- Every tool runs inside its request scope. Cancellation: a
130
- `notifications/cancelled` for the request, or a closed connection, aborts the
131
- in-flight collector fetch instead of waiting out its timeout. Progress: a
132
- request that carries a `progressToken` gets `notifications/progress` per
133
- completed step, one per collector round trip plus a final "Result ready"
134
- (`ci_log` with a `run_id` reports the flatten into legs as a step of its own).
135
- Logging: the server declares no `logging` capability and sends no
136
- `notifications/message`, including when a client supplies a log level.
137
- Operational error diagnostics go to stderr; native tool timing/status telemetry
138
- uses OpenTelemetry. Requested progress and cancellation remain available.
139
- [Source and test commands/output, 2026-10-08](https://github.com/ANcpLua/qyl.mcp/blob/main/docs/evidence/2026-10-08-followup-01.md).
66
+ The server publishes 32 tools, including one app-only read tool. Reads use the collector's
67
+ analysis queries and the generated qyl API contracts.
140
68
 
69
+ | Purpose | Tools |
70
+ | --- | --- |
71
+ | Investigate failures | `triage`, `list_failures`, `get_failure_context`, `compare_groups`, `compare_traces`, `verify_fix` |
72
+ | Explore telemetry | `aggregate_telemetry`, `discover_attributes`, `get_agent_run`, `list_releases`, `get_service_map`, `check_telemetry_health`, `get_mcp_stats` |
73
+ | Read executions | `list_sessions`, `list_traces`, `get_trace`, `search_logs`, `ci_log` |
74
+ | Read metrics | `list_metrics`, `get_metric_series`, `query_metric` |
75
+ | Saved questions | `list_saved_queries`, `run_saved_query` |
76
+ | Interactive views | `display_traces`, `display_mcp_dashboard`, `fetch_telemetry` (app-only) |
77
+ | Write project records | `create_annotation`, `update_annotation`, `create_saved_query`, `update_saved_query`, `delete`, `update_failure_status` |
78
+
79
+ Read tools accept an absolute RFC 3339 time window or `lookback_minutes` and report the
80
+ resolved `window` and `coverage`: examined, matched and returned counts, truncation,
81
+ scan completeness and observation time. Unknown counts are null. Filtering happens before
82
+ pagination; reuse an opaque `next_cursor` with the same filters to continue a page.
83
+
84
+ Shared matchers support `eq`, `neq`, `in`, `prefix`, `contains`, `exists`, `gt`, `gte`,
85
+ `lt` and `lte`, with span, resource or log scope. Span durations are milliseconds;
86
+ metrics retain their recorded units. Histogram percentiles identify their approximation,
87
+ and cumulative counter changes account for resets. Verification reports insufficient
88
+ traffic as pending rather than calling an unobserved failure fixed.
89
+
90
+ `get_trace` supports all spans, errors, errors with ancestors, or the critical path,
91
+ selected attributes and correlated logs. `display_traces` preserves the selected span
92
+ and can compare two executions. Notes and bookmarks are created only through explicit
93
+ viewer actions. `display_mcp_dashboard` uses the same MCP aggregates as `get_mcp_stats`,
94
+ shows the numerator and denominator behind rates, classifies failures, and opens matching
95
+ calls from aggregate selections. `fetch_telemetry` serves five app-only views: traces,
96
+ trace, logs, MCP statistics and comparison, with incremental refresh and field selection.
97
+
98
+ The 26 read tools carry `readOnlyHint: true`. Six write tools change annotations, saved
99
+ queries or failure status in the caller's project. An annotation can target a trace, span,
100
+ session or failure and has optional labels and a classification. A bookmark is a note
101
+ labelled `bookmark`. Updates and deletes require the current `etag`; stale writes are
102
+ rejected. Create calls reuse the stored result for 24 hours. Without an explicit
103
+ `idempotency_key`, the server derives one from the project, operation and request
104
+ body, so identical retries are safe. Supply a different key to deliberately create
105
+ another identical record. No tool edits or deletes recorded telemetry.
106
+
107
+ `qyl:read` covers reads, `qyl:write` adds creation and updates, and `qyl:delete` permits
108
+ `delete`. A missing scope returns the supported OAuth step-up challenge. Failed calls
109
+ carry a stable code, retryability, the problem type and field-level validation details
110
+ when available. Secrets are redacted before model text or structured content is returned.
111
+
112
+ Every tool runs inside its request scope, forwarding cancellation to the collector.
113
+ Requested progress reports completion; no logging notifications are sent to clients.
114
+ Analysis reads require a live collector. Synthetic data is used only by test fixtures, and is never substituted when a collector fails.
141
115
 
142
116
  Every inbound `tools/call` on a local server — `--stdio`, or HTTP without
143
117
  `MCP_PUBLIC_URL` — records only its tool name, timing, status and error type,
@@ -155,14 +129,13 @@ multi-tenant audit log.
155
129
  | --- | --- |
156
130
  | `QYL_COLLECTOR_URL` | Collector read API base; default `http://127.0.0.1:5100`. Also the OTLP base when set. |
157
131
  | `QYL_API_KEY` | Collector credential for reads and OTLP; the write tools need the Collector's `write` and `delete` roles on it. Outgoing only. |
158
- | `QYL_PROJECT` | Server-owned collector project scope. Unset, the server sends no project-scope header, so the Collector's default project applies; the Events subscription source key records that as `default`. Never accepted as tool input. This is the only place that states the default; other documents link here. |
132
+ | `QYL_PROJECT` | Server-owned collector project scope. Unset, the server sends no project-scope header, so the Collector's default project applies. Never accepted as tool input. This is the only place that states the default; other documents link here. |
159
133
  | `MCP_COLLECTOR_PROJECTS` | Optional secret JSON mapping validated Auth0 subjects to project-bound Collector keys; see account isolation below. |
160
134
  | `QYL_OTLP_ENDPOINT` | Optional OTLP base for self-telemetry. |
161
- | `QYL_DEMO=1` | Explicit, visibly labelled demo telemetry. A collector failure never silently substitutes demo data. |
162
135
  | `QYL_MCP_TELEMETRY=0` | Disable MCP spans, metrics, and operation logs. |
163
136
  | `QYL_MCP_CAPTURE_CONTENT=1` | Workbench content capture; native incoming tool-call telemetry never supplies request or response bodies. |
164
137
  | `QYL_MCP_NATIVE_STATE_PATH` | Override the native execution-evidence path. |
165
- | `MCP_EVENTS_STORE` | Persistent Events subscription file; requires Auth0 and the access-check credentials below. |
138
+ | `MCP_EVENTS_STORE` | Optional internal Events subscription file; leave unset for the shared ChatGPT/Claude deployment. |
166
139
  | `MCP_EVENTS_AUTH0_CLIENT_ID` / `MCP_EVENTS_AUTH0_CLIENT_SECRET` | Dedicated Management API application with `read:users`, `read:clients`, `read:client_grants`, `read:grants`; resolves CIMD identities and keeps access checks current without storing subscriber tokens. |
167
140
  | `MCP_EVENTS_POLL_MS` | Collector polling interval, at least 5000 ms; default 30000 ms. |
168
141
  | `PORT` | HTTP listener port; default `3001`. |
@@ -170,9 +143,8 @@ multi-tenant audit log.
170
143
  Secrets are redacted before results reach the model, structured content, or
171
144
  durable evidence.
172
145
 
173
- `--stdio` runs under Node.js 24 or Bun 1.4, which is what `npx` gives you.
174
- The HTTP entry is a web-standard fetch handler served by its default export,
175
- so serving it requires Bun.
146
+ `npx` and `pnpm dlx` also work when Bun 1.4 or newer is installed.
147
+ Both the HTTP and stdio executables use Bun 1.4 or newer.
176
148
 
177
149
  ### Account isolation for hosted Auth0
178
150
 
@@ -202,20 +174,48 @@ existing deployment-wide credential behavior is retained.
202
174
 
203
175
  Only the verified SDK `AuthInfo.extra.subject` selects the project. Tool inputs
204
176
  and request metadata cannot override it. All telemetry tools, viewer refreshes
205
- and Events queries use that account's project credential. Removing the account
206
- assignment revokes its Events subscription on the next access check. Project
177
+ use that account's project credential. Project
207
178
  keys are redacted from text and structured results, including keys nested in
208
179
  this JSON configuration. Keep the map in host secrets and out of the plugin ZIP.
209
180
 
210
181
  `bun run smoke:projects` from the repository root checks every tool, the
211
- writes included, viewer query paths, both protocol eras and Events against a
212
- real local Collector with two temporary projects. Set `QYL_COLLECTOR_PROJECT` to its
213
- `.csproj` when using a different checkout. The script uses local test identities
182
+ writes included, viewer query paths and both protocol eras against a
183
+ real local Collector with two temporary projects. It reuses the completed Release
184
+ build; set `QYL_COLLECTOR_DLL` for another build. The script uses local test identities
214
185
  and an in-process signed webhook receiver; the hosted reviewer OAuth login and
215
186
  real ChatGPT demonstration are separate checks before upload.
216
187
 
188
+ ### Seeded analysis verification
189
+
190
+ `bun run --cwd server test:answer-key` starts a fresh temporary collector database,
191
+ seeds real OTLP, and runs the 32 analysis checks through MCP and generated validators.
192
+ It reuses the collector's completed build; set `QYL_COLLECTOR_DLL` when its location
193
+ or configuration differs. `mise run check` includes this verification and the quiet
194
+ SSE check. No pre-existing temporary file or manually seeded database is required.
195
+
196
+ `QYL_BIN=/path/to/installed/qyl node live-tools-smoke.mjs` additionally checks
197
+ all 32 tools against an isolated collector started by the published CLI.
198
+
217
199
  ## Release notes
218
200
 
201
+ ### 8.0.0
202
+
203
+ - The executable now requires Bun 1.4 or later, including stdio. Library subpaths remain usable on Node 24; TypeScript 7 continues to emit the package.
204
+ - Start HTTP explicitly with a 60-second idle timeout so quiet SSE responses survive the SDK keep-alive. Stop the HTTP server during shutdown.
205
+ - Request read, write and delete scopes at initial sign-in; step-up challenges name only missing scopes.
206
+ - Return useful text summaries, bounded evidence and continuations; validate failure updates and make create retries idempotent by default.
207
+ - Use collector contract 12.1.1 for corrected analysis paging, coverage and failure timestamps. Remove the obsolete demo runtime and duplicate read implementations.
208
+ - Pin SemanticConventions 9.9.1, including the canonical `qyl.gen_ai.tool.call.arguments_hash` definition used by collector 12.1.1 for repeated-call analysis.
209
+ - Preserve note drafts, render trace drill-down results and use consistent dashboard filters. Gate the real OTLP answer-key and Bun quiet-stream regressions.
210
+
211
+ ### 7.7.0
212
+
213
+ - Expand to 32 tools: failure triage and lifecycle, trace/group comparisons, fix verification, telemetry aggregation and discovery, agent runs, releases, service maps, telemetry health and MCP statistics.
214
+ - Use the collector's shared typed analysis contracts for filtering, pagination, coverage and saved-query execution; retain official SDKs/exporters and project-scoped authorization.
215
+ - Add responsive trace comparison, explicit note/bookmark controls, dashboard filters and drill-downs, with denominator counts behind rates.
216
+ - Preserve numeric agent token usage during secret redaction, and verify the new surface against real OTLP fixtures plus both protocol eras.
217
+
218
+
219
219
  ### 7.6.1
220
220
 
221
221
  - Manage existing Auth0 API permissions, client grants and mapped-user permissions with scoped tenant configuration and a drift check.
@@ -0,0 +1,8 @@
1
+ import type { CallToolResult } from "@modelcontextprotocol/server";
2
+ export declare const ANALYSIS_RESPONSE_BYTES = 24000;
3
+ export declare const responseBytes: (result: object) => number;
4
+ /** Final compaction for a single large record, after the Collector has paged it.
5
+ * Stable identities, counts and signed continuations are preserved. Bulk text and
6
+ * nested evidence can be omitted; totals and the text response explain the loss.
7
+ */
8
+ export declare function compactAnalysisResult(operation: string, original: object): CallToolResult;
@@ -0,0 +1,73 @@
1
+ import { analysisSummary } from "./analysis-summary.js";
2
+ import { telemetryToolResult } from "./telemetry-redaction.js";
3
+ export const ANALYSIS_RESPONSE_BYTES = 24_000;
4
+ export const responseBytes = (result) => Buffer.byteLength(JSON.stringify(result), "utf8");
5
+ /** Final compaction for a single large record, after the Collector has paged it.
6
+ * Stable identities, counts and signed continuations are preserved. Bulk text and
7
+ * nested evidence can be omitted; totals and the text response explain the loss.
8
+ */
9
+ export function compactAnalysisResult(operation, original) {
10
+ const output = structuredClone(original);
11
+ const totals = { ...output.page_totals };
12
+ let omitted = 0;
13
+ let shortened = 0;
14
+ const coverage = { ...output.coverage, truncated: true, returned: null };
15
+ output.coverage = coverage;
16
+ output.page_totals = totals;
17
+ const result = () => telemetryToolResult(`${analysisSummary(operation, output)}\nResponse budget: ${omitted} other evidence item(s) omitted; ${shortened} text field(s) shortened. Narrow the filters or use the continuation for more evidence.`, output);
18
+ // These fields are descriptions/content, never identifiers, credentials or cursors.
19
+ const textFields = new Set(["body", "text", "message", "status_message", "description", "brief", "summary", "pattern", "value", "name"]);
20
+ function trimText(value, cap) {
21
+ if (Array.isArray(value)) {
22
+ for (const item of value)
23
+ trimText(item, cap);
24
+ return;
25
+ }
26
+ if (value === null || typeof value !== "object")
27
+ return;
28
+ for (const [key, item] of Object.entries(value)) {
29
+ if (typeof item === "string" && item.length > cap && textFields.has(key)) {
30
+ value[key] = `${Array.from(item).slice(0, cap).join("")}…`;
31
+ shortened++;
32
+ }
33
+ else
34
+ trimText(item, cap);
35
+ }
36
+ }
37
+ trimText(output, 512);
38
+ for (let iteration = 0; responseBytes(result()) > ANALYSIS_RESPONSE_BYTES && iteration < 128; iteration++) {
39
+ const arrays = [];
40
+ function collect(value, path) {
41
+ if (Array.isArray(value)) {
42
+ if (value.length > 0)
43
+ arrays.push({ values: value, path, bytes: responseBytes(value) });
44
+ value.forEach((item, index) => collect(item, `${path}.${index}`));
45
+ }
46
+ else if (value !== null && typeof value === "object") {
47
+ for (const [key, item] of Object.entries(value)) {
48
+ if (key !== "page_totals" && key !== "coverage")
49
+ collect(item, path ? `${path}.${key}` : key);
50
+ }
51
+ }
52
+ }
53
+ collect(output, "");
54
+ // Prefer removing bulk inside a trace over removing the trace itself.
55
+ arrays.sort((a, b) => (b.path.split(".").length > 1 ? b.bytes : b.bytes / 4) - (a.path.split(".").length > 1 ? a.bytes : a.bytes / 4));
56
+ const candidate = arrays[0];
57
+ if (!candidate) {
58
+ trimText(output, 64);
59
+ break;
60
+ }
61
+ const removed = candidate.values.splice(Math.floor(candidate.values.length / 2)).length;
62
+ omitted += removed;
63
+ totals[`other.${candidate.path}`] = (totals[`other.${candidate.path}`] ?? 0) + removed;
64
+ }
65
+ // A cursor can encode large filters. Keeping it must not defeat the response cap.
66
+ if (responseBytes(result()) > ANALYSIS_RESPONSE_BYTES) {
67
+ delete output.next_cursor;
68
+ delete output.next_phase_cursor;
69
+ trimText(output, 64);
70
+ }
71
+ return result();
72
+ }
73
+ //# sourceMappingURL=analysis-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis-budget.js","sourceRoot":"","sources":["../src/analysis-budget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** Shared HTTP transport; every callable analysis operation is registered by name. */
2
+ import type { CallToolResult } from "@modelcontextprotocol/server";
3
+ import type * as z from "zod/v4";
4
+ import type { ToolScope } from "./request-scope.js";
5
+ export declare function queryAnalysis<Input extends object, Output extends object>(operation: string, input: Input, schema: z.ZodType<Output>, scope: ToolScope): Promise<CallToolResult>;
@@ -0,0 +1,46 @@
1
+ import { CollectorError, collectorPost, parseCollectorBody } from "./collector.js";
2
+ import { ANALYSIS_RESPONSE_BYTES, compactAnalysisResult, responseBytes } from "./analysis-budget.js";
3
+ import { analysisSummary } from "./analysis-summary.js";
4
+ import { telemetryToolResult } from "./telemetry-redaction.js";
5
+ export async function queryAnalysis(operation, input, schema, scope) {
6
+ const path = `/api/v1/analysis/${operation}`;
7
+ const deadline = Date.now() + 55_000;
8
+ let query = input;
9
+ let previousPageSize = Infinity;
10
+ for (;;) {
11
+ const remaining = deadline - Date.now();
12
+ if (remaining <= 0)
13
+ throw new CollectorError("The query exceeded its time budget; narrow the time window and matchers.");
14
+ const response = await collectorPost(path, query, { ...scope.collector, timeoutMs: remaining });
15
+ const output = parseCollectorBody(response, path, schema);
16
+ const result = telemetryToolResult(analysisSummary(operation, output), output);
17
+ // Bytes give a conservative upper bound even for token-dense identifiers.
18
+ const bytes = responseBytes(result);
19
+ if (bytes <= ANALYSIS_RESPONSE_BYTES) {
20
+ await scope.step(`Queried ${operation}`);
21
+ return result;
22
+ }
23
+ // Re-query the collector so its cursor, coverage and totals describe the
24
+ // smaller page. Never slice a response and leave its paging metadata stale.
25
+ const args = query;
26
+ const page = output;
27
+ const traceView = operation === "get_trace" || operation === "fetch_telemetry" && args.view === "trace";
28
+ const sizeKey = traceView ? "max_spans" : operation === "query_metric" ? "series_limit" : operation === "get_agent_run" ? "max_steps" : "limit";
29
+ const trace = page.trace;
30
+ const observed = page.observed;
31
+ const sizes = [trace?.spans?.length, observed?.error_spans?.length, observed?.logs?.length,
32
+ ...Object.values(page).filter(Array.isArray).map((items) => items.length)].filter((size) => size !== undefined);
33
+ const pageSize = Math.max(0, ...sizes);
34
+ if (pageSize > 1 && pageSize < previousPageSize) {
35
+ previousPageSize = pageSize;
36
+ const limit = Math.max(1, Math.floor(pageSize * ANALYSIS_RESPONSE_BYTES / bytes * 0.8));
37
+ // The collector creates the smaller page and its continuation together.
38
+ query = { ...args, ...page.window, [sizeKey]: limit,
39
+ ...(operation === "get_failure_context" ? { max_spans: limit, max_logs: limit } : {}) };
40
+ continue;
41
+ }
42
+ await scope.step(`Queried ${operation}; large evidence compacted`);
43
+ return compactAnalysisResult(operation, output);
44
+ }
45
+ }
46
+ //# sourceMappingURL=analysis-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis-client.js","sourceRoot":"","sources":["../src/analysis-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ /** Compact evidence for hosts that show text without expanding structuredContent. */
2
+ export declare function analysisSummary(operation: string, output: object): string;
@@ -0,0 +1,54 @@
1
+ /** Compact evidence for hosts that show text without expanding structuredContent. */
2
+ export function analysisSummary(operation, output) {
3
+ const data = output;
4
+ const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
5
+ const short = (value) => (value == null ? "unknown" : typeof value === "string" ? value : JSON.stringify(value) ?? "unknown").replace(/\s+/gu, " ").slice(0, 180);
6
+ const lines = [operation.replaceAll("_", " ")];
7
+ const coverage = record(data.coverage);
8
+ if (Object.keys(coverage).length)
9
+ lines.push(`Matched ${short(coverage.matched)}; returned ${short(coverage.returned)}. ${coverage.scan_complete === true ? "Scan complete." : "Scan incomplete; totals may be unknown."}`);
10
+ for (const key of ["verdict", "reason", "settled", "method", "unit", "approximate"]) {
11
+ if (data[key] !== undefined)
12
+ lines.push(`${key}: ${short(data[key])}`);
13
+ }
14
+ const totals = record(data.totals ?? record(data.stats).totals);
15
+ if (totals.requests !== undefined)
16
+ lines.push(`${short(totals.errors)} errors / ${short(totals.requests)} requests; p95 ${short(totals.p95_ms)} ms.`);
17
+ const trace = record(data.trace);
18
+ if (trace.trace_id)
19
+ lines.push(`Trace ${short(trace.trace_id)}: ${short(trace.span_count)} spans${trace.has_error ? ", contains errors" : ""}.`);
20
+ const cause = record(record(data.observed).root_cause_span);
21
+ if (cause.name)
22
+ lines.push(`Recorded failure: ${short(cause.service)} / ${short(cause.name)} — ${short(record(cause.exception).message ?? cause.status)}`);
23
+ const collections = ["failures", "regressions", "groups", "steps", "traces", "sessions", "logs", "items", "attributes", "releases", "nodes", "runs", "phases", "saved_queries"];
24
+ let evidence = 0;
25
+ for (const field of collections) {
26
+ const rows = data[field];
27
+ if (!Array.isArray(rows))
28
+ continue;
29
+ lines.push(`${field.replaceAll("_", " ")}: ${rows.length} on this page.`);
30
+ for (const value of rows) {
31
+ if (evidence >= 3)
32
+ break;
33
+ const row = record(value);
34
+ const title = row.normalized_message ?? row.name ?? row.operation ?? row.key ?? row.root_span_name ?? row.body ?? row.service ?? row.session_id;
35
+ if (title === undefined)
36
+ continue;
37
+ const label = typeof title === "object" ? JSON.stringify(title) : title;
38
+ const stats = row.count ?? row.requests ?? row.status ?? row.change;
39
+ const id = row.failure_id ?? row.trace_id;
40
+ lines.push(`- ${short(label)}${stats === undefined ? "" : ` (${short(stats)})`}${id === undefined ? "" : ` · ${short(id)}`}`);
41
+ evidence++;
42
+ }
43
+ }
44
+ if (data.has_more === true && typeof data.next_cursor === "string")
45
+ lines.push("More results: repeat with next_cursor and the same filters.");
46
+ else if (data.has_more === true && typeof data.next_phase_cursor === "string")
47
+ lines.push("More phases: repeat with next_phase_cursor as phase_cursor and the same filters.");
48
+ else if (data.has_more === true)
49
+ lines.push("More evidence exists; narrow the filters to retrieve it.");
50
+ else if (coverage.truncated === true)
51
+ lines.push("Evidence is truncated; narrow the query for more detail.");
52
+ return lines.slice(0, 14).join("\n");
53
+ }
54
+ //# sourceMappingURL=analysis-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis-summary.js","sourceRoot":"","sources":["../src/analysis-summary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Named analysis tools backed by the collector's generated query contracts. */
2
+ import type { McpServer } from "@modelcontextprotocol/server";
3
+ export declare function registerAnalysisTools(server: McpServer): void;