qyl-mcp-server 0.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.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -0
  3. package/dist/atomic-json-store.d.ts +37 -0
  4. package/dist/atomic-json-store.js +143 -0
  5. package/dist/atomic-json-store.js.map +1 -0
  6. package/dist/ci.d.ts +51 -0
  7. package/dist/ci.js +158 -0
  8. package/dist/ci.js.map +1 -0
  9. package/dist/collector.d.ts +43 -0
  10. package/dist/collector.js +163 -0
  11. package/dist/collector.js.map +1 -0
  12. package/dist/config.d.ts +14 -0
  13. package/dist/config.js +39 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/contract-validation.d.ts +146 -0
  16. package/dist/contract-validation.js +350 -0
  17. package/dist/contract-validation.js.map +1 -0
  18. package/dist/data.d.ts +46 -0
  19. package/dist/data.js +138 -0
  20. package/dist/data.js.map +1 -0
  21. package/dist/demo.d.ts +23 -0
  22. package/dist/demo.js +836 -0
  23. package/dist/demo.js.map +1 -0
  24. package/dist/execution-evidence.d.ts +13 -0
  25. package/dist/execution-evidence.js +81 -0
  26. package/dist/execution-evidence.js.map +1 -0
  27. package/dist/execution-result.d.ts +5 -0
  28. package/dist/execution-result.js +17 -0
  29. package/dist/execution-result.js.map +1 -0
  30. package/dist/http-security.d.ts +36 -0
  31. package/dist/http-security.js +101 -0
  32. package/dist/http-security.js.map +1 -0
  33. package/dist/log-body.d.ts +3 -0
  34. package/dist/log-body.js +12 -0
  35. package/dist/log-body.js.map +1 -0
  36. package/dist/main.d.ts +51 -0
  37. package/dist/main.js +215 -0
  38. package/dist/main.js.map +1 -0
  39. package/dist/mcp-app.html +218 -0
  40. package/dist/mcp-dashboard.html +223 -0
  41. package/dist/mcp-errors.d.ts +5 -0
  42. package/dist/mcp-errors.js +15 -0
  43. package/dist/mcp-errors.js.map +1 -0
  44. package/dist/mcp-semconv.d.ts +68 -0
  45. package/dist/mcp-semconv.js +208 -0
  46. package/dist/mcp-semconv.js.map +1 -0
  47. package/dist/native-execution.d.ts +132 -0
  48. package/dist/native-execution.js +508 -0
  49. package/dist/native-execution.js.map +1 -0
  50. package/dist/observability-suppression.d.ts +8 -0
  51. package/dist/observability-suppression.js +15 -0
  52. package/dist/observability-suppression.js.map +1 -0
  53. package/dist/secret-redactor.d.ts +30 -0
  54. package/dist/secret-redactor.js +255 -0
  55. package/dist/secret-redactor.js.map +1 -0
  56. package/dist/server.d.ts +25 -0
  57. package/dist/server.js +207 -0
  58. package/dist/server.js.map +1 -0
  59. package/dist/stats.d.ts +18 -0
  60. package/dist/stats.js +141 -0
  61. package/dist/stats.js.map +1 -0
  62. package/dist/summaries.d.ts +14 -0
  63. package/dist/summaries.js +128 -0
  64. package/dist/summaries.js.map +1 -0
  65. package/dist/telemetry-redaction.d.ts +6 -0
  66. package/dist/telemetry-redaction.js +28 -0
  67. package/dist/telemetry-redaction.js.map +1 -0
  68. package/dist/telemetry.d.ts +72 -0
  69. package/dist/telemetry.js +362 -0
  70. package/dist/telemetry.js.map +1 -0
  71. package/dist/tools.d.ts +17 -0
  72. package/dist/tools.js +111 -0
  73. package/dist/tools.js.map +1 -0
  74. package/dist/wire.d.ts +10 -0
  75. package/dist/wire.js +7 -0
  76. package/dist/wire.js.map +1 -0
  77. package/package.json +91 -0
