qyl-mcp-server 7.7.0 → 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 (70) hide show
  1. package/README.md +28 -25
  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.js +20 -14
  6. package/dist/analysis-client.js.map +1 -1
  7. package/dist/analysis-summary.d.ts +2 -0
  8. package/dist/analysis-summary.js +54 -0
  9. package/dist/analysis-summary.js.map +1 -0
  10. package/dist/analysis-tools.js +11 -9
  11. package/dist/analysis-tools.js.map +1 -1
  12. package/dist/authorization.d.ts +2 -0
  13. package/dist/authorization.js +8 -6
  14. package/dist/authorization.js.map +1 -1
  15. package/dist/ci.d.ts +1 -22
  16. package/dist/ci.js +0 -64
  17. package/dist/ci.js.map +1 -1
  18. package/dist/collector-resources.d.ts +11 -25
  19. package/dist/collector-resources.js +14 -132
  20. package/dist/collector-resources.js.map +1 -1
  21. package/dist/collector.d.ts +4 -42
  22. package/dist/collector.js +11 -171
  23. package/dist/collector.js.map +1 -1
  24. package/dist/config.d.ts +2 -2
  25. package/dist/config.js +2 -2
  26. package/dist/contract-handshake.js +0 -6
  27. package/dist/contract-handshake.js.map +1 -1
  28. package/dist/contract-validation.d.ts +0 -1
  29. package/dist/contract-validation.js +0 -1
  30. package/dist/contract-validation.js.map +1 -1
  31. package/dist/data.d.ts +3 -69
  32. package/dist/data.js +6 -182
  33. package/dist/data.js.map +1 -1
  34. package/dist/events-authorization.d.ts +1 -1
  35. package/dist/events.d.ts +3 -2
  36. package/dist/events.js +1 -1
  37. package/dist/events.js.map +1 -1
  38. package/dist/main.d.ts +1 -8
  39. package/dist/main.js +6 -10
  40. package/dist/main.js.map +1 -1
  41. package/dist/mcp-app.html +2 -3
  42. package/dist/mcp-dashboard.html +2 -3
  43. package/dist/mcp-home.html +1 -1
  44. package/dist/server.d.ts +3 -16
  45. package/dist/server.js +8 -23
  46. package/dist/server.js.map +1 -1
  47. package/dist/summaries.d.ts +2 -45
  48. package/dist/summaries.js +1 -207
  49. package/dist/summaries.js.map +1 -1
  50. package/dist/tool-scopes.js +2 -14
  51. package/dist/tool-scopes.js.map +1 -1
  52. package/dist/tools.d.ts +0 -2
  53. package/dist/tools.js +0 -2
  54. package/dist/tools.js.map +1 -1
  55. package/dist/write-tools.d.ts +12 -4
  56. package/dist/write-tools.js +6 -6
  57. package/dist/write-tools.js.map +1 -1
  58. package/package.json +13 -8
  59. package/dist/demo.d.ts +0 -41
  60. package/dist/demo.js +0 -941
  61. package/dist/demo.js.map +0 -1
  62. package/dist/metrics.d.ts +0 -35
  63. package/dist/metrics.js +0 -279
  64. package/dist/metrics.js.map +0 -1
  65. package/dist/paging.d.ts +0 -16
  66. package/dist/paging.js +0 -33
  67. package/dist/paging.js.map +0 -1
  68. package/dist/stats.d.ts +0 -18
  69. package/dist/stats.js +0 -144
  70. 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:
@@ -38,7 +38,8 @@ with PKCE S256, both `private_key_jwt` and `none` for ChatGPT CIMD compatibility
38
38
  issuance; this server validates resource-bound RFC 9068 access tokens on every
39
39
  MCP request. It rejects malformed/query credentials, invalid tokens and
40
40
  insufficient scopes with distinct 400/401/403 responses. Every request needs
