airbyte_ops_mcp.constants

Constants for the Airbyte Admin MCP server.

  1# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
  2"""Constants for the Airbyte Admin MCP server."""
  3
  4from __future__ import annotations
  5
  6from enum import Enum, StrEnum
  7
  8from airbyte.exceptions import PyAirbyteInputError
  9
 10from airbyte_ops_mcp.registry._constants import PROD_METADATA_SERVICE_BUCKET_NAME
 11
 12MCP_SERVER_NAME = "airbyte-internal-ops"
 13"""The name of the MCP server."""
 14
 15PACKAGE_NAME = "airbyte-internal-ops"
 16"""The installed package name, as declared in `pyproject.toml`."""
 17
 18
 19class ServerConfigKey(StrEnum):
 20    """Config keys for MCP server configuration arguments.
 21
 22    These keys are used both when defining server_config_args in mcp_server()
 23    and when retrieving config values via get_mcp_config().
 24    """
 25
 26    BEARER_TOKEN = "bearer_token"
 27    CLIENT_ID = "client_id"
 28    CLIENT_SECRET = "client_secret"
 29
 30
 31USER_AGENT = "Airbyte-Internal-Ops Python client"
 32"""User-Agent string for HTTP requests to Airbyte Cloud APIs."""
 33
 34# Environment variable names for internal admin authentication
 35ENV_AIRBYTE_INTERNAL_ADMIN_FLAG = "AIRBYTE_INTERNAL_ADMIN_FLAG"
 36ENV_AIRBYTE_INTERNAL_ADMIN_USER = "AIRBYTE_INTERNAL_ADMIN_USER"
 37
 38# Environment variable for GCP credentials (JSON content, not file path)
 39ENV_GCP_PROD_DB_ACCESS_CREDENTIALS = "GCP_PROD_DB_ACCESS_CREDENTIALS"
 40"""Environment variable containing GCP service account JSON credentials for prod DB access."""
 41
 42ENV_K_SERVICE = "K_SERVICE"
 43"""Cloud Run env var set to the service name, used only for runtime detection."""
 44
 45# Expected values for internal admin authentication
 46EXPECTED_ADMIN_FLAG_VALUE = "airbyte.io"
 47EXPECTED_ADMIN_EMAIL_DOMAIN = "@airbyte.io"
 48
 49# =============================================================================
 50# HTTP Header Names for Airbyte Cloud Authentication
 51# =============================================================================
 52# These headers follow the PyAirbyte convention for passing credentials
 53# via HTTP when running as an MCP HTTP server.
 54
 55HEADER_AIRBYTE_CLOUD_CLIENT_ID = "X-Airbyte-Cloud-Client-Id"
 56"""HTTP header for OAuth client ID."""
 57
 58HEADER_AIRBYTE_CLOUD_CLIENT_SECRET = "X-Airbyte-Cloud-Client-Secret"
 59"""HTTP header for OAuth client secret."""
 60
 61HEADER_AIRBYTE_CLOUD_WORKSPACE_ID = "X-Airbyte-Cloud-Workspace-Id"
 62"""HTTP header for default workspace ID."""
 63
 64HEADER_AIRBYTE_CLOUD_API_URL = "X-Airbyte-Cloud-Api-Url"
 65"""HTTP header for API root URL override."""
 66
 67# =============================================================================
 68# GCP and Prod DB Constants (from connection-retriever)
 69# =============================================================================
 70
 71GCP_PROJECT_NAME = "prod-ab-cloud-proj"
 72"""The GCP project name for Airbyte Cloud production."""
 73
 74CLOUD_SQL_INSTANCE = "prod-ab-cloud-proj:us-west3:prod-pgsql-replica"
 75"""The Cloud SQL instance connection name for the Prod DB Replica."""
 76
 77DEFAULT_CLOUD_SQL_PROXY_PORT = 15432
 78"""Default port for Cloud SQL Proxy connections."""
 79
 80CLOUD_SQL_PROXY_PID_FILE = "/tmp/airbyte-cloud-sql-proxy.pid"
 81"""PID file for tracking the Cloud SQL Proxy process."""
 82
 83CLOUD_REGISTRY_URL = (
 84    "https://connectors.airbyte.com/files/registries/v0/cloud_registry.json"
 85)
 86"""URL for the Airbyte Cloud connector registry."""
 87
 88CLOUD_REGISTRY_GCS_URL = (
 89    "https://storage.googleapis.com/"
 90    f"{PROD_METADATA_SERVICE_BUCKET_NAME}/registries/v0/cloud_registry.json"
 91)
 92"""Direct GCS URL for the Airbyte Cloud connector registry."""
 93
 94# =============================================================================
 95# Organization ID Aliases
 96# =============================================================================
 97
 98
 99class OrganizationAliasEnum(StrEnum):
