@testrelic/mcp 2.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 (204) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +198 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/cache/blob.d.ts +22 -0
  5. package/dist/cache/blob.d.ts.map +1 -0
  6. package/dist/cache/blob.js +92 -0
  7. package/dist/cache/blob.js.map +1 -0
  8. package/dist/cache/diff-reader.d.ts +29 -0
  9. package/dist/cache/diff-reader.d.ts.map +1 -0
  10. package/dist/cache/diff-reader.js +34 -0
  11. package/dist/cache/diff-reader.js.map +1 -0
  12. package/dist/cache/index.d.ts +57 -0
  13. package/dist/cache/index.d.ts.map +1 -0
  14. package/dist/cache/index.js +99 -0
  15. package/dist/cache/index.js.map +1 -0
  16. package/dist/cache/key.d.ts +15 -0
  17. package/dist/cache/key.d.ts.map +1 -0
  18. package/dist/cache/key.js +32 -0
  19. package/dist/cache/key.js.map +1 -0
  20. package/dist/cache/lru.d.ts +21 -0
  21. package/dist/cache/lru.d.ts.map +1 -0
  22. package/dist/cache/lru.js +32 -0
  23. package/dist/cache/lru.js.map +1 -0
  24. package/dist/cache/sqlite.d.ts +22 -0
  25. package/dist/cache/sqlite.d.ts.map +1 -0
  26. package/dist/cache/sqlite.js +102 -0
  27. package/dist/cache/sqlite.js.map +1 -0
  28. package/dist/cache/vector.d.ts +42 -0
  29. package/dist/cache/vector.d.ts.map +1 -0
  30. package/dist/cache/vector.js +187 -0
  31. package/dist/cache/vector.js.map +1 -0
  32. package/dist/cli.d.ts +3 -0
  33. package/dist/cli.d.ts.map +1 -0
  34. package/dist/cli.js +205 -0
  35. package/dist/cli.js.map +1 -0
  36. package/dist/clients/amplitude.d.ts +24 -0
  37. package/dist/clients/amplitude.d.ts.map +1 -0
  38. package/dist/clients/amplitude.js +15 -0
  39. package/dist/clients/amplitude.js.map +1 -0
  40. package/dist/clients/clickhouse.d.ts +10 -0
  41. package/dist/clients/clickhouse.d.ts.map +1 -0
  42. package/dist/clients/clickhouse.js +8 -0
  43. package/dist/clients/clickhouse.js.map +1 -0
  44. package/dist/clients/cloud.d.ts +347 -0
  45. package/dist/clients/cloud.d.ts.map +1 -0
  46. package/dist/clients/cloud.js +402 -0
  47. package/dist/clients/cloud.js.map +1 -0
  48. package/dist/clients/http.d.ts +40 -0
  49. package/dist/clients/http.d.ts.map +1 -0
  50. package/dist/clients/http.js +67 -0
  51. package/dist/clients/http.js.map +1 -0
  52. package/dist/clients/index.d.ts +38 -0
  53. package/dist/clients/index.d.ts.map +1 -0
  54. package/dist/clients/index.js +24 -0
  55. package/dist/clients/index.js.map +1 -0
  56. package/dist/clients/jira.d.ts +16 -0
  57. package/dist/clients/jira.d.ts.map +1 -0
  58. package/dist/clients/jira.js +11 -0
  59. package/dist/clients/jira.js.map +1 -0
  60. package/dist/clients/loki.d.ts +7 -0
  61. package/dist/clients/loki.d.ts.map +1 -0
  62. package/dist/clients/loki.js +8 -0
  63. package/dist/clients/loki.js.map +1 -0
  64. package/dist/clients/retry.d.ts +28 -0
  65. package/dist/clients/retry.d.ts.map +1 -0
  66. package/dist/clients/retry.js +79 -0
  67. package/dist/clients/retry.js.map +1 -0
  68. package/dist/clients/testrelic.d.ts +90 -0
  69. package/dist/clients/testrelic.d.ts.map +1 -0
  70. package/dist/clients/testrelic.js +68 -0
  71. package/dist/clients/testrelic.js.map +1 -0
  72. package/dist/config.d.ts +216 -0
  73. package/dist/config.d.ts.map +1 -0
  74. package/dist/config.js +233 -0
  75. package/dist/config.js.map +1 -0
  76. package/dist/context/code-map.d.ts +35 -0
  77. package/dist/context/code-map.d.ts.map +1 -0
  78. package/dist/context/code-map.js +187 -0
  79. package/dist/context/code-map.js.map +1 -0
  80. package/dist/context/correlator.d.ts +32 -0
  81. package/dist/context/correlator.d.ts.map +1 -0
  82. package/dist/context/correlator.js +106 -0
  83. package/dist/context/correlator.js.map +1 -0
  84. package/dist/context/coverage-map.d.ts +25 -0
  85. package/dist/context/coverage-map.d.ts.map +1 -0
  86. package/dist/context/coverage-map.js +44 -0
  87. package/dist/context/coverage-map.js.map +1 -0
  88. package/dist/context/index.d.ts +20 -0
  89. package/dist/context/index.d.ts.map +1 -0
  90. package/dist/context/index.js +18 -0
  91. package/dist/context/index.js.map +1 -0
  92. package/dist/context/journey-graph.d.ts +22 -0
  93. package/dist/context/journey-graph.d.ts.map +1 -0
  94. package/dist/context/journey-graph.js +38 -0
  95. package/dist/context/journey-graph.js.map +1 -0
  96. package/dist/context/signal-map.d.ts +26 -0
  97. package/dist/context/signal-map.d.ts.map +1 -0
  98. package/dist/context/signal-map.js +30 -0
  99. package/dist/context/signal-map.js.map +1 -0
  100. package/dist/elicit/ask.d.ts +28 -0
  101. package/dist/elicit/ask.d.ts.map +1 -0
  102. package/dist/elicit/ask.js +31 -0
  103. package/dist/elicit/ask.js.map +1 -0
  104. package/dist/elicit/zod-to-json.d.ts +7 -0
  105. package/dist/elicit/zod-to-json.d.ts.map +1 -0
  106. package/dist/elicit/zod-to-json.js +37 -0
  107. package/dist/elicit/zod-to-json.js.map +1 -0
  108. package/dist/errors.d.ts +59 -0
  109. package/dist/errors.d.ts.map +1 -0
  110. package/dist/errors.js +122 -0
  111. package/dist/errors.js.map +1 -0
  112. package/dist/index.d.ts +43 -0
  113. package/dist/index.d.ts.map +1 -0
  114. package/dist/index.js +127 -0
  115. package/dist/index.js.map +1 -0
  116. package/dist/logger.d.ts +6 -0
  117. package/dist/logger.d.ts.map +1 -0
  118. package/dist/logger.js +29 -0
  119. package/dist/logger.js.map +1 -0
  120. package/dist/prompts/index.d.ts +8 -0
  121. package/dist/prompts/index.d.ts.map +1 -0
  122. package/dist/prompts/index.js +86 -0
  123. package/dist/prompts/index.js.map +1 -0
  124. package/dist/registry/index.d.ts +70 -0
  125. package/dist/registry/index.d.ts.map +1 -0
  126. package/dist/registry/index.js +88 -0
  127. package/dist/registry/index.js.map +1 -0
  128. package/dist/registry/project.d.ts +20 -0
  129. package/dist/registry/project.d.ts.map +1 -0
  130. package/dist/registry/project.js +44 -0
  131. package/dist/registry/project.js.map +1 -0
  132. package/dist/resources/index.d.ts +13 -0
  133. package/dist/resources/index.d.ts.map +1 -0
  134. package/dist/resources/index.js +76 -0
  135. package/dist/resources/index.js.map +1 -0
  136. package/dist/sampling/bridge.d.ts +35 -0
  137. package/dist/sampling/bridge.d.ts.map +1 -0
  138. package/dist/sampling/bridge.js +39 -0
  139. package/dist/sampling/bridge.js.map +1 -0
  140. package/dist/telemetry/metrics.d.ts +29 -0
  141. package/dist/telemetry/metrics.d.ts.map +1 -0
  142. package/dist/telemetry/metrics.js +46 -0
  143. package/dist/telemetry/metrics.js.map +1 -0
  144. package/dist/telemetry/tokens.d.ts +16 -0
  145. package/dist/telemetry/tokens.d.ts.map +1 -0
  146. package/dist/telemetry/tokens.js +40 -0
  147. package/dist/telemetry/tokens.js.map +1 -0
  148. package/dist/tools/core/index.d.ts +8 -0
  149. package/dist/tools/core/index.d.ts.map +1 -0
  150. package/dist/tools/core/index.js +219 -0
  151. package/dist/tools/core/index.js.map +1 -0
  152. package/dist/tools/coverage/index.d.ts +9 -0
  153. package/dist/tools/coverage/index.d.ts.map +1 -0
  154. package/dist/tools/coverage/index.js +247 -0
  155. package/dist/tools/coverage/index.js.map +1 -0
  156. package/dist/tools/creation/index.d.ts +9 -0
  157. package/dist/tools/creation/index.d.ts.map +1 -0
  158. package/dist/tools/creation/index.js +357 -0
  159. package/dist/tools/creation/index.js.map +1 -0
  160. package/dist/tools/creation/templates.d.ts +17 -0
  161. package/dist/tools/creation/templates.d.ts.map +1 -0
  162. package/dist/tools/creation/templates.js +63 -0
  163. package/dist/tools/creation/templates.js.map +1 -0
  164. package/dist/tools/devtools/index.d.ts +9 -0
  165. package/dist/tools/devtools/index.d.ts.map +1 -0
  166. package/dist/tools/devtools/index.js +106 -0
  167. package/dist/tools/devtools/index.js.map +1 -0
  168. package/dist/tools/healing/index.d.ts +10 -0
  169. package/dist/tools/healing/index.d.ts.map +1 -0
  170. package/dist/tools/healing/index.js +190 -0
  171. package/dist/tools/healing/index.js.map +1 -0
  172. package/dist/tools/impact/index.d.ts +8 -0
  173. package/dist/tools/impact/index.d.ts.map +1 -0
  174. package/dist/tools/impact/index.js +215 -0
  175. package/dist/tools/impact/index.js.map +1 -0
  176. package/dist/tools/index.d.ts +9 -0
  177. package/dist/tools/index.d.ts.map +1 -0
  178. package/dist/tools/index.js +29 -0
  179. package/dist/tools/index.js.map +1 -0
  180. package/dist/tools/signals/index.d.ts +9 -0
  181. package/dist/tools/signals/index.d.ts.map +1 -0
  182. package/dist/tools/signals/index.js +100 -0
  183. package/dist/tools/signals/index.js.map +1 -0
  184. package/dist/tools/triage/index.d.ts +9 -0
  185. package/dist/tools/triage/index.d.ts.map +1 -0
  186. package/dist/tools/triage/index.js +366 -0
  187. package/dist/tools/triage/index.js.map +1 -0
  188. package/dist/transport/http.d.ts +16 -0
  189. package/dist/transport/http.d.ts.map +1 -0
  190. package/dist/transport/http.js +110 -0
  191. package/dist/transport/http.js.map +1 -0
  192. package/dist/transport/stdio.d.ts +6 -0
  193. package/dist/transport/stdio.d.ts.map +1 -0
  194. package/dist/transport/stdio.js +19 -0
  195. package/dist/transport/stdio.js.map +1 -0
  196. package/dist/types/index.d.ts +268 -0
  197. package/dist/types/index.d.ts.map +1 -0
  198. package/dist/types/index.js +6 -0
  199. package/dist/types/index.js.map +1 -0
  200. package/dist/version.d.ts +7 -0
  201. package/dist/version.d.ts.map +1 -0
  202. package/dist/version.js +7 -0
  203. package/dist/version.js.map +1 -0
  204. package/package.json +84 -0
