From 2e87e37712d795c09212da949e1559db267e75ac Mon Sep 17 00:00:00 2001 From: William Mak Date: Tue, 9 Jun 2026 16:34:11 -0400 Subject: [PATCH] chore(validation): Remove experimental validation call - This endpoint was experimental and we're removing it in favour of a planned validate endpoint that will look at the entire query instead of just the attributes - Removing this since currently everyone hitting is just getting a 403 anyways --- .../mcp-core/src/api-client/client.test.ts | 56 ------------------ packages/mcp-core/src/api-client/client.ts | 59 ------------------- .../src/tools/support/search-events/utils.ts | 31 ---------- 3 files changed, 146 deletions(-) diff --git a/packages/mcp-core/src/api-client/client.test.ts b/packages/mcp-core/src/api-client/client.test.ts index 956f0f4c..f83262c6 100644 --- a/packages/mcp-core/src/api-client/client.test.ts +++ b/packages/mcp-core/src/api-client/client.test.ts @@ -1286,62 +1286,6 @@ describe("API query builders", () => { urls.map((url) => new URL(url).searchParams.get("attributeType")), ).toEqual(["string", "boolean"]); }); - - it("should validate exact trace item attributes", async () => { - const apiService = new SentryApiService({ - host: "sentry.io", - accessToken: "test-token", - }); - let requestUrl: string | undefined; - let requestOptions: RequestInit | undefined; - - globalThis.fetch = vi - .fn() - .mockImplementation((url: string, options: RequestInit) => { - requestUrl = url; - requestOptions = options; - return Promise.resolve({ - ok: true, - headers: { - get: (key: string) => - key === "content-type" ? "application/json" : null, - }, - json: () => - Promise.resolve({ - attributes: { - "tags[type]": { valid: true, type: "string" }, - "tags[missing]": { - valid: false, - error: "Unknown attribute: tags[missing]", - }, - }, - }), - }); - }); - - const result = await apiService.validateTraceItemAttributes({ - organizationSlug: "test-org", - itemType: "spans", - attributes: ["tags[type]", "tags[missing]"], - project: "123", - statsPeriod: "7d", - }); - - expect(result).toEqual({ - "tags[type]": { valid: true, type: "string" }, - "tags[missing]": { - valid: false, - error: "Unknown attribute: tags[missing]", - }, - }); - expect(requestUrl).toContain( - "/api/0/organizations/test-org/trace-items/attributes/validate/?itemType=spans&project=123&statsPeriod=7d", - ); - expect(requestOptions?.method).toBe("POST"); - expect(JSON.parse(String(requestOptions?.body))).toEqual({ - attributes: ["tags[type]", "tags[missing]"], - }); - }); }); describe("Web URL builders", () => { diff --git a/packages/mcp-core/src/api-client/client.ts b/packages/mcp-core/src/api-client/client.ts index db81433f..8c2dd59d 100644 --- a/packages/mcp-core/src/api-client/client.ts +++ b/packages/mcp-core/src/api-client/client.ts @@ -1960,65 +1960,6 @@ export class SentryApiService { return attributeResponses.flat(); } - async validateTraceItemAttributes( - { - organizationSlug, - itemType = "spans", - attributes, - project, - statsPeriod, - start, - end, - }: { - organizationSlug: string; - itemType?: TraceItemType; - attributes: string[]; - project?: string; - statsPeriod?: string; - start?: string; - end?: string; - }, - opts?: RequestOptions, - ): Promise> { - const queryParams = new URLSearchParams(); - queryParams.set("itemType", itemType); - if (project) { - queryParams.set("project", project); - } - this.applyTimeParams(queryParams, statsPeriod, start, end); - - const body = await this.requestJSON( - `/organizations/${organizationSlug}/trace-items/attributes/validate/?${queryParams.toString()}`, - { - method: "POST", - body: JSON.stringify({ attributes }), - }, - opts, - ); - - if (!isRecord(body) || !isRecord(body.attributes)) { - return {}; - } - - const results: Record = {}; - for (const [attribute, value] of Object.entries(body.attributes)) { - if (!isRecord(value) || typeof value.valid !== "boolean") { - continue; - } - const validationResult: TraceItemAttributeValidationResult = { - valid: value.valid, - }; - if (isTraceItemAttributeType(value.type)) { - validationResult.type = value.type; - } - if (typeof value.error === "string") { - validationResult.error = value.error; - } - results[attribute] = validationResult; - } - return results; - } - private async fetchTraceItemAttributesByType( organizationSlug: string, itemType: TraceItemType, diff --git a/packages/mcp-core/src/tools/support/search-events/utils.ts b/packages/mcp-core/src/tools/support/search-events/utils.ts index a334bc79..e5867fcd 100644 --- a/packages/mcp-core/src/tools/support/search-events/utils.ts +++ b/packages/mcp-core/src/tools/support/search-events/utils.ts @@ -423,26 +423,6 @@ function getTraceItemType(dataset: EventsDataset): TraceItemType | null { return null; } -function formatValidationResults( - validationResults: Record, -): string { - const entries = Object.entries(validationResults); - if (entries.length === 0) { - return ""; - } - - return `Validated Attributes: -${entries - .map(([attribute, result]) => { - if (result.valid) { - return `- ${attribute}: valid${result.type ? ` (${result.type})` : ""}`; - } - return `- ${attribute}: invalid${result.error ? ` (${result.error})` : ""}`; - }) - .join("\n")} -`; -} - /** * Create a tool for the agent to query available attributes by dataset * The tool is pre-bound with the API service and organization configured for the appropriate region @@ -513,16 +493,6 @@ export function createDatasetAttributesTool(options: { const normalizedDataset = normalizeEventsDataset(dataset); const traceItemType = getTraceItemType(normalizedDataset); const attributeTimeParams = { statsPeriod: "14d" }; - const validationResults = - traceItemType && attributes?.length - ? await apiService.validateTraceItemAttributes({ - organizationSlug, - itemType: traceItemType, - attributes, - project: projectId, - ...attributeTimeParams, - }) - : {}; const { attributes: customAttributes, fieldTypes } = await fetchCustomAttributes( apiService, @@ -560,7 +530,6 @@ export function createDatasetAttributesTool(options: { recordAgentToolResultCount(fieldCount); return `Dataset: ${dataset} -${formatValidationResults(validationResults)} Available Fields (${fieldCount} total): ${Object.entries(allFields)