airbyte-agent-mcp 0.1.30__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_agent_mcp/__init__.py +0 -0
- airbyte_agent_mcp/__main__.py +26 -0
- airbyte_agent_mcp/_vendored/__init__.py +1 -0
- airbyte_agent_mcp/_vendored/connector_sdk/__init__.py +82 -0
- airbyte_agent_mcp/_vendored/connector_sdk/auth_strategies.py +1123 -0
- airbyte_agent_mcp/_vendored/connector_sdk/auth_template.py +135 -0
- airbyte_agent_mcp/_vendored/connector_sdk/connector_model_loader.py +938 -0
- airbyte_agent_mcp/_vendored/connector_sdk/constants.py +78 -0
- airbyte_agent_mcp/_vendored/connector_sdk/exceptions.py +23 -0
- airbyte_agent_mcp/_vendored/connector_sdk/executor/__init__.py +31 -0
- airbyte_agent_mcp/_vendored/connector_sdk/executor/hosted_executor.py +188 -0
- airbyte_agent_mcp/_vendored/connector_sdk/executor/local_executor.py +1504 -0
- airbyte_agent_mcp/_vendored/connector_sdk/executor/models.py +190 -0
- airbyte_agent_mcp/_vendored/connector_sdk/extensions.py +655 -0
- airbyte_agent_mcp/_vendored/connector_sdk/http/__init__.py +37 -0
- airbyte_agent_mcp/_vendored/connector_sdk/http/adapters/__init__.py +9 -0
- airbyte_agent_mcp/_vendored/connector_sdk/http/adapters/httpx_adapter.py +251 -0
- airbyte_agent_mcp/_vendored/connector_sdk/http/config.py +98 -0
- airbyte_agent_mcp/_vendored/connector_sdk/http/exceptions.py +119 -0
- airbyte_agent_mcp/_vendored/connector_sdk/http/protocols.py +114 -0
- airbyte_agent_mcp/_vendored/connector_sdk/http/response.py +102 -0
- airbyte_agent_mcp/_vendored/connector_sdk/http_client.py +679 -0
- airbyte_agent_mcp/_vendored/connector_sdk/logging/__init__.py +11 -0
- airbyte_agent_mcp/_vendored/connector_sdk/logging/logger.py +264 -0
- airbyte_agent_mcp/_vendored/connector_sdk/logging/types.py +92 -0
- airbyte_agent_mcp/_vendored/connector_sdk/observability/__init__.py +11 -0
- airbyte_agent_mcp/_vendored/connector_sdk/observability/models.py +19 -0
- airbyte_agent_mcp/_vendored/connector_sdk/observability/redactor.py +81 -0
- airbyte_agent_mcp/_vendored/connector_sdk/observability/session.py +94 -0
- airbyte_agent_mcp/_vendored/connector_sdk/performance/__init__.py +6 -0
- airbyte_agent_mcp/_vendored/connector_sdk/performance/instrumentation.py +57 -0
- airbyte_agent_mcp/_vendored/connector_sdk/performance/metrics.py +93 -0
- airbyte_agent_mcp/_vendored/connector_sdk/schema/__init__.py +75 -0
- airbyte_agent_mcp/_vendored/connector_sdk/schema/base.py +160 -0
- airbyte_agent_mcp/_vendored/connector_sdk/schema/components.py +238 -0
- airbyte_agent_mcp/_vendored/connector_sdk/schema/connector.py +131 -0
- airbyte_agent_mcp/_vendored/connector_sdk/schema/extensions.py +109 -0
- airbyte_agent_mcp/_vendored/connector_sdk/schema/operations.py +146 -0
- airbyte_agent_mcp/_vendored/connector_sdk/schema/security.py +213 -0
- airbyte_agent_mcp/_vendored/connector_sdk/secrets.py +182 -0
- airbyte_agent_mcp/_vendored/connector_sdk/telemetry/__init__.py +10 -0
- airbyte_agent_mcp/_vendored/connector_sdk/telemetry/config.py +32 -0
- airbyte_agent_mcp/_vendored/connector_sdk/telemetry/events.py +58 -0
- airbyte_agent_mcp/_vendored/connector_sdk/telemetry/tracker.py +151 -0
- airbyte_agent_mcp/_vendored/connector_sdk/types.py +239 -0
- airbyte_agent_mcp/_vendored/connector_sdk/utils.py +60 -0
- airbyte_agent_mcp/_vendored/connector_sdk/validation.py +822 -0
- airbyte_agent_mcp/config.py +97 -0
- airbyte_agent_mcp/connector_manager.py +340 -0
- airbyte_agent_mcp/models.py +147 -0
- airbyte_agent_mcp/registry_client.py +103 -0
- airbyte_agent_mcp/secret_manager.py +94 -0
- airbyte_agent_mcp/server.py +265 -0
- airbyte_agent_mcp-0.1.30.dist-info/METADATA +134 -0
- airbyte_agent_mcp-0.1.30.dist-info/RECORD +56 -0
- airbyte_agent_mcp-0.1.30.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Constants used throughout the Airbyte SDK.
|
|
3
|
+
|
|
4
|
+
This module centralizes configuration defaults and commonly used values to improve
|
|
5
|
+
maintainability and consistency across the codebase.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
11
|
+
|
|
12
|
+
# ============================================================================
|
|
13
|
+
# HTTP Connection and Timeout Defaults
|
|
14
|
+
# ============================================================================
|
|
15
|
+
|
|
16
|
+
# Connection pooling limits
|
|
17
|
+
DEFAULT_MAX_CONNECTIONS = 100
|
|
18
|
+
"""Maximum number of concurrent HTTP connections to maintain in the pool."""
|
|
19
|
+
|
|
20
|
+
DEFAULT_MAX_KEEPALIVE_CONNECTIONS = 20
|
|
21
|
+
"""Maximum number of keepalive connections to maintain in the pool."""
|
|
22
|
+
|
|
23
|
+
# Timeout values (in seconds)
|
|
24
|
+
DEFAULT_CONNECT_TIMEOUT = 5.0
|
|
25
|
+
"""Default timeout for establishing a new connection (seconds)."""
|
|
26
|
+
|
|
27
|
+
DEFAULT_READ_TIMEOUT = 30.0
|
|
28
|
+
"""Default timeout for reading response data (seconds)."""
|
|
29
|
+
|
|
30
|
+
DEFAULT_WRITE_TIMEOUT = 30.0
|
|
31
|
+
"""Default timeout for writing request data (seconds)."""
|
|
32
|
+
|
|
33
|
+
DEFAULT_POOL_TIMEOUT = 5.0
|
|
34
|
+
"""Default timeout for acquiring a connection from the pool (seconds)."""
|
|
35
|
+
|
|
36
|
+
DEFAULT_REQUEST_TIMEOUT = 30.0
|
|
37
|
+
"""Default overall request timeout (seconds)."""
|
|
38
|
+
|
|
39
|
+
# ============================================================================
|
|
40
|
+
# OpenAPI Specification
|
|
41
|
+
# ============================================================================
|
|
42
|
+
|
|
43
|
+
OPENAPI_VERSION_PREFIX = "3.1."
|
|
44
|
+
"""Required OpenAPI version prefix. Only 3.1.x specifications are supported."""
|
|
45
|
+
|
|
46
|
+
OPENAPI_DEFAULT_VERSION = "1.0.0"
|
|
47
|
+
"""Default version string for connectors that don't specify a version."""
|
|
48
|
+
|
|
49
|
+
# ============================================================================
|
|
50
|
+
# Performance and Metrics
|
|
51
|
+
# ============================================================================
|
|
52
|
+
|
|
53
|
+
MILLISECONDS_PER_SECOND = 1000
|
|
54
|
+
"""Conversion factor from seconds to milliseconds."""
|
|
55
|
+
|
|
56
|
+
# ============================================================================
|
|
57
|
+
# Retry and Backoff Defaults
|
|
58
|
+
# ============================================================================
|
|
59
|
+
|
|
60
|
+
DEFAULT_INITIAL_DELAY_SECONDS = 1.0
|
|
61
|
+
"""Default initial delay for retry backoff (seconds)."""
|
|
62
|
+
|
|
63
|
+
DEFAULT_MAX_DELAY_SECONDS = 60.0
|
|
64
|
+
"""Default maximum delay for retry backoff (seconds)."""
|
|
65
|
+
|
|
66
|
+
# ============================================================================
|
|
67
|
+
# SDK Version
|
|
68
|
+
# ============================================================================
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
SDK_VERSION = version("connector-sdk")
|
|
72
|
+
except PackageNotFoundError:
|
|
73
|
+
# Fallback for development when package isn't installed
|
|
74
|
+
SDK_VERSION = "0.0.0-dev"
|
|
75
|
+
"""Current version of the Airbyte SDK."""
|
|
76
|
+
|
|
77
|
+
MINIMUM_PYTHON_VERSION = "3.9"
|
|
78
|
+
"""Minimum Python version required to run the SDK."""
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Exceptions for the Airbyte SDK.
|
|
2
|
+
|
|
3
|
+
DEPRECATED: HTTP exceptions have been moved to connector_sdk.http.exceptions.
|
|
4
|
+
This module re-exports them for backward compatibility.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .http.exceptions import (
|
|
8
|
+
AuthenticationError,
|
|
9
|
+
HTTPClientError,
|
|
10
|
+
HTTPStatusError,
|
|
11
|
+
NetworkError,
|
|
12
|
+
RateLimitError,
|
|
13
|
+
TimeoutError,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"HTTPClientError",
|
|
18
|
+
"HTTPStatusError",
|
|
19
|
+
"AuthenticationError",
|
|
20
|
+
"RateLimitError",
|
|
21
|
+
"NetworkError",
|
|
22
|
+
"TimeoutError",
|
|
23
|
+
]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Executor implementations for connector operations."""
|
|
2
|
+
|
|
3
|
+
from .hosted_executor import HostedExecutor
|
|
4
|
+
from .local_executor import LocalExecutor
|
|
5
|
+
from .models import (
|
|
6
|
+
ActionNotSupportedError,
|
|
7
|
+
EntityNotFoundError,
|
|
8
|
+
ExecutionConfig,
|
|
9
|
+
ExecutionResult,
|
|
10
|
+
ExecutorError,
|
|
11
|
+
ExecutorProtocol,
|
|
12
|
+
InvalidParameterError,
|
|
13
|
+
MissingParameterError,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
# Config and Result types
|
|
18
|
+
"ExecutionConfig",
|
|
19
|
+
"ExecutionResult",
|
|
20
|
+
# Protocol
|
|
21
|
+
"ExecutorProtocol",
|
|
22
|
+
# Executors
|
|
23
|
+
"LocalExecutor",
|
|
24
|
+
"HostedExecutor",
|
|
25
|
+
# Exceptions
|
|
26
|
+
"ExecutorError",
|
|
27
|
+
"EntityNotFoundError",
|
|
28
|
+
"ActionNotSupportedError",
|
|
29
|
+
"MissingParameterError",
|
|
30
|
+
"InvalidParameterError",
|
|
31
|
+
]
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""Hosted executor for proxying operations through the backend API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
from opentelemetry import trace
|
|
9
|
+
|
|
10
|
+
from .models import (
|
|
11
|
+
ExecutionConfig,
|
|
12
|
+
ExecutionResult,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class HostedExecutor:
|
|
17
|
+
"""Executor that proxies execution through the Sonar backend API.
|
|
18
|
+
|
|
19
|
+
This is the "hosted mode" executor that makes HTTP calls to the backend API
|
|
20
|
+
instead of directly calling external services. The backend handles all
|
|
21
|
+
connector logic, secrets management, and execution.
|
|
22
|
+
|
|
23
|
+
The API URL is configured at initialization via the api_url parameter,
|
|
24
|
+
which defaults to the AIRBYTE_CONNECTOR_API_URL environment variable.
|
|
25
|
+
|
|
26
|
+
Implements ExecutorProtocol.
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
executor = HostedExecutor(
|
|
30
|
+
connector_id="stripe-prod-123",
|
|
31
|
+
airbyte_client_id="client_abc123",
|
|
32
|
+
airbyte_client_secret="secret_xyz789"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
config = ExecutionConfig(
|
|
36
|
+
entity="customers",
|
|
37
|
+
action="list"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
result = await executor.execute(config)
|
|
41
|
+
if result.success:
|
|
42
|
+
print(f"Data: {result.data}")
|
|
43
|
+
else:
|
|
44
|
+
print(f"Error: {result.error}")
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
connector_id: str,
|
|
50
|
+
airbyte_client_id: str,
|
|
51
|
+
airbyte_client_secret: str,
|
|
52
|
+
api_url: str | None = None,
|
|
53
|
+
):
|
|
54
|
+
"""Initialize hosted executor.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
connector_id: ID of the connector to execute (e.g., "stripe-prod-123")
|
|
58
|
+
airbyte_client_id: Airbyte client ID for authentication
|
|
59
|
+
airbyte_client_secret: Airbyte client secret for authentication
|
|
60
|
+
api_url: API URL for the hosted executor backend. Defaults to
|
|
61
|
+
AIRBYTE_CONNECTOR_API_URL environment variable or "http://localhost:8001"
|
|
62
|
+
|
|
63
|
+
Example:
|
|
64
|
+
executor = HostedExecutor(
|
|
65
|
+
connector_id="my-connector-id",
|
|
66
|
+
airbyte_client_id="client_abc123",
|
|
67
|
+
airbyte_client_secret="secret_xyz789"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Or with custom API URL:
|
|
71
|
+
executor = HostedExecutor(
|
|
72
|
+
connector_id="my-connector-id",
|
|
73
|
+
airbyte_client_id="client_abc123",
|
|
74
|
+
airbyte_client_secret="secret_xyz789",
|
|
75
|
+
api_url="https://api.production.com"
|
|
76
|
+
)
|
|
77
|
+
"""
|
|
78
|
+
self.connector_id = connector_id
|
|
79
|
+
self.airbyte_client_id = airbyte_client_id
|
|
80
|
+
self.airbyte_client_secret = airbyte_client_secret
|
|
81
|
+
self.api_url = api_url or os.getenv("AIRBYTE_CONNECTOR_API_URL", "http://localhost:8001")
|
|
82
|
+
|
|
83
|
+
# Create synchronous HTTP client
|
|
84
|
+
# We use sync client even though execute() is async for simplicity
|
|
85
|
+
# The async wrapper allows it to work with the protocol
|
|
86
|
+
self.client = httpx.Client(
|
|
87
|
+
timeout=httpx.Timeout(300.0), # 5 minute timeout
|
|
88
|
+
follow_redirects=True,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
async def execute(self, config: ExecutionConfig) -> ExecutionResult:
|
|
92
|
+
"""Execute connector via backend API (ExecutorProtocol implementation).
|
|
93
|
+
|
|
94
|
+
Makes an HTTP POST request to /connectors/{connector_id}/execute with
|
|
95
|
+
OAuth authentication and the configuration in the request body.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
config: Execution configuration (entity, action, params)
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
ExecutionResult with success/failure status
|
|
102
|
+
|
|
103
|
+
Raises:
|
|
104
|
+
httpx.HTTPStatusError: If API returns 4xx/5xx status code
|
|
105
|
+
httpx.RequestError: If network request fails
|
|
106
|
+
|
|
107
|
+
Example:
|
|
108
|
+
config = ExecutionConfig(
|
|
109
|
+
entity="customers",
|
|
110
|
+
action="list"
|
|
111
|
+
)
|
|
112
|
+
result = await executor.execute(config)
|
|
113
|
+
"""
|
|
114
|
+
tracer = trace.get_tracer("airbyte.connector-sdk.executor.hosted")
|
|
115
|
+
|
|
116
|
+
with tracer.start_as_current_span("airbyte.hosted_executor.execute") as span:
|
|
117
|
+
# Add span attributes
|
|
118
|
+
span.set_attribute("connector.id", self.connector_id)
|
|
119
|
+
span.set_attribute("connector.entity", config.entity)
|
|
120
|
+
span.set_attribute("connector.action", config.action)
|
|
121
|
+
span.set_attribute("connector.api_url", self.api_url)
|
|
122
|
+
if config.params:
|
|
123
|
+
# Only add non-sensitive param keys
|
|
124
|
+
span.set_attribute("connector.param_keys", list(config.params.keys()))
|
|
125
|
+
|
|
126
|
+
# Build API URL from instance api_url
|
|
127
|
+
url = f"{self.api_url}/connectors/{self.connector_id}/execute"
|
|
128
|
+
span.set_attribute("http.url", url)
|
|
129
|
+
|
|
130
|
+
# Build request body matching ExecutionRequest model
|
|
131
|
+
# Extract entity, action, and params from config attributes
|
|
132
|
+
request_body = {
|
|
133
|
+
"entity": config.entity,
|
|
134
|
+
"action": config.action,
|
|
135
|
+
"params": config.params,
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
# Make synchronous HTTP request
|
|
140
|
+
# (wrapped in async method for protocol compatibility)
|
|
141
|
+
response = self.client.post(url, json=request_body)
|
|
142
|
+
|
|
143
|
+
# Add response status code to span
|
|
144
|
+
span.set_attribute("http.status_code", response.status_code)
|
|
145
|
+
|
|
146
|
+
# Raise exception for 4xx/5xx status codes
|
|
147
|
+
response.raise_for_status()
|
|
148
|
+
|
|
149
|
+
# Parse JSON response
|
|
150
|
+
result_data = response.json()
|
|
151
|
+
|
|
152
|
+
# Mark span as successful
|
|
153
|
+
span.set_attribute("connector.success", True)
|
|
154
|
+
|
|
155
|
+
# Return success result
|
|
156
|
+
return ExecutionResult(success=True, data=result_data, error=None)
|
|
157
|
+
|
|
158
|
+
except httpx.HTTPStatusError as e:
|
|
159
|
+
# HTTP error (4xx, 5xx) - record and re-raise
|
|
160
|
+
span.set_attribute("connector.success", False)
|
|
161
|
+
span.set_attribute("connector.error_type", "HTTPStatusError")
|
|
162
|
+
span.set_attribute("http.status_code", e.response.status_code)
|
|
163
|
+
span.record_exception(e)
|
|
164
|
+
raise
|
|
165
|
+
|
|
166
|
+
except Exception as e:
|
|
167
|
+
# Catch-all for any other unexpected exceptions
|
|
168
|
+
span.set_attribute("connector.success", False)
|
|
169
|
+
span.set_attribute("connector.error_type", type(e).__name__)
|
|
170
|
+
span.record_exception(e)
|
|
171
|
+
raise
|
|
172
|
+
|
|
173
|
+
def close(self):
|
|
174
|
+
"""Close the HTTP client.
|
|
175
|
+
|
|
176
|
+
Call this when you're done using the executor to clean up resources.
|
|
177
|
+
|
|
178
|
+
Example:
|
|
179
|
+
executor = HostedExecutor(
|
|
180
|
+
workspace_id="workspace-123",
|
|
181
|
+
connector_id="my-connector"
|
|
182
|
+
)
|
|
183
|
+
try:
|
|
184
|
+
result = await executor.execute(config)
|
|
185
|
+
finally:
|
|
186
|
+
executor.close()
|
|
187
|
+
"""
|
|
188
|
+
self.client.close()
|