Skip to content

Commit 1349fae

Browse files
authored
Add Seer permission (#567)
1 parent ff98548 commit 1349fae

7 files changed

Lines changed: 34 additions & 15 deletions

File tree

‎packages/mcp-cloudflare/src/server/lib/approval-dialog.ts‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,16 @@ export function renderApprovalDialog(
704704
<!-- Optional permissions section -->
705705
<div class="optional-permissions">
706706
<h4 class="optional-permissions-title">Optional additional access:</h4>
707-
707+
708+
<label class="optional-permission-item">
709+
<input type="checkbox" name="permission" value="seer" checked>
710+
<span class="permission-checkbox"></span>
711+
<div class="optional-permission-content">
712+
<span class="optional-permission-name">Seer</span>
713+
<div class="optional-permission-description">Use Seer to analyze issues and generate fix recommendations (may incur costs)</div>
714+
</div>
715+
</label>
716+
708717
<label class="optional-permission-item">
709718
<input type="checkbox" name="permission" value="issue_triage">
710719
<span class="permission-checkbox"></span>
@@ -713,7 +722,7 @@ export function renderApprovalDialog(
713722
<div class="optional-permission-description">Update and manage issues - resolve, assign, and analyze problems</div>
714723
</div>
715724
</label>
716-
725+
717726
<label class="optional-permission-item">
718727
<input type="checkbox" name="permission" value="project_management">
719728
<span class="permission-checkbox"></span>

‎packages/mcp-cloudflare/src/server/oauth/routes/callback.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ interface AuthRequestWithPermissions extends AuthRequest {
2020
* Convert selected permissions to granted scopes
2121
* Permissions are additive:
2222
* - Base (always included): org:read, project:read, team:read, event:read
23+
* - Seer adds: seer (virtual scope)
2324
* - Issue Triage adds: event:write
2425
* - Project Management adds: project:write, team:write
2526
* @param permissions Array of permission strings
2627
*/
2728
function getScopesFromPermissions(permissions?: unknown): Set<Scope> {
28-
// Start with base read-only scopes (always granted)
29+
// Start with base read-only scopes (always granted via DEFAULT_SCOPES)
2930
const scopes = new Set<Scope>(DEFAULT_SCOPES);
3031

3132
// Validate permissions is an array of strings
@@ -37,6 +38,10 @@ function getScopesFromPermissions(permissions?: unknown): Set<Scope> {
3738
);
3839

3940
// Add scopes based on selected permissions
41+
if (perms.includes("seer")) {
42+
scopes.add("seer");
43+
}
44+
4045
if (perms.includes("issue_triage")) {
4146
scopes.add("event:write");
4247
}

‎packages/mcp-server/src/internal/formatting.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,7 +1399,7 @@ function formatContexts(contexts: z.infer<typeof EventSchema>["contexts"]) {
13991399
}
14001400

14011401
/**
1402-
* Formats a brief Seer AI analysis summary for inclusion in issue details.
1402+
* Formats a brief Seer analysis summary for inclusion in issue details.
14031403
* Shows current status and high-level insights, prompting to use analyze_issue_with_seer for full details.
14041404
*
14051405
* @param autofixState - The autofix state containing Seer analysis data
@@ -1419,7 +1419,7 @@ function formatSeerSummary(
14191419
const { autofix } = autofixState;
14201420
const parts: string[] = [];
14211421

1422-
parts.push("## Seer AI Analysis");
1422+
parts.push("## Seer Analysis");
14231423
parts.push("");
14241424

14251425
// Show status first

‎packages/mcp-server/src/permissions.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ export type Scope =
2525
| "event:read" // Read events and issues
2626
| "event:write" // Update issues (includes read)
2727
| "event:admin" // Delete issues (includes write and read)
28-
| "project:releases"; // Access release endpoints
28+
| "project:releases" // Access release endpoints
29+
| "seer"; // Virtual scope: Use Seer analysis (not respected by upstream Sentry API)
2930

3031
/**
3132
* Scope hierarchy - higher scopes include lower ones
@@ -58,6 +59,9 @@ const SCOPE_HIERARCHY: Record<Scope, Set<Scope>> = {
5859

5960
// Special scopes
6061
"project:releases": new Set(["project:releases"]),
62+
63+
// Virtual scopes (not respected by upstream Sentry API)
64+
seer: new Set(["seer"]),
6165
};
6266

6367
/**
@@ -113,6 +117,7 @@ export const SCOPE_DESCRIPTIONS: Record<Scope, string> = {
113117
"event:write": "Update and manage issues",
114118
"event:admin": "Delete issues",
115119
"project:releases": "Access release information",
120+
seer: "Use Seer for issue analysis (may incur costs)",
116121
};
117122

118123
/**

‎packages/mcp-server/src/tools/analyze-issue-with-seer.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe("analyze_issue_with_seer", () => {
3434
},
3535
);
3636

37-
expect(result).toContain("# Seer AI Analysis for Issue CLOUDFLARE-MCP-45");
37+
expect(result).toContain("# Seer Analysis for Issue CLOUDFLARE-MCP-45");
3838
expect(result).toContain("Found existing analysis (Run ID: 13)");
3939
expect(result).toContain("## Analysis Complete");
4040
expect(result).toContain("## 1. **Root Cause Analysis**");
@@ -78,7 +78,7 @@ describe("analyze_issue_with_seer", () => {
7878
const result = await promise;
7979

8080
expect(attempts).toBe(3);
81-
expect(result).toContain("# Seer AI Analysis for Issue CLOUDFLARE-MCP-99");
81+
expect(result).toContain("# Seer Analysis for Issue CLOUDFLARE-MCP-99");
8282
expect(result).toContain("Found existing analysis");
8383
});
8484

@@ -122,7 +122,7 @@ describe("analyze_issue_with_seer", () => {
122122
const result = await promise;
123123

124124
expect(attempts).toBe(2);
125-
expect(result).toContain("# Seer AI Analysis for Issue CLOUDFLARE-MCP-500");
125+
expect(result).toContain("# Seer Analysis for Issue CLOUDFLARE-MCP-500");
126126
});
127127

128128
it.skip("handles polling with transient errors", async () => {

‎packages/mcp-server/src/tools/analyze-issue-with-seer.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ import {
2525

2626
export default defineTool({
2727
name: "analyze_issue_with_seer",
28-
requiredScopes: ["event:read"],
28+
requiredScopes: ["event:read", "seer"],
2929
description: [
30-
"Use Seer AI to analyze production errors and get detailed root cause analysis with specific code fixes.",
30+
"Use Seer to analyze production errors and get detailed root cause analysis with specific code fixes.",
3131
"",
3232
"Use this tool when you need:",
3333
"- Detailed AI-powered root cause analysis",
@@ -90,7 +90,7 @@ export default defineTool({
9090

9191
setTag("organization.slug", orgSlug);
9292

93-
let output = `# Seer AI Analysis for Issue ${parsedIssueId}\n\n`;
93+
let output = `# Seer Analysis for Issue ${parsedIssueId}\n\n`;
9494

9595
// Step 1: Check if analysis already exists
9696
let autofixState = await retryWithBackoff(

‎packages/mcp-server/src/tools/get-issue-details.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ describe("get_issue_details", () => {
806806
},
807807
);
808808

809-
expect(result).toContain("## Seer AI Analysis");
809+
expect(result).toContain("## Seer Analysis");
810810
expect(result).toContain("**Status:** Processing");
811811
expect(result).toContain("**Root Cause Identified:**");
812812
expect(result).toContain(
@@ -853,7 +853,7 @@ describe("get_issue_details", () => {
853853
},
854854
);
855855

856-
expect(result).toContain("## Seer AI Analysis");
856+
expect(result).toContain("## Seer Analysis");
857857
expect(result).toContain("**Status:** Analysis failed.");
858858
expect(result).toContain(
859859
"For detailed root cause analysis and solutions, call `analyze_issue_with_seer(organizationSlug='sentry-mcp-evals', issueId='CLOUDFLARE-MCP-41')`",
@@ -915,7 +915,7 @@ describe("get_issue_details", () => {
915915
},
916916
);
917917

918-
expect(result).toContain("## Seer AI Analysis");
918+
expect(result).toContain("## Seer Analysis");
919919
expect(result).toContain("**Root Cause Identified:**");
920920
expect(result).toContain(
921921
"Partial analysis completed but more context needed.",

0 commit comments

Comments
 (0)