qyl-mcp-server 7.7.0 → 8.1.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.
- package/README.md +34 -25
- package/dist/analysis-budget.d.ts +8 -0
- package/dist/analysis-budget.js +73 -0
- package/dist/analysis-budget.js.map +1 -0
- package/dist/analysis-client.js +20 -14
- package/dist/analysis-client.js.map +1 -1
- package/dist/analysis-summary.d.ts +2 -0
- package/dist/analysis-summary.js +54 -0
- package/dist/analysis-summary.js.map +1 -0
- package/dist/analysis-tools.js +11 -10
- package/dist/analysis-tools.js.map +1 -1
- package/dist/authorization.d.ts +2 -0
- package/dist/authorization.js +8 -6
- package/dist/authorization.js.map +1 -1
- package/dist/ci.d.ts +1 -22
- package/dist/ci.js +0 -64
- package/dist/ci.js.map +1 -1
- package/dist/collector-resources.d.ts +11 -25
- package/dist/collector-resources.js +14 -132
- package/dist/collector-resources.js.map +1 -1
- package/dist/collector.d.ts +4 -42
- package/dist/collector.js +11 -171
- package/dist/collector.js.map +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.js +2 -2
- package/dist/contract-handshake.js +0 -6
- package/dist/contract-handshake.js.map +1 -1
- package/dist/contract-validation.d.ts +11 -16
- package/dist/contract-validation.js +18 -27
- package/dist/contract-validation.js.map +1 -1
- package/dist/data.d.ts +3 -69
- package/dist/data.js +6 -182
- package/dist/data.js.map +1 -1
- package/dist/events-authorization.d.ts +1 -1
- package/dist/events.d.ts +3 -2
- package/dist/events.js +1 -1
- package/dist/events.js.map +1 -1
- package/dist/main.d.ts +1 -8
- package/dist/main.js +6 -10
- package/dist/main.js.map +1 -1
- package/dist/mcp-app.html +2 -3
- package/dist/mcp-dashboard.html +2 -3
- package/dist/mcp-home.html +1 -1
- package/dist/request-scope.js +0 -8
- package/dist/request-scope.js.map +1 -1
- package/dist/server.d.ts +3 -16
- package/dist/server.js +11 -23
- package/dist/server.js.map +1 -1
- package/dist/skills/qyl-investigate/SKILL.md +120 -0
- package/dist/skills.d.ts +27 -0
- package/dist/skills.js +142 -0
- package/dist/skills.js.map +1 -0
- package/dist/summaries.d.ts +2 -45
- package/dist/summaries.js +1 -207
- package/dist/summaries.js.map +1 -1
- package/dist/tool-scopes.d.ts +4 -22
- package/dist/tool-scopes.js +4 -58
- package/dist/tool-scopes.js.map +1 -1
- package/dist/tools.d.ts +0 -2
- package/dist/tools.js +0 -2
- package/dist/tools.js.map +1 -1
- package/dist/write-tools.d.ts +12 -4
- package/dist/write-tools.js +7 -12
- package/dist/write-tools.js.map +1 -1
- package/package.json +16 -10
- package/dist/demo.d.ts +0 -41
- package/dist/demo.js +0 -941
- package/dist/demo.js.map +0 -1
- package/dist/metrics.d.ts +0 -35
- package/dist/metrics.js +0 -279
- package/dist/metrics.js.map +0 -1
- package/dist/paging.d.ts +0 -16
- package/dist/paging.js +0 -33
- package/dist/paging.js.map +0 -1
- package/dist/stats.d.ts +0 -18
- package/dist/stats.js +0 -144
- 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
|
-
|
|
9
|
-
|
|
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
|
|
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.
|
|
102
|
-
|
|
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
|
|
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
|
-
|
|
146
|
-
|
|
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,40 @@ 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.
|
|
184
|
-
|
|
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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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.1.0
|
|
202
|
+
|
|
203
|
+
- Serve the qyl-investigate skill from the server through the MCP skills extension (`io.modelcontextprotocol/skills`: `skills/list`, `skills/get` and `resources/read` under `skill://qyl/`), so the OpenAI plugin portal imports it at Scan Tools and the npm package carries it in `dist/skills`. The skill now names the tool to start with for each question, the defaults every tool applies, the accepted `aggregate_telemetry` measures, and the one-call connection rule: no fan-out before one call has returned telemetry, one retry after sign-in, then stop.
|
|
204
|
+
- Advertise output schemas inlined rather than hoisted into `$defs`: ChatGPT does not resolve `$ref`, so `verify_fix.verdict` and most of `get_failure_context` reached the model as `unknown`. The redundant date-time regex is dropped from advertised schemas.
|
|
205
|
+
- Use collector contract 12.1.2, whose tool descriptions state the default window, baseline, page sizes, span selection and the accepted measure and ordering values.
|
|
206
|
+
|
|
207
|
+
### 8.0.0
|
|
208
|
+
|
|
209
|
+
- 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.
|
|
210
|
+
- Start HTTP explicitly with a 60-second idle timeout so quiet SSE responses survive the SDK keep-alive. Stop the HTTP server during shutdown.
|
|
211
|
+
- Request read, write and delete scopes at initial sign-in; step-up challenges name only missing scopes.
|
|
212
|
+
- Return useful text summaries, bounded evidence and continuations; validate failure updates and make create retries idempotent by default.
|
|
213
|
+
- Use collector contract 12.1.1 for corrected analysis paging, coverage and failure timestamps. Remove the obsolete demo runtime and duplicate read implementations.
|
|
214
|
+
- 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.
|
|
215
|
+
- Preserve note drafts, render trace drill-down results and use consistent dashboard filters. Gate the real OTLP answer-key and Bun quiet-stream regressions.
|
|
216
|
+
|
|
208
217
|
### 7.7.0
|
|
209
218
|
|
|
210
219
|
- 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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"}
|
package/dist/analysis-client.js
CHANGED
|
@@ -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(
|
|
16
|
+
const result = telemetryToolResult(analysisSummary(operation, output), output);
|
|
18
17
|
// Bytes give a conservative upper bound even for token-dense identifiers.
|
|
19
|
-
const bytes =
|
|
20
|
-
if (bytes <=
|
|
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
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
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;
|
|
1
|
+
{"version":3,"file":"analysis-client.js","sourceRoot":"","sources":["../src/analysis-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -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":"AAAA,qFAAqF;AACrF,MAAM,UAAU,eAAe,CAAC,SAAiB,EAAE,MAAc;IAC/D,MAAM,IAAI,GAAG,MAAiC,CAAC;IAC/C,MAAM,MAAM,GAAG,CAAC,KAAc,EAA2B,EAAE,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAgC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzK,MAAM,KAAK,GAAG,CAAC,KAAc,EAAU,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnL,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,yCAAyC,EAAE,CAAC,CAAC;IAC5N,KAAK,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,CAAC;QACpF,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;IAChE,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACtJ,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACjJ,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,CAAC;IAC5D,IAAI,KAAK,CAAC,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,qBAAqB,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3J,MAAM,WAAW,GAAG,CAAC,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IAChL,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,SAAS;QACnC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,gBAAgB,CAAC,CAAC;QAC1E,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YACzB,IAAI,QAAQ,IAAI,CAAC;gBAAE,MAAM;YACzB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,kBAAkB,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC;YAChJ,IAAI,KAAK,KAAK,SAAS;gBAAE,SAAS;YAClC,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YACxE,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC;YACpE,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,QAAQ,CAAC;YAC1C,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9H,QAAQ,EAAE,CAAC;QACb,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;SACzI,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC,iBAAiB,KAAK,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,kFAAkF,CAAC,CAAC;SACzK,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;SACnG,IAAI,QAAQ,CAAC,SAAS,KAAK,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;IAC7G,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC"}
|
package/dist/analysis-tools.js
CHANGED
|
@@ -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";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { ifMatch, refusals, changeRefusals } from "./collector-resources.js";
|
|
7
|
+
import { toolScopeChallenge } from "./tool-scopes.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,18 @@ 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:
|
|
150
|
-
scopeChallenge: toolScopeChallenge("update_failure_status",
|
|
151
|
-
_meta:
|
|
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
|
-
|
|
153
|
+
if (args.ignore_until !== undefined && args.status !== "ignored")
|
|
154
|
+
throw new CollectorError("ignore_until is valid only with status=ignored", false, 400, "invalid_argument");
|
|
154
155
|
const { failure_id, etag, ...changes } = args;
|
|
155
156
|
const path = `/api/v1/failures/${encodeURIComponent(failure_id)}`;
|
|
156
|
-
const response = await collectorPatch(path, changes, {
|
|
157
|
+
const response = await refusals(changeRefusals("failure", failure_id, "write"), () => collectorPatch(path, changes, {
|
|
157
158
|
...scope.collector,
|
|
158
159
|
headers: { ...scope.collector.headers, ...ifMatch(etag) },
|
|
159
|
-
});
|
|
160
|
+
}));
|
|
160
161
|
const output = parseCollectorBody(response, path, UpdateFailureStatusOutputSchema);
|
|
161
162
|
await scope.step("Failure status saved");
|
|
162
163
|
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":"AAEA,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,oCAAoC,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAC5F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"analysis-tools.js","sourceRoot":"","sources":["../src/analysis-tools.ts"],"names":[],"mappings":"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"}
|
package/dist/authorization.d.ts
CHANGED
|
@@ -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
|
}
|
package/dist/authorization.js
CHANGED
|
@@ -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
|
-
...(
|
|
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
|
-
//
|
|
70
|
-
//
|
|
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":"AAAA,OAAO,EACL,iBAAiB,GAGlB,MAAM,8BAA8B,CAAC;
|
|
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;
|