Skip to content

Commit 463ebde

Browse files
dcramerclaude
andauthored
fix: support 'default' event type in get_issue_details tool (#571)
The 'default' event type represents error events without exception data. Previously, these events were rejected with "Unknown event type: default" error, causing the tool to fail. Changes: - Added DefaultEventSchema to handle events with type: "default" - Updated EventSchema union to include DefaultEventSchema - Updated API client validation to accept "default" events - Updated isErrorEvent() type guard to include default events - Updated formatting to show dateCreated for default events - Added comprehensive test coverage to prevent regressions Fixes #570 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Code <noreply@anthropic.com>
1 parent 9a3dce6 commit 463ebde

6 files changed

Lines changed: 107 additions & 7 deletions

File tree

‎packages/mcp-server/src/api-client/client.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,8 +1529,9 @@ export class SentryApiService {
15291529
);
15301530
const rawEvent = EventSchema.parse(body);
15311531

1532-
// Filter out unknown events - only return known error/transaction types
1533-
if (rawEvent.type === "error") {
1532+
// Filter out unknown events - only return known error/default/transaction types
1533+
// "default" type represents error events without exception data
1534+
if (rawEvent.type === "error" || rawEvent.type === "default") {
15341535
return rawEvent as Event;
15351536
}
15361537
if (rawEvent.type === "transaction") {
@@ -1542,7 +1543,7 @@ export class SentryApiService {
15421543
throw new ApiValidationError(
15431544
`Unknown event type: ${eventType}`,
15441545
400,
1545-
`Only error and transaction events are supported, got: ${eventType}`,
1546+
`Only error, default, and transaction events are supported, got: ${eventType}`,
15461547
body,
15471548
);
15481549
}

‎packages/mcp-server/src/api-client/schema.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,14 @@ export const ErrorEventSchema = BaseEventSchema.omit({
381381
dateCreated: z.string().datetime(),
382382
});
383383

384+
export const DefaultEventSchema = BaseEventSchema.omit({
385+
type: true,
386+
}).extend({
387+
type: z.literal("default"),
388+
culprit: z.string().nullable().optional(),
389+
dateCreated: z.string().datetime(),
390+
});
391+
384392
export const TransactionEventSchema = BaseEventSchema.omit({
385393
type: true,
386394
}).extend({
@@ -425,6 +433,7 @@ export const UnknownEventSchema = BaseEventSchema.omit({
425433
// are completely different, for example.
426434
export const EventSchema = z.union([
427435
ErrorEventSchema,
436+
DefaultEventSchema,
428437
TransactionEventSchema,
429438
UnknownEventSchema,
430439
]);

‎packages/mcp-server/src/api-client/types.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import type {
4646
ClientKeyListSchema,
4747
ClientKeySchema,
4848
ErrorEventSchema,
49+
DefaultEventSchema,
4950
TransactionEventSchema,
5051
UnknownEventSchema,
5152
EventSchema,
@@ -80,12 +81,13 @@ export type Issue = z.infer<typeof IssueSchema>;
8081

8182
// Individual event types
8283
export type ErrorEvent = z.infer<typeof ErrorEventSchema>;
84+
export type DefaultEvent = z.infer<typeof DefaultEventSchema>;
8385
export type TransactionEvent = z.infer<typeof TransactionEventSchema>;
8486
export type UnknownEvent = z.infer<typeof UnknownEventSchema>;
8587

8688
// Event union - use RawEvent for parsing, Event for known types only
8789
export type RawEvent = z.infer<typeof EventSchema>;
88-
export type Event = ErrorEvent | TransactionEvent;
90+
export type Event = ErrorEvent | DefaultEvent | TransactionEvent;
8991

9092
export type EventAttachment = z.infer<typeof EventAttachmentSchema>;
9193
export type Tag = z.infer<typeof TagSchema>;

‎packages/mcp-server/src/internal/formatting.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1596,7 +1596,8 @@ export function formatIssueOutput({
15961596
output += "\n";
15971597
output += "## Event Details\n\n";
15981598
output += `**Event ID**: ${event.id}\n`;
1599-
if (event.type === "error") {
1599+
// "default" type represents error events without exception data
1600+
if (event.type === "error" || event.type === "default") {
16001601
output += `**Occurred At**: ${new Date((event as z.infer<typeof ErrorEventSchema>).dateCreated).toISOString()}\n`;
16011602
}
16021603
if (event.message) {

‎packages/mcp-server/src/tools/get-issue-details.test.ts‎

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,4 +927,89 @@ describe("get_issue_details", () => {
927927
"For detailed root cause analysis and solutions, call `analyze_issue_with_seer(organizationSlug='sentry-mcp-evals', issueId='CLOUDFLARE-MCP-41')`",
928928
);
929929
});
930+
931+
it("handles default event type (error without exception data)", async () => {
932+
// Mock a "default" event type - represents errors without exception data
933+
mswServer.use(
934+
http.get(
935+
"https://sentry.io/api/0/organizations/sentry-mcp-evals/issues/DEFAULT-001/events/latest/",
936+
() => {
937+
return HttpResponse.json({
938+
id: "abc123def456",
939+
title: "Error without exception data",
940+
message: "Something went wrong",
941+
platform: "python",
942+
type: "default", // This is the key part - default event type
943+
dateCreated: "2025-10-02T12:00:00.000Z",
944+
culprit: "unknown",
945+
entries: [
946+
{
947+
type: "message",
948+
data: {
949+
formatted: "Something went wrong",
950+
message: "Something went wrong",
951+
},
952+
},
953+
],
954+
tags: [
955+
{ key: "level", value: "error" },
956+
{ key: "environment", value: "production" },
957+
],
958+
contexts: {},
959+
});
960+
},
961+
),
962+
http.get(
963+
"https://sentry.io/api/0/organizations/sentry-mcp-evals/issues/DEFAULT-001/",
964+
() => {
965+
return HttpResponse.json({
966+
id: "123456",
967+
shortId: "DEFAULT-001",
968+
title: "Error without exception data",
969+
firstSeen: "2025-10-02T10:00:00.000Z",
970+
lastSeen: "2025-10-02T12:00:00.000Z",
971+
count: "5",
972+
userCount: 2,
973+
permalink: "https://sentry-mcp-evals.sentry.io/issues/123456/",
974+
project: {
975+
id: "4509062593708032",
976+
name: "TEST-PROJECT",
977+
slug: "test-project",
978+
platform: "python",
979+
},
980+
status: "unresolved",
981+
culprit: "unknown",
982+
type: "default",
983+
platform: "python",
984+
});
985+
},
986+
),
987+
);
988+
989+
const result = await getIssueDetails.handler(
990+
{
991+
organizationSlug: "sentry-mcp-evals",
992+
issueId: "DEFAULT-001",
993+
eventId: undefined,
994+
issueUrl: undefined,
995+
regionUrl: undefined,
996+
},
997+
{
998+
constraints: {
999+
organizationSlug: null,
1000+
},
1001+
accessToken: "access-token",
1002+
userId: "1",
1003+
},
1004+
);
1005+
1006+
// Verify the event was processed successfully
1007+
expect(result).toContain("# Issue DEFAULT-001 in **sentry-mcp-evals**");
1008+
expect(result).toContain("Error without exception data");
1009+
expect(result).toContain("**Event ID**: abc123def456");
1010+
// Default events should show dateCreated just like error events
1011+
expect(result).toContain("**Occurred At**: 2025-10-02T12:00:00.000Z");
1012+
expect(result).toContain("### Error");
1013+
expect(result).toContain("Something went wrong");
1014+
});
9301015
});

‎packages/mcp-server/src/tools/get-issue-details.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type { SentryApiService } from "../api-client";
1212
import type {
1313
Event,
1414
ErrorEvent,
15+
DefaultEvent,
1516
TransactionEvent,
1617
Trace,
1718
} from "../api-client/types";
@@ -244,8 +245,9 @@ async function maybeFetchPerformanceTrace({
244245
}
245246
}
246247

247-
function isErrorEvent(event: Event): event is ErrorEvent {
248-
return event.type === "error";
248+
function isErrorEvent(event: Event): event is ErrorEvent | DefaultEvent {
249+
// "default" type represents error events without exception data
250+
return event.type === "error" || event.type === "default";
249251
}
250252

251253
function isTransactionEvent(event: Event): event is TransactionEvent {

0 commit comments

Comments
 (0)