airbyte-internal-ops 0.6.1__py3-none-any.whl → 0.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {airbyte_internal_ops-0.6.1.dist-info → airbyte_internal_ops-0.7.1.dist-info}/METADATA +6 -1
- {airbyte_internal_ops-0.6.1.dist-info → airbyte_internal_ops-0.7.1.dist-info}/RECORD +33 -30
- airbyte_ops_mcp/_sentry.py +101 -0
- airbyte_ops_mcp/cli/app.py +1 -1
- airbyte_ops_mcp/cli/{repo.py → local.py} +131 -8
- airbyte_ops_mcp/connector_ops/__init__.py +17 -0
- airbyte_ops_mcp/connector_ops/utils.py +859 -0
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/assets.py +4 -5
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/documentation/__init__.py +1 -1
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/documentation/documentation.py +23 -22
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/documentation/models.py +7 -7
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/metadata.py +15 -15
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/packaging.py +11 -9
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/security.py +16 -20
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/version.py +94 -18
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/cli.py +6 -8
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/models.py +7 -8
- airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/utils.py +2 -2
- airbyte_ops_mcp/mcp/_guidance.py +37 -0
- airbyte_ops_mcp/mcp/cloud_connector_versions.py +46 -9
- airbyte_ops_mcp/mcp/server.py +5 -0
- {airbyte_internal_ops-0.6.1.dist-info → airbyte_internal_ops-0.7.1.dist-info}/WHEEL +0 -0
- {airbyte_internal_ops-0.6.1.dist-info → airbyte_internal_ops-0.7.1.dist-info}/entry_points.txt +0 -0
- /airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/README.md +0 -0
- /airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/__init__.py +0 -0
- /airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/__init__.py +0 -0
- /airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/documentation/helpers.py +0 -0
- /airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/documentation/templates/documentation_headers_check_description.md.j2 +0 -0
- /airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/documentation/templates/section_content_description.md.j2 +0 -0
- /airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/documentation/templates/template.md.j2 +0 -0
- /airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/consts.py +0 -0
- /airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/templates/__init__.py +0 -0
- /airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/templates/qa_checks.md.j2 +0 -0
|
@@ -7,21 +7,21 @@ import asyncclick as click
|
|
|
7
7
|
import asyncer
|
|
8
8
|
from jinja2 import Environment, PackageLoader, select_autoescape
|
|
9
9
|
|
|
10
|
-
from airbyte_ops_mcp.
|
|
10
|
+
from airbyte_ops_mcp.connector_ops.utils import (
|
|
11
11
|
Connector, # type: ignore
|
|
12
12
|
)
|
|
13
|
-
from airbyte_ops_mcp.
|
|
14
|
-
from airbyte_ops_mcp.
|
|
13
|
+
from airbyte_ops_mcp.connector_qa.checks import ENABLED_CHECKS
|
|
14
|
+
from airbyte_ops_mcp.connector_qa.consts import (
|
|
15
15
|
CONNECTORS_QA_DOC_TEMPLATE_NAME,
|
|
16
16
|
)
|
|
17
|
-
from airbyte_ops_mcp.
|
|
17
|
+
from airbyte_ops_mcp.connector_qa.models import (
|
|
18
18
|
Check,
|
|
19
19
|
CheckCategory,
|
|
20
20
|
CheckResult,
|
|
21
21
|
CheckStatus,
|
|
22
22
|
Report,
|
|
23
23
|
)
|
|
24
|
-
from airbyte_ops_mcp.
|
|
24
|
+
from airbyte_ops_mcp.connector_qa.utils import (
|
|
25
25
|
get_all_connectors_in_directory,
|
|
26
26
|
remove_strict_encrypt_suffix,
|
|
27
27
|
)
|
|
@@ -97,9 +97,7 @@ async def run(
|
|
|
97
97
|
if connector_directory:
|
|
98
98
|
connectors += get_all_connectors_in_directory(connector_directory)
|
|
99
99
|
|
|
100
|
-
connectors = sorted(
|
|
101
|
-
list(connectors), key=lambda connector: connector.technical_name
|
|
102
|
-
)
|
|
100
|
+
connectors = sorted(connectors, key=lambda connector: connector.technical_name)
|
|
103
101
|
|
|
104
102
|
if not connectors:
|
|
105
103
|
raise click.UsageError(
|
|
@@ -8,13 +8,12 @@ from dataclasses import dataclass
|
|
|
8
8
|
from datetime import datetime
|
|
9
9
|
from enum import Enum
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import Dict, List, Optional
|
|
12
11
|
|
|
13
|
-
from airbyte_ops_mcp.
|
|
12
|
+
from airbyte_ops_mcp.connector_ops.utils import (
|
|
14
13
|
Connector,
|
|
15
14
|
ConnectorLanguage,
|
|
16
15
|
) # type: ignore
|
|
17
|
-
from airbyte_ops_mcp.
|
|
16
|
+
from airbyte_ops_mcp.connector_qa import consts
|
|
18
17
|
|
|
19
18
|
ALL_LANGUAGES = [
|
|
20
19
|
ConnectorLanguage.JAVA,
|
|
@@ -109,7 +108,7 @@ class Check(ABC):
|
|
|
109
108
|
)
|
|
110
109
|
|
|
111
110
|
@property
|
|
112
|
-
def applies_to_connector_languages(self) ->
|
|
111
|
+
def applies_to_connector_languages(self) -> list[ConnectorLanguage]:
|
|
113
112
|
"""The connector languages that the QA check applies to
|
|
114
113
|
|
|
115
114
|
Raises:
|
|
@@ -121,7 +120,7 @@ class Check(ABC):
|
|
|
121
120
|
return ALL_LANGUAGES
|
|
122
121
|
|
|
123
122
|
@property
|
|
124
|
-
def applies_to_connector_types(self) ->
|
|
123
|
+
def applies_to_connector_types(self) -> list[str]:
|
|
125
124
|
"""The connector types that the QA check applies to
|
|
126
125
|
|
|
127
126
|
Returns:
|
|
@@ -154,7 +153,7 @@ class Check(ABC):
|
|
|
154
153
|
)
|
|
155
154
|
|
|
156
155
|
@property
|
|
157
|
-
def applies_to_connector_support_levels(self) ->
|
|
156
|
+
def applies_to_connector_support_levels(self) -> list[str] | None:
|
|
158
157
|
"""The connector's support levels that the QA check applies to
|
|
159
158
|
|
|
160
159
|
Returns:
|
|
@@ -163,7 +162,7 @@ class Check(ABC):
|
|
|
163
162
|
return None
|
|
164
163
|
|
|
165
164
|
@property
|
|
166
|
-
def applies_to_connector_cloud_usage(self) ->
|
|
165
|
+
def applies_to_connector_cloud_usage(self) -> list[str] | None:
|
|
167
166
|
"""The connector's cloud usage level that the QA check applies to
|
|
168
167
|
|
|
169
168
|
Returns:
|
|
@@ -270,7 +269,7 @@ class Report:
|
|
|
270
269
|
Returns:
|
|
271
270
|
str: The connectors_report as a JSON string
|
|
272
271
|
"""
|
|
273
|
-
connectors_report:
|
|
272
|
+
connectors_report: dict[str, dict] = {}
|
|
274
273
|
for check_result in self.check_results:
|
|
275
274
|
connector = check_result.connector
|
|
276
275
|
connectors_report.setdefault(
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Set
|
|
5
5
|
|
|
6
|
-
from airbyte_ops_mcp.
|
|
6
|
+
from airbyte_ops_mcp.connector_ops.utils import (
|
|
7
7
|
Connector, # type: ignore
|
|
8
8
|
)
|
|
9
|
-
from airbyte_ops_mcp.
|
|
9
|
+
from airbyte_ops_mcp.connector_qa import consts
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def remove_strict_encrypt_suffix(connector_technical_name: str) -> str:
|
airbyte_ops_mcp/mcp/_guidance.py
CHANGED
|
@@ -4,6 +4,43 @@
|
|
|
4
4
|
This module contains prompt text constants used by the MCP server's prompt templates.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
# =============================================================================
|
|
8
|
+
# Server Instructions
|
|
9
|
+
# =============================================================================
|
|
10
|
+
# This text is provided to AI agents via the MCP protocol's "instructions" field.
|
|
11
|
+
# It helps agents understand when to use this server's tools, especially when
|
|
12
|
+
# tool search is enabled. For more context, see:
|
|
13
|
+
# - FastMCP docs: https://gofastmcp.com/servers/overview
|
|
14
|
+
# - Claude tool search: https://www.anthropic.com/news/tool-use-improvements
|
|
15
|
+
# =============================================================================
|
|
16
|
+
|
|
17
|
+
MCP_SERVER_INSTRUCTIONS = """
|
|
18
|
+
Airbyte internal operations server for connector management, cloud administration,
|
|
19
|
+
and production database queries.
|
|
20
|
+
|
|
21
|
+
Use this server for:
|
|
22
|
+
- Publishing connector prereleases and managing version overrides/pins
|
|
23
|
+
- Running connector regression tests (single-version and comparison modes)
|
|
24
|
+
- Querying the Airbyte Cloud production database for workspace, connector, sync,
|
|
25
|
+
and connection diagnostics
|
|
26
|
+
- Triggering and monitoring GitHub Actions CI workflows
|
|
27
|
+
- Looking up Cloud Logging errors for debugging connector issues
|
|
28
|
+
- Performing repository operations on the Airbyte monorepo (for example, listing
|
|
29
|
+
connectors in the repo or inspecting connector definitions)
|
|
30
|
+
|
|
31
|
+
Requirements:
|
|
32
|
+
- GCP credentials for database queries and Cloud Logging access
|
|
33
|
+
- Airbyte Cloud credentials for cloud administration operations
|
|
34
|
+
- GitHub token for workflow dispatch and repository operations
|
|
35
|
+
- Local checkout of the Airbyte repository for repo tools (typically at `../airbyte`)
|
|
36
|
+
|
|
37
|
+
Note: This server is for Airbyte internal use only.
|
|
38
|
+
""".strip()
|
|
39
|
+
|
|
40
|
+
# =============================================================================
|
|
41
|
+
# Prompt Guidance Text
|
|
42
|
+
# =============================================================================
|
|
43
|
+
|
|
7
44
|
TEST_MY_TOOLS_GUIDANCE = """
|
|
8
45
|
Test all available tools in this MCP server to confirm they are working properly.
|
|
9
46
|
|
|
@@ -112,6 +112,15 @@ def get_cloud_connector_version(
|
|
|
112
112
|
Literal["source", "destination"],
|
|
113
113
|
"The type of connector (source or destination)",
|
|
114
114
|
],
|
|
115
|
+
config_api_root: Annotated[
|
|
116
|
+
str | None,
|
|
117
|
+
Field(
|
|
118
|
+
description="Optional API root URL override for the Config API. "
|
|
119
|
+
"Defaults to Airbyte Cloud (https://cloud.airbyte.com/api/v1). "
|
|
120
|
+
"Use this to target local or self-hosted deployments.",
|
|
121
|
+
default=None,
|
|
122
|
+
),
|
|
123
|
+
] = None,
|
|
115
124
|
*,
|
|
116
125
|
ctx: Context,
|
|
117
126
|
) -> ConnectorVersionInfo:
|
|
@@ -137,7 +146,7 @@ def get_cloud_connector_version(
|
|
|
137
146
|
version_data = api_client.get_connector_version(
|
|
138
147
|
connector_id=actor_id,
|
|
139
148
|
connector_type=actor_type,
|
|
140
|
-
config_api_root=constants.CLOUD_CONFIG_API_ROOT,
|
|
149
|
+
config_api_root=config_api_root or constants.CLOUD_CONFIG_API_ROOT,
|
|
141
150
|
client_id=auth.client_id,
|
|
142
151
|
client_secret=auth.client_secret,
|
|
143
152
|
bearer_token=auth.bearer_token,
|
|
@@ -250,7 +259,16 @@ def set_cloud_connector_version_override(
|
|
|
250
259
|
"Provides additional auditability for AI-driven operations.",
|
|
251
260
|
default=None,
|
|
252
261
|
),
|
|
253
|
-
],
|
|
262
|
+
] = None,
|
|
263
|
+
config_api_root: Annotated[
|
|
264
|
+
str | None,
|
|
265
|
+
Field(
|
|
266
|
+
description="Optional API root URL override for the Config API. "
|
|
267
|
+
"Defaults to Airbyte Cloud (https://cloud.airbyte.com/api/v1). "
|
|
268
|
+
"Use this to target local or self-hosted deployments.",
|
|
269
|
+
default=None,
|
|
270
|
+
),
|
|
271
|
+
] = None,
|
|
254
272
|
*,
|
|
255
273
|
ctx: Context,
|
|
256
274
|
) -> VersionOverrideOperationResult:
|
|
@@ -363,6 +381,7 @@ def set_cloud_connector_version_override(
|
|
|
363
381
|
enhanced_override_reason = " | ".join(audit_parts)
|
|
364
382
|
|
|
365
383
|
# Resolve auth and get current version info
|
|
384
|
+
resolved_config_api_root = config_api_root or constants.CLOUD_CONFIG_API_ROOT
|
|
366
385
|
try:
|
|
367
386
|
auth = _resolve_cloud_auth(ctx)
|
|
368
387
|
|
|
@@ -370,7 +389,7 @@ def set_cloud_connector_version_override(
|
|
|
370
389
|
current_version_data = api_client.get_connector_version(
|
|
371
390
|
connector_id=actor_id,
|
|
372
391
|
connector_type=actor_type,
|
|
373
|
-
config_api_root=
|
|
392
|
+
config_api_root=resolved_config_api_root,
|
|
374
393
|
client_id=auth.client_id,
|
|
375
394
|
client_secret=auth.client_secret,
|
|
376
395
|
bearer_token=auth.bearer_token,
|
|
@@ -391,7 +410,7 @@ def set_cloud_connector_version_override(
|
|
|
391
410
|
result = api_client.set_connector_version_override(
|
|
392
411
|
connector_id=actor_id,
|
|
393
412
|
connector_type=actor_type,
|
|
394
|
-
config_api_root=
|
|
413
|
+
config_api_root=resolved_config_api_root,
|
|
395
414
|
client_id=auth.client_id,
|
|
396
415
|
client_secret=auth.client_secret,
|
|
397
416
|
workspace_id=resolved_workspace_id,
|
|
@@ -407,7 +426,7 @@ def set_cloud_connector_version_override(
|
|
|
407
426
|
updated_version_data = api_client.get_connector_version(
|
|
408
427
|
connector_id=actor_id,
|
|
409
428
|
connector_type=actor_type,
|
|
410
|
-
config_api_root=
|
|
429
|
+
config_api_root=resolved_config_api_root,
|
|
411
430
|
client_id=auth.client_id,
|
|
412
431
|
client_secret=auth.client_secret,
|
|
413
432
|
bearer_token=auth.bearer_token,
|
|
@@ -533,7 +552,16 @@ def set_workspace_connector_version_override(
|
|
|
533
552
|
"Provides additional auditability for AI-driven operations.",
|
|
534
553
|
default=None,
|
|
535
554
|
),
|
|
536
|
-
],
|
|
555
|
+
] = None,
|
|
556
|
+
config_api_root: Annotated[
|
|
557
|
+
str | None,
|
|
558
|
+
Field(
|
|
559
|
+
description="Optional API root URL override for the Config API. "
|
|
560
|
+
"Defaults to Airbyte Cloud (https://cloud.airbyte.com/api/v1). "
|
|
561
|
+
"Use this to target local or self-hosted deployments.",
|
|
562
|
+
default=None,
|
|
563
|
+
),
|
|
564
|
+
] = None,
|
|
537
565
|
*,
|
|
538
566
|
ctx: Context,
|
|
539
567
|
) -> WorkspaceVersionOverrideResult:
|
|
@@ -647,7 +675,7 @@ def set_workspace_connector_version_override(
|
|
|
647
675
|
workspace_id=resolved_workspace_id,
|
|
648
676
|
connector_name=connector_name,
|
|
649
677
|
connector_type=connector_type,
|
|
650
|
-
config_api_root=constants.CLOUD_CONFIG_API_ROOT,
|
|
678
|
+
config_api_root=config_api_root or constants.CLOUD_CONFIG_API_ROOT,
|
|
651
679
|
client_id=auth.client_id,
|
|
652
680
|
client_secret=auth.client_secret,
|
|
653
681
|
bearer_token=auth.bearer_token,
|
|
@@ -768,7 +796,16 @@ def set_organization_connector_version_override(
|
|
|
768
796
|
"Provides additional auditability for AI-driven operations.",
|
|
769
797
|
default=None,
|
|
770
798
|
),
|
|
771
|
-
],
|
|
799
|
+
] = None,
|
|
800
|
+
config_api_root: Annotated[
|
|
801
|
+
str | None,
|
|
802
|
+
Field(
|
|
803
|
+
description="Optional API root URL override for the Config API. "
|
|
804
|
+
"Defaults to Airbyte Cloud (https://cloud.airbyte.com/api/v1). "
|
|
805
|
+
"Use this to target local or self-hosted deployments.",
|
|
806
|
+
default=None,
|
|
807
|
+
),
|
|
808
|
+
] = None,
|
|
772
809
|
*,
|
|
773
810
|
ctx: Context,
|
|
774
811
|
) -> OrganizationVersionOverrideResult:
|
|
@@ -878,7 +915,7 @@ def set_organization_connector_version_override(
|
|
|
878
915
|
organization_id=organization_id,
|
|
879
916
|
connector_name=connector_name,
|
|
880
917
|
connector_type=connector_type,
|
|
881
|
-
config_api_root=constants.CLOUD_CONFIG_API_ROOT,
|
|
918
|
+
config_api_root=config_api_root or constants.CLOUD_CONFIG_API_ROOT,
|
|
882
919
|
client_id=auth.client_id,
|
|
883
920
|
client_secret=auth.client_secret,
|
|
884
921
|
bearer_token=auth.bearer_token,
|
airbyte_ops_mcp/mcp/server.py
CHANGED
|
@@ -22,12 +22,14 @@ from dotenv import load_dotenv
|
|
|
22
22
|
from fastmcp import FastMCP
|
|
23
23
|
from fastmcp_extensions import MCPServerConfigArg, mcp_server
|
|
24
24
|
|
|
25
|
+
from airbyte_ops_mcp._sentry import init_sentry_tracking
|
|
25
26
|
from airbyte_ops_mcp.constants import (
|
|
26
27
|
HEADER_AIRBYTE_CLOUD_CLIENT_ID,
|
|
27
28
|
HEADER_AIRBYTE_CLOUD_CLIENT_SECRET,
|
|
28
29
|
MCP_SERVER_NAME,
|
|
29
30
|
ServerConfigKey,
|
|
30
31
|
)
|
|
32
|
+
from airbyte_ops_mcp.mcp._guidance import MCP_SERVER_INSTRUCTIONS
|
|
31
33
|
from airbyte_ops_mcp.mcp.cloud_connector_versions import (
|
|
32
34
|
register_cloud_connector_version_tools,
|
|
33
35
|
)
|
|
@@ -59,6 +61,7 @@ def _normalize_bearer_token(value: str) -> str | None:
|
|
|
59
61
|
# Create the MCP server with built-in server info resource
|
|
60
62
|
app = mcp_server(
|
|
61
63
|
name=MCP_SERVER_NAME,
|
|
64
|
+
instructions=MCP_SERVER_INSTRUCTIONS,
|
|
62
65
|
package_name="airbyte-internal-ops",
|
|
63
66
|
advertised_properties={
|
|
64
67
|
"docs_url": "https://github.com/airbytehq/airbyte-ops-mcp",
|
|
@@ -138,6 +141,7 @@ def main() -> None:
|
|
|
138
141
|
suitable for direct MCP client connections.
|
|
139
142
|
"""
|
|
140
143
|
_load_env()
|
|
144
|
+
init_sentry_tracking()
|
|
141
145
|
|
|
142
146
|
print("=" * 60, flush=True, file=sys.stderr)
|
|
143
147
|
print("Starting Airbyte Admin MCP server (stdio mode).", file=sys.stderr)
|
|
@@ -188,6 +192,7 @@ def main_http() -> None:
|
|
|
188
192
|
MCP_HTTP_PORT: Port to listen on (default: 8082)
|
|
189
193
|
"""
|
|
190
194
|
_load_env()
|
|
195
|
+
init_sentry_tracking()
|
|
191
196
|
|
|
192
197
|
host = os.getenv("MCP_HTTP_HOST", DEFAULT_HTTP_HOST)
|
|
193
198
|
port = _parse_port(os.getenv("MCP_HTTP_PORT"), DEFAULT_HTTP_PORT)
|
|
File without changes
|
{airbyte_internal_ops-0.6.1.dist-info → airbyte_internal_ops-0.7.1.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/airbyte_ops_mcp/{_legacy/airbyte_ci/connector_qa → connector_qa}/checks/documentation/helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|