@@ -0,0 +1,366 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Triage capability — migration of the v1 tool set, plus one new entry
4
+ * (tr_search_failures → v1 search-failures). Every v2 tool registers an
5
+ * alias under its old flat name so existing integrations keep working.
6
+ */
7
+ export const triageTools = [
8
+ {
9
+ name: "tr_diagnose_run",
10
+ capability: "triage",
11
+ title: "Diagnose a failing run",
12
+ description: "Pulls run metadata, all failures, and ClickHouse flakiness scores; returns a compact diagnostic with video markers (when include_video is true).",
13
+ inputSchema: {
14
+ run_id: z.string(),
15
+ include_video: z.boolean().optional().default(false),
16
+ },
17
+ aliases: [{ name: "testrelic_diagnose_failure", description: "Diagnose a failing run." }],
18
+ handler: async (input, ctx) => {
19
+ const run_id = input.run_id;
20
+ const include_video = input.include_video;
21
+ const [run, failureData, flakinessData] = await Promise.all([
22
+ ctx.clients.testrelic.getRun(run_id),
23
+ ctx.clients.testrelic.getRunFailures(run_id),
24
+ ctx.clients.clickhouse.queryFlakinessScores(run_id).catch(() => ({ data: [], rows: 0 })),
25
+ ]);
26
+ if (run.status === "passed") {
27
+ return { text: `Run ${run_id} passed all ${run.total} tests in ${(run.duration_ms / 1000).toFixed(1)}s.`, structured: { run } };
28
+ }
29
+ const flakinessMap = new Map(flakinessData.data.map((f) => [f.test_id, f]));
30
+ const { failures } = failureData;
31
+ const lines = [
32
+ `## Failure Diagnosis: ${run_id}`,
33
+ "",
34
+ `**Run summary:** ${run.failed} failed / ${run.flaky} flaky / ${run.passed} passed (${run.total} total)`,
35
+ `**Branch:** ${run.branch} | **Commit:** ${run.commit_sha}`,
36
+ `**Started:** ${run.started_at} | **Duration:** ${(run.duration_ms / 1000).toFixed(1)}s`,
37
+ "",
38
+ `### Failures (${failures.length})`,
39
+ "",
40
+ ];
41
+ for (const f of failures) {
42
+ const flakiness = flakinessMap.get(f.test_id);
43
+ lines.push(`#### ${f.test_name}`);
44
+ lines.push(`- **Error type:** ${f.error_type}`);
45
+ lines.push(`- **Message:** ${f.error_message}`);
46
+ if (flakiness) {
47
+ lines.push(`- **Flakiness:** ${(flakiness.flakiness_score * 100).toFixed(0)}% (${flakiness.failure_count_7d}/${flakiness.run_count_7d} in 7d)`);
48
+ }
49
+ if (f.retry_count > 0)
50
+ lines.push(`- **Retried:** ${f.retry_count}x`);
51
+ if (include_video && f.video_url)
52
+ lines.push(`- **Video:** ${f.video_url} @ ${(f.video_timestamp_ms / 1000).toFixed(1)}s`);
53
+ lines.push("");
54
+ }
55
+ return { text: lines.join("\n"), structured: { run, failures, flakiness: flakinessData.data } };
56
+ },
57
+ },
58
+ {
59
+ name: "tr_flaky_audit",
60
+ capability: "triage",
61
+ title: "Flaky-test audit",
62
+ description: "Ranks flaky tests above a threshold over a lookback window.",
63
+ inputSchema: {
64
+ project_id: z.string().optional(),
65
+ days: z.number().int().min(1).max(90).optional().default(7),
66
+ threshold: z.number().min(0).max(1).optional().default(0.3),
67
+ },
68
+ aliases: [{ name: "testrelic_get_flaky_tests", description: "Ranks flaky tests." }],
69
+ handler: async (input, ctx) => {
70
+ const result = await ctx.clients.testrelic.getFlakyTests({
71
+ project_id: input.project_id,
72
+ days: input.days,
73
+ threshold: input.threshold,
74
+ });
75
+ if (!result.data.length)
76
+ return { text: `No flaky tests above threshold.`, structured: { tests: [], total: 0 } };
77
+ const lines = [`## Flaky Tests (${result.total} above threshold, last ${input.days ?? 7} days)`, ""];
78
+ for (const t of result.data) {
79
+ const scoreBar = "█".repeat(Math.round(t.flakiness_score * 10)) + "░".repeat(10 - Math.round(t.flakiness_score * 10));
80
+ lines.push(`- **${t.test_name}**${t.known_flaky ? ` [known: ${t.known_flaky_reason}]` : ""}`);
81
+ lines.push(` ${(t.flakiness_score * 100).toFixed(0)}% ${scoreBar} | ${t.failure_count}/${t.failure_count + t.pass_count} | ${t.suite} | ${t.test_id}`);
82
+ }
83
+ return { text: lines.join("\n"), structured: { tests: result.data, total: result.total } };
84
+ },
85
+ },
86
+ {
87
+ name: "tr_compare_runs",
88
+ capability: "triage",
89
+ title: "Compare two runs",
90
+ description: "Diffs two runs for regressions, fixes, and persistent failures.",
91
+ inputSchema: {
92
+ run_id_a: z.string(),
93
+ run_id_b: z.string(),
94
+ },
95
+ aliases: [{ name: "testrelic_compare_runs", description: "Diff two runs." }],
96
+ handler: async (input, ctx) => {
97
+ const [runA, runB, failuresA, failuresB] = await Promise.all([
98
+ ctx.clients.testrelic.getRun(input.run_id_a),
99
+ ctx.clients.testrelic.getRun(input.run_id_b),
100
+ ctx.clients.testrelic.getRunFailures(input.run_id_a),
101
+ ctx.clients.testrelic.getRunFailures(input.run_id_b),
102
+ ]);
103
+ const failingInA = new Set(failuresA.failures.map((f) => f.test_id));
104
+ const failingInB = new Set(failuresB.failures.map((f) => f.test_id));
105
+ const regressions = failuresA.failures.filter((f) => !failingInB.has(f.test_id));
106
+ const fixes = failuresB.failures.filter((f) => !failingInA.has(f.test_id));
107
+ const persistent = failuresA.failures.filter((f) => failingInB.has(f.test_id));
108
+ const text = [
109
+ `## Compare ${input.run_id_a} vs ${input.run_id_b}`,
110
+ "",
111
+ `| | ${input.run_id_a} | ${input.run_id_b} |`,
112
+ `|---|---|---|`,
113
+ `| status | ${runA.status} | ${runB.status} |`,
114
+ `| failed | ${runA.failed} | ${runB.failed} |`,
115
+ `| flaky | ${runA.flaky} | ${runB.flaky} |`,
116
+ "",
117
+ `**Regressions:** ${regressions.length} · **Fixes:** ${fixes.length} · **Persistent:** ${persistent.length}`,
118
+ ].join("\n");
119
+ return { text, structured: { regressions, fixes, persistent } };
120
+ },
121
+ },
122
+ {
123
+ name: "tr_search_failures",
124
+ capability: "triage",
125
+ title: "Search failures by text",
126
+ description: "Searches recent failed runs for text matches across test names, error messages, and stack traces.",
127
+ inputSchema: {
128
+ query: z.string(),
129
+ project_id: z.string().optional(),
130
+ date_range: z.string().optional(),
131
+ },
132
+ aliases: [{ name: "testrelic_search_failures", description: "Search recent failures by text." }],
133
+ handler: async (input, ctx) => {
134
+ const allRuns = (await ctx.clients.testrelic.listRuns({ project_id: input.project_id, status: "failed", limit: 20 })).data;
135
+ let filtered = allRuns;
136
+ if (input.date_range) {
137
+ const [from, to] = input.date_range.split("/");
138
+ filtered = allRuns.filter((r) => {
139
+ const d = r.started_at.split("T")[0];
140
+ return from && to && d !== undefined && d >= from && d <= to;
141
+ });
142
+ }
143
+ const q = input.query.toLowerCase();
144
+ const matches = [];
145
+ for (const run of filtered) {
146
+ try {
147
+ const failures = (await ctx.clients.testrelic.getRunFailures(run.run_id)).failures;
148
+ for (const f of failures) {
149
+ const hay = [f.test_name, f.error_message, f.stack_trace, f.error_type].join(" ").toLowerCase();
150
+ if (hay.includes(q))
151
+ matches.push({ run_id: run.run_id, test_name: f.test_name, error_type: f.error_type, error_message: f.error_message, occurred_at: run.started_at });
152
+ }
153
+ }
154
+ catch {
155
+ // skip
156
+ }
157
+ }
158
+ if (!matches.length)
159
+ return { text: `No failures matching "${input.query}"`, structured: { matches: [] } };
160
+ const lines = [`## Search Results for "${input.query}" (${matches.length})`, ""];
161
+ for (const m of matches)
162
+ lines.push(`- **[${m.run_id}]** ${m.test_name}\n ${m.error_type}: ${m.error_message}\n _${m.occurred_at}_`);
163
+ return { text: lines.join("\n"), structured: { matches } };
164
+ },
165
+ },
166
+ {
167
+ name: "tr_ai_rca",
168
+ capability: "triage",
169
+ title: "AI root cause analysis",
170
+ description: "Fetches the platform-generated RCA for a run (falls back to sampling when the platform has none).",
171
+ inputSchema: { run_id: z.string() },
172
+ aliases: [{ name: "testrelic_get_ai_rca", description: "Fetch AI RCA for a run." }],
173
+ handler: async (input, ctx) => {
174
+ const run_id = input.run_id;
175
+ try {
176
+ const rca = await ctx.clients.testrelic.getAiRca(run_id);
177
+ const text = [
178
+ `## AI RCA — ${run_id}`,
179
+ `**Confidence:** ${(rca.confidence * 100).toFixed(0)}%`,
180
+ `**Affected component:** ${rca.affected_component}`,
181
+ "",
182
+ `### Root cause`,
183
+ rca.root_cause,
184
+ "",
185
+ `### Evidence`,
186
+ ...rca.evidence.map((e) => `- ${e}`),
187
+ "",
188
+ `### Suggested fix`,
189
+ rca.suggested_fix,
190
+ ].join("\n");
191
+ return { text, structured: { rca } };
192
+ }
193
+ catch (err) {
194
+ // Platform RCA unavailable — try sampling with the failure context.
195
+ const failures = (await ctx.clients.testrelic.getRunFailures(run_id)).failures;
196
+ if (!failures.length)
197
+ throw err;
198
+ const prompt = [
199
+ `Propose a root cause and fix for these test failures.`,
200
+ ...failures.slice(0, 3).map((f) => `- ${f.test_name}: ${f.error_type} — ${f.error_message}`),
201
+ "",
202
+ `Return 1-2 sentences for root cause and 1-2 sentences for suggested fix.`,
203
+ ].join("\n");
204
+ const sampled = await ctx.sampling.createMessage(prompt, { maxTokens: 300, temperature: 0.2 });
205
+ return {
206
+ text: [`## AI RCA — ${run_id} (sampled fallback)`, "", sampled.text || "RCA not available."].join("\n"),
207
+ structured: { sampled: true, text: sampled.text },
208
+ };
209
+ }
210
+ },
211
+ },
212
+ {
213
+ name: "tr_suggest_fix",
214
+ capability: "triage",
215
+ title: "Platform-suggested fix",
216
+ description: "Returns the TestRelic platform's code-level fix suggestion for a named test in a run.",
217
+ inputSchema: { run_id: z.string(), test_name: z.string() },
218
+ aliases: [{ name: "testrelic_suggest_fix", description: "Platform-suggested code-level fix." }],
219
+ handler: async (input, ctx) => {
220
+ const result = await ctx.clients.testrelic.suggestFix(input.run_id, input.test_name);
221
+ const { suggestion } = result;
222
+ const text = [
223
+ `## Fix suggestion: ${input.test_name}`,
224
+ `**Confidence:** ${(suggestion.confidence * 100).toFixed(0)}%`,
225
+ `**Affected files:** ${suggestion.affected_files.join(", ")}`,
226
+ "",
227
+ suggestion.description,
228
+ "",
229
+ "```diff",
230
+ suggestion.code_diff,
231
+ "```",
232
+ ].join("\n");
233
+ return { text, structured: result };
234
+ },
235
+ },
236
+ {
237
+ name: "tr_create_jira",
238
+ capability: "triage",
239
+ title: "Create a Jira ticket (with dedupe)",
240
+ description: "Creates or returns an existing Jira ticket for a run. Populates with RCA and user impact when available.",
241
+ inputSchema: {
242
+ run_id: z.string(),
243
+ project_key: z.string().optional().default("ENG"),
244
+ priority: z.enum(["P1", "P2", "P3", "P4"]).optional().default("P2"),
245
+ dry_run: z.boolean().optional().default(false),
246
+ },
247
+ aliases: [{ name: "testrelic_create_jira_ticket", description: "Create or dedupe a Jira ticket for a run." }],
248
+ handler: async (input, ctx) => {
249
+ const run_id = input.run_id;
250
+ const project_key = input.project_key ?? "ENG";
251
+ const priority = input.priority ?? "P2";
252
+ const dry_run = input.dry_run;
253
+ const existing = (await ctx.clients.jira.findIssuesByLabel(run_id)).issues.filter((t) => t.status !== "Done");
254
+ if (existing.length > 0) {
255
+ const t = existing[0];
256
+ return {
257
+ text: [
258
+ `## Existing Jira ticket — ${t.key}`,
259
+ `**Summary:** ${t.summary}`,
260
+ `**Status:** ${t.status} · **Priority:** ${t.priority}`,
261
+ `**URL:** ${t.url}`,
262
+ "",
263
+ `No new ticket created to avoid duplicates.`,
264
+ ].join("\n"),
265
+ structured: { existing: t, created: false },
266
+ };
267
+ }
268
+ const [run, failuresData] = await Promise.all([
269
+ ctx.clients.testrelic.getRun(run_id),
270
+ ctx.clients.testrelic.getRunFailures(run_id),
271
+ ]);
272
+ const rcaData = await ctx.clients.testrelic.getAiRca(run_id).catch(() => null);
273
+ const userImpact = await ctx.clients.amplitude.getUserCount(run_id).catch(() => null);
274
+ const topFailure = failuresData.failures[0];
275
+ const summary = `[TestRelic] ${topFailure?.suite ?? "unknown"} ${topFailure?.error_type ?? "failures"} — ${run_id}`;
276
+ const descParts = [
277
+ `*Automatically created by TestRelic MCP Server.*`,
278
+ "",
279
+ `*Run:* ${run_id} | *Branch:* ${run.branch} @ ${run.commit_sha}`,
280
+ `*Failures:* ${failuresData.failures.length} / ${run.total}`,
281
+ `*Time:* ${run.started_at}`,
282
+ ];
283
+ if (userImpact)
284
+ descParts.push(`*Users impacted:* ${userImpact.affected_users.toLocaleString()} at ${userImpact.error_path}`);
285
+ if (rcaData)
286
+ descParts.push("", `*Root cause (${(rcaData.confidence * 100).toFixed(0)}%):* ${rcaData.root_cause}`, `*Suggested fix:* ${rcaData.suggested_fix}`);
287
+ if (topFailure) {
288
+ descParts.push("", `*Primary failure:* ${topFailure.test_name}`, `{code}${topFailure.stack_trace}{code}`);
289
+ }
290
+ const description = descParts.join("\n");
291
+ const labels = ["testrelic", run_id, topFailure?.suite ?? "unknown"];
292
+ if (dry_run) {
293
+ return {
294
+ text: ["## Dry run — ticket preview", "", `**Summary:** ${summary}`, `**Priority:** ${priority}`, `**Labels:** ${labels.join(", ")}`, "", "**Description:**", description].join("\n"),
295
+ structured: { dry_run: true, summary, priority, labels, description, project_key },
296
+ };
297
+ }
298
+ const ticket = await ctx.clients.jira.createIssue({ summary, priority, labels, description });
299
+ return {
300
+ text: [
301
+ `## Jira created — ${ticket.key}`,
302
+ `**Summary:** ${ticket.summary}`,
303
+ `**Status:** ${ticket.status}`,
304
+ `**Priority:** ${ticket.priority}`,
305
+ `**URL:** ${ticket.url}`,
306
+ ].join("\n"),
307
+ structured: { ticket, created: true },
308
+ };
309
+ },
310
+ },
311
+ {
312
+ name: "tr_dismiss_flaky",
313
+ capability: "triage",
314
+ title: "Dismiss a test as known flaky",
315
+ description: "Marks a test as known-flaky (suppresses alerts) with a required reason.",
316
+ inputSchema: {
317
+ test_id: z.string(),
318
+ reason: z.string().min(10),
319
+ },
320
+ aliases: [{ name: "testrelic_dismiss_flaky", description: "Mark a test as known flaky." }],
321
+ handler: async (input, ctx) => {
322
+ const result = await ctx.clients.testrelic.dismissFlakyTest(input.test_id, input.reason);
323
+ if (!result.success)
324
+ return { text: `Failed to mark ${input.test_id} as known flaky.`, structured: { ok: false } };
325
+ const text = [
326
+ `## ${result.test_id} — known flaky`,
327
+ "",
328
+ `**Reason:** ${input.reason}`,
329
+ "",
330
+ `Alerts and failure noise from this test will be suppressed until the flag is cleared in the TestRelic dashboard.`,
331
+ ].join("\n");
332
+ return { text, structured: { ok: true, test_id: result.test_id } };
333
+ },
334
+ },
335
+ {
336
+ name: "tr_list_runs",
337
+ capability: "triage",
338
+ title: "List recent runs (legacy alias of tr_recent_runs)",
339
+ description: "Alias retained for v1 compatibility; behaviour identical to tr_recent_runs under the core capability.",
340
+ inputSchema: {
341
+ project_id: z.string().optional(),
342
+ framework: z.enum(["playwright", "cypress", "jest", "vitest"]).optional(),
343
+ status: z.enum(["passed", "failed", "running", "cancelled"]).optional(),
344
+ cursor: z.string().optional(),
345
+ limit: z.number().int().min(1).max(20).optional().default(5),
346
+ },
347
+ aliases: [{ name: "testrelic_list_runs", description: "List recent runs." }],
348
+ deprecated: true,
349
+ handler: async (input, ctx) => {
350
+ const result = await ctx.clients.testrelic.listRuns(input);
351
+ const { data: runs, next_cursor, total } = result;
352
+ if (!runs.length)
353
+ return { text: "No test runs found.", structured: { runs: [] } };
354
+ const lines = [`## Test Runs (${runs.length} of ${total})`, ""];
355
+ for (const run of runs) {
356
+ lines.push(`- **${run.run_id}** [${run.status}] — ${run.failed} failed · ${run.flaky} flaky — ${run.branch}@${run.commit_sha}`);
357
+ }
358
+ return { text: lines.join("\n"), structured: { runs, next_cursor, total } };
359
+ },
360
+ },
361
+ ];
362
+ export function registerTriageTools(ctx, register) {
363
+ for (const t of triageTools)
364
+ register(t);
365
+ }
366
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/triage/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ResolvedConfig } from "../config.js";
3
+ /**
4
+ * Streamable HTTP transport. One Express server, two relevant routes:
5
+ * GET /healthz — JSON health probe
6
+ * POST /mcp — MCP JSON-RPC
7
+ *
8
+ * Session management is by the `Mcp-Session-Id` header per the spec.
9
+ *
10
+ * `McpServer` is a single-connection object — it throws on a second
11
+ * `connect()`. For Streamable HTTP we therefore build a fresh server
12
+ * per session via the `buildServer` factory. Subsequent requests on
13
+ * the same session are routed to the already-connected transport.
14
+ */
15
+ export declare function startHttp(buildServer: () => McpServer, config: ResolvedConfig): Promise<() => Promise<void>>;
16
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD;;;;;;;;;;;GAWG;AACH,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,SAAS,EAC5B,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CA6F9B"}
@@ -0,0 +1,110 @@
1
+ import express from "express";
2
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
+ import { randomUUID } from "node:crypto";
4
+ import { getLogger } from "../logger.js";
5
+ import { version } from "../version.js";
6
+ /**
7
+ * Streamable HTTP transport. One Express server, two relevant routes:
8
+ * GET /healthz — JSON health probe
9
+ * POST /mcp — MCP JSON-RPC
10
+ *
11
+ * Session management is by the `Mcp-Session-Id` header per the spec.
12
+ *
13
+ * `McpServer` is a single-connection object — it throws on a second
14
+ * `connect()`. For Streamable HTTP we therefore build a fresh server
15
+ * per session via the `buildServer` factory. Subsequent requests on
16
+ * the same session are routed to the already-connected transport.
17
+ */
18
+ export async function startHttp(buildServer, config) {
19
+ const app = express();
20
+ app.use(express.json({ limit: "4mb" }));
21
+ app.get("/healthz", (_req, res) => {
22
+ res.json({ ok: true, version, transport: "http", capabilities: config.capabilities });
23
+ });
24
+ const transports = new Map();
25
+ const servers = new Map();
26
+ app.post("/mcp", async (req, res) => {
27
+ const sessionHeader = req.header("mcp-session-id");
28
+ let transport = sessionHeader ? transports.get(sessionHeader) : undefined;
29
+ if (!transport) {
30
+ const newSessionId = randomUUID();
31
+ const sessionServer = buildServer();
32
+ transport = new StreamableHTTPServerTransport({
33
+ sessionIdGenerator: () => newSessionId,
34
+ onsessioninitialized: (id) => {
35
+ transports.set(id, transport);
36
+ servers.set(id, sessionServer);
37
+ },
38
+ onsessionclosed: (id) => {
39
+ transports.delete(id);
40
+ const s = servers.get(id);
41
+ servers.delete(id);
42
+ if (s)
43
+ void s.close().catch(() => undefined);
44
+ },
45
+ });
46
+ await sessionServer.connect(transport);
47
+ }
48
+ try {
49
+ await transport.handleRequest(req, res, req.body);
50
+ }
51
+ catch (err) {
52
+ getLogger().error({ err }, "http transport request failed");
53
+ if (!res.headersSent)
54
+ res.status(500).json({ error: "transport error" });
55
+ }
56
+ });
57
+ app.get("/mcp", async (req, res) => {
58
+ const sessionHeader = req.header("mcp-session-id");
59
+ const transport = sessionHeader ? transports.get(sessionHeader) : undefined;
60
+ if (!transport) {
61
+ res.status(400).json({ error: "missing or invalid mcp-session-id" });
62
+ return;
63
+ }
64
+ await transport.handleRequest(req, res);
65
+ });
66
+ app.delete("/mcp", async (req, res) => {
67
+ const sessionHeader = req.header("mcp-session-id");
68
+ const transport = sessionHeader ? transports.get(sessionHeader) : undefined;
69
+ if (!transport) {
70
+ res.status(404).json({ error: "session not found" });
71
+ return;
72
+ }
73
+ await transport.close();
74
+ transports.delete(sessionHeader);
75
+ const s = servers.get(sessionHeader);
76
+ servers.delete(sessionHeader);
77
+ if (s)
78
+ await s.close().catch(() => undefined);
79
+ res.json({ ok: true });
80
+ });
81
+ const port = config.server.port || 3000;
82
+ const host = config.server.host || "127.0.0.1";
83
+ return new Promise((resolve) => {
84
+ const httpServer = app.listen(port, host, () => {
85
+ getLogger().info({ host, port, version, capabilities: config.capabilities }, "http transport listening");
86
+ resolve(async () => {
87
+ for (const [, t] of transports) {
88
+ try {
89
+ await t.close();
90
+ }
91
+ catch {
92
+ // ignore
93
+ }
94
+ }
95
+ transports.clear();
96
+ for (const [, s] of servers) {
97
+ try {
98
+ await s.close();
99
+ }
100
+ catch {
101
+ // ignore
102
+ }
103
+ }
104
+ servers.clear();
105
+ await new Promise((done) => httpServer.close(() => done()));
106
+ });
107
+ });
108
+ });
109
+ }
110
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Stdio transport wiring. The MCP SDK handles framing — we just connect.
4
+ */
5
+ export declare function startStdio(server: McpServer): Promise<() => Promise<void>>;
6
+ //# sourceMappingURL=stdio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/transport/stdio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAWhF"}
@@ -0,0 +1,19 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ import { getLogger } from "../logger.js";
3
+ /**
4
+ * Stdio transport wiring. The MCP SDK handles framing — we just connect.
5
+ */
6
+ export async function startStdio(server) {
7
+ const transport = new StdioServerTransport();
8
+ await server.connect(transport);
9
+ getLogger().info("stdio transport connected");
10
+ return async () => {
11
+ try {
12
+ await transport.close();
13
+ }
14
+ catch {
15
+ // best effort
16
+ }
17
+ };
18
+ }
19
+ //# sourceMappingURL=stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/transport/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAiB;IAChD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,SAAS,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAC9C,OAAO,KAAK,IAAI,EAAE;QAChB,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,cAAc;QAChB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}