@rui.branco/sentry-mcp 1.0.1 → 1.0.2
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/index.js +24 -97
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -156,7 +156,26 @@ async function fetchSentry(apiPath, instance, options = {}) {
|
|
|
156
156
|
|
|
157
157
|
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
158
158
|
|
|
159
|
-
|
|
159
|
+
// Strip noisy/internal fields that waste context but keep everything useful
|
|
160
|
+
function cleanIssueData(issue) {
|
|
161
|
+
const skip = new Set(["pluginActions", "pluginContexts", "pluginIssues", "activity", "seenBy", "stats"]);
|
|
162
|
+
const cleaned = {};
|
|
163
|
+
for (const [k, v] of Object.entries(issue)) {
|
|
164
|
+
if (!skip.has(k) && v != null && v !== "") cleaned[k] = v;
|
|
165
|
+
}
|
|
166
|
+
return cleaned;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function cleanEventData(event) {
|
|
170
|
+
const skip = new Set(["_meta", "groupID", "eventID", "sdk", "dist", "fingerprints"]);
|
|
171
|
+
const cleaned = {};
|
|
172
|
+
for (const [k, v] of Object.entries(event)) {
|
|
173
|
+
if (!skip.has(k) && v != null && v !== "") cleaned[k] = v;
|
|
174
|
+
}
|
|
175
|
+
return cleaned;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function formatIssueSummary(issue) {
|
|
160
179
|
const meta = issue.metadata || {};
|
|
161
180
|
const lines = [];
|
|
162
181
|
lines.push(`**${issue.title}**`);
|
|
@@ -175,98 +194,6 @@ function formatIssue(issue) {
|
|
|
175
194
|
return lines.join("\n");
|
|
176
195
|
}
|
|
177
196
|
|
|
178
|
-
function formatEvent(event) {
|
|
179
|
-
const lines = [];
|
|
180
|
-
|
|
181
|
-
// Stack traces
|
|
182
|
-
const exceptions =
|
|
183
|
-
event.entries?.find((e) => e.type === "exception")?.data?.values || [];
|
|
184
|
-
if (exceptions.length) {
|
|
185
|
-
lines.push("## Stack Trace\n");
|
|
186
|
-
for (const ex of exceptions) {
|
|
187
|
-
if (ex.type || ex.value) lines.push(`**${ex.type || "Exception"}:** ${ex.value || ""}\n`);
|
|
188
|
-
const frames = ex.stacktrace?.frames;
|
|
189
|
-
if (frames?.length) {
|
|
190
|
-
lines.push("```");
|
|
191
|
-
for (const f of frames) {
|
|
192
|
-
const loc = f.lineNo ? `:${f.lineNo}${f.colNo ? ":" + f.colNo : ""}` : "";
|
|
193
|
-
const marker = f.inApp ? "-> " : " ";
|
|
194
|
-
lines.push(`${marker}${f.function || "?"} (${f.filename || "?"}${loc})`);
|
|
195
|
-
}
|
|
196
|
-
lines.push("```\n");
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Breadcrumbs
|
|
202
|
-
const breadcrumbs =
|
|
203
|
-
event.entries?.find((e) => e.type === "breadcrumbs")?.data?.values || [];
|
|
204
|
-
if (breadcrumbs.length) {
|
|
205
|
-
const last = breadcrumbs.slice(-20);
|
|
206
|
-
lines.push(`## Breadcrumbs (last ${last.length})\n`);
|
|
207
|
-
for (const bc of last) {
|
|
208
|
-
const msg = bc.message || bc.data?.url || bc.data?.to || "";
|
|
209
|
-
lines.push(`- **${bc.category || "?"}** [${bc.level || "info"}] ${msg}`);
|
|
210
|
-
}
|
|
211
|
-
lines.push("");
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// HTTP Request
|
|
215
|
-
const httpReq =
|
|
216
|
-
event.entries?.find((e) => e.type === "request")?.data;
|
|
217
|
-
if (httpReq) {
|
|
218
|
-
lines.push("## HTTP Request\n");
|
|
219
|
-
lines.push(`\`${httpReq.method || "GET"} ${httpReq.url || ""}\``);
|
|
220
|
-
if (httpReq.headers) {
|
|
221
|
-
lines.push("\n```");
|
|
222
|
-
for (const [k, v] of httpReq.headers) {
|
|
223
|
-
lines.push(`${k}: ${v}`);
|
|
224
|
-
}
|
|
225
|
-
lines.push("```");
|
|
226
|
-
}
|
|
227
|
-
lines.push("");
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Tags
|
|
231
|
-
if (event.tags?.length) {
|
|
232
|
-
lines.push("## Tags\n");
|
|
233
|
-
lines.push("| Key | Value |");
|
|
234
|
-
lines.push("|-----|-------|");
|
|
235
|
-
for (const t of event.tags) {
|
|
236
|
-
lines.push(`| ${t.key} | ${t.value} |`);
|
|
237
|
-
}
|
|
238
|
-
lines.push("");
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Contexts
|
|
242
|
-
if (event.contexts) {
|
|
243
|
-
lines.push("## Contexts\n");
|
|
244
|
-
for (const [name, ctx] of Object.entries(event.contexts)) {
|
|
245
|
-
if (name === "trace" || name === "replay" || !ctx || typeof ctx !== "object") continue;
|
|
246
|
-
const entries = Object.entries(ctx).filter(([k, v]) => k !== "type" && v != null && v !== "");
|
|
247
|
-
if (!entries.length) continue;
|
|
248
|
-
const title = name.charAt(0).toUpperCase() + name.slice(1).replace(/_/g, " ");
|
|
249
|
-
lines.push(`**${title}:**`);
|
|
250
|
-
for (const [k, v] of entries.slice(0, 15)) {
|
|
251
|
-
const display = typeof v === "object" ? JSON.stringify(v) : String(v);
|
|
252
|
-
lines.push(`- ${k}: ${display}`);
|
|
253
|
-
}
|
|
254
|
-
lines.push("");
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// User
|
|
259
|
-
if (event.user) {
|
|
260
|
-
const u = event.user;
|
|
261
|
-
lines.push("## User\n");
|
|
262
|
-
lines.push(`${u.username || u.name || u.email || u.id || "unknown"}${u.email ? " (" + u.email + ")" : ""}`);
|
|
263
|
-
if (u.ip_address) lines.push(`IP: ${u.ip_address}`);
|
|
264
|
-
lines.push("");
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return lines.join("\n") || "No event data available.";
|
|
268
|
-
}
|
|
269
|
-
|
|
270
197
|
// ── MCP Server ──────────────────────────────────────────────────────────────
|
|
271
198
|
|
|
272
199
|
const server = new Server(
|
|
@@ -573,7 +500,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
573
500
|
content: [{ type: "text", text: `No issues found for query: ${query}` }],
|
|
574
501
|
};
|
|
575
502
|
}
|
|
576
|
-
const formatted = data.map(
|
|
503
|
+
const formatted = data.map(formatIssueSummary);
|
|
577
504
|
return {
|
|
578
505
|
content: [
|
|
579
506
|
{
|
|
@@ -591,7 +518,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
591
518
|
inst,
|
|
592
519
|
);
|
|
593
520
|
return {
|
|
594
|
-
content: [{ type: "text", text:
|
|
521
|
+
content: [{ type: "text", text: JSON.stringify(cleanIssueData(data), null, 2) }],
|
|
595
522
|
};
|
|
596
523
|
|
|
597
524
|
} else if (name === "sentry_get_latest_event") {
|
|
@@ -602,7 +529,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
602
529
|
inst,
|
|
603
530
|
);
|
|
604
531
|
return {
|
|
605
|
-
content: [{ type: "text", text:
|
|
532
|
+
content: [{ type: "text", text: JSON.stringify(cleanEventData(data), null, 2) }],
|
|
606
533
|
};
|
|
607
534
|
|
|
608
535
|
} else if (name === "sentry_resolve_issue") {
|
|
@@ -659,7 +586,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
659
586
|
content: [{ type: "text", text: `No issues found for query: ${args.query}` }],
|
|
660
587
|
};
|
|
661
588
|
}
|
|
662
|
-
const formatted = data.map(
|
|
589
|
+
const formatted = data.map(formatIssueSummary);
|
|
663
590
|
return {
|
|
664
591
|
content: [
|
|
665
592
|
{
|
package/package.json
CHANGED