41
- `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
42
43
  `403` with `error="insufficient_scope"` naming the scopes to request, in both
43
44
  protocol eras, before the handler runs.
44
45
 
@@ -98,8 +99,10 @@ The 26 read tools carry `readOnlyHint: true`. Six write tools change annotations
98
99
  queries or failure status in the caller's project. An annotation can target a trace, span,
99
100
  session or failure and has optional labels and a classification. A bookmark is a note
100
101
  labelled `bookmark`. Updates and deletes require the current `etag`; stale writes are
101
- rejected. Optional `idempotency_key` on create calls reuses the stored result for 24 hours.
102
- Omitting it creates a new record. No tool edits or deletes recorded telemetry.
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.
103
106
 
104
107
  `qyl:read` covers reads, `qyl:write` adds creation and updates, and `qyl:delete` permits
105
108
  `delete`. A missing scope returns the supported OAuth step-up challenge. Failed calls
@@ -108,8 +111,7 @@ when available. Secrets are redacted before model text or structured content is
108
111
 
109
112
  Every tool runs inside its request scope, forwarding cancellation to the collector.
110
113
  Requested progress reports completion; no logging notifications are sent to clients.
111
- Analysis reads require a live collector. Synthetic demo data remains available for local
112
- UI fixtures, and is never substituted when a collector fails.
114
+ Analysis reads require a live collector. Synthetic data is used only by test fixtures, and is never substituted when a collector fails.
113
115
 
114
116
  Every inbound `tools/call` on a local server — `--stdio`, or HTTP without
115
117
  `MCP_PUBLIC_URL` — records only its tool name, timing, status and error type,
@@ -130,7 +132,6 @@ multi-tenant audit log.
130
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. |
131
133
  | `MCP_COLLECTOR_PROJECTS` | Optional secret JSON mapping validated Auth0 subjects to project-bound Collector keys; see account isolation below. |
132
134
  | `QYL_OTLP_ENDPOINT` | Optional OTLP base for self-telemetry. |
133
- | `QYL_DEMO=1` | Local synthetic UI fixtures; analysis tools require a live collector. |
134
135
  | `QYL_MCP_TELEMETRY=0` | Disable MCP spans, metrics, and operation logs. |
135
136
  | `QYL_MCP_CAPTURE_CONTENT=1` | Workbench content capture; native incoming tool-call telemetry never supplies request or response bodies. |
136
137
  | `QYL_MCP_NATIVE_STATE_PATH` | Override the native execution-evidence path. |
@@ -142,9 +143,8 @@ multi-tenant audit log.
142
143
  Secrets are redacted before results reach the model, structured content, or
143
144
  durable evidence.
144
145
 
145
- `--stdio` runs under Node.js 24 or Bun 1.4, which is what `npx` gives you.
146
- The HTTP entry is a web-standard fetch handler served by its default export,
147
- 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.
148
148
 
149
149
  ### Account isolation for hosted Auth0
150
150
 
@@ -180,31 +180,34 @@ this JSON configuration. Keep the map in host secrets and out of the plugin ZIP.
180
180
 
181
181
  `bun run smoke:projects` from the repository root checks every tool, the
182
182
  writes included, viewer query paths and both protocol eras against a
183
- real local Collector with two temporary projects. Set `QYL_COLLECTOR_PROJECT` to its
184
- `.csproj` when using a different checkout. The script uses local test identities
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
185
185
  and an in-process signed webhook receiver; the hosted reviewer OAuth login and
186
186
  real ChatGPT demonstration are separate checks before upload.
187
187
 
188
188
  ### Seeded analysis verification
189
189
 
190
- The collector fixture `tests/Qyl.Collector.Tests/Fixtures/seed-answer-key.py`
191
- emits real OTLP data and writes the trace IDs and absolute windows used by
192
- `server/verify-answer-key.mjs`. Seed a fresh temporary collector database before
193
- each run because the checks exercise annotations and failure status changes.
194
- After building this workspace, run the verifier from `server/`:
195
-
196
- ```sh
197
- QYL_ANSWER_KEY_FILE=/tmp/qyl-answer-key.json \
198
- QYL_ANSWER_KEY_COLLECTOR=http://127.0.0.1:5510 \
199
- QYL_ANSWER_KEY_OTLP=http://127.0.0.1:5518 \
200
- node --test verify-answer-key.mjs
201
- ```
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.
202
195
 
203
196
  `QYL_BIN=/path/to/installed/qyl node live-tools-smoke.mjs` additionally checks
204
197
  all 32 tools against an isolated collector started by the published CLI.
205
198
 
206
199
  ## Release notes
207
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
+
208
211
  ### 7.7.0
209
212
 
210
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.
@@ -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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"}
@@ -1,9 +1,8 @@
1
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";
2
4
  import { telemetryToolResult } from "./telemetry-redaction.js";
3
5
  export async function queryAnalysis(operation, input, schema, scope) {
4
- if (process.env.QYL_DEMO === "1") {
5
- throw new CollectorError("Analysis needs a live qyl Collector; unset QYL_DEMO to query recorded telemetry.");
6
- }
7
6
  const path = `/api/v1/analysis/${operation}`;
8
7
  const deadline = Date.now() + 55_000;
9
8
  let query = input;
@@ -14,10 +13,10 @@ export async function queryAnalysis(operation, input, schema, scope) {
14
13
  throw new CollectorError("The query exceeded its time budget; narrow the time window and matchers.");
15
14
  const response = await collectorPost(path, query, { ...scope.collector, timeoutMs: remaining });
16
15
  const output = parseCollectorBody(response, path, schema);
17
- const result = telemetryToolResult(`${operation}: results are in the structured data.`, output);
16
+ const result = telemetryToolResult(analysisSummary(operation, output), output);
18
17
  // Bytes give a conservative upper bound even for token-dense identifiers.
19
- const bytes = Buffer.byteLength(JSON.stringify(result), "utf8");
20
- if (bytes <= 24_000) {
18
+ const bytes = responseBytes(result);
19
+ if (bytes <= ANALYSIS_RESPONSE_BYTES) {
21
20
  await scope.step(`Queried ${operation}`);
22
21
  return result;
23
22
  }
@@ -25,16 +24,23 @@ export async function queryAnalysis(operation, input, schema, scope) {
25
24
  // smaller page. Never slice a response and leave its paging metadata stale.
26
25
  const args = query;
27
26
  const page = output;
28
- const canPage = (operation === "display_traces" && !args.trace_id)
29
- || (operation === "fetch_telemetry" && args.view === "traces");
30
- if (canPage && Array.isArray(page.traces) && page.traces.length > 1 && page.traces.length < previousPageSize) {
31
- previousPageSize = page.traces.length;
32
- const limit = Math.max(1, Math.floor(page.traces.length * 24_000 / bytes * 0.8));
33
- const window = page.window;
34
- query = { ...args, ...window, limit };
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 } : {}) };
35
40
  continue;
36
41
  }
37
- throw new CollectorError("The result exceeds the response budget; reduce limit or narrow the time window and matchers.", false, 413, "collector_rejected");
42
+ await scope.step(`Queried ${operation}; large evidence compacted`);
43
+ return compactAnalysisResult(operation, output);
38
44
  }
39
45
  }
40
46
  //# sourceMappingURL=analysis-client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"analysis-client.js","sourceRoot":"","sources":["../src/analysis-client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,SAAiB,EACjB,KAAY,EACZ,MAAyB,EACzB,KAAgB;IAEhB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;QACjC,MAAM,IAAI,cAAc,CAAC,kFAAkF,CAAC,CAAC;IAC/G,CAAC;IACD,MAAM,IAAI,GAAG,oBAAoB,SAAS,EAAE,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC;IACrC,IAAI,KAAK,GAAW,KAAK,CAAC;IAC1B,IAAI,gBAAgB,GAAG,QAAQ,CAAC;IAChC,SAAS,CAAC;QACR,MAAM,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACxC,IAAI,SAAS,IAAI,CAAC;YAAE,MAAM,IAAI,cAAc,CAAC,0EAA0E,CAAC,CAAC;QACzH,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;QAChG,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,SAAS,uCAAuC,EAAE,MAAM,CAAC,CAAC;QAChG,0EAA0E;QAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;QAChE,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;YACpB,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,SAAS,EAAE,CAAC,CAAC;YACzC,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,yEAAyE;QACzE,4EAA4E;QAC5E,MAAM,IAAI,GAAG,KAAgC,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAiC,CAAC;QAC/C,MAAM,OAAO,GAAG,CAAC,SAAS,KAAK,gBAAgB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;eAC7D,CAAC,SAAS,KAAK,iBAAiB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACjE,IAAI,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;YAC7G,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YACtC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC;YACjF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAgE,CAAC;YACrF,KAAK,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC;YACtC,SAAS;QACX,CAAC;QACD,MAAM,IAAI,cAAc,CACtB,8FAA8F,EAC9F,KAAK,EAAE,GAAG,EAAE,oBAAoB,CACjC,CAAC;IACJ,CAAC;AACH,CAAC"}
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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"}
@@ -3,9 +3,10 @@ import { runTool } from "./request-scope.js";
3
3
  import { READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS, TELEMETRY_TOOL_AUTH_META } from "./tools.js";
4
4
  import { queryAnalysis } from "./analysis-client.js";
5
5
  import { collectorPatch, parseCollectorBody } from "./collector.js";
6
- import { ifMatch } from "./collector-resources.js";
6
+ import { ifMatch, refusals, changeRefusals } from "./collector-resources.js";
7
7
  import { assertToolScopes, toolScopeChallenge } from "./tool-scopes.js";
8
- import { QYL_MCP_SCOPE, QYL_MCP_WRITE_SCOPE } from "./oauth.js";
8
+ import { WRITE_SCOPES, UPDATE_TOOL_ANNOTATIONS, securityMeta } from "./write-tools.js";
9
+ import { CollectorError } from "./collector.js";
9
10
  import { telemetryToolResult } from "./telemetry-redaction.js";
10
11
  const TriageInputSchema = contractSchema("Mcp.Tools.TriageInput");
11
12
  const TriageOutputSchema = contractSchema("Mcp.Tools.TriageOutput");
@@ -35,7 +36,6 @@ const GetMcpStatsInputSchema = contractSchema("Mcp.Tools.GetMcpStatsInput");
35
36
  const GetMcpStatsOutputSchema = contractSchema("Mcp.Tools.GetMcpStatsOutput");
36
37
  const UpdateFailureStatusInputSchema = contractSchema("Mcp.Tools.UpdateFailureStatusInput");
37
38
  const UpdateFailureStatusOutputSchema = contractSchema("Mcp.Tools.UpdateFailureStatusOutput");
38
- const FAILURE_WRITE_SCOPES = [QYL_MCP_SCOPE, QYL_MCP_WRITE_SCOPE];
39
39
  export function registerAnalysisTools(server) {
40
40
  server.registerTool("triage", {
41
41
  title: "Triage",
@@ -146,17 +146,19 @@ export function registerAnalysisTools(server) {
146
146
  description: "Set a failure's status or assignee when recording triage decisions, returning the stored failure available through list_failures.",
147
147
  inputSchema: UpdateFailureStatusInputSchema,
148
148
  outputSchema: compactOutputSchema(UpdateFailureStatusOutputSchema),
149
- annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
150
- scopeChallenge: toolScopeChallenge("update_failure_status", FAILURE_WRITE_SCOPES),
151
- _meta: { securitySchemes: [{ type: "oauth2", scopes: [...FAILURE_WRITE_SCOPES] }] },
149
+ annotations: UPDATE_TOOL_ANNOTATIONS,
150
+ scopeChallenge: toolScopeChallenge("update_failure_status", WRITE_SCOPES),
151
+ _meta: securityMeta(WRITE_SCOPES),
152
152
  }, (args, ctx) => runTool(ctx, 1, async (scope) => {
153
- assertToolScopes("update_failure_status", FAILURE_WRITE_SCOPES, ctx.http?.authInfo);
153
+ assertToolScopes("update_failure_status", WRITE_SCOPES, ctx.http?.authInfo);
154
+ if (args.ignore_until !== undefined && args.status !== "ignored")
155
+ throw new CollectorError("ignore_until is valid only with status=ignored", false, 400, "invalid_argument");
154
156
  const { failure_id, etag, ...changes } = args;
155
157
  const path = `/api/v1/failures/${encodeURIComponent(failure_id)}`;
156
- const response = await collectorPatch(path, changes, {
158
+ const response = await refusals(changeRefusals("failure", failure_id, "write"), () => collectorPatch(path, changes, {
157
159
  ...scope.collector,
158
160
  headers: { ...scope.collector.headers, ...ifMatch(etag) },
159
- });
161
+ }));
160
162
  const output = parseCollectorBody(response, path, UpdateFailureStatusOutputSchema);
161
163
  await scope.step("Failure status saved");
162
164
  return telemetryToolResult("Failure status saved; list_failures returns the current failure.", output);
@@ -1 +1 @@
1
- {"version":3,"file":"analysis-tools.js","sourceRoot":"","sources":["../src/analysis-tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analysis-tools.js","sourceRoot":"","sources":["../src/analysis-tools.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,8 @@ export interface ResourceAuthorizationOptions {
3
3
  readonly verifier: OAuthTokenVerifier;
4
4
  readonly resourceMetadataUrl: string;
5
5
  readonly requiredScopes: readonly string[];
6
+ /** Scopes requested at initial sign-in; individual operations still enforce their own requirements. */
7
+ readonly authorizationScopes?: readonly string[];
6
8
  /** Explicit implications only; a wildcard-looking string grants nothing by itself. */
7
9
  readonly scopeImplications?: Readonly<Record<string, readonly string[]>>;
8
10
  }
@@ -27,6 +27,8 @@ export function scopeClosure(granted, implications) {
27
27
  export function createResourceAuthorization(options) {
28
28
  const requiredScopes = [...new Set(options.requiredScopes)].sort();
29
29
  validateScopes(requiredScopes);
30
+ const authorizationScopes = [...new Set(options.authorizationScopes ?? requiredScopes)];
31
+ validateScopes(authorizationScopes);
30
32
  const implications = new Map(Object.entries(options.scopeImplications ?? {})
31
33
  .map(([scope, implied]) => {
32
34
  validateScopes([scope, ...implied]);
@@ -42,10 +44,10 @@ export function createResourceAuthorization(options) {
42
44
  verifier: options.verifier,
43
45
  resourceMetadataUrl: metadataUrl.href,
44
46
  });
45
- const challenge = (status, error) => {
47
+ const challenge = (status, error, scopes = requiredScopes) => {
46
48
  const parameters = [
47
49
  ...(error === undefined ? [] : [`error="${error}"`]),
48
- ...(requiredScopes.length === 0 ? [] : [`scope="${requiredScopes.join(" ")}"`]),
50
+ ...(scopes.length === 0 ? [] : [`scope="${scopes.join(" ")}"`]),
49
51
  `resource_metadata="${metadataUrl.href}"`,
50
52
  ];
51
53
  return Response.json({ error: error ?? "unauthorized" }, {
@@ -66,15 +68,15 @@ export function createResourceAuthorization(options) {
66
68
  headers: { authorization: `Bearer ${bearer[1]}` },
67
69
  }));
68
70
  if (auth instanceof Response) {
69
- // Keep authentication failures distinct from authorization failures and
70
- // include the complete operation scope set on every challenge.
71
+ // Hosts use this scope list for sign-in. Request the complete product
72
+ // grant here without requiring every scope for a read-only request.
71
73
  if (auth.status === 401)
72
- return challenge(401, authorization === null ? undefined : "invalid_token");
74
+ return challenge(401, authorization === null ? undefined : "invalid_token", authorizationScopes);
73
75
  return auth;
74
76
  }
75
77
  const effectiveScopes = scopeClosure(auth.scopes, implications);
76
78
  if (!requiredScopes.every((scope) => effectiveScopes.has(scope))) {
77
- return challenge(403, "insufficient_scope");
79
+ return challenge(403, "insufficient_scope", requiredScopes.filter((scope) => !effectiveScopes.has(scope)));
78
80
  }
79
81
  return auth;
80
82
  };
@@ -1 +1 @@
1
- {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../src/authorization.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../src/authorization.ts"],"names":[],"mappings":"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"}
package/dist/ci.d.ts CHANGED
@@ -1,25 +1,4 @@
1
- /**
2
- * Qyl's CI dogfooding block (the fourth tool block next to traces, sessions,
3
- * and logs): answers "which CI leg hung on what" from qyl's OWN telemetry
4
- * instead of wrapping the GitHub API.
5
- *
6
- * Emitter convention (what CI runs must send to appear here):
7
- * - resource `service.name` starts with "qyl-ci" (e.g. "qyl-ci-smoke"),
8
- * - `session.id` identifies one workflow run (e.g. "nuget-publish-<run_id>"),
9
- * - one span per phase, named after the phase, carrying a `ci.leg` string
10
- * attribute (e.g. "macos-latest"); a failed phase sets span status error.
11
- *
12
- */
13
- import type { CiPhase, CiRunSummary } from "@ancplua/qyl-api-schema/types";
1
+ /** CI evidence is computed by the Collector from recorded pipeline tasks. */
14
2
  import type { McpServer } from "@modelcontextprotocol/server";
15
- import type { Mode, QylSession, QylTrace } from "./wire.js";
16
- /** Resource service-name prefix that marks telemetry as CI-emitted. */
17
- export declare const CI_SERVICE_PREFIX = "qyl-ci";
18
- /** CI sessions carry at least one service matching the requested prefix. */
19
- export declare function filterCiSessions(sessions: QylSession[], servicePrefix?: string): QylSession[];
20
- /** Flatten a run's traces into per-leg phases, failures first. */
21
- export declare function collectCiPhases(traces: QylTrace[], servicePrefix?: string): CiPhase[];
22
- export declare function summarizeCiRuns(runs: CiRunSummary[], mode: Mode, servicePrefix?: string): string;
23
- export declare function summarizeCiRun(runId: string, phases: CiPhase[], mode: Mode, servicePrefix?: string): string;
24
3
  /** Query all matching CI telemetry before pagination. */
25
4
  export declare function registerCiTools(server: McpServer): void;
package/dist/ci.js CHANGED
@@ -2,70 +2,6 @@ import { compactOutputSchema, contractSchema } from "./contract-validation.js";
2
2
  import { queryAnalysis } from "./analysis-client.js";
3
3
  import { runTool } from "./request-scope.js";
4
4
  import { READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS, TELEMETRY_TOOL_AUTH_META } from "./tools.js";
5
- /** Resource service-name prefix that marks telemetry as CI-emitted. */
6
- export const CI_SERVICE_PREFIX = "qyl-ci";
7
- /** CI sessions carry at least one service matching the requested prefix. */
8
- export function filterCiSessions(sessions, servicePrefix = CI_SERVICE_PREFIX) {
9
- return sessions.filter((session) => session.services.some((service) => service.startsWith(servicePrefix)));
10
- }
11
- function spanLeg(span) {
12
- const attribute = span.attributes?.find((entry) => entry.key === "ci.leg");
13
- return typeof attribute?.value === "string"
14
- ? attribute.value
15
- : span.resource.service_name;
16
- }
17
- /** Flatten a run's traces into per-leg phases, failures first. */
18
- export function collectCiPhases(traces, servicePrefix = CI_SERVICE_PREFIX) {
19
- const phases = traces.flatMap((trace) => trace.spans.filter((span) => span.resource.service_name.startsWith(servicePrefix)).map((span) => ({
20
- leg: spanLeg(span),
21
- phase: span.name,
22
- status: span.status.code === 2 ? "error" : span.status.code === 1 ? "ok" : "unset",
23
- duration_ms: Math.max(0, Math.round(Number(BigInt(span.end_time_unix_nano) - BigInt(span.start_time_unix_nano)) / 1_000_000)),
24
- ...(span.status.message ? { message: span.status.message } : {}),
25
- })));
26
- return phases.sort((a, b) => a.status === b.status
27
- ? a.leg.localeCompare(b.leg) || a.phase.localeCompare(b.phase)
28
- : a.status === "error"
29
- ? -1
30
- : b.status === "error"
31
- ? 1
32
- : 0);
33
- }
34
- export function summarizeCiRuns(runs, mode, servicePrefix = CI_SERVICE_PREFIX) {
35
- if (runs.length === 0) {
36
- return `No CI runs found (${mode} mode). CI telemetry appears once runs emit ` +
37
- `spans with a '${servicePrefix}*' service.name.`;
38
- }
39
- const lines = runs.map((run) => {
40
- const failure = run.error_count > 0 ? `${run.error_count} error(s)` : "clean";
41
- const duration = run.duration_ms === undefined ? "?" : `${Math.round(run.duration_ms / 1000)}s`;
42
- return `- ${run.run_id} [${run.state}] ${run.start_time} ${duration} — ${failure}`;
43
- });
44
- return `${runs.length} CI run(s) (${mode} mode), pass a run_id for the per-leg breakdown:\n${lines.join("\n")}`;
45
- }
46
- export function summarizeCiRun(runId, phases, mode, servicePrefix = CI_SERVICE_PREFIX) {
47
- if (phases.length === 0) {
48
- return `CI run ${runId} has no phase spans matching '${servicePrefix}*' (${mode} mode).`;
49
- }
50
- const legs = new Map();
51
- for (const phase of phases) {
52
- const existing = legs.get(phase.leg);
53
- if (existing)
54
- existing.push(phase);
55
- else
56
- legs.set(phase.leg, [phase]);
57
- }
58
- const lines = [];
59
- for (const [leg, legPhases] of legs) {
60
- const failed = legPhases.filter((phase) => phase.status === "error");
61
- lines.push(`${failed.length > 0 ? "✗" : "✓"} ${leg}`);
62
- for (const phase of failed.length > 0 ? failed : legPhases) {
63
- const detail = phase.message ? ` — ${phase.message}` : "";
64
- lines.push(` ${phase.status === "error" ? "✗" : "·"} ${phase.phase} (${phase.duration_ms}ms)${detail}`);
65
- }
66
- }
67
- return `CI run ${runId} (${mode} mode):\n${lines.join("\n")}`;
68
- }
69
5
  /** Query all matching CI telemetry before pagination. */
70
6
  export function registerCiTools(server) {
71
7
  server.registerTool("ci_log", {