@@ -0,0 +1,255 @@
1
+ const DEFAULT_REPLACEMENT = "[REDACTED]";
2
+ const DEFAULT_MAX_DEPTH = 32;
3
+ const DEFAULT_MAX_STRING_LENGTH = 16_384;
4
+ const SecretKeyNames = new Set([
5
+ "authorization",
6
+ "proxyauthorization",
7
+ "cookie",
8
+ "setcookie",
9
+ "apikey",
10
+ "accesskey",
11
+ "secret",
12
+ "secretkey",
13
+ "clientsecret",
14
+ "password",
15
+ "passwd",
16
+ "pwd",
17
+ "credential",
18
+ "credentials",
19
+ "privatekey",
20
+ "token",
21
+ "accesstoken",
22
+ "refreshtoken",
23
+ "authtoken",
24
+ "bearertoken",
25
+ "sessiontoken",
26
+ "sessionkey",
27
+ "idtoken",
28
+ ]);
29
+ const SafeTokenKeys = new Set([
30
+ "inputtokens",
31
+ "outputtokens",
32
+ "tokencount",
33
+ "tokencounts",
34
+ "progresstoken",
35
+ "maxtokens",
36
+ "totaltokens",
37
+ "prompttokens",
38
+ "completiontokens",
39
+ "cachedinputtokens",
40
+ "reasoningtokens",
41
+ ]);
42
+ const EnvironmentNamePattern = /^[A-Za-z_][A-Za-z0-9_]*$/u;
43
+ const EmbeddedUrlPattern = /\b[a-z][a-z0-9+.-]*:\/\/[^\s<>"'`]+|(?<![:\w])\/\/[^\s<>"'`]+/giu;
44
+ /**
45
+ * Redacts credentials from diagnostic values without retaining or emitting the
46
+ * secret source. The result is safe to serialize but deliberately does not
47
+ * preserve object prototypes.
48
+ */
49
+ export class SecretRedactor {
50
+ replacement;
51
+ maxDepth;
52
+ maxStringLength;
53
+ registeredSecretValues = new Set();
54
+ secretValues = [];
55
+ constructor(options = {}) {
56
+ this.replacement = options.replacement ?? DEFAULT_REPLACEMENT;
57
+ this.maxDepth = positiveInteger(options.maxDepth ?? DEFAULT_MAX_DEPTH, "maxDepth");
58
+ this.maxStringLength = positiveInteger(options.maxStringLength ?? DEFAULT_MAX_STRING_LENGTH, "maxStringLength");
59
+ for (const value of options.secretValues ?? []) {
60
+ addSecretValue(this.registeredSecretValues, value, true);
61
+ }
62
+ for (const [name, value] of Object.entries(options.environment ?? {})) {
63
+ if (isCredentialKey(name) && value !== undefined) {
64
+ addSecretValue(this.registeredSecretValues, value, false);
65
+ }
66
+ }
67
+ this.refreshSecretValues();
68
+ }
69
+ /** Registers credential values resolved after construction. */
70
+ registerSecretValues(values) {
71
+ const previousSize = this.registeredSecretValues.size;
72
+ for (const value of values) {
73
+ addSecretValue(this.registeredSecretValues, value, true);
74
+ }
75
+ if (this.registeredSecretValues.size !== previousSize)
76
+ this.refreshSecretValues();
77
+ }
78
+ redact(value) {
79
+ return this.redactValue(value, 0, new WeakSet());
80
+ }
81
+ redactText(value) {
82
+ let redacted = redactEmbeddedUrls(value);
83
+ for (const secret of this.secretValues) {
84
+ redacted = redacted.split(secret).join(this.replacement);
85
+ }
86
+ redacted = redacted
87
+ .replace(/\b(authorization|proxy-authorization|x[-_]?api[-_]?key|api[-_]?key|x[-_]?otlp[-_]?api[-_]?key)\s*[:=]\s*(?:"[^"\r\n]*"|'[^'\r\n]*'|[^\r\n,;}]+)/giu, (_match, name) => `${name}: ${this.replacement}`)
88
+ .replace(/(?<![A-Za-z0-9_])(["']?)(token|access[-_]?token|refresh[-_]?token|auth[-_]?token|session[-_]?token|id[-_]?token|password|passwd|pwd|secret|secret[-_]?key|client[-_]?secret|private[-_]?key)\1(?![A-Za-z0-9_])\s*[:=]\s*(?:"[^"\r\n]*"|'[^'\r\n]*'|[^\r\n,;}]+)/giu, (_match, quote, name) => `${quote}${name}${quote}: ${this.replacement}`)
89
+ .replace(/\b(cookie|set-cookie)\s*[:=]\s*[^\r\n]*/giu, (_match, name) => `${name}: ${this.replacement}`)
90
+ .replace(/\b(bearer|basic)\s+[A-Za-z0-9._~+/=-]+/giu, (_match, scheme) => `${scheme} ${this.replacement}`);
91
+ if (redacted.length <= this.maxStringLength)
92
+ return redacted;
93
+ return `${redacted.slice(0, this.maxStringLength - 1)}…`;
94
+ }
95
+ redactUri(value) {
96
+ try {
97
+ const networkPath = value.startsWith("//");
98
+ const url = networkPath
99
+ ? new URL(value, "http://redaction.invalid")
100
+ : new URL(value);
101
+ url.username = "";
102
+ url.password = "";
103
+ url.search = "";
104
+ url.hash = "";
105
+ const result = networkPath
106
+ ? `//${url.host}${url.pathname}`
107
+ : url.toString();
108
+ return this.redactTextWithoutUrls(result);
109
+ }
110
+ catch {
111
+ return this.redactText(value.split(/[?#]/u, 1)[0]);
112
+ }
113
+ }
114
+ redactValue(value, depth, seen) {
115
+ if (typeof value === "string")
116
+ return this.redactText(value);
117
+ if (value === null ||
118
+ typeof value === "number" ||
119
+ typeof value === "boolean" ||
120
+ typeof value === "undefined") {
121
+ return value;
122
+ }
123
+ if (typeof value === "bigint")
124
+ return value.toString();
125
+ if (typeof value === "symbol" || typeof value === "function")
126
+ return String(value);
127
+ if (depth >= this.maxDepth)
128
+ return "[MAX_DEPTH]";
129
+ if (seen.has(value))
130
+ return "[CIRCULAR]";
131
+ seen.add(value);
132
+ try {
133
+ if (Array.isArray(value)) {
134
+ return value.map((item) => this.redactValue(item, depth + 1, seen));
135
+ }
136
+ if (value instanceof Date)
137
+ return value.toISOString();
138
+ if (value instanceof URL)
139
+ return this.redactUri(value.toString());
140
+ if (value instanceof Error) {
141
+ return {
142
+ name: value.name,
143
+ message: this.redactText(value.message),
144
+ };
145
+ }
146
+ const source = value;
147
+ const semanticKey = semanticCredentialKey(source);
148
+ const result = {};
149
+ for (const [key, child] of Object.entries(source)) {
150
+ if (semanticKey !== undefined && key === "value") {
151
+ result[key] = this.replacement;
152
+ }
153
+ else if (isCredentialKey(key)) {
154
+ result[key] = this.replacement;
155
+ }
156
+ else if (typeof child === "string" && isUriKey(key)) {
157
+ result[key] = this.redactUri(child);
158
+ }
159
+ else {
160
+ result[key] = this.redactValue(child, depth + 1, seen);
161
+ }
162
+ }
163
+ return result;
164
+ }
165
+ finally {
166
+ seen.delete(value);
167
+ }
168
+ }
169
+ redactTextWithoutUrls(value) {
170
+ let redacted = value;
171
+ for (const secret of this.secretValues) {
172
+ redacted = redacted.split(secret).join(this.replacement);
173
+ }
174
+ return redacted;
175
+ }
176
+ refreshSecretValues() {
177
+ this.secretValues = [...this.registeredSecretValues]
178
+ .sort((left, right) => right.length - left.length);
179
+ }
180
+ }
181
+ function semanticCredentialKey(value) {
182
+ if (!("value" in value))
183
+ return undefined;
184
+ for (const field of ["key", "name", "header"]) {
185
+ const candidate = value[field];
186
+ if (typeof candidate === "string" && isCredentialKey(candidate))
187
+ return candidate;
188
+ }
189
+ return undefined;
190
+ }
191
+ export function isCredentialKey(key) {
192
+ const normalized = key.toLowerCase().replace(/[^a-z0-9]/gu, "");
193
+ if ([...SafeTokenKeys].some((safeKey) => normalized.endsWith(safeKey)))
194
+ return false;
195
+ if (SecretKeyNames.has(normalized))
196
+ return true;
197
+ return (normalized.endsWith("apikey") ||
198
+ normalized.endsWith("token") ||
199
+ normalized.endsWith("tokens") ||
200
+ normalized.endsWith("password") ||
201
+ normalized.endsWith("secret") ||
202
+ normalized.endsWith("credential") ||
203
+ normalized.endsWith("accesstoken") ||
204
+ normalized.endsWith("refreshtoken") ||
205
+ normalized.endsWith("accesskeyid") ||
206
+ normalized.endsWith("clientsecret") ||
207
+ normalized.endsWith("privatekey"));
208
+ }
209
+ export function validateEnvironmentVariableName(name) {
210
+ if (!EnvironmentNamePattern.test(name)) {
211
+ throw new Error(`Invalid environment variable name '${name}'.`);
212
+ }
213
+ }
214
+ function redactEmbeddedUrls(value) {
215
+ return value.replace(EmbeddedUrlPattern, (candidate) => {
216
+ const punctuation = /[),.!?]$/u.exec(candidate)?.[0] ?? "";
217
+ const urlText = punctuation ? candidate.slice(0, -1) : candidate;
218
+ try {
219
+ const networkPath = urlText.startsWith("//");
220
+ const url = networkPath
221
+ ? new URL(urlText, "http://redaction.invalid")
222
+ : new URL(urlText);
223
+ url.username = "";
224
+ url.password = "";
225
+ url.search = "";
226
+ url.hash = "";
227
+ const result = networkPath
228
+ ? `//${url.host}${url.pathname}`
229
+ : url.toString();
230
+ return `${result}${punctuation}`;
231
+ }
232
+ catch {
233
+ return candidate;
234
+ }
235
+ });
236
+ }
237
+ function isUriKey(key) {
238
+ const normalized = key.toLowerCase().replace(/[^a-z0-9]/gu, "");
239
+ return normalized === "uri" ||
240
+ normalized.endsWith("uri") ||
241
+ normalized === "url" ||
242
+ normalized.endsWith("url") ||
243
+ normalized === "endpoint";
244
+ }
245
+ function addSecretValue(values, value, explicit) {
246
+ if (value.length > 0 && (explicit || value.length >= 4))
247
+ values.add(value);
248
+ }
249
+ function positiveInteger(value, name) {
250
+ if (!Number.isSafeInteger(value) || value <= 0) {
251
+ throw new Error(`${name} must be a positive integer.`);
252
+ }
253
+ return value;
254
+ }
255
+ //# sourceMappingURL=secret-redactor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-redactor.js","sourceRoot":"","sources":["../src/secret-redactor.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG,YAAY,CAAC;AACzC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAC7B,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEzC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,eAAe;IACf,oBAAoB;IACpB,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,WAAW;IACX,cAAc;IACd,UAAU;IACV,QAAQ;IACR,KAAK;IACL,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,OAAO;IACP,aAAa;IACb,cAAc;IACd,WAAW;IACX,aAAa;IACb,cAAc;IACd,YAAY;IACZ,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,aAAa;IACb,cAAc;IACd,YAAY;IACZ,aAAa;IACb,eAAe;IACf,WAAW;IACX,aAAa;IACb,cAAc;IACd,kBAAkB;IAClB,mBAAmB;IACnB,iBAAiB;CAClB,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,2BAA2B,CAAC;AAC3D,MAAM,kBAAkB,GAAG,kEAAkE,CAAC;AAU9F;;;;GAIG;AACH,MAAM,OAAO,cAAc;IAChB,WAAW,CAAS;IACZ,QAAQ,CAAS;IACjB,eAAe,CAAS;IACxB,sBAAsB,GAAG,IAAI,GAAG,EAAU,CAAC;IACpD,YAAY,GAAsB,EAAE,CAAC;IAE7C,YAAY,OAAO,GAA0B,EAAE;QAC7C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,mBAAmB,CAAC;QAC9D,IAAI,CAAC,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,IAAI,iBAAiB,EAAE,UAAU,CAAC,CAAC;QACnF,IAAI,CAAC,eAAe,GAAG,eAAe,CACpC,OAAO,CAAC,eAAe,IAAI,yBAAyB,EACpD,iBAAiB,CAClB,CAAC;QAEF,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;YAC/C,cAAc,CAAC,IAAI,CAAC,sBAAsB,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC3D,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,CAAC;YACtE,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACjD,cAAc,CAAC,IAAI,CAAC,sBAAsB,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QACD,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAED,+DAA+D;IAC/D,oBAAoB,CAAC,MAAyB;QAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC;QACtD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,cAAc,CAAC,IAAI,CAAC,sBAAsB,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,IAAI,CAAC,sBAAsB,CAAC,IAAI,KAAK,YAAY;YAAE,IAAI,CAAC,mBAAmB,EAAE,CAAC;IACpF,CAAC;IAED,MAAM,CAAC,KAAc;QACnB,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,OAAO,EAAU,CAAC,CAAC;IAC3D,CAAC;IAED,UAAU,CAAC,KAAa;QACtB,IAAI,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAEzC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3D,CAAC;QAED,QAAQ,GAAG,QAAQ;aAChB,OAAO,CACN,oJAAoJ,EACpJ,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,CACzD;aACA,OAAO,CACN,oQAAoQ,EACpQ,CAAC,MAAM,EAAE,KAAa,EAAE,IAAY,EAAE,EAAE,CACtC,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,WAAW,EAAE,CACjD;aACA,OAAO,CACN,4CAA4C,EAC5C,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,CACzD;aACA,OAAO,CACN,2CAA2C,EAC3C,CAAC,MAAM,EAAE,MAAc,EAAE,EAAE,CAAC,GAAG,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAC5D,CAAC;QAEJ,IAAI,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO,QAAQ,CAAC;QAC7D,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC,GAAG,CAAC;IAC3D,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAC3C,MAAM,GAAG,GAAG,WAAW;gBACrB,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,0BAA0B,CAAC;gBAC5C,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;YACnB,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC;YAClB,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC;YAClB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;YAChB,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,WAAW;gBACxB,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE;gBAChC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,KAAc,EAAE,KAAa,EAAE,IAAqB;QACtE,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC7D,IACE,KAAK,KAAK,IAAI;YACd,OAAO,KAAK,KAAK,QAAQ;YACzB,OAAO,KAAK,KAAK,SAAS;YAC1B,OAAO,KAAK,KAAK,WAAW,EAC5B,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;QACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,UAAU;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACnF,IAAI,KAAK,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,aAAa,CAAC;QAEjD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO,YAAY,CAAC;QACzC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChB,IAAI,CAAC;YACH,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YACtE,CAAC;YACD,IAAI,KAAK,YAAY,IAAI;gBAAE,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;YACtD,IAAI,KAAK,YAAY,GAAG;gBAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YAClE,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,OAAO;oBACL,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;iBACxC,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,KAAgC,CAAC;YAChD,MAAM,WAAW,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;YAClD,MAAM,MAAM,GAA4B,EAAE,CAAC;YAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClD,IAAI,WAAW,KAAK,SAAS,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;oBACjD,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC;gBACjC,CAAC;qBAAM,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;oBAChC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC;gBACjC,CAAC;qBAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtD,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBACtC,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;gBACzD,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAEO,qBAAqB,CAAC,KAAa;QACzC,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEO,mBAAmB;QACzB,IAAI,CAAC,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,sBAAsB,CAAC;aACjD,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IACvD,CAAC;CACF;AAED,SAAS,qBAAqB,CAAC,KAAwC;IACrE,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAU,EAAE,CAAC;QACvD,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,eAAe,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IACpF,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAChE,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrF,IAAI,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,OAAO,CACL,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC7B,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC;QAC5B,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC7B,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC/B,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC7B,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC;QACjC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC;QAClC,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC;QACnC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC;QAClC,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC;QACnC,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,CAClC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,IAAY;IAC1D,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,sCAAsC,IAAI,IAAI,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACvC,OAAO,KAAK,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,SAAS,EAAE,EAAE;QACrD,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3D,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACjE,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,GAAG,GAAG,WAAW;gBACrB,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,0BAA0B,CAAC;gBAC9C,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;YACrB,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC;YAClB,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC;YAClB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;YAChB,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,WAAW;gBACxB,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE;gBAChC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO,GAAG,MAAM,GAAG,WAAW,EAAE,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAChE,OAAO,UAAU,KAAK,KAAK;QACzB,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC1B,UAAU,KAAK,KAAK;QACpB,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC1B,UAAU,KAAK,UAAU,CAAC;AAC9B,CAAC;AAED,SAAS,cAAc,CAAC,MAAmB,EAAE,KAAa,EAAE,QAAiB;IAC3E,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,eAAe,CAAC,KAAa,EAAE,IAAY;IAClD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,8BAA8B,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * qyl telemetry MCP Apps server (the visual half of qyl.mcp).
3
+ *
4
+ * Tool surface:
5
+ * - display_traces: trace explorer UI (waterfall + logs) — THE app tool
6
+ * - display_mcp_dashboard: aggregate MCP traffic dashboard UI
7
+ * - list_traces, get_trace, list_sessions, search_logs: direct read tools
8
+ * - fetch_telemetry: app-only (viewer iframes; hidden from the model)
9
+ *
10
+ * Modes: live against the qyl collector REST API (QYL_COLLECTOR_URL, default
11
+ * http://127.0.0.1:5100), or explicit generated demo telemetry when
12
+ * QYL_DEMO=1. A collector failure remains an error and never changes modes.
13
+ */
14
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
15
+ import type { McpTelemetryTransport } from "./mcp-semconv.js";
16
+ import { type NativeExecutionRuntime } from "./native-execution.js";
17
+ export { closeDefaultNativeExecutionRuntime, hasNativeExecutionTelemetry, } from "./native-execution.js";
18
+ export interface CreateServerOptions {
19
+ /** Transport identity recorded on native server spans and durable evidence. */
20
+ transport?: McpTelemetryTransport;
21
+ /** Test/embedding override. Native evidence is automatic unless explicitly disabled. */
22
+ nativeExecution?: NativeExecutionRuntime | false;
23
+ }
24
+ /** Creates a server with automatic native execution evidence for every tool. */
25
+ export declare function createServer(options?: CreateServerOptions): McpServer;
package/dist/server.js ADDED
@@ -0,0 +1,207 @@
1
+ /**
2
+ * qyl telemetry MCP Apps server (the visual half of qyl.mcp).
3
+ *
4
+ * Tool surface:
5
+ * - display_traces: trace explorer UI (waterfall + logs) — THE app tool
6
+ * - display_mcp_dashboard: aggregate MCP traffic dashboard UI
7
+ * - list_traces, get_trace, list_sessions, search_logs: direct read tools
8
+ * - fetch_telemetry: app-only (viewer iframes; hidden from the model)
9
+ *
10
+ * Modes: live against the qyl collector REST API (QYL_COLLECTOR_URL, default
11
+ * http://127.0.0.1:5100), or explicit generated demo telemetry when
12
+ * QYL_DEMO=1. A collector failure remains an error and never changes modes.
13
+ */
14
+ import { registerAppResource, registerAppTool, RESOURCE_MIME_TYPE, } from "@modelcontextprotocol/ext-apps/server";
15
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
16
+ import fs from "node:fs/promises";
17
+ import path from "node:path";
18
+ import packageMetadata from "../package.json" with { type: "json" };
19
+ import { DASHBOARD_RESOURCE_URI, RESOURCE_URI } from "./config.js";
20
+ import { CollectorError } from "./collector.js";
21
+ import { DisplayMcpDashboardInputSchema, DisplayMcpDashboardOutputSchema, DisplayTracesInputSchema, DisplayTracesOutputSchema, FetchTelemetryInputSchema, FetchTelemetryOutputSchema, } from "./contract-validation.js";
22
+ import { fetchLogs, fetchMcpStats, fetchTrace, fetchTraces, fetchTracesForDisplay, } from "./data.js";
23
+ import { humanizeNs, rootSpanName, shortId, summarizeMcpStats, } from "./summaries.js";
24
+ import { READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS, registerTelemetryTools, toolError, } from "./tools.js";
25
+ import { registerCiTools } from "./ci.js";
26
+ import { telemetryToolResult } from "./telemetry-redaction.js";
27
+ import { defaultNativeExecutionRuntime, installNativeExecutionRecording, } from "./native-execution.js";
28
+ export { closeDefaultNativeExecutionRuntime, hasNativeExecutionTelemetry, } from "./native-execution.js";
29
+ // The vite-built single-file viewers live next to the compiled server code.
30
+ const DIST_DIR = import.meta.dirname;
31
+ // Cached across createServer() calls — in stateless HTTP deployments a fresh
32
+ // server is created per request and per-instance caches would be useless.
33
+ let cachedAppHtml;
34
+ let cachedDashboardHtml;
35
+ /** Creates a server with automatic native execution evidence for every tool. */
36
+ export function createServer(options = {}) {
37
+ const server = new McpServer({
38
+ name: "qyl.mcp",
39
+ version: packageMetadata.version,
40
+ });
41
+ if (options.nativeExecution !== false) {
42
+ installNativeExecutionRecording(server, options.nativeExecution ?? defaultNativeExecutionRuntime(), options.transport ?? "builtin");
43
+ }
44
+ registerAppTool(server, "display_traces", {
45
+ title: "Display Traces",
46
+ description: "Show qyl traces in the interactive trace explorer with a span waterfall, " +
47
+ "detail panel, and correlated logs. Pass a trace_id to open one trace, a " +
48
+ "session_id for that session's traces, or neither for recent traces. Prefer " +
49
+ "this over list_traces/get_trace whenever the user wants to " +
50
+ "look at traces.",
51
+ inputSchema: DisplayTracesInputSchema,
52
+ outputSchema: DisplayTracesOutputSchema,
53
+ annotations: READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS,
54
+ _meta: { ui: { resourceUri: RESOURCE_URI } },
55
+ }, async ({ trace_id, session_id, limit }) => {
56
+ try {
57
+ const result = await fetchTracesForDisplay({
58
+ trace_id,
59
+ session_id,
60
+ limit: limit ?? 20,
61
+ });
62
+ let text;
63
+ if (result.selected_trace_id) {
64
+ const trace = result.traces[0];
65
+ text =
66
+ `Showing trace ${shortId(trace.trace_id)} (${rootSpanName(trace)}, ` +
67
+ `${trace.span_count} spans, ${humanizeNs(trace.duration_ns)}) in the qyl explorer` +
68
+ `${result.mode === "demo" ? " (demo data)" : ""}.`;
69
+ }
70
+ else {
71
+ const errorCount = result.traces.filter((t) => t.has_error).length;
72
+ const scope = session_id ? `session ${session_id}` : "recent";
73
+ text =
74
+ `Showing ${result.traces.length} ${scope} traces in the qyl explorer` +
75
+ `${errorCount > 0 ? ` (${errorCount} with errors)` : ""}` +
76
+ `${result.mode === "demo" ? " (demo data)" : ""}.`;
77
+ }
78
+ const output = {
79
+ traces: result.traces,
80
+ ...(result.selected_trace_id
81
+ ? { selected_trace_id: result.selected_trace_id }
82
+ : {}),
83
+ mode: result.mode,
84
+ };
85
+ return telemetryToolResult(text, output);
86
+ }
87
+ catch (err) {
88
+ return toolError(err);
89
+ }
90
+ });
91
+ registerAppTool(server, "display_mcp_dashboard", {
92
+ title: "Display MCP Dashboard",
93
+ description: "Show an aggregate dashboard of MCP traffic (spans carrying an " +
94
+ "`mcp.method.name` attribute): request/error timeline, per-server and " +
95
+ "per-transport breakdowns, and per-tool latency and error " +
96
+ "rates. Prefer this when the user asks about MCP usage, tool health, " +
97
+ "or MCP monitoring.",
98
+ inputSchema: DisplayMcpDashboardInputSchema,
99
+ outputSchema: DisplayMcpDashboardOutputSchema,
100
+ annotations: READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS,
101
+ _meta: { ui: { resourceUri: DASHBOARD_RESOURCE_URI } },
102
+ }, async ({ hours }) => {
103
+ try {
104
+ const window = hours ?? 24;
105
+ const stats = await fetchMcpStats(window);
106
+ const output = { stats };
107
+ return telemetryToolResult(summarizeMcpStats(stats, window), output);
108
+ }
109
+ catch (err) {
110
+ return toolError(err);
111
+ }
112
+ });
113
+ registerTelemetryTools(server);
114
+ registerCiTools(server);
115
+ registerAppTool(server, "fetch_telemetry", {
116
+ title: "Fetch Telemetry",
117
+ description: "Fetch traces, a single trace, or logs for the trace explorer UI. " +
118
+ "The model should NOT call this tool directly.",
119
+ inputSchema: FetchTelemetryInputSchema,
120
+ outputSchema: FetchTelemetryOutputSchema,
121
+ annotations: READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS,
122
+ _meta: { ui: { visibility: ["app"] } },
123
+ }, async ({ view, trace_id, service_name, severity_min, query, limit, hours, }) => {
124
+ try {
125
+ if (view === "mcp_stats") {
126
+ const stats = await fetchMcpStats(hours ?? 24);
127
+ const output = { stats, mode: stats.mode };
128
+ return telemetryToolResult(`Fetched MCP stats: ${stats.totals.requests} requests over ${hours ?? 24}h (${stats.mode} mode).`, output);
129
+ }
130
+ if (view === "trace") {
131
+ if (!trace_id) {
132
+ throw new CollectorError('view "trace" requires a `trace_id`.');
133
+ }
134
+ const { trace, mode } = await fetchTrace(trace_id);
135
+ const output = { trace, mode };
136
+ return telemetryToolResult(`Fetched trace ${shortId(trace.trace_id)} (${trace.span_count} spans, ${mode} mode).`, output);
137
+ }
138
+ if (view === "logs") {
139
+ const { logs, mode } = await fetchLogs({
140
+ trace_id,
141
+ service_name,
142
+ severity_min,
143
+ query,
144
+ limit: limit ?? 50,
145
+ });
146
+ const output = { logs, mode };
147
+ return telemetryToolResult(`Fetched ${logs.length} logs (${mode} mode).`, output);
148
+ }
149
+ const { traces, mode } = await fetchTraces(limit ?? 20);
150
+ const output = { traces, mode };
151
+ return telemetryToolResult(`Fetched ${traces.length} traces (${mode} mode).`, output);
152
+ }
153
+ catch (err) {
154
+ return toolError(err);
155
+ }
156
+ });
157
+ registerAppResource(server, RESOURCE_URI, RESOURCE_URI, { mimeType: RESOURCE_MIME_TYPE }, async () => {
158
+ const html = (cachedAppHtml ??= await fs.readFile(path.join(DIST_DIR, "mcp-app.html"), "utf-8"));
159
+ return {
160
+ contents: [
161
+ {
162
+ uri: RESOURCE_URI,
163
+ mimeType: RESOURCE_MIME_TYPE,
164
+ text: html,
165
+ _meta: {
166
+ ui: {
167
+ csp: {
168
+ connectDomains: [],
169
+ resourceDomains: [],
170
+ },
171
+ },
172
+ },
173
+ },
174
+ ],
175
+ };
176
+ });
177
+ registerAppResource(server, DASHBOARD_RESOURCE_URI, DASHBOARD_RESOURCE_URI, { mimeType: RESOURCE_MIME_TYPE }, async () => {
178
+ if (cachedDashboardHtml === undefined) {
179
+ try {
180
+ cachedDashboardHtml = await fs.readFile(path.join(DIST_DIR, "mcp-dashboard.html"), "utf-8");
181
+ }
182
+ catch {
183
+ throw new Error("dashboard UI not built yet: dist/mcp-dashboard.html is missing — " +
184
+ "build the mcp-dashboard.html vite entry (`npm run build`) first");
185
+ }
186
+ }
187
+ return {
188
+ contents: [
189
+ {
190
+ uri: DASHBOARD_RESOURCE_URI,
191
+ mimeType: RESOURCE_MIME_TYPE,
192
+ text: cachedDashboardHtml,
193
+ _meta: {
194
+ ui: {
195
+ csp: {
196
+ connectDomains: [],
197
+ resourceDomains: [],
198
+ },
199
+ },
200
+ },
201
+ },
202
+ ],
203
+ };
204
+ });
205
+ return server;
206
+ }
207
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * MCP dashboard aggregation — shared verbatim by the demo and live paths so
3
+ * the demo dataset exercises exactly the code that renders production stats.
4
+ */
5
+ import type { McpDashboardStats, QylSpan } from "./wire.js";
6
+ export declare function spanAttr(span: QylSpan, key: string): string | undefined;
7
+ /**
8
+ * Pick a clean bucket size that tiles the window into 24–48 buckets.
9
+ * For every integer hours in 1–168 the resulting count lands in range.
10
+ */
11
+ export declare function pickBucketMs(windowMs: number): number;
12
+ /**
13
+ * Aggregate flattened spans into McpDashboardStats (minus mode/truncated,
14
+ * which depend on the data source). Classified MCP spans starting inside
15
+ * [windowStart, windowEnd] count; durations come from the span nano fields;
16
+ * error = status.code 2.
17
+ */
18
+ export declare function aggregateMcpStats(spans: QylSpan[], windowStart: number, windowEnd: number, bucketMs: number): Omit<McpDashboardStats, "mode" | "truncated">;