diff --git a/frontend/src/app/workspaces/[workspaceId]/integrations/[providerId]/page.tsx b/frontend/src/app/workspaces/[workspaceId]/integrations/[providerId]/page.tsx
index 31b44254ec..3ca7c9e284 100644
--- a/frontend/src/app/workspaces/[workspaceId]/integrations/[providerId]/page.tsx
+++ b/frontend/src/app/workspaces/[workspaceId]/integrations/[providerId]/page.tsx
@@ -103,6 +103,15 @@ export default function ProviderDetailPage() {
type ProviderDetailTab = "overview" | "configuration"
+/**
+ * Check if a provider is an MCP (Model Context Protocol) provider.
+ * MCP providers don't require user-provided client credentials.
+ */
+function isMCPProvider(provider: ProviderRead): boolean {
+ // MCP providers follow the naming convention of ending with "_mcp"
+ return provider.metadata.id.endsWith("_mcp")
+}
+
function ProviderDetailContent({ provider }: { provider: ProviderRead }) {
const workspaceId = useWorkspaceId()
const router = useRouter()
@@ -110,11 +119,14 @@ function ProviderDetailContent({ provider }: { provider: ProviderRead }) {
const [errorMessage, setErrorMessage] = useState("")
const [_showConnectPrompt, setShowConnectPrompt] = useState(false)
const providerId = provider.metadata.id
+ const isMCP = isMCPProvider(provider)
// Get active tab from URL query params, default to "overview"
+ // For MCP providers, always use "overview" since there's no configuration tab
const activeTab = (
searchParams &&
- ["overview", "configuration"].includes(searchParams.get("tab") || "")
+ ["overview", "configuration"].includes(searchParams.get("tab") || "") &&
+ !isMCP // Don't allow configuration tab for MCP providers
? (searchParams.get("tab") ?? "overview")
: "overview"
) as ProviderDetailTab
@@ -294,11 +306,21 @@ function ProviderDetailContent({ provider }: { provider: ProviderRead }) {
variant="outline"
size="sm"
className="h-[22px] px-2 py-0 text-xs font-medium"
- onClick={() => handleTabChange("configuration")}
- disabled={!isEnabled}
+ onClick={
+ isMCP
+ ? handleOAuthConnect
+ : () => handleTabChange("configuration")
+ }
+ disabled={!isEnabled || (isMCP && connectProviderIsPending)}
>
-
- Configure
+ {isMCP && connectProviderIsPending ? (
+
+ ) : isMCP ? (
+
+ ) : (
+
+ )}
+ {isMCP ? "Connect" : "Configure"}
)}
@@ -307,15 +329,6 @@ function ProviderDetailContent({ provider }: { provider: ProviderRead }) {
- {errorMessage && (
-
-
-
- {errorMessage}
-
-
- )}
-
{/* Tabs */}
Overview
-
-
- Configuration
-
+ {!isMCP && (
+
+
+ Configuration
+
+ )}
@@ -514,54 +529,56 @@ function ProviderDetailContent({ provider }: { provider: ProviderRead }) {
-
- {/* Configuration Form */}
-
-
- {testConnectionIsPending ? (
- <>
-
- Testing...
- >
- ) : (
- <>
-
- Test connection
- >
- )}
-
- ) : (
-
- {connectProviderIsPending ? (
- <>
-
- Connecting...
- >
- ) : (
- <>
-
- Connect with OAuth
- >
- )}
-
- )
- ) : null
- }
- />
-
-
+ {!isMCP && (
+
+ {/* Configuration Form */}
+
+
+ {testConnectionIsPending ? (
+ <>
+
+ Testing...
+ >
+ ) : (
+ <>
+
+ Test connection
+ >
+ )}
+
+ ) : (
+
+ {connectProviderIsPending ? (
+ <>
+
+ Connecting...
+ >
+ ) : (
+ <>
+
+ Connect with OAuth
+ >
+ )}
+
+ )
+ ) : null
+ }
+ />
+
+
+ )}
)
diff --git a/frontend/src/components/provider-config-form.tsx b/frontend/src/components/provider-config-form.tsx
index 7b44427e5d..8ebee33d25 100644
--- a/frontend/src/components/provider-config-form.tsx
+++ b/frontend/src/components/provider-config-form.tsx
@@ -86,6 +86,15 @@ interface ProviderConfigFormProps {
additionalButtons?: React.ReactNode
}
+/**
+ * Check if a provider is an MCP (Model Context Protocol) provider.
+ * MCP providers don't require user-provided client credentials.
+ */
+function isMCPProvider(provider: ProviderRead): boolean {
+ // MCP providers follow the naming convention of ending with "_mcp"
+ return provider.metadata.id.endsWith("_mcp")
+}
+
export function ProviderConfigForm({
provider,
onSuccess,
@@ -98,6 +107,7 @@ export function ProviderConfigForm({
grant_type: grantType,
} = provider
const workspaceId = useWorkspaceId()
+ const isMCP = isMCPProvider(provider)
const {
integration,
integrationIsLoading,
@@ -171,6 +181,42 @@ export function ProviderConfigForm({
return
}
+ // For MCP providers, show a simplified message
+ if (isMCP) {
+ return (
+
+
+
+ MCP OAuth Provider
+
+
+
+ This is a Model Context Protocol (MCP) provider that uses
+ server-managed OAuth credentials. No client configuration is
+ required - simply click "Connect" to authenticate.
+
+ {defaultScopes && defaultScopes.length > 0 && (
+
+
Default scopes
+
+ {defaultScopes.map((scope) => (
+
+ {scope}
+
+ ))}
+
+
+ The authorization server will determine the granted scopes
+ based on your permissions.
+
+
+ )}
+
+
+
+ )
+ }
+
return (
{/* Current Configuration Summary */}
diff --git a/tracecat/integrations/providers/__init__.py b/tracecat/integrations/providers/__init__.py
index c242eb20f3..602fc709c7 100644
--- a/tracecat/integrations/providers/__init__.py
+++ b/tracecat/integrations/providers/__init__.py
@@ -2,20 +2,32 @@
from tracecat.integrations.models import ProviderKey
from tracecat.integrations.providers.base import BaseOAuthProvider
+from tracecat.integrations.providers.github.mcp import GitHubMCPProvider
+from tracecat.integrations.providers.linear.mcp import LinearMCPProvider
from tracecat.integrations.providers.microsoft.graph import (
MicrosoftGraphACProvider,
MicrosoftGraphCCProvider,
)
+from tracecat.integrations.providers.microsoft.mcp import MicrosoftLearnMCPProvider
from tracecat.integrations.providers.microsoft.teams import (
MicrosoftTeamsACProvider,
MicrosoftTeamsCCProvider,
)
+from tracecat.integrations.providers.notion.mcp import NotionMCPProvider
+from tracecat.integrations.providers.runreveal.mcp import RunRevealMCPProvider
+from tracecat.integrations.providers.sentry.mcp import SentryMCPProvider
_PROVIDER_CLASSES: list[type[BaseOAuthProvider]] = [
MicrosoftGraphACProvider,
MicrosoftGraphCCProvider,
MicrosoftTeamsACProvider,
MicrosoftTeamsCCProvider,
+ MicrosoftLearnMCPProvider,
+ GitHubMCPProvider,
+ LinearMCPProvider,
+ NotionMCPProvider,
+ RunRevealMCPProvider,
+ SentryMCPProvider,
]
diff --git a/tracecat/integrations/providers/base.py b/tracecat/integrations/providers/base.py
index 59cc9f173f..935eb7f16d 100644
--- a/tracecat/integrations/providers/base.py
+++ b/tracecat/integrations/providers/base.py
@@ -2,7 +2,9 @@
from abc import ABC
from typing import Any, ClassVar, Self, cast
+from urllib.parse import urlparse
+import httpx
from authlib.integrations.httpx_client import AsyncOAuth2Client
from pydantic import BaseModel, SecretStr
@@ -63,10 +65,13 @@ def __init__(
client_kwargs = {
"client_id": self.client_id,
"client_secret": self.client_secret,
- "scope": " ".join(self.requested_scopes),
"grant_type": self.grant_type,
}
+ # Only add scope if not empty
+ if self.requested_scopes:
+ client_kwargs["scope"] = " ".join(self.requested_scopes)
+
# Let subclasses add grant-specific parameters
client_kwargs.update(self._get_client_kwargs())
@@ -269,3 +274,113 @@ async def get_client_credentials_token(self) -> TokenResponse:
error=str(e),
)
raise
+
+
+class MCPAuthProvider(AuthorizationCodeOAuthProvider):
+ """Base OAuth provider for Model Context Protocol (MCP) servers using OAuth 2.1.
+
+ MCP OAuth follows OAuth 2.1 standards with:
+ - PKCE required for authorization code flow
+ - Resource parameter to identify the MCP server
+ - Flexible scope handling (server determines granted scopes)
+ - Dynamic discovery of OAuth endpoints
+ - Optional dynamic client registration
+ """
+
+ _mcp_server_uri: ClassVar[str]
+
+ def __init__(self, **kwargs):
+ """Initialize MCP provider with dynamic endpoint discovery."""
+ # Initialize logger early for discovery
+ self.logger = logger.bind(service=f"{self.__class__.__name__}")
+
+ # Discover OAuth endpoints before parent initialization
+ self._discover_oauth_endpoints()
+ super().__init__(**kwargs)
+
+ @property
+ def authorization_endpoint(self) -> str:
+ """Return the discovered authorization endpoint."""
+ return self._discovered_auth_endpoint
+
+ @property
+ def token_endpoint(self) -> str:
+ """Return the discovered token endpoint."""
+ return self._discovered_token_endpoint
+
+ def _get_base_url(self) -> str:
+ """Extract base URL from MCP server URI."""
+ parsed = urlparse(self._mcp_server_uri)
+ return f"{parsed.scheme}://{parsed.netloc}"
+
+ def _discover_oauth_endpoints(self) -> None:
+ """Discover OAuth endpoints from .well-known configuration with fallback support."""
+ base_url = self._get_base_url()
+ discovery_url = f"{base_url}/.well-known/oauth-authorization-server"
+
+ try:
+ # Synchronous discovery during initialization
+ with httpx.Client() as client:
+ response = client.get(discovery_url, timeout=10.0)
+ response.raise_for_status()
+ discovery_doc = response.json()
+
+ # Store discovered endpoints as instance variables
+ self._discovered_auth_endpoint = discovery_doc["authorization_endpoint"]
+ self._discovered_token_endpoint = discovery_doc["token_endpoint"]
+
+ # Store registration endpoint if available
+ self._registration_endpoint = discovery_doc.get("registration_endpoint")
+
+ self.logger.info(
+ "Discovered OAuth endpoints",
+ provider=self.id,
+ authorization=self._discovered_auth_endpoint,
+ token=self._discovered_token_endpoint,
+ )
+ except Exception as e:
+ # Check if subclass provides fallback endpoints
+ if hasattr(self, "_fallback_auth_endpoint") and hasattr(
+ self, "_fallback_token_endpoint"
+ ):
+ self._discovered_auth_endpoint = self._fallback_auth_endpoint
+ self._discovered_token_endpoint = self._fallback_token_endpoint
+ self.logger.info(
+ "Using fallback OAuth endpoints",
+ provider=self.id,
+ authorization=self._discovered_auth_endpoint,
+ token=self._discovered_token_endpoint,
+ )
+ else:
+ self.logger.error(
+ "Failed to discover OAuth endpoints",
+ provider=self.id,
+ error=str(e),
+ discovery_url=discovery_url,
+ )
+ raise ValueError(
+ f"Could not discover OAuth endpoints from {discovery_url} "
+ f"and no fallback endpoints provided"
+ ) from e
+
+ def _use_pkce(self) -> bool:
+ """PKCE is mandatory for OAuth 2.1 compliance."""
+ return True
+
+ def _get_additional_authorize_params(self) -> dict[str, Any]:
+ """Add MCP-specific authorization parameters.
+
+ The resource parameter identifies the MCP server that the token will be used with.
+ """
+ params = super()._get_additional_authorize_params()
+ params["resource"] = self._mcp_server_uri
+ return params
+
+ def _get_additional_token_params(self) -> dict[str, Any]:
+ """Add MCP-specific token exchange parameters.
+
+ The resource parameter must be included in token requests per MCP spec.
+ """
+ params = super()._get_additional_token_params()
+ params["resource"] = self._mcp_server_uri
+ return params
diff --git a/tracecat/integrations/providers/github/mcp.py b/tracecat/integrations/providers/github/mcp.py
new file mode 100644
index 0000000000..a40354826f
--- /dev/null
+++ b/tracecat/integrations/providers/github/mcp.py
@@ -0,0 +1,52 @@
+"""GitHub Copilot MCP OAuth integration using Model Context Protocol."""
+
+from typing import ClassVar
+
+from tracecat.integrations.models import ProviderMetadata, ProviderScopes
+from tracecat.integrations.providers.base import MCPAuthProvider
+
+
+class GitHubMCPProvider(MCPAuthProvider):
+ """GitHub Copilot OAuth provider for Model Context Protocol integration.
+
+ This provider enables integration with GitHub Copilot's MCP server for:
+ - Code assistance and suggestions
+ - Repository context understanding
+ - Development workflow automation
+
+ Uses fallback OAuth endpoints since GitHub doesn't support discovery.
+ """
+
+ id: ClassVar[str] = "github_mcp"
+
+ # MCP server endpoint
+ _mcp_server_uri: ClassVar[str] = "https://api.githubcopilot.com/mcp"
+
+ # Fallback OAuth endpoints (GitHub doesn't support discovery)
+ _fallback_auth_endpoint: ClassVar[str] = "https://github.com/login/oauth/authorize"
+ _fallback_token_endpoint: ClassVar[str] = (
+ "https://github.com/login/oauth/access_token"
+ )
+
+ # No default scopes - authorization server determines based on user permissions
+ scopes: ClassVar[ProviderScopes] = ProviderScopes(default=[])
+
+ # Provider metadata
+ metadata: ClassVar[ProviderMetadata] = ProviderMetadata(
+ id="github_mcp",
+ name="GitHub Copilot MCP",
+ description="GitHub Copilot MCP provider for repo and code access",
+ enabled=True,
+ requires_config=False,
+ setup_instructions=(
+ "Connect to GitHub Copilot MCP to enable AI-powered code assistance and repository context. "
+ "Permissions are automatically determined based on your GitHub account and organization settings."
+ ),
+ setup_steps=[
+ "Click 'Connect' to begin OAuth authorization",
+ "Authenticate with your GitHub account",
+ "Review and approve the OAuth client permissions",
+ "Complete authorization to enable MCP integration",
+ ],
+ api_docs_url="https://docs.github.com/en/copilot",
+ )
diff --git a/tracecat/integrations/providers/linear/mcp.py b/tracecat/integrations/providers/linear/mcp.py
new file mode 100644
index 0000000000..ea616ee8f0
--- /dev/null
+++ b/tracecat/integrations/providers/linear/mcp.py
@@ -0,0 +1,46 @@
+"""Linear MCP OAuth integration using Model Context Protocol."""
+
+from typing import ClassVar
+
+from tracecat.integrations.models import ProviderMetadata, ProviderScopes
+from tracecat.integrations.providers.base import MCPAuthProvider
+
+
+class LinearMCPProvider(MCPAuthProvider):
+ """Linear OAuth provider for Model Context Protocol integration.
+
+ This provider enables integration with Linear's MCP server for:
+ - Accessing and managing issues, projects, and teams
+ - Running GraphQL queries against Linear's API
+ - Automating workflows and issue management
+
+ OAuth endpoints are automatically discovered from the server.
+ """
+
+ id: ClassVar[str] = "linear_mcp"
+
+ # MCP server endpoint - OAuth endpoints discovered automatically
+ _mcp_server_uri: ClassVar[str] = "https://mcp.linear.app/mcp"
+
+ # No default scopes - authorization server determines based on user permissions
+ scopes: ClassVar[ProviderScopes] = ProviderScopes(default=[])
+
+ # Provider metadata
+ metadata: ClassVar[ProviderMetadata] = ProviderMetadata(
+ id="linear_mcp",
+ name="Linear MCP",
+ description="Linear MCP providerfor issue tracking and project management",
+ enabled=True,
+ requires_config=False,
+ setup_instructions=(
+ "Connect to Linear MCP to access issues, projects, and teams. "
+ "Permissions are automatically determined based on your Linear workspace access."
+ ),
+ setup_steps=[
+ "Click 'Connect' to begin OAuth authorization",
+ "Select your Linear workspace if prompted",
+ "Review and approve the OAuth client permissions",
+ "Complete authorization to enable MCP integration",
+ ],
+ api_docs_url="https://linear.app/docs/mcp",
+ )
diff --git a/tracecat/integrations/providers/microsoft/mcp.py b/tracecat/integrations/providers/microsoft/mcp.py
new file mode 100644
index 0000000000..b8db4695b8
--- /dev/null
+++ b/tracecat/integrations/providers/microsoft/mcp.py
@@ -0,0 +1,56 @@
+"""Microsoft Learn MCP OAuth integration using Model Context Protocol."""
+
+from typing import ClassVar
+
+from tracecat.integrations.models import ProviderMetadata, ProviderScopes
+from tracecat.integrations.providers.base import MCPAuthProvider
+
+
+class MicrosoftLearnMCPProvider(MCPAuthProvider):
+ """Microsoft Learn OAuth provider for Model Context Protocol integration.
+
+ This provider enables integration with Microsoft Learn's MCP server for:
+ - Real-time access to official Microsoft documentation
+ - AI-powered documentation search and retrieval
+ - Technical knowledge from Microsoft's documentation library
+
+ Uses Microsoft Entra ID (Azure AD) for authentication.
+ Uses fallback OAuth endpoints since discovery is not supported.
+ """
+
+ id: ClassVar[str] = "microsoft_learn_mcp"
+
+ # MCP server endpoint
+ _mcp_server_uri: ClassVar[str] = "https://learn.microsoft.com/api/mcp"
+
+ # Microsoft Entra ID OAuth endpoints (fallback since discovery isn't supported)
+ _fallback_auth_endpoint: ClassVar[str] = (
+ "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
+ )
+ _fallback_token_endpoint: ClassVar[str] = (
+ "https://login.microsoftonline.com/common/oauth2/v2.0/token"
+ )
+
+ # No default scopes - authorization server determines based on user permissions
+ scopes: ClassVar[ProviderScopes] = ProviderScopes(default=[])
+
+ # Provider metadata
+ metadata: ClassVar[ProviderMetadata] = ProviderMetadata(
+ id="microsoft_learn_mcp",
+ name="Microsoft Learn MCP",
+ description="Microsoft Learn MCP provider for Learn knowlege services.",
+ enabled=True,
+ requires_config=False,
+ setup_instructions=(
+ "Connect to Microsoft Learn MCP to access real-time Microsoft documentation. "
+ "This integration provides AI assistance with official Microsoft technical documentation. "
+ "Authentication is handled through Microsoft Entra ID (Azure AD)."
+ ),
+ setup_steps=[
+ "Click 'Connect' to begin OAuth authorization",
+ "Sign in with your Microsoft account",
+ "Review and approve the OAuth permissions",
+ "Complete authorization to enable Microsoft Learn MCP integration",
+ ],
+ api_docs_url="https://learn.microsoft.com/en-us/training/support/mcp",
+ )
diff --git a/tracecat/integrations/providers/notion/mcp.py b/tracecat/integrations/providers/notion/mcp.py
new file mode 100644
index 0000000000..dbd83e09dc
--- /dev/null
+++ b/tracecat/integrations/providers/notion/mcp.py
@@ -0,0 +1,46 @@
+"""Notion MCP OAuth integration using Model Context Protocol."""
+
+from typing import ClassVar
+
+from tracecat.integrations.models import ProviderMetadata, ProviderScopes
+from tracecat.integrations.providers.base import MCPAuthProvider
+
+
+class NotionMCPProvider(MCPAuthProvider):
+ """Notion OAuth provider for Model Context Protocol integration.
+
+ This provider enables AI-powered integration with Notion workspaces for:
+ - Reading and writing pages, databases, and comments
+ - AI-optimized Markdown-based content retrieval
+ - Dynamic workspace access based on user permissions
+
+ OAuth endpoints are automatically discovered from the server.
+ """
+
+ id: ClassVar[str] = "notion_mcp"
+
+ # MCP server endpoint - OAuth endpoints discovered automatically
+ _mcp_server_uri: ClassVar[str] = "https://mcp.notion.com/mcp"
+
+ # No default scopes - authorization server determines based on user permissions
+ scopes: ClassVar[ProviderScopes] = ProviderScopes(default=[])
+
+ # Provider metadata
+ metadata: ClassVar[ProviderMetadata] = ProviderMetadata(
+ id="notion_mcp",
+ name="Notion MCP",
+ description="Notion MCP provider for Notion workspace access",
+ enabled=True,
+ requires_config=False,
+ setup_instructions=(
+ "Connect to Notion MCP to enable AI tools to interact with your Notion workspace. "
+ "Full read and write access to pages, databases, and comments based on your permissions."
+ ),
+ setup_steps=[
+ "Click 'Connect' to begin OAuth authorization",
+ "Select your Notion workspace",
+ "Review and approve the permissions",
+ "Complete authorization to enable MCP integration",
+ ],
+ api_docs_url="https://developers.notion.com/docs/mcp",
+ )
diff --git a/tracecat/integrations/providers/runreveal/mcp.py b/tracecat/integrations/providers/runreveal/mcp.py
new file mode 100644
index 0000000000..88716df0f6
--- /dev/null
+++ b/tracecat/integrations/providers/runreveal/mcp.py
@@ -0,0 +1,47 @@
+"""RunReveal MCP OAuth integration using Model Context Protocol."""
+
+from typing import ClassVar
+
+from tracecat.integrations.models import ProviderMetadata, ProviderScopes
+from tracecat.integrations.providers.base import MCPAuthProvider
+
+
+class RunRevealMCPProvider(MCPAuthProvider):
+ """RunReveal OAuth provider for Model Context Protocol integration.
+
+ This provider enables integration with RunReveal's MCP server for:
+ - Running queries and detections
+ - Accessing table schemas
+ - Managing detection configurations
+
+ Permissions are determined by the user's role in the selected workspace.
+ OAuth endpoints are automatically discovered from the server.
+ """
+
+ id: ClassVar[str] = "runreveal_mcp"
+
+ # MCP server endpoint - OAuth endpoints discovered automatically
+ _mcp_server_uri: ClassVar[str] = "https://api.runreveal.com/mcp"
+
+ # No default scopes - authorization server determines based on user/workspace permissions
+ scopes: ClassVar[ProviderScopes] = ProviderScopes(default=[])
+
+ # Provider metadata
+ metadata: ClassVar[ProviderMetadata] = ProviderMetadata(
+ id="runreveal_mcp",
+ name="RunReveal MCP",
+ description="RunReveal MCP provider for security data analysis",
+ enabled=True,
+ requires_config=False,
+ setup_instructions=(
+ "Connect to RunReveal MCP to access queries, detections, and table schemas. "
+ "Permissions are automatically determined based on your workspace role."
+ ),
+ setup_steps=[
+ "Click 'Connect' to begin OAuth authorization",
+ "Select your RunReveal workspace",
+ "Review and approve the OAuth client permissions",
+ "Complete authorization to enable MCP integration",
+ ],
+ api_docs_url="https://docs.runreveal.com/ai-chat/model-context-protocol",
+ )
diff --git a/tracecat/integrations/providers/sentry/mcp.py b/tracecat/integrations/providers/sentry/mcp.py
new file mode 100644
index 0000000000..a11fb29ca2
--- /dev/null
+++ b/tracecat/integrations/providers/sentry/mcp.py
@@ -0,0 +1,48 @@
+"""Sentry MCP OAuth integration using Model Context Protocol."""
+
+from typing import ClassVar
+
+from tracecat.integrations.models import ProviderMetadata, ProviderScopes
+from tracecat.integrations.providers.base import MCPAuthProvider
+
+
+class SentryMCPProvider(MCPAuthProvider):
+ """Sentry OAuth provider for Model Context Protocol integration.
+
+ This provider enables integration with Sentry's MCP server for:
+ - Accessing and managing error tracking and performance monitoring
+ - Querying issues, events, and performance data
+ - Managing projects, teams, and organizations
+ - Analyzing error patterns and performance metrics
+
+ OAuth endpoints are automatically discovered from the server.
+ """
+
+ id: ClassVar[str] = "sentry_mcp"
+
+ # MCP server endpoint - OAuth endpoints discovered automatically
+ _mcp_server_uri: ClassVar[str] = "https://mcp.sentry.dev/mcp"
+
+ # No default scopes - authorization server determines based on user permissions
+ scopes: ClassVar[ProviderScopes] = ProviderScopes(default=[])
+
+ # Provider metadata
+ metadata: ClassVar[ProviderMetadata] = ProviderMetadata(
+ id="sentry_mcp",
+ name="Sentry MCP",
+ description="Sentry MCP provider for issues tracking and performance monitoring",
+ enabled=True,
+ requires_config=False,
+ setup_instructions=(
+ "Connect to Sentry MCP to access issues and performance monitoring. "
+ "Permissions are automatically determined based on your Sentry organization access."
+ ),
+ setup_steps=[
+ "Click 'Connect' to begin OAuth authorization",
+ "Authenticate with your Sentry account",
+ "Select your Sentry organization if prompted",
+ "Review and approve the OAuth client permissions",
+ "Complete authorization to enable MCP integration",
+ ],
+ api_docs_url="https://docs.sentry.io/product/sentry-mcp/",
+ )