100    """Organization ID aliases that can be used in place of UUIDs.
101
102    Each member's name is the alias (e.g., "@airbyte-internal") and its value
103    is the actual organization UUID. Use `OrganizationAliasEnum.resolve()` to
104    resolve aliases to actual IDs.
105    """
106
107    AIRBYTE_INTERNAL = "664c690e-5263-49ba-b01f-4a6759b3330a"
108    """The Airbyte internal organization for testing and internal operations.
109
110    Alias: @airbyte-internal
111    """
112
113    @classmethod
114    def resolve(cls, org_id: str | None) -> str | None:
115        """Resolve an organization ID alias to its actual UUID.
116
117        Accepts either an alias string (e.g., "@airbyte-internal") or an
118        OrganizationAliasEnum enum member, and returns the actual UUID.
119
120        Returns:
121            The resolved organization ID (UUID), or None if input is None.
122            If the input doesn't start with "@", it is returned unchanged.
123
124        Raises:
125            PyAirbyteInputError: If the input starts with "@" but is not a recognized alias.
126        """
127        if org_id is None:
128            return None
129
130        # Handle OrganizationAliasEnum enum members directly
131        if isinstance(org_id, cls):
132            return org_id.value
133
134        # If it doesn't look like an alias, return as-is (assume it's a UUID)
135        if not org_id.startswith("@"):
136            return org_id
137
138        # Handle alias strings or raise an error if invalid
139        alias_mapping = {
140            "@airbyte-internal": cls.AIRBYTE_INTERNAL.value,
141        }
142        if org_id not in alias_mapping:
143            raise PyAirbyteInputError(
144                message=f"Unknown organization alias: {org_id}",
145                context={
146                    "valid_aliases": list(alias_mapping.keys()),
147                },
148            )
149        return alias_mapping[org_id]
150
151
152# =============================================================================
153# Workspace ID Aliases
154# =============================================================================
155
156
157class WorkspaceAliasEnum(StrEnum):
158    """Workspace ID aliases that can be used in place of UUIDs.
159
160    Each member's name is the alias (e.g., "@devin-ai-sandbox") and its value
161    is the actual workspace UUID. Use `WorkspaceAliasEnum.resolve()` to
162    resolve aliases to actual IDs.
163    """
164
165    DEVIN_AI_SANDBOX = "266ebdfe-0d7b-4540-9817-de7e4505ba61"
166    """The Devin AI sandbox workspace for testing and development.
167
168    Alias: @devin-ai-sandbox
169    """
170
171    @classmethod
172    def resolve(cls, workspace_id: str | None) -> str | None:
173        """Resolve a workspace ID alias to its actual UUID.
174
175        Accepts either an alias string (e.g., "@devin-ai-sandbox") or a
176        WorkspaceAliasEnum enum member, and returns the actual UUID.
177
178        Returns:
179            The resolved workspace ID (UUID), or None if input is None.
180            If the input doesn't start with "@", it is returned unchanged.
181
182        Raises:
183            PyAirbyteInputError: If the input starts with "@" but is not a recognized alias.
184        """
185        if workspace_id is None:
186            return None
187
188        # Handle WorkspaceAliasEnum enum members directly
189        if isinstance(workspace_id, cls):
190            return workspace_id.value
191
192        # If it doesn't look like an alias, return as-is (assume it's a UUID)
193        if not workspace_id.startswith("@"):
194            return workspace_id
195
196        # Handle alias strings or raise an error if invalid
197        alias_mapping = {
198            "@devin-ai-sandbox": cls.DEVIN_AI_SANDBOX.value,
199        }
200        if workspace_id not in alias_mapping:
201            raise PyAirbyteInputError(
202                message=f"Unknown workspace alias: {workspace_id}",
203                context={
204                    "valid_aliases": list(alias_mapping.keys()),
205                },
206            )
207        return alias_mapping[workspace_id]
208
209
210MEDIC_MODE_ENV_VAR = "AIRBYTE_OPS_MEDIC_MODE"
211"""Environment variable to enable emergency 'medic mode' write tools.
212
213When set to '1' or 'true', destructive MCP tools for connection state and catalog
214writes are registered. These are "break glass" operations for emergency use only.
215"""
216
217CONNECTION_RETRIEVER_PG_CONNECTION_DETAILS_SECRET_ID = (
218    "projects/587336813068/secrets/CONNECTION_RETRIEVER_PG_CONNECTION_DETAILS"
219)
220"""GCP Secret Manager ID for Prod DB connection details."""
221
222
223class ConnectionObject(Enum):
224    """Types of connection objects that can be retrieved."""
225
226    CONNECTION = "connection"
227    SOURCE_ID = "source-id"
228    DESTINATION_ID = "destination-id"
229    DESTINATION_CONFIG = "destination-config"
230    SOURCE_CONFIG = "source-config"
231    CATALOG = "catalog"
232    CONFIGURED_CATALOG = "configured-catalog"
233    STATE = "state"
234    WORKSPACE_ID = "workspace-id"
235    DESTINATION_DOCKER_IMAGE = "destination-docker-image"
236    SOURCE_DOCKER_IMAGE = "source-docker-image"
MCP_SERVER_NAME = 'airbyte-internal-ops'

The name of the MCP server.

PACKAGE_NAME = 'airbyte-internal-ops'

The installed package name, as declared in pyproject.toml.

class ServerConfigKey(enum.StrEnum):
20class ServerConfigKey(StrEnum):
21    """Config keys for MCP server configuration arguments.
22
23    These keys are used both when defining server_config_args in mcp_server()
24    and when retrieving config values via get_mcp_config().
25    """
26
27    BEARER_TOKEN = "bearer_token"
28    CLIENT_ID = "client_id"
29    CLIENT_SECRET = "client_secret"

Config keys for MCP server configuration arguments.

These keys are used both when defining server_config_args in mcp_server() and when retrieving config values via get_mcp_config().

BEARER_TOKEN = <ServerConfigKey.BEARER_TOKEN: 'bearer_token'>
CLIENT_ID = <ServerConfigKey.CLIENT_ID: 'client_id'>
CLIENT_SECRET = <ServerConfigKey.CLIENT_SECRET: 'client_secret'>
USER_AGENT = 'Airbyte-Internal-Ops Python client'

User-Agent string for HTTP requests to Airbyte Cloud APIs.

ENV_AIRBYTE_INTERNAL_ADMIN_FLAG = 'AIRBYTE_INTERNAL_ADMIN_FLAG'
ENV_AIRBYTE_INTERNAL_ADMIN_USER = 'AIRBYTE_INTERNAL_ADMIN_USER'
ENV_GCP_PROD_DB_ACCESS_CREDENTIALS = 'GCP_PROD_DB_ACCESS_CREDENTIALS'

Environment variable containing GCP service account JSON credentials for prod DB access.

ENV_K_SERVICE = 'K_SERVICE'

Cloud Run env var set to the service name, used only for runtime detection.

EXPECTED_ADMIN_FLAG_VALUE = 'airbyte.io'
EXPECTED_ADMIN_EMAIL_DOMAIN = '@airbyte.io'
HEADER_AIRBYTE_CLOUD_CLIENT_ID = 'X-Airbyte-Cloud-Client-Id'

HTTP header for OAuth client ID.

HEADER_AIRBYTE_CLOUD_CLIENT_SECRET = 'X-Airbyte-Cloud-Client-Secret'

HTTP header for OAuth client secret.

HEADER_AIRBYTE_CLOUD_WORKSPACE_ID = 'X-Airbyte-Cloud-Workspace-Id'

HTTP header for default workspace ID.

HEADER_AIRBYTE_CLOUD_API_URL = 'X-Airbyte-Cloud-Api-Url'

HTTP header for API root URL override.

GCP_PROJECT_NAME = 'prod-ab-cloud-proj'

The GCP project name for Airbyte Cloud production.

CLOUD_SQL_INSTANCE = 'prod-ab-cloud-proj:us-west3:prod-pgsql-replica'

The Cloud SQL instance connection name for the Prod DB Replica.

DEFAULT_CLOUD_SQL_PROXY_PORT = 15432

Default port for Cloud SQL Proxy connections.

CLOUD_SQL_PROXY_PID_FILE = '/tmp/airbyte-cloud-sql-proxy.pid'

PID file for tracking the Cloud SQL Proxy process.

CLOUD_REGISTRY_URL = 'https://connectors.airbyte.com/files/registries/v0/cloud_registry.json'

URL for the Airbyte Cloud connector registry.

CLOUD_REGISTRY_GCS_URL = 'https://storage.googleapis.com/prod-airbyte-cloud-connector-metadata-service/registries/v0/cloud_registry.json'

Direct GCS URL for the Airbyte Cloud connector registry.

class OrganizationAliasEnum(enum.StrEnum):
100class OrganizationAliasEnum(StrEnum):
101    """Organization ID aliases that can be used in place of UUIDs.
102
103    Each member's name is the alias (e.g., "@airbyte-internal") and its value
104    is the actual organization UUID. Use `OrganizationAliasEnum.resolve()` to
105    resolve aliases to actual IDs.
106    """
107
108    AIRBYTE_INTERNAL = "664c690e-5263-49ba-b01f-4a6759b3330a"
109    """The Airbyte internal organization for testing and internal operations.
110
111    Alias: @airbyte-internal
112    """
113
114    @classmethod
115    def resolve(cls, org_id: str | None) -> str | None:
116        """Resolve an organization ID alias to its actual UUID.
117
118        Accepts either an alias string (e.g., "@airbyte-internal") or an
119        OrganizationAliasEnum enum member, and returns the actual UUID.
120
121        Returns:
122            The resolved organization ID (UUID), or None if input is None.
123            If the input doesn't start with "@", it is returned unchanged.
124
125        Raises:
126            PyAirbyteInputError: If the input starts with "@" but is not a recognized alias.
127        """
128        if org_id is None:
129            return None
130
131        # Handle OrganizationAliasEnum enum members directly
132        if isinstance(org_id, cls):
133            return org_id.value
134
135        # If it doesn't look like an alias, return as-is (assume it's a UUID)
136        if not org_id.startswith("@"):
137            return org_id
138
139        # Handle alias strings or raise an error if invalid
140        alias_mapping = {
141            "@airbyte-internal": cls.AIRBYTE_INTERNAL.value,
142        }
143        if org_id not in alias_mapping:
144            raise PyAirbyteInputError(
145                message=f"Unknown organization alias: {org_id}",
146                context={
147                    "valid_aliases": list(alias_mapping.keys()),
148                },
149            )
150        return alias_mapping[org_id]

Organization ID aliases that can be used in place of UUIDs.

Each member's name is the alias (e.g., "@airbyte-internal") and its value is the actual organization UUID. Use OrganizationAliasEnum.resolve() to resolve aliases to actual IDs.

AIRBYTE_INTERNAL = <OrganizationAliasEnum.AIRBYTE_INTERNAL: '664c690e-5263-49ba-b01f-4a6759b3330a'>

The Airbyte internal organization for testing and internal operations.

Alias: @airbyte-internal

@classmethod
def resolve(cls, org_id: str | None) -> str | None:
114    @classmethod
115    def resolve(cls, org_id: str | None) -> str | None:
116        """Resolve an organization ID alias to its actual UUID.
117
118        Accepts either an alias string (e.g., "@airbyte-internal") or an
119        OrganizationAliasEnum enum member, and returns the actual UUID.
120
121        Returns:
122            The resolved organization ID (UUID), or None if input is None.
123            If the input doesn't start with "@", it is returned unchanged.
124
125        Raises:
126            PyAirbyteInputError: If the input starts with "@" but is not a recognized alias.
127        """
128        if org_id is None:
129            return None
130
131        # Handle OrganizationAliasEnum enum members directly
132        if isinstance(org_id, cls):
133            return org_id.value
134
135        # If it doesn't look like an alias, return as-is (assume it's a UUID)
136        if not org_id.startswith("@"):
137            return org_id
138
139        # Handle alias strings or raise an error if invalid
140        alias_mapping = {
141            "@airbyte-internal": cls.AIRBYTE_INTERNAL.value,
142        }
143        if org_id not in alias_mapping:
144            raise PyAirbyteInputError(
145                message=f"Unknown organization alias: {org_id}",
146                context={
147                    "valid_aliases": list(alias_mapping.keys()),
148                },
149            )
150        return alias_mapping[org_id]

Resolve an organization ID alias to its actual UUID.

Accepts either an alias string (e.g., "@airbyte-internal") or an OrganizationAliasEnum enum member, and returns the actual UUID.

Returns:

The resolved organization ID (UUID), or None if input is None. If the input doesn't start with "@", it is returned unchanged.

Raises:
  • PyAirbyteInputError: If the input starts with "@" but is not a recognized alias.
class WorkspaceAliasEnum(enum.StrEnum):
158class WorkspaceAliasEnum(StrEnum):
159    """Workspace ID aliases that can be used in place of UUIDs.
160
161    Each member's name is the alias (e.g., "@devin-ai-sandbox") and its value
162    is the actual workspace UUID. Use `WorkspaceAliasEnum.resolve()` to
163    resolve aliases to actual IDs.
164    """
165
166    DEVIN_AI_SANDBOX = "266ebdfe-0d7b-4540-9817-de7e4505ba61"
167    """The Devin AI sandbox workspace for testing and development.
168
169    Alias: @devin-ai-sandbox
170    """
171
172    @classmethod
173    def resolve(cls, workspace_id: str | None) -> str | None:
174        """Resolve a workspace ID alias to its actual UUID.
175
176        Accepts either an alias string (e.g., "@devin-ai-sandbox") or a
177        WorkspaceAliasEnum enum member, and returns the actual UUID.
178
179        Returns:
180            The resolved workspace ID (UUID), or None if input is None.
181            If the input doesn't start with "@", it is returned unchanged.
182
183        Raises:
184            PyAirbyteInputError: If the input starts with "@" but is not a recognized alias.
185        """
186        if workspace_id is None:
187            return None
188
189        # Handle WorkspaceAliasEnum enum members directly
190        if isinstance(workspace_id, cls):
191            return workspace_id.value
192
193        # If it doesn't look like an alias, return as-is (assume it's a UUID)
194        if not workspace_id.startswith("@"):
195            return workspace_id
196
197        # Handle alias strings or raise an error if invalid
198        alias_mapping = {
199            "@devin-ai-sandbox": cls.DEVIN_AI_SANDBOX.value,
200        }
201        if workspace_id not in alias_mapping:
202            raise PyAirbyteInputError(
203                message=f"Unknown workspace alias: {workspace_id}",
204                context={
205                    "valid_aliases": list(alias_mapping.keys()),
206                },
207            )
208        return alias_mapping[workspace_id]

Workspace ID aliases that can be used in place of UUIDs.

Each member's name is the alias (e.g., "@devin-ai-sandbox") and its value is the actual workspace UUID. Use WorkspaceAliasEnum.resolve() to resolve aliases to actual IDs.

DEVIN_AI_SANDBOX = <WorkspaceAliasEnum.DEVIN_AI_SANDBOX: '266ebdfe-0d7b-4540-9817-de7e4505ba61'>

The Devin AI sandbox workspace for testing and development.

Alias: @devin-ai-sandbox

@classmethod
def resolve(cls, workspace_id: str | None) -> str | None:
172    @classmethod
173    def resolve(cls, workspace_id: str | None) -> str | None:
174        """Resolve a workspace ID alias to its actual UUID.
175
176        Accepts either an alias string (e.g., "@devin-ai-sandbox") or a
177        WorkspaceAliasEnum enum member, and returns the actual UUID.
178
179        Returns:
180            The resolved workspace ID (UUID), or None if input is None.
181            If the input doesn't start with "@", it is returned unchanged.
182
183        Raises:
184            PyAirbyteInputError: If the input starts with "@" but is not a recognized alias.
185        """
186        if workspace_id is None:
187            return None
188
189        # Handle WorkspaceAliasEnum enum members directly
190        if isinstance(workspace_id, cls):
191            return workspace_id.value
192
193        # If it doesn't look like an alias, return as-is (assume it's a UUID)
194        if not workspace_id.startswith("@"):
195            return workspace_id
196
197        # Handle alias strings or raise an error if invalid
198        alias_mapping = {
199            "@devin-ai-sandbox": cls.DEVIN_AI_SANDBOX.value,
200        }
201        if workspace_id not in alias_mapping:
202            raise PyAirbyteInputError(
203                message=f"Unknown workspace alias: {workspace_id}",
204                context={
205                    "valid_aliases": list(alias_mapping.keys()),
206                },
207            )
208        return alias_mapping[workspace_id]

Resolve a workspace ID alias to its actual UUID.

Accepts either an alias string (e.g., "@devin-ai-sandbox") or a WorkspaceAliasEnum enum member, and returns the actual UUID.

Returns:

The resolved workspace ID (UUID), or None if input is None. If the input doesn't start with "@", it is returned unchanged.

Raises:
  • PyAirbyteInputError: If the input starts with "@" but is not a recognized alias.
MEDIC_MODE_ENV_VAR = 'AIRBYTE_OPS_MEDIC_MODE'

Environment variable to enable emergency 'medic mode' write tools.

When set to '1' or 'true', destructive MCP tools for connection state and catalog writes are registered. These are "break glass" operations for emergency use only.

CONNECTION_RETRIEVER_PG_CONNECTION_DETAILS_SECRET_ID = 'projects/587336813068/secrets/CONNECTION_RETRIEVER_PG_CONNECTION_DETAILS'

GCP Secret Manager ID for Prod DB connection details.

class ConnectionObject(enum.Enum):
224class ConnectionObject(Enum):
225    """Types of connection objects that can be retrieved."""
226
227    CONNECTION = "connection"
228    SOURCE_ID = "source-id"
229    DESTINATION_ID = "destination-id"
230    DESTINATION_CONFIG = "destination-config"
231    SOURCE_CONFIG = "source-config"
232    CATALOG = "catalog"
233    CONFIGURED_CATALOG = "configured-catalog"
234    STATE = "state"
235    WORKSPACE_ID = "workspace-id"
236    DESTINATION_DOCKER_IMAGE = "destination-docker-image"
237    SOURCE_DOCKER_IMAGE = "source-docker-image"

Types of connection objects that can be retrieved.

CONNECTION = <ConnectionObject.CONNECTION: 'connection'>
SOURCE_ID = <ConnectionObject.SOURCE_ID: 'source-id'>
DESTINATION_ID = <ConnectionObject.DESTINATION_ID: 'destination-id'>
DESTINATION_CONFIG = <ConnectionObject.DESTINATION_CONFIG: 'destination-config'>
SOURCE_CONFIG = <ConnectionObject.SOURCE_CONFIG: 'source-config'>
CATALOG = <ConnectionObject.CATALOG: 'catalog'>
CONFIGURED_CATALOG = <ConnectionObject.CONFIGURED_CATALOG: 'configured-catalog'>
STATE = <ConnectionObject.STATE: 'state'>
WORKSPACE_ID = <ConnectionObject.WORKSPACE_ID: 'workspace-id'>
DESTINATION_DOCKER_IMAGE = <ConnectionObject.DESTINATION_DOCKER_IMAGE: 'destination-docker-image'>
SOURCE_DOCKER_IMAGE = <ConnectionObject.SOURCE_DOCKER_IMAGE: 'source-docker-image'>