diff --git a/packages/mcp-core/src/skillDefinitions.json b/packages/mcp-core/src/skillDefinitions.json index bf5f5e664..9b7a4a2fa 100644 --- a/packages/mcp-core/src/skillDefinitions.json +++ b/packages/mcp-core/src/skillDefinitions.json @@ -605,7 +605,7 @@ }, { "name": "find_dsns", - "description": "List the DSNs (client keys) for a Sentry project: the SENTRY_DSN an SDK uses to send events.\n\nUse this tool when you need to:\n- Retrieve a SENTRY_DSN for a specific project\n- Configure a Sentry SDK for an existing project\n\n\n- If the user passes a parameter in the form of name/otherName, its likely in the format of /.\n- If only one parameter is provided, and it could be either `organizationSlug` or `projectSlug`, its probably `organizationSlug`, but if you're really uncertain you might want to call `find_organizations()` first.\n", + "description": "List the DSNs (client keys) for a Sentry project: the SENTRY_DSN an SDK uses to send events. Each DSN includes its status and rate limit.\n\nUse this tool when you need to:\n- Retrieve a SENTRY_DSN for a specific project\n- Configure a Sentry SDK for an existing project\n- Check whether a DSN is active or what rate limit it has\n\n\n- If the user passes a parameter in the form of name/otherName, its likely in the format of /.\n- If only one parameter is provided, and it could be either `organizationSlug` or `projectSlug`, its probably `organizationSlug`, but if you're really uncertain you might want to call `find_organizations()` first.\n", "requiredScopes": ["project:read"] }, { diff --git a/packages/mcp-core/src/toolDefinitions.json b/packages/mcp-core/src/toolDefinitions.json index 8876e1d16..aa0474092 100644 --- a/packages/mcp-core/src/toolDefinitions.json +++ b/packages/mcp-core/src/toolDefinitions.json @@ -2462,7 +2462,7 @@ { "name": "find_dsns", "title": "Find DSNs", - "description": "List the DSNs (client keys) for a Sentry project: the SENTRY_DSN an SDK uses to send events.\n\nUse this tool when you need to:\n- Retrieve a SENTRY_DSN for a specific project\n- Configure a Sentry SDK for an existing project\n\n\n- If the user passes a parameter in the form of name/otherName, its likely in the format of /.\n- If only one parameter is provided, and it could be either `organizationSlug` or `projectSlug`, its probably `organizationSlug`, but if you're really uncertain you might want to call `find_organizations()` first.\n", + "description": "List the DSNs (client keys) for a Sentry project: the SENTRY_DSN an SDK uses to send events. Each DSN includes its status and rate limit.\n\nUse this tool when you need to:\n- Retrieve a SENTRY_DSN for a specific project\n- Configure a Sentry SDK for an existing project\n- Check whether a DSN is active or what rate limit it has\n\n\n- If the user passes a parameter in the form of name/otherName, its likely in the format of /.\n- If only one parameter is provided, and it could be either `organizationSlug` or `projectSlug`, its probably `organizationSlug`, but if you're really uncertain you might want to call `find_organizations()` first.\n", "inputSchema": { "type": "object", "properties": { @@ -2509,9 +2509,33 @@ }, "dsn": { "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "rateLimit": { + "anyOf": [ + { + "type": "object", + "properties": { + "count": { + "type": "number" + }, + "windowSeconds": { + "type": "number" + } + }, + "required": ["count", "windowSeconds"], + "additionalProperties": false + }, + { + "type": "null" + } + ], + "description": "Null when rate limiting is disabled." } }, - "required": ["id", "name", "dsn"], + "required": ["id", "name", "dsn", "isActive", "rateLimit"], "additionalProperties": false } } diff --git a/packages/mcp-core/src/tools/catalog/find-dsns.test.ts b/packages/mcp-core/src/tools/catalog/find-dsns.test.ts index 6f914e3c0..608d84366 100644 --- a/packages/mcp-core/src/tools/catalog/find-dsns.test.ts +++ b/packages/mcp-core/src/tools/catalog/find-dsns.test.ts @@ -9,7 +9,7 @@ import { import findDsns from "./find-dsns.js"; describe("find_dsns", () => { - it("returns all project DSNs as structured content", async () => { + it("returns all project DSNs with status and rate limit as structured content", async () => { mswServer.use( http.get( "https://sentry.io/api/0/projects/test-org/test-project/keys/", @@ -24,6 +24,7 @@ describe("find_dsns", () => { }, isActive: true, dateCreated: "2026-07-28T12:00:00.000Z", + rateLimit: { window: 3600, count: 1000 }, secretKey: "do-not-leak", backendOnlyField: "do-not-leak", }, @@ -35,6 +36,7 @@ describe("find_dsns", () => { }, isActive: false, dateCreated: "2026-07-28T12:00:00.000Z", + rateLimit: null, }, ]), ), @@ -56,12 +58,19 @@ describe("find_dsns", () => { { "dsn": "https://public@example.ingest.sentry.io/1", "id": "123", + "isActive": true, "name": "Production", + "rateLimit": { + "count": 1000, + "windowSeconds": 3600, + }, }, { "dsn": "https://development@example.ingest.sentry.io/2", "id": "456", + "isActive": false, "name": "Development", + "rateLimit": null, }, ], } diff --git a/packages/mcp-core/src/tools/catalog/find-dsns.ts b/packages/mcp-core/src/tools/catalog/find-dsns.ts index f7ae0932e..b6425182b 100644 --- a/packages/mcp-core/src/tools/catalog/find-dsns.ts +++ b/packages/mcp-core/src/tools/catalog/find-dsns.ts @@ -16,6 +16,14 @@ export const findDsnsOutputSchema = z.object({ id: z.string(), name: z.string(), dsn: z.string(), + isActive: z.boolean(), + rateLimit: z + .object({ + count: z.number(), + windowSeconds: z.number(), + }) + .nullable() + .describe("Null when rate limiting is disabled."), }), ), }); @@ -26,11 +34,12 @@ export default defineTool({ skills: ["project-management"], // DSN management is part of project setup requiredScopes: ["project:read"], description: [ - "List the DSNs (client keys) for a Sentry project: the SENTRY_DSN an SDK uses to send events.", + "List the DSNs (client keys) for a Sentry project: the SENTRY_DSN an SDK uses to send events. Each DSN includes its status and rate limit.", "", "Use this tool when you need to:", "- Retrieve a SENTRY_DSN for a specific project", "- Configure a Sentry SDK for an existing project", + "- Check whether a DSN is active or what rate limit it has", "", "", "- If the user passes a parameter in the form of name/otherName, its likely in the format of /.", @@ -66,6 +75,13 @@ export default defineTool({ id: String(clientKey.id), name: clientKey.name, dsn: clientKey.dsn.public, + isActive: clientKey.isActive, + rateLimit: clientKey.rateLimit + ? { + count: clientKey.rateLimit.count, + windowSeconds: clientKey.rateLimit.window, + } + : null, })), }); },