diff --git a/packages/mcp-core/src/skillDefinitions.json b/packages/mcp-core/src/skillDefinitions.json
index b6c491fc1..8a9bda721 100644
--- a/packages/mcp-core/src/skillDefinitions.json
+++ b/packages/mcp-core/src/skillDefinitions.json
@@ -19,7 +19,7 @@
},
{
"name": "find_dropped_events",
- "description": "Find events dropped before they were stored in Sentry — ground-truth data-fidelity information about what was and wasn't captured.\n\nEvents can be dropped client-side in the SDK (sample_rate, before_send) or\nserver-side at ingest (rate limited, over quota, filtered, invalid, abuse/spike\nprotection, cardinality limited). Accepted-only views (searches, aggregates,\ncharts) can't show this, so the data may be incomplete in ways they don't reveal\n— for example, a flat or spiky chart caused entirely by drops.\n\nUse this tool when you need to:\n- Explain why a chart is flat, lower than expected, or doesn't match what the user is sending\n- Confirm the data you need is actually in Sentry (not dropped) before trusting a query, aggregate, or dashboard\n- Attribute a volume anomaly to a specific drop reason (quota, spike protection, sampling, filters)\n- Tell the user why their data is missing and what to do about it (raise quota, fix sampling, etc.)\n\nReturns dropped event volume bucketed over time, with the drop `outcome` and `reason`\nfor each bucket, plus the accepted volume per bucket so you can compute the dropped share.\n\n\nfind_dropped_events(organizationSlug='my-org', dataset='spans', projectSlug='my-project')\nfind_dropped_events(organizationSlug='my-org', dataset='logs', statsPeriod='30d')\nfind_dropped_events(organizationSlug='my-org', dataset='errors', outcome='rate_limited')\n\n\n\n- This is independent of any search query — it reports drops for the whole project/time range.\n- `outcome` is the drop kind (e.g. rate_limited, filtered); `reason` is the sub-cause (e.g. key_quota, sample_rate).\n- Pass `outcome` and/or `reason` to scope the dropped side to one classification; the accepted volume is always returned in full.\n- An empty `droppedEvents` list means no drops in the window — the data can be trusted.\n",
+ "description": "Find events dropped before they were stored in Sentry — ground-truth data-fidelity information about what was and wasn't captured.\n\nEvents can be dropped client-side in the SDK (sample_rate, before_send) or\nserver-side at ingest (rate limited, over quota, filtered, invalid, abuse/spike\nprotection, cardinality limited). Accepted-only views (searches, aggregates,\ncharts) can't show this, so the data may be incomplete in ways they don't reveal\n— for example, a flat or spiky chart caused entirely by drops.\n\nUse this tool when you need to:\n- Explain why a chart is flat, lower than expected, or doesn't match what the user is sending\n- Confirm the data you need is actually in Sentry (not dropped) before trusting a query, aggregate, or dashboard\n- Attribute a volume anomaly to a specific drop reason (quota, spike protection, sampling, filters)\n- Tell the user why their data is missing and what to do about it (raise quota, fix sampling, etc.)\n\nReturns dropped event volume bucketed over time, with the drop `outcome` and `reason`\nfor each bucket, plus the accepted volume per bucket so you can compute the dropped share.\n\n\nfind_dropped_events(organizationSlug='my-org', dataset='spans', projectSlug='my-project')\nfind_dropped_events(organizationSlug='my-org', dataset='logs', statsPeriod='30d')\nfind_dropped_events(organizationSlug='my-org', dataset='errors', outcome='rate_limited')\n\n\n\n- This is independent of any search query — it reports drops for the whole project/time range.\n- `outcome` is the drop kind (e.g. rate_limited, filtered); `reason` is the sub-cause (e.g. key_quota, sample_rate).\n- Each bucket's `tags` classify the drop: `intentional` (user-configured, e.g. sampling or filters) vs `unintentional` (not intended, e.g. quota or abuse).\n- Pass `outcome` and/or `reason` to scope the dropped side to one classification; the accepted volume is always returned in full.\n- An empty `droppedEvents` list means no drops in the window — the data can be trusted.\n",
"requiredScopes": ["event:read"]
},
{
diff --git a/packages/mcp-core/src/toolDefinitions.json b/packages/mcp-core/src/toolDefinitions.json
index 7b621db13..7082428b5 100644
--- a/packages/mcp-core/src/toolDefinitions.json
+++ b/packages/mcp-core/src/toolDefinitions.json
@@ -2291,7 +2291,7 @@
},
{
"name": "find_dropped_events",
- "description": "Find events dropped before they were stored in Sentry — ground-truth data-fidelity information about what was and wasn't captured.\n\nEvents can be dropped client-side in the SDK (sample_rate, before_send) or\nserver-side at ingest (rate limited, over quota, filtered, invalid, abuse/spike\nprotection, cardinality limited). Accepted-only views (searches, aggregates,\ncharts) can't show this, so the data may be incomplete in ways they don't reveal\n— for example, a flat or spiky chart caused entirely by drops.\n\nUse this tool when you need to:\n- Explain why a chart is flat, lower than expected, or doesn't match what the user is sending\n- Confirm the data you need is actually in Sentry (not dropped) before trusting a query, aggregate, or dashboard\n- Attribute a volume anomaly to a specific drop reason (quota, spike protection, sampling, filters)\n- Tell the user why their data is missing and what to do about it (raise quota, fix sampling, etc.)\n\nReturns dropped event volume bucketed over time, with the drop `outcome` and `reason`\nfor each bucket, plus the accepted volume per bucket so you can compute the dropped share.\n\n\nfind_dropped_events(organizationSlug='my-org', dataset='spans', projectSlug='my-project')\nfind_dropped_events(organizationSlug='my-org', dataset='logs', statsPeriod='30d')\nfind_dropped_events(organizationSlug='my-org', dataset='errors', outcome='rate_limited')\n\n\n\n- This is independent of any search query — it reports drops for the whole project/time range.\n- `outcome` is the drop kind (e.g. rate_limited, filtered); `reason` is the sub-cause (e.g. key_quota, sample_rate).\n- Pass `outcome` and/or `reason` to scope the dropped side to one classification; the accepted volume is always returned in full.\n- An empty `droppedEvents` list means no drops in the window — the data can be trusted.\n",
+ "description": "Find events dropped before they were stored in Sentry — ground-truth data-fidelity information about what was and wasn't captured.\n\nEvents can be dropped client-side in the SDK (sample_rate, before_send) or\nserver-side at ingest (rate limited, over quota, filtered, invalid, abuse/spike\nprotection, cardinality limited). Accepted-only views (searches, aggregates,\ncharts) can't show this, so the data may be incomplete in ways they don't reveal\n— for example, a flat or spiky chart caused entirely by drops.\n\nUse this tool when you need to:\n- Explain why a chart is flat, lower than expected, or doesn't match what the user is sending\n- Confirm the data you need is actually in Sentry (not dropped) before trusting a query, aggregate, or dashboard\n- Attribute a volume anomaly to a specific drop reason (quota, spike protection, sampling, filters)\n- Tell the user why their data is missing and what to do about it (raise quota, fix sampling, etc.)\n\nReturns dropped event volume bucketed over time, with the drop `outcome` and `reason`\nfor each bucket, plus the accepted volume per bucket so you can compute the dropped share.\n\n\nfind_dropped_events(organizationSlug='my-org', dataset='spans', projectSlug='my-project')\nfind_dropped_events(organizationSlug='my-org', dataset='logs', statsPeriod='30d')\nfind_dropped_events(organizationSlug='my-org', dataset='errors', outcome='rate_limited')\n\n\n\n- This is independent of any search query — it reports drops for the whole project/time range.\n- `outcome` is the drop kind (e.g. rate_limited, filtered); `reason` is the sub-cause (e.g. key_quota, sample_rate).\n- Each bucket's `tags` classify the drop: `intentional` (user-configured, e.g. sampling or filters) vs `unintentional` (not intended, e.g. quota or abuse).\n- Pass `outcome` and/or `reason` to scope the dropped side to one classification; the accepted volume is always returned in full.\n- An empty `droppedEvents` list means no drops in the window — the data can be trusted.\n",
"inputSchema": {
"type": "object",
"properties": {
@@ -2443,6 +2443,13 @@
},
"count": {
"type": "number"
+ },
+ "tags": {
+ "default": [],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
}
},
"required": [
@@ -2451,7 +2458,8 @@
"category",
"start",
"end",
- "count"
+ "count",
+ "tags"
],
"additionalProperties": false
}
@@ -2478,6 +2486,13 @@
},
"count": {
"type": "number"
+ },
+ "tags": {
+ "default": [],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
}
},
"required": [
@@ -2486,7 +2501,8 @@
"category",
"start",
"end",
- "count"
+ "count",
+ "tags"
],
"additionalProperties": false
}
diff --git a/packages/mcp-core/src/tools/catalog/find-dropped-events.test.ts b/packages/mcp-core/src/tools/catalog/find-dropped-events.test.ts
index d9d01e734..bdc0be39a 100644
--- a/packages/mcp-core/src/tools/catalog/find-dropped-events.test.ts
+++ b/packages/mcp-core/src/tools/catalog/find-dropped-events.test.ts
@@ -33,6 +33,7 @@ const DROPPED_EVENTS_RESPONSE = {
start: 1_700_000_000_000,
end: 1_700_003_600_000,
count: 400,
+ tags: ["unintentional"],
},
],
acceptedEvents: [
@@ -44,6 +45,7 @@ const DROPPED_EVENTS_RESPONSE = {
start: 1_700_000_000_000,
end: 1_700_003_600_000,
count: 1000,
+ tags: [],
},
],
};
@@ -89,6 +91,7 @@ describe("find_dropped_events", () => {
"outcome": "accepted",
"reason": "accepted",
"start": 1700000000000,
+ "tags": [],
},
],
"dataset": "spans",
@@ -100,6 +103,9 @@ describe("find_dropped_events", () => {
"outcome": "rate_limited",
"reason": "key_quota",
"start": 1700000000000,
+ "tags": [
+ "unintentional",
+ ],
},
],
"interval": 3600000,
diff --git a/packages/mcp-core/src/tools/catalog/find-dropped-events.ts b/packages/mcp-core/src/tools/catalog/find-dropped-events.ts
index 3048cd26e..0ba40458d 100644
--- a/packages/mcp-core/src/tools/catalog/find-dropped-events.ts
+++ b/packages/mcp-core/src/tools/catalog/find-dropped-events.ts
@@ -28,6 +28,7 @@ const droppedBucketSchema = z.object({
start: z.number(),
end: z.number(),
count: z.number(),
+ tags: z.array(z.string()).default([]),
});
export const findDroppedEventsOutputSchema = z.object({
@@ -68,6 +69,7 @@ export default defineTool({
"",
"- This is independent of any search query — it reports drops for the whole project/time range.",
"- `outcome` is the drop kind (e.g. rate_limited, filtered); `reason` is the sub-cause (e.g. key_quota, sample_rate).",
+ "- Each bucket's `tags` classify the drop: `intentional` (user-configured, e.g. sampling or filters) vs `unintentional` (not intended, e.g. quota or abuse).",
"- Pass `outcome` and/or `reason` to scope the dropped side to one classification; the accepted volume is always returned in full.",
"- An empty `droppedEvents` list means no drops in the window — the data can be trusted.",
"",
@@ -169,6 +171,7 @@ export default defineTool({
start: number;
end: number;
count: number;
+ tags?: string[];
}) => ({
outcome: bucket.outcome,
reason: bucket.reason,
@@ -176,6 +179,7 @@ export default defineTool({
start: bucket.start,
end: bucket.end,
count: bucket.count,
+ tags: bucket.tags ?? [],
});
return structuredResult({