Skip to main content
Glama
resolve.ts3.08 kB
import { parseSkills, SKILLS, type Skill } from "@sentry/mcp-core/skills"; import { validateAndParseSentryUrlThrows, validateOpenAiBaseUrlThrows, validateSentryHostThrows, } from "@sentry/mcp-core/utils/url-utils"; import type { MergedArgs, ResolvedConfig } from "./types"; export function formatInvalidSkills( invalid: string[], envName?: string, ): string { const where = envName ? `${envName} provided` : "Invalid skills provided"; const allSkills = Object.keys(SKILLS).join(", "); return `Error: ${where}: ${invalid.join(", ")}\nAvailable skills: ${allSkills}`; } export function finalize(input: MergedArgs): ResolvedConfig { // Access token required if (!input.accessToken) { throw new Error( "Error: No access token was provided. Pass one with `--access-token` or via `SENTRY_ACCESS_TOKEN`.", ); } // Determine host from url/host with validation let sentryHost = "sentry.io"; if (input.url) { sentryHost = validateAndParseSentryUrlThrows(input.url); } else if (input.host) { validateSentryHostThrows(input.host); sentryHost = input.host; } // Skills resolution // // IMPORTANT: stdio (CLI) intentionally defaults to ALL skills when no --skills flag is provided // // This differs from the OAuth flow, which requires explicit user selection: // - stdio/CLI: Non-interactive, defaults to ALL skills (inspect, docs, seer, triage, project-management) // - OAuth: Interactive, requires user to explicitly select skills (with sensible defaults pre-checked) // // Rationale: // We don't want the MCP to break if users don't specify skills. stdio is typically used in // local development and CI/CD environments where maximum access by default is expected. // OAuth is used in multi-tenant hosted environments where users should consciously grant // permissions on a per-app basis. // // For OAuth validation that enforces minimum 1 skill selection, see: // packages/mcp-cloudflare/src/server/oauth/routes/callback.ts (lines 234-248) // let finalSkills: Set<Skill> | undefined = undefined; if (input.skills) { // Override: use only the specified skills const { valid, invalid } = parseSkills(input.skills); if (invalid.length > 0) { throw new Error(formatInvalidSkills(invalid)); } if (valid.size === 0) { throw new Error("Error: Invalid skills provided. No valid skills found."); } finalSkills = valid; } else { // Default: grant ALL skills when no flag is provided (see comment block above for rationale) const allSkills = Object.keys(SKILLS) as Skill[]; finalSkills = new Set<Skill>(allSkills); } const resolvedOpenAiBaseUrl = input.openaiBaseUrl ? validateOpenAiBaseUrlThrows(input.openaiBaseUrl) : undefined; return { accessToken: input.accessToken, sentryHost, mcpUrl: input.mcpUrl, sentryDsn: input.sentryDsn, openaiBaseUrl: resolvedOpenAiBaseUrl, openaiModel: input.openaiModel, finalSkills, organizationSlug: input.organizationSlug, projectSlug: input.projectSlug, }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/getsentry/sentry-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server