Skip to content
Closed
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
78 changes: 41 additions & 37 deletions packages/mcp-core/src/api-client/client.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
import { z } from "zod";
import { ConfigurationError } from "../errors";
import { logIssue, logWarn } from "../telem/logging";
import {
getIssueUrl as getIssueUrlUtil,
getReplayUrl as getReplayUrlUtil,
getTraceUrl as getTraceUrlUtil,
isSentryHost,
} from "../utils/url-utils";
import { logIssue, logWarn } from "../telem/logging";
import { USER_AGENT } from "../version";
import { ApiNotFoundError, ApiValidationError, createApiError } from "./errors";
import {
ApiErrorSchema,
AutofixRunSchema,
AutofixRunStateSchema,
ClientKeyListSchema,
ClientKeySchema,
ErrorsSearchResponseSchema,
EventAttachmentListSchema,
EventSchema,
ExternalIssueListSchema,
FlamegraphSchema,
IssueListSchema,
IssueSchema,
IssueTagValuesSchema,
OrganizationListSchema,
OrganizationSchema,
ClientKeySchema,
TeamListSchema,
TeamSchema,
ProfileChunkResponseSchema,
ProjectListSchema,
ProjectSchema,
ReleaseListSchema,
IssueListSchema,
IssueSchema,
IssueTagValuesSchema,
ExternalIssueListSchema,
EventSchema,
EventAttachmentListSchema,
ErrorsSearchResponseSchema,
ReplayDetailsSchema,
ReplayIdsByResourceSchema,
ReplayRecordingSegmentsSchema,
SpansSearchResponseSchema,
TagListSchema,
ApiErrorSchema,
ClientKeyListSchema,
AutofixRunSchema,
AutofixRunStateSchema,
TeamListSchema,
TeamSchema,
TraceMetaSchema,
TraceSchema,
UserSchema,
UserRegionsSchema,
FlamegraphSchema,
ProfileChunkResponseSchema,
ReplayDetailsSchema,
ReplayIdsByResourceSchema,
ReplayRecordingSegmentsSchema,
UserSchema,
} from "./schema";
import { ConfigurationError } from "../errors";
import { createApiError, ApiNotFoundError, ApiValidationError } from "./errors";
import { USER_AGENT } from "../version";
import type {
AutofixRun,
AutofixRunState,
Expand All @@ -49,24 +49,24 @@ import type {
Event,
EventAttachment,
EventAttachmentList,
ExternalIssueList,
Flamegraph,
Issue,
IssueList,
IssueTagValues,
ExternalIssueList,
OrganizationList,
ProfileChunk,
Project,
ProjectList,
ReleaseList,
ReplayDetails,
ReplayRecordingSegments,
TagList,
Team,
TeamList,
Trace,
TraceMeta,
User,
Flamegraph,
ProfileChunk,
ReplayDetails,
ReplayRecordingSegments,
} from "./types";
// TODO: this is shared - so ideally, for safety, it uses @sentry/core, but currently
// logger isnt exposed (or rather, it is, but its not the right logger)
Expand Down Expand Up @@ -550,6 +550,7 @@ export class SentryApiService {
end?: string;
aggregateFunctions?: string[];
groupByFields?: string[];
dataset?: string;
}): string {
const {
organizationSlug,
Expand All @@ -567,7 +568,7 @@ export class SentryApiService {
const urlParams = new URLSearchParams();

// Discover API specific parameters
urlParams.set("dataset", "errors");
urlParams.set("dataset", params.dataset ?? "errors");
urlParams.set("queryDataset", "error-events");
urlParams.set("query", query);

Expand Down Expand Up @@ -782,7 +783,7 @@ export class SentryApiService {
organizationSlug: string,
query: string,
projectId?: string,
dataset: "spans" | "errors" | "logs" = "spans",
dataset: "spans" | "errors" | "logs" | "metrics" = "spans",
fields?: string[],
sort?: string,
aggregateFunctions?: string[],
Expand All @@ -791,8 +792,8 @@ export class SentryApiService {
start?: string,
end?: string,
): string {
if (dataset === "errors") {
// Route to legacy Discover API
if (dataset === "errors" || dataset === "metrics") {
// Route to legacy Discover API (errors and metrics use discover-style API)
return this.buildDiscoverUrl({
organizationSlug,
query,
Expand All @@ -804,6 +805,7 @@ export class SentryApiService {
end,
aggregateFunctions,
groupByFields,
dataset: dataset === "metrics" ? "metrics" : undefined,
});
}

Expand Down Expand Up @@ -2119,13 +2121,14 @@ export class SentryApiService {
start?: string;
end?: string;
sort: string;
dataset?: string;
}): URLSearchParams {
const queryParams = new URLSearchParams();

// Basic parameters
queryParams.set("per_page", params.limit.toString());
queryParams.set("query", params.query);
queryParams.set("dataset", "errors");
queryParams.set("dataset", params.dataset ?? "errors");

this.applyTimeParams(
queryParams,
Expand Down Expand Up @@ -2259,7 +2262,7 @@ export class SentryApiService {
fields: string[];
limit?: number;
projectId?: string;
dataset?: "spans" | "errors" | "logs";
dataset?: "spans" | "errors" | "logs" | "metrics";
statsPeriod?: string;
start?: string;
end?: string;
Expand All @@ -2269,8 +2272,8 @@ export class SentryApiService {
) {
let queryParams: URLSearchParams;

if (dataset === "errors") {
// Use Discover API query builder
if (dataset === "errors" || dataset === "metrics") {
// Use Discover API query builder (errors and metrics use the same discover-style endpoint)
queryParams = this.buildDiscoverApiQuery({
query,
fields,
Expand All @@ -2280,6 +2283,7 @@ export class SentryApiService {
start,
end,
sort,
dataset: dataset === "metrics" ? "metrics" : undefined,
});
} else {
// Use EAP API query builder for spans and logs
Expand Down
6 changes: 3 additions & 3 deletions packages/mcp-core/src/skillDefinitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
},
{
"name": "search_events",
"description": "Search for events AND perform counts/aggregations - the ONLY tool for statistics and counts.\n\nSupports TWO query types:\n1. AGGREGATIONS (counts, sums, averages): 'how many errors', 'count of issues', 'total tokens'\n2. Individual events with timestamps: 'show me error logs from last hour'\n\nUSE THIS FOR ALL COUNTS/STATISTICS:\n- 'how many errors today' → returns count\n- 'count of database failures' → returns count\n- 'total number of issues' → returns count\n- 'average response time' → returns avg()\n- 'sum of tokens used' → returns sum()\n\nALSO USE FOR INDIVIDUAL EVENTS:\n- 'error logs from last hour' → returns event list\n- 'database errors with timestamps' → returns event list\n- 'trace spans for slow API calls' → returns span list\n\nDataset Selection (AI automatically chooses):\n- errors: Exception/crash events\n- logs: Log entries\n- spans: Performance data, AI/LLM calls, token usage\n\nDO NOT USE for grouped issue lists → use search_issues\n\n<examples>\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='how many errors today')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='count of database failures this week')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='total tokens used by model')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='error logs from the last hour')\n</examples>\n\n<hints>\n- If the user passes a parameter in the form of name/otherName, it's likely in the format of <organizationSlug>/<projectSlug>.\n- Parse org/project notation directly without calling find_organizations or find_projects.\n</hints>",
"description": "Search for events AND perform counts/aggregations - the ONLY tool for statistics and counts.\n\nSupports TWO query types:\n1. AGGREGATIONS (counts, sums, averages): 'how many errors', 'count of issues', 'total tokens'\n2. Individual events with timestamps: 'show me error logs from last hour'\n\nUSE THIS FOR ALL COUNTS/STATISTICS:\n- 'how many errors today' → returns count\n- 'count of database failures' → returns count\n- 'total number of issues' → returns count\n- 'average response time' → returns avg()\n- 'sum of tokens used' → returns sum()\n\nALSO USE FOR INDIVIDUAL EVENTS:\n- 'error logs from last hour' → returns event list\n- 'database errors with timestamps' → returns event list\n- 'trace spans for slow API calls' → returns span list\n\nDataset Selection (AI automatically chooses):\n- errors: Exception/crash events\n- logs: Log entries\n- spans: Performance data, AI/LLM calls, token usage\n- metrics: Transaction performance metrics (apdex, failure_rate, p75/p95, tpm/epm)\n\nDO NOT USE for grouped issue lists → use search_issues\n\n<examples>\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='how many errors today')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='count of database failures this week')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='total tokens used by model')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='error logs from the last hour')\n</examples>\n\n<hints>\n- If the user passes a parameter in the form of name/otherName, it's likely in the format of <organizationSlug>/<projectSlug>.\n- Parse org/project notation directly without calling find_organizations or find_projects.\n</hints>",
"requiredScopes": ["event:read"]
},
{
Expand Down Expand Up @@ -129,7 +129,7 @@
},
{
"name": "search_events",
"description": "Search for events AND perform counts/aggregations - the ONLY tool for statistics and counts.\n\nSupports TWO query types:\n1. AGGREGATIONS (counts, sums, averages): 'how many errors', 'count of issues', 'total tokens'\n2. Individual events with timestamps: 'show me error logs from last hour'\n\nUSE THIS FOR ALL COUNTS/STATISTICS:\n- 'how many errors today' → returns count\n- 'count of database failures' → returns count\n- 'total number of issues' → returns count\n- 'average response time' → returns avg()\n- 'sum of tokens used' → returns sum()\n\nALSO USE FOR INDIVIDUAL EVENTS:\n- 'error logs from last hour' → returns event list\n- 'database errors with timestamps' → returns event list\n- 'trace spans for slow API calls' → returns span list\n\nDataset Selection (AI automatically chooses):\n- errors: Exception/crash events\n- logs: Log entries\n- spans: Performance data, AI/LLM calls, token usage\n\nDO NOT USE for grouped issue lists → use search_issues\n\n<examples>\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='how many errors today')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='count of database failures this week')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='total tokens used by model')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='error logs from the last hour')\n</examples>\n\n<hints>\n- If the user passes a parameter in the form of name/otherName, it's likely in the format of <organizationSlug>/<projectSlug>.\n- Parse org/project notation directly without calling find_organizations or find_projects.\n</hints>",
"description": "Search for events AND perform counts/aggregations - the ONLY tool for statistics and counts.\n\nSupports TWO query types:\n1. AGGREGATIONS (counts, sums, averages): 'how many errors', 'count of issues', 'total tokens'\n2. Individual events with timestamps: 'show me error logs from last hour'\n\nUSE THIS FOR ALL COUNTS/STATISTICS:\n- 'how many errors today' → returns count\n- 'count of database failures' → returns count\n- 'total number of issues' → returns count\n- 'average response time' → returns avg()\n- 'sum of tokens used' → returns sum()\n\nALSO USE FOR INDIVIDUAL EVENTS:\n- 'error logs from last hour' → returns event list\n- 'database errors with timestamps' → returns event list\n- 'trace spans for slow API calls' → returns span list\n\nDataset Selection (AI automatically chooses):\n- errors: Exception/crash events\n- logs: Log entries\n- spans: Performance data, AI/LLM calls, token usage\n- metrics: Transaction performance metrics (apdex, failure_rate, p75/p95, tpm/epm)\n\nDO NOT USE for grouped issue lists → use search_issues\n\n<examples>\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='how many errors today')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='count of database failures this week')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='total tokens used by model')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='error logs from the last hour')\n</examples>\n\n<hints>\n- If the user passes a parameter in the form of name/otherName, it's likely in the format of <organizationSlug>/<projectSlug>.\n- Parse org/project notation directly without calling find_organizations or find_projects.\n</hints>",
"requiredScopes": ["event:read"]
},
{
Expand Down Expand Up @@ -224,7 +224,7 @@
},
{
"name": "search_events",
"description": "Search for events AND perform counts/aggregations - the ONLY tool for statistics and counts.\n\nSupports TWO query types:\n1. AGGREGATIONS (counts, sums, averages): 'how many errors', 'count of issues', 'total tokens'\n2. Individual events with timestamps: 'show me error logs from last hour'\n\nUSE THIS FOR ALL COUNTS/STATISTICS:\n- 'how many errors today' → returns count\n- 'count of database failures' → returns count\n- 'total number of issues' → returns count\n- 'average response time' → returns avg()\n- 'sum of tokens used' → returns sum()\n\nALSO USE FOR INDIVIDUAL EVENTS:\n- 'error logs from last hour' → returns event list\n- 'database errors with timestamps' → returns event list\n- 'trace spans for slow API calls' → returns span list\n\nDataset Selection (AI automatically chooses):\n- errors: Exception/crash events\n- logs: Log entries\n- spans: Performance data, AI/LLM calls, token usage\n\nDO NOT USE for grouped issue lists → use search_issues\n\n<examples>\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='how many errors today')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='count of database failures this week')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='total tokens used by model')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='error logs from the last hour')\n</examples>\n\n<hints>\n- If the user passes a parameter in the form of name/otherName, it's likely in the format of <organizationSlug>/<projectSlug>.\n- Parse org/project notation directly without calling find_organizations or find_projects.\n</hints>",
"description": "Search for events AND perform counts/aggregations - the ONLY tool for statistics and counts.\n\nSupports TWO query types:\n1. AGGREGATIONS (counts, sums, averages): 'how many errors', 'count of issues', 'total tokens'\n2. Individual events with timestamps: 'show me error logs from last hour'\n\nUSE THIS FOR ALL COUNTS/STATISTICS:\n- 'how many errors today' → returns count\n- 'count of database failures' → returns count\n- 'total number of issues' → returns count\n- 'average response time' → returns avg()\n- 'sum of tokens used' → returns sum()\n\nALSO USE FOR INDIVIDUAL EVENTS:\n- 'error logs from last hour' → returns event list\n- 'database errors with timestamps' → returns event list\n- 'trace spans for slow API calls' → returns span list\n\nDataset Selection (AI automatically chooses):\n- errors: Exception/crash events\n- logs: Log entries\n- spans: Performance data, AI/LLM calls, token usage\n- metrics: Transaction performance metrics (apdex, failure_rate, p75/p95, tpm/epm)\n\nDO NOT USE for grouped issue lists → use search_issues\n\n<examples>\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='how many errors today')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='count of database failures this week')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='total tokens used by model')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='error logs from the last hour')\n</examples>\n\n<hints>\n- If the user passes a parameter in the form of name/otherName, it's likely in the format of <organizationSlug>/<projectSlug>.\n- Parse org/project notation directly without calling find_organizations or find_projects.\n</hints>",
"requiredScopes": ["event:read"]
},
{
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp-core/src/toolDefinitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@
},
{
"name": "search_events",
"description": "Search for events AND perform counts/aggregations - the ONLY tool for statistics and counts.\n\nSupports TWO query types:\n1. AGGREGATIONS (counts, sums, averages): 'how many errors', 'count of issues', 'total tokens'\n2. Individual events with timestamps: 'show me error logs from last hour'\n\nUSE THIS FOR ALL COUNTS/STATISTICS:\n- 'how many errors today' → returns count\n- 'count of database failures' → returns count\n- 'total number of issues' → returns count\n- 'average response time' → returns avg()\n- 'sum of tokens used' → returns sum()\n\nALSO USE FOR INDIVIDUAL EVENTS:\n- 'error logs from last hour' → returns event list\n- 'database errors with timestamps' → returns event list\n- 'trace spans for slow API calls' → returns span list\n\nDataset Selection (AI automatically chooses):\n- errors: Exception/crash events\n- logs: Log entries\n- spans: Performance data, AI/LLM calls, token usage\n\nDO NOT USE for grouped issue lists → use search_issues\n\n<examples>\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='how many errors today')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='count of database failures this week')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='total tokens used by model')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='error logs from the last hour')\n</examples>\n\n<hints>\n- If the user passes a parameter in the form of name/otherName, it's likely in the format of <organizationSlug>/<projectSlug>.\n- Parse org/project notation directly without calling find_organizations or find_projects.\n</hints>",
"description": "Search for events AND perform counts/aggregations - the ONLY tool for statistics and counts.\n\nSupports TWO query types:\n1. AGGREGATIONS (counts, sums, averages): 'how many errors', 'count of issues', 'total tokens'\n2. Individual events with timestamps: 'show me error logs from last hour'\n\nUSE THIS FOR ALL COUNTS/STATISTICS:\n- 'how many errors today' → returns count\n- 'count of database failures' → returns count\n- 'total number of issues' → returns count\n- 'average response time' → returns avg()\n- 'sum of tokens used' → returns sum()\n\nALSO USE FOR INDIVIDUAL EVENTS:\n- 'error logs from last hour' → returns event list\n- 'database errors with timestamps' → returns event list\n- 'trace spans for slow API calls' → returns span list\n\nDataset Selection (AI automatically chooses):\n- errors: Exception/crash events\n- logs: Log entries\n- spans: Performance data, AI/LLM calls, token usage\n- metrics: Transaction performance metrics (apdex, failure_rate, p75/p95, tpm/epm)\n\nDO NOT USE for grouped issue lists → use search_issues\n\n<examples>\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='how many errors today')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='count of database failures this week')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='total tokens used by model')\nsearch_events(organizationSlug='my-org', naturalLanguageQuery='error logs from the last hour')\n</examples>\n\n<hints>\n- If the user passes a parameter in the form of name/otherName, it's likely in the format of <organizationSlug>/<projectSlug>.\n- Parse org/project notation directly without calling find_organizations or find_projects.\n</hints>",
"inputSchema": {
"type": "object",
"properties": {
Expand Down
Loading
Loading