Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/contributing/tool-responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ omits the section. Commit lookup is optional: failures do not prevent issue
details from loading, but unexpected server or response-validation failures
are reported to Sentry.

The event API's legacy `context` field (extra data) can be `null`. Issue details
must still load; omit the `Extra Data` section for null or empty values while
preserving the event's error, stacktrace, and structured `contexts` data.

## Structured Content

MCP tools may expose `structuredContent` alongside generated text `content`.
Expand Down
3 changes: 2 additions & 1 deletion packages/mcp-core/src/api-client/client-event.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ describe("getEventForIssue context validation", () => {
});

it.each([
{ context: null, contextType: "null" },
{ context: ["private-extra-value"], contextType: "array" },
{ context: "private-extra-value", contextType: "string" },
{ context: 12345, contextType: "number" },
{ context: false, contextType: "boolean" },
// Valid context can accompany a failure in another field.
{ context: null, contextType: "null", title: null },
{ context: undefined, contextType: "undefined", title: null },
{
context: { "private-extra-key": "private-extra-value" },
Expand Down Expand Up @@ -68,6 +68,7 @@ describe("getEventForIssue context validation", () => {

it.each([
undefined,
null,
{},
{ array: [1, "two"], nested: { value: false }, nullable: null },
])("preserves valid context: %j", async (context) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/mcp-core/src/api-client/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1133,7 +1133,8 @@ const BaseEventSchema = z.object({
.optional(),
// "context" (singular) is the legacy "extra" field for arbitrary user-defined data
// This is different from "contexts" (plural) which are structured contexts
context: z.record(z.string(), z.unknown()).optional(),
// Sentry preserves null when the event's extra data is explicitly null.
context: z.record(z.string(), z.unknown()).nullable().optional(),
sdk: z
.object({
name: z.string().nullable().optional(),
Expand Down
32 changes: 32 additions & 0 deletions packages/mcp-core/src/tools/catalog/get-issue-details.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
createRegressedIssue,
createUnknownEvent,
createUnsupportedIssue,
eventFixture,
issueNullCulpritFixture,
mswServer,
} from "@sentry/mcp-server-mocks";
Expand Down Expand Up @@ -2055,6 +2056,37 @@ describe("get_issue_details", () => {
expect(result).toContain("### Additional Context");
});

it("returns event details when legacy context is null", async () => {
mswServer.use(
http.get(
"https://sentry.io/api/0/organizations/sentry-mcp-evals/issues/6507376925/events/latest/",
() => HttpResponse.json({ ...eventFixture, context: null }),
{ once: true },
),
);

const result = await getIssueDetails.handler(
{
organizationSlug: "sentry-mcp-evals",
issueId: "CLOUDFLARE-MCP-41",
eventId: undefined,
issueUrl: undefined,
regionUrl: null,
},
baseContext,
);

expect(result).toContain("## Event Details");
expect(result).toContain(`**Event ID**: ${eventFixture.id}`);
expect(result).toContain(
"Error: Tool list_organizations is already registered",
);
expect(result).toContain("index.js:19631:28 (Object.fetch)");
expect(result).toContain("### Additional Context");
expect(result).toContain('name: "cloudflare"');
expect(result).not.toContain("### Extra Data");
});

it("handles regressed performance issues (generic type with empty entries)", async () => {
// This tests the actual structure from issue #633
// Regressed performance issues have:
Expand Down
Loading