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,94 @@
|
|
|
1
|
+
"""Secrets management with pluggable backends."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
|
|
6
|
+
from dotenv import load_dotenv
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SecretsBackend(ABC):
|
|
10
|
+
"""Abstract base class for secrets backends."""
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def get_secret(self, key: str) -> str | None:
|
|
14
|
+
"""Get a secret value by key."""
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DotEnvSecretsBackend(SecretsBackend):
|
|
19
|
+
"""Secrets backend that loads from .env file and environment variables."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, dotenv_path: str = ".env"):
|
|
22
|
+
"""Initialize backend.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
dotenv_path: Path to .env file (default: ".env" in current directory)
|
|
26
|
+
"""
|
|
27
|
+
self.dotenv_path = dotenv_path
|
|
28
|
+
self._cache: dict[str, str] = {}
|
|
29
|
+
|
|
30
|
+
# Load .env file if it exists
|
|
31
|
+
if os.path.exists(dotenv_path):
|
|
32
|
+
load_dotenv(dotenv_path, override=True)
|
|
33
|
+
|
|
34
|
+
def get_secret(self, key: str) -> str | None:
|
|
35
|
+
"""Get secret from cache, then environment.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
key: Secret key to look up
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Secret value or None if not found
|
|
42
|
+
"""
|
|
43
|
+
# Check cache first
|
|
44
|
+
if key in self._cache:
|
|
45
|
+
return self._cache[key]
|
|
46
|
+
|
|
47
|
+
# Try environment variable
|
|
48
|
+
value = os.getenv(key)
|
|
49
|
+
if value is not None:
|
|
50
|
+
self._cache[key] = value
|
|
51
|
+
return value
|
|
52
|
+
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class SecretsManager:
|
|
57
|
+
"""Facade for managing secrets resolution."""
|
|
58
|
+
|
|
59
|
+
def __init__(self, backend: SecretsBackend):
|
|
60
|
+
"""Initialize manager with a backend.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
backend: Secrets backend implementation
|
|
64
|
+
"""
|
|
65
|
+
self.backend = backend
|
|
66
|
+
|
|
67
|
+
def get_secrets(self, secret_mapping: dict[str, str]) -> dict[str, str]:
|
|
68
|
+
"""Resolve multiple secrets from a mapping.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
secret_mapping: Dict mapping param names to secret keys
|
|
72
|
+
Example: {"api_key": "STRIPE_API_KEY"}
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Dict mapping param names to secret values
|
|
76
|
+
Example: {"api_key": "sk_test_abc123"}
|
|
77
|
+
|
|
78
|
+
Raises:
|
|
79
|
+
ValueError: If any secret is not found
|
|
80
|
+
"""
|
|
81
|
+
resolved = {}
|
|
82
|
+
missing = []
|
|
83
|
+
|
|
84
|
+
for param_name, secret_key in secret_mapping.items():
|
|
85
|
+
value = self.backend.get_secret(secret_key)
|
|
86
|
+
if value is None:
|
|
87
|
+
missing.append(secret_key)
|
|
88
|
+
else:
|
|
89
|
+
resolved[param_name] = value
|
|
90
|
+
|
|
91
|
+
if missing:
|
|
92
|
+
raise ValueError(f"Required secrets not found: {', '.join(missing)}. Check your .env file or environment variables.")
|
|
93
|
+
|
|
94
|
+
return resolved
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"""FastMCP server with connector tools."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from fastmcp import FastMCP
|
|
7
|
+
|
|
8
|
+
from airbyte_agent_mcp.config import load_connector_config, validate_connectors
|
|
9
|
+
from airbyte_agent_mcp.connector_manager import ConnectorManager
|
|
10
|
+
from airbyte_agent_mcp.models import ExecuteResponse, ListEntitiesResponse
|
|
11
|
+
from airbyte_agent_mcp.secret_manager import DotEnvSecretsBackend, SecretsManager
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
# Initialize FastMCP server
|
|
16
|
+
mcp = FastMCP("airbyte-agent-mcp")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _serialize_exception(e: Exception) -> dict:
|
|
20
|
+
"""Serialize an exception to a JSON-safe dictionary.
|
|
21
|
+
|
|
22
|
+
Handles SDK exceptions that may contain non-serializable objects
|
|
23
|
+
like HTTPResponse in their __dict__.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
e: The exception to serialize
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
A JSON-serializable error dictionary
|
|
30
|
+
"""
|
|
31
|
+
error_type = type(e).__name__
|
|
32
|
+
|
|
33
|
+
# Build error dict with safe, serializable values
|
|
34
|
+
error_dict: dict = {
|
|
35
|
+
"type": error_type,
|
|
36
|
+
"message": str(e),
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# Extract useful fields from HTTP exceptions without including HTTPResponse objects
|
|
40
|
+
if hasattr(e, "status_code"):
|
|
41
|
+
error_dict["status_code"] = e.status_code
|
|
42
|
+
|
|
43
|
+
if hasattr(e, "retry_after") and e.retry_after is not None:
|
|
44
|
+
error_dict["retry_after"] = e.retry_after
|
|
45
|
+
|
|
46
|
+
if hasattr(e, "timeout_type") and e.timeout_type is not None:
|
|
47
|
+
error_dict["timeout_type"] = e.timeout_type
|
|
48
|
+
|
|
49
|
+
return error_dict
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@mcp.tool()
|
|
53
|
+
async def execute(connector_id: str, entity: str, action: str, params: dict[str, Any] | None = None) -> dict:
|
|
54
|
+
"""Execute an operation on a connector.
|
|
55
|
+
|
|
56
|
+
This is the primary tool for interacting with connectors. It creates a fresh
|
|
57
|
+
connector instance, executes the operation, and returns the result.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
connector_id: Connector identifier from configured_connectors.yaml
|
|
61
|
+
entity: Entity name (e.g., "customers", "invoices"). The entity is not a URL path.
|
|
62
|
+
action: Operation action (e.g., "get", "list", "create", "update", "delete")
|
|
63
|
+
params: Operation parameters (optional, depends on action)
|
|
64
|
+
- For "get": {"id": "..."}
|
|
65
|
+
- For "list": {"limit": 10, "starting_after": "..."}
|
|
66
|
+
- For "create": {"field1": "value1", ...}
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Execution result with success status and data or error
|
|
70
|
+
|
|
71
|
+
Example:
|
|
72
|
+
execute(
|
|
73
|
+
connector_id="stripe",
|
|
74
|
+
entity="customers",
|
|
75
|
+
action="list",
|
|
76
|
+
params={"limit": 10}
|
|
77
|
+
)
|
|
78
|
+
"""
|
|
79
|
+
params = params or {}
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
logger.info(f"Tool call: execute({connector_id}, {entity}, {action})")
|
|
83
|
+
|
|
84
|
+
# Execute operation
|
|
85
|
+
result = await mcp.connector_manager.execute(
|
|
86
|
+
connector_id=connector_id,
|
|
87
|
+
entity=entity,
|
|
88
|
+
action=action,
|
|
89
|
+
params=params,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
response = ExecuteResponse(
|
|
93
|
+
success=True,
|
|
94
|
+
data=result,
|
|
95
|
+
connector_id=connector_id,
|
|
96
|
+
entity=entity,
|
|
97
|
+
action=action,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return response.model_dump()
|
|
101
|
+
|
|
102
|
+
except Exception as e:
|
|
103
|
+
logger.error(f"Execution failed: {e}", exc_info=True)
|
|
104
|
+
|
|
105
|
+
response = ExecuteResponse(
|
|
106
|
+
success=False,
|
|
107
|
+
error=_serialize_exception(e),
|
|
108
|
+
connector_id=connector_id,
|
|
109
|
+
entity=entity,
|
|
110
|
+
action=action,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
return response.model_dump()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@mcp.tool()
|
|
117
|
+
async def describe_connector(connector_id: str) -> dict:
|
|
118
|
+
"""Describe a connector's available entities and operations.
|
|
119
|
+
|
|
120
|
+
Discovers what entities (data types) a connector provides and what
|
|
121
|
+
operations (actions) are available for each entity by parsing the
|
|
122
|
+
connector's OpenAPI specification.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
connector_id: Connector identifier from configured_connectors.yaml
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Dictionary containing:
|
|
129
|
+
- connector_id: The connector identifier
|
|
130
|
+
- entities: List of entity objects, each with:
|
|
131
|
+
- entity_name: Entity identifier used in operations
|
|
132
|
+
- description: Entity description
|
|
133
|
+
- available_actions: List of supported operation actions
|
|
134
|
+
|
|
135
|
+
Example:
|
|
136
|
+
describe_connector(connector_id="stripe")
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
{
|
|
140
|
+
"connector_id": "stripe",
|
|
141
|
+
"entities": [
|
|
142
|
+
{
|
|
143
|
+
"entity_name": "customers",
|
|
144
|
+
"description": "Customer objects",
|
|
145
|
+
"available_actions": ["list", "retrieve"]
|
|
146
|
+
},
|
|
147
|
+
...
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
"""
|
|
151
|
+
try:
|
|
152
|
+
logger.info(f"Tool call: describe_connector({connector_id})")
|
|
153
|
+
|
|
154
|
+
entities = await mcp.connector_manager.describe_connector(connector_id)
|
|
155
|
+
|
|
156
|
+
response = ListEntitiesResponse(connector_id=connector_id, entities=entities)
|
|
157
|
+
|
|
158
|
+
return response.model_dump()
|
|
159
|
+
|
|
160
|
+
except Exception as e:
|
|
161
|
+
logger.error(f"Failed to list entities: {e}", exc_info=True)
|
|
162
|
+
return {"error": str(e), "connector_id": connector_id}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@mcp.tool()
|
|
166
|
+
async def discover_connectors() -> dict:
|
|
167
|
+
"""Discover all available configured connectors.
|
|
168
|
+
|
|
169
|
+
Returns a list of all connectors defined in the configured_connectors.yaml configuration
|
|
170
|
+
file. This allows you to see what connectors are available before executing
|
|
171
|
+
operations or describing their resources.
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
Dictionary containing:
|
|
175
|
+
- connectors: List of connector objects, each with:
|
|
176
|
+
- id: Connector identifier used in other operations
|
|
177
|
+
- type: Connector type (local or remote)
|
|
178
|
+
- description: Human-readable description
|
|
179
|
+
|
|
180
|
+
Example:
|
|
181
|
+
discover_connectors()
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
{
|
|
185
|
+
"connectors": [
|
|
186
|
+
{
|
|
187
|
+
"id": "stripe",
|
|
188
|
+
"type": "local",
|
|
189
|
+
"description": "Stripe API connector"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"id": "shopify",
|
|
193
|
+
"type": "remote",
|
|
194
|
+
"description": "Shopify connector from registry"
|
|
195
|
+
}
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
"""
|
|
199
|
+
try:
|
|
200
|
+
logger.info("Tool call: discover_connectors()")
|
|
201
|
+
return mcp.connector_manager.discover_connectors()
|
|
202
|
+
|
|
203
|
+
except Exception as e:
|
|
204
|
+
logger.error(f"Failed to discover connectors: {e}", exc_info=True)
|
|
205
|
+
return {"error": str(e), "connectors": []}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def init_server(config_path: str = "configured_connectors.yaml", dotenv_path: str = ".env"):
|
|
209
|
+
"""Initialize the MCP server with configuration.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
config_path: Path to configured_connectors.yaml
|
|
213
|
+
dotenv_path: Path to .env file with secrets
|
|
214
|
+
|
|
215
|
+
Raises:
|
|
216
|
+
SystemExit: If initialization fails
|
|
217
|
+
"""
|
|
218
|
+
logging.basicConfig(
|
|
219
|
+
level=logging.INFO,
|
|
220
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
logger.info("Initializing airbyte-agent-mcp server...")
|
|
224
|
+
|
|
225
|
+
try:
|
|
226
|
+
# Load configuration
|
|
227
|
+
config = load_connector_config(config_path)
|
|
228
|
+
logger.info(f"Loaded configuration with {len(config.connectors)} connector(s)")
|
|
229
|
+
|
|
230
|
+
# Validate connectors
|
|
231
|
+
errors = validate_connectors(config)
|
|
232
|
+
if errors:
|
|
233
|
+
logger.error("Connector validation failed:")
|
|
234
|
+
for error in errors:
|
|
235
|
+
logger.error(f" - {error}")
|
|
236
|
+
raise SystemExit(1)
|
|
237
|
+
|
|
238
|
+
# Initialize secrets manager
|
|
239
|
+
secrets_backend = DotEnvSecretsBackend(dotenv_path)
|
|
240
|
+
secrets_manager = SecretsManager(secrets_backend)
|
|
241
|
+
logger.info("Initialized secrets manager")
|
|
242
|
+
|
|
243
|
+
# Store managers on MCP instance (application-wide state)
|
|
244
|
+
mcp.connector_manager = ConnectorManager(config, secrets_manager)
|
|
245
|
+
logger.info("Initialized connector manager")
|
|
246
|
+
|
|
247
|
+
logger.info(" Server initialization complete")
|
|
248
|
+
|
|
249
|
+
except Exception as e:
|
|
250
|
+
logger.error(f"Failed to initialize server: {e}", exc_info=True)
|
|
251
|
+
raise SystemExit(1)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def run_server(config_path: str = "configured_connectors.yaml", dotenv_path: str = ".env"):
|
|
255
|
+
"""Run the MCP server.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
config_path: Path to configured_connectors.yaml
|
|
259
|
+
dotenv_path: Path to .env file
|
|
260
|
+
"""
|
|
261
|
+
init_server(config_path, dotenv_path)
|
|
262
|
+
|
|
263
|
+
# FastMCP handles the server loop
|
|
264
|
+
logger.info("Starting MCP server on stdio transport...")
|
|
265
|
+
mcp.run()
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: airbyte-agent-mcp
|
|
3
|
+
Version: 0.1.30
|
|
4
|
+
Summary: MCP server that exposes Airbyte Connector SDK as MCP tools
|
|
5
|
+
Author-email: Airbyte Support <support@airbyte.io>
|
|
6
|
+
Requires-Python: >=3.13
|
|
7
|
+
Requires-Dist: click>=8.0.0
|
|
8
|
+
Requires-Dist: fastmcp>=2.10.5
|
|
9
|
+
Requires-Dist: httpx>=0.24.0
|
|
10
|
+
Requires-Dist: jinja2>=3.0.0
|
|
11
|
+
Requires-Dist: jsonpath-ng>=1.6.1
|
|
12
|
+
Requires-Dist: jsonref>=1.1.0
|
|
13
|
+
Requires-Dist: jsonschema>=4.0.0
|
|
14
|
+
Requires-Dist: opentelemetry-api>=1.37.0
|
|
15
|
+
Requires-Dist: opentelemetry-sdk>=1.37.0
|
|
16
|
+
Requires-Dist: pydantic>=2.0.0
|
|
17
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
18
|
+
Requires-Dist: pyyaml>=6.0
|
|
19
|
+
Requires-Dist: segment-analytics-python>=2.2.0
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest-asyncio<1.0.0,>=0.24.0; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest<9.0.0,>=8.3.3; extra == 'dev'
|
|
23
|
+
Requires-Dist: ruff==0.7.3; extra == 'dev'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# Airbyte Agent MCP Server
|
|
27
|
+
|
|
28
|
+
MCP server that exposes the Airbyte Connector SDK as Model Context Protocol tools.
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
- **Execute**: Run operations on any connector (primary tool)
|
|
33
|
+
- **List Entities**: Discover available entities in a connector
|
|
34
|
+
- **Describe Entity**: Get detailed schema for an entity
|
|
35
|
+
- **Validate Operation**: Check parameters before execution
|
|
36
|
+
|
|
37
|
+
## Configuration
|
|
38
|
+
|
|
39
|
+
### 1. Create configured_connectors.yaml
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
# Connector definitions
|
|
43
|
+
connectors:
|
|
44
|
+
# Load connector from the Airbyte registry (recommended)
|
|
45
|
+
- id: stripe
|
|
46
|
+
type: local
|
|
47
|
+
connector_name: stripe
|
|
48
|
+
description: "My Stripe API connector"
|
|
49
|
+
secrets:
|
|
50
|
+
token: STRIPE_API_KEY
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
You can pin to a specific version from the registry:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
connectors:
|
|
57
|
+
- id: stripe
|
|
58
|
+
type: local
|
|
59
|
+
connector_name: stripe
|
|
60
|
+
version: 0.1.0
|
|
61
|
+
description: "Stripe connector pinned to v0.1.0"
|
|
62
|
+
secrets:
|
|
63
|
+
token: STRIPE_API_KEY
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
You can also load connectors from a local file path (version pinning not supported):
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
connectors:
|
|
70
|
+
- id: my_api
|
|
71
|
+
type: local
|
|
72
|
+
path: ./connectors/my-api/connector.yaml
|
|
73
|
+
description: "My custom API connector"
|
|
74
|
+
secrets:
|
|
75
|
+
token: MY_API_KEY
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
See `configured_connectors.yaml.example` for more examples.
|
|
79
|
+
|
|
80
|
+
### 2. Create .env file
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
STRIPE_API_KEY=sk_test_your_stripe_api_key_here
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Running
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
uv run airbyte_agent_mcp
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The server also takes in args for specific paths to the configured_connectors.yaml file and the env file. With custom paths:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
python -m airbyte_agent_mcp path/to/configured_connectors.yaml path/to/.env
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The default paths are `./configured_connectors.yaml` and `./.env`
|
|
99
|
+
|
|
100
|
+
## Usage with Claude Code
|
|
101
|
+
|
|
102
|
+
Add to `~/.claude.json`:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
"mcpServers": {
|
|
106
|
+
"airbyte-agent-mcp": {
|
|
107
|
+
"type": "stdio",
|
|
108
|
+
"command": "uv",
|
|
109
|
+
"args": [
|
|
110
|
+
"--directory",
|
|
111
|
+
"/path/to/sonar/airbyte-agent-mcp",
|
|
112
|
+
"run",
|
|
113
|
+
"airbyte_agent_mcp"
|
|
114
|
+
],
|
|
115
|
+
"env": {}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Development / Testing
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Install dev dependencies
|
|
124
|
+
uv sync --all-extras
|
|
125
|
+
|
|
126
|
+
# Run tests
|
|
127
|
+
uv run pytest
|
|
128
|
+
|
|
129
|
+
# Format code
|
|
130
|
+
uv run ruff format .
|
|
131
|
+
|
|
132
|
+
# Lint code
|
|
133
|
+
uv run ruff check .
|
|
134
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
airbyte_agent_mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
airbyte_agent_mcp/__main__.py,sha256=Ty8kXk2remMz6FFOnXTl5mg9mvOzI2JYYlu75z8hGXI,541
|
|
3
|
+
airbyte_agent_mcp/config.py,sha256=Z3NeYC8Xi69M4J4ZbOaUhB-CSu9QuxNBuQZ87Ce5R9A,3172
|
|
4
|
+
airbyte_agent_mcp/connector_manager.py,sha256=FLkN2AfBS6YDckokyPGwhcL_TwSIl-a93xN1o5Jv6oI,12931
|
|
5
|
+
airbyte_agent_mcp/models.py,sha256=yTA9Syu_RVQbZT8CisIfSBpL0Iee4-qEmXQWxYgFjLg,5001
|
|
6
|
+
airbyte_agent_mcp/registry_client.py,sha256=_boYT9ZzY8pAsb7LHTgOz7IHfhrbqKRQ_n-cTPDh4dE,3278
|
|
7
|
+
airbyte_agent_mcp/secret_manager.py,sha256=BeDWcYX4d_SxtCBdNoaYarV39qCJBbZcqJcy3LUumDE,2600
|
|
8
|
+
airbyte_agent_mcp/server.py,sha256=iYE4UJuSkaDgh5ph4cxFPVJ3mfgfB0_wq12uNDLB81w,8290
|
|
9
|
+
airbyte_agent_mcp/_vendored/__init__.py,sha256=ILl7AHXMui__swyrjxrh9yRa4dLiwBvV6axPWFWty80,38
|
|
10
|
+
airbyte_agent_mcp/_vendored/connector_sdk/__init__.py,sha256=T5o7roU6NSpH-lCAGZ338sE5dlh4ZU6i6IkeG1zpems,1949
|
|
11
|
+
airbyte_agent_mcp/_vendored/connector_sdk/auth_strategies.py,sha256=0BfIISVzuvZTAYZjQFOOhKTpw0QuKDlLQBQ1PQo-V2M,39967
|
|
12
|
+
airbyte_agent_mcp/_vendored/connector_sdk/auth_template.py,sha256=vKnyA21Jp33EuDjkIUAf1PGicwk4t9kZAPJuAgAZKzU,4458
|
|
13
|
+
airbyte_agent_mcp/_vendored/connector_sdk/connector_model_loader.py,sha256=OEaXMI8lhjH-vAPfgaefrSijZJfttNqC6Ee3u2apYnA,33901
|
|
14
|
+
airbyte_agent_mcp/_vendored/connector_sdk/constants.py,sha256=uH4rjBX6WsBP8M0jt7AUJI9w5Adn4wvJwib7Gdfkr1M,2736
|
|
15
|
+
airbyte_agent_mcp/_vendored/connector_sdk/exceptions.py,sha256=ss5MGv9eVPmsbLcLWetuu3sDmvturwfo6Pw3M37Oq5k,481
|
|
16
|
+
airbyte_agent_mcp/_vendored/connector_sdk/extensions.py,sha256=iWA2i0kiiGZY84H8P25A6QmfbuZwu7euMcj4-Vx2DOQ,20185
|
|
17
|
+
airbyte_agent_mcp/_vendored/connector_sdk/http_client.py,sha256=Uv86Hye3uIs2F4TbXXFWnB4E6BHfvJQLBwak7J1_0kw,27073
|
|
18
|
+
airbyte_agent_mcp/_vendored/connector_sdk/secrets.py,sha256=UWcO9fP-vZwcfkAuvlZahlOCTOwdNN860BIwe8X4jxw,6868
|
|
19
|
+
airbyte_agent_mcp/_vendored/connector_sdk/types.py,sha256=1yz4O8wjL5Aytzz0duluxJZ7ntEFIBlA4_6XSAlizpE,8079
|
|
20
|
+
airbyte_agent_mcp/_vendored/connector_sdk/utils.py,sha256=G4LUXOC2HzPoND2v4tQW68R9uuPX9NQyCjaGxb7Kpl0,1958
|
|
21
|
+
airbyte_agent_mcp/_vendored/connector_sdk/validation.py,sha256=CDjCux1eg35a0Y4BegSivzIwZjiTqOxYWotWNLqTSVU,31792
|
|
22
|
+
airbyte_agent_mcp/_vendored/connector_sdk/executor/__init__.py,sha256=EmG9YQNAjSuYCVB4D5VoLm4qpD1KfeiiOf7bpALj8p8,702
|
|
23
|
+
airbyte_agent_mcp/_vendored/connector_sdk/executor/hosted_executor.py,sha256=FXlV4JgYbYMHVHMbeMH8LOdhsXuw-flEJjHXf7JmMtc,6756
|
|
24
|
+
airbyte_agent_mcp/_vendored/connector_sdk/executor/local_executor.py,sha256=hHlBTtvykrUcfypzyW0e61fU4e3vlxc90mypCFzgSl0,61879
|
|
25
|
+
airbyte_agent_mcp/_vendored/connector_sdk/executor/models.py,sha256=lYVT_bNcw-PoIks4WHNyl2VY-lJVf2FntzINSOBIheE,5845
|
|
26
|
+
airbyte_agent_mcp/_vendored/connector_sdk/http/__init__.py,sha256=y8fbzZn-3yV9OxtYz8Dy6FFGI5v6TOqADd1G3xHH3Hw,911
|
|
27
|
+
airbyte_agent_mcp/_vendored/connector_sdk/http/config.py,sha256=6J7YIIwHC6sRu9i-yKa5XvArwK2KU60rlnmxzDZq3lw,3283
|
|
28
|
+
airbyte_agent_mcp/_vendored/connector_sdk/http/exceptions.py,sha256=eYdYmxqcwA6pgrSoRXNfR6_nRBGRH6upp2-r1jcKaZo,3586
|
|
29
|
+
airbyte_agent_mcp/_vendored/connector_sdk/http/protocols.py,sha256=eV7NbBIQOcPLw-iu8mtkV2zCVgScDwP0ek1SbPNQo0g,3323
|
|
30
|
+
airbyte_agent_mcp/_vendored/connector_sdk/http/response.py,sha256=r7QFYRkw6is-Na7WozAyzZynpCQ90RBUhnX4pBSJ1Yc,3338
|
|
31
|
+
airbyte_agent_mcp/_vendored/connector_sdk/http/adapters/__init__.py,sha256=gjbWdU4LfzUG2PETI0TkfkukdzoCAhpL6FZtIEnkO-s,209
|
|
32
|
+
airbyte_agent_mcp/_vendored/connector_sdk/http/adapters/httpx_adapter.py,sha256=dkYhzBWiKBmzWZlc-cRTx50Hb6fy3OI8kOQvXRfS1CQ,8465
|
|
33
|
+
airbyte_agent_mcp/_vendored/connector_sdk/logging/__init__.py,sha256=IZoE5yXhwSA0m3xQqh0FiCifjp1sB3S8jnnFPuJLYf8,227
|
|
34
|
+
airbyte_agent_mcp/_vendored/connector_sdk/logging/logger.py,sha256=Nh0h3C0aO-rAqZhDIyeEXG6Jd7yj1Gk32ECMPth0wl8,8118
|
|
35
|
+
airbyte_agent_mcp/_vendored/connector_sdk/logging/types.py,sha256=iI-xLoOg33OUGQOp3CeaxKtHh73WXE-oul6ZCNf3Nzc,3209
|
|
36
|
+
airbyte_agent_mcp/_vendored/connector_sdk/observability/__init__.py,sha256=ojx1n9vaWCXFFvb3-90Pwtg845trFdV2v6wcCoO75Ko,269
|
|
37
|
+
airbyte_agent_mcp/_vendored/connector_sdk/observability/models.py,sha256=rF6-SoAAywqL8bhEv7yCbmr_W_w0vmApO-MCxcHq9RI,473
|
|
38
|
+
airbyte_agent_mcp/_vendored/connector_sdk/observability/redactor.py,sha256=HRbSwGxsfQYbYlG4QBVvv8Qnw0d4SMowMv0dTFHsHqQ,2361
|
|
39
|
+
airbyte_agent_mcp/_vendored/connector_sdk/observability/session.py,sha256=fLBgb9olATdoC0IMtd8MKe581t1HuK73MiGbghPzUHQ,3083
|
|
40
|
+
airbyte_agent_mcp/_vendored/connector_sdk/performance/__init__.py,sha256=Sp5fSd1LvtIQkv-fnrKqPsM7-6IWp0sSZSK0mhzal_A,200
|
|
41
|
+
airbyte_agent_mcp/_vendored/connector_sdk/performance/instrumentation.py,sha256=_dXvNiqdndIBwDjeDKNViWzn_M5FkSUsMmJtFldrmsM,1504
|
|
42
|
+
airbyte_agent_mcp/_vendored/connector_sdk/performance/metrics.py,sha256=3-wPwlJyfVLUIG3y7ESxk0avhkILk3z8K7zSrnlZf5U,2833
|
|
43
|
+
airbyte_agent_mcp/_vendored/connector_sdk/schema/__init__.py,sha256=Uymu-QuzGJuMxexBagIvUxpVAigIuIhz3KeBl_Vu4Ko,1638
|
|
44
|
+
airbyte_agent_mcp/_vendored/connector_sdk/schema/base.py,sha256=le4UqbUrPFtWxIwmoTAyS0chYFO5ksEMYDyrkK5ORlI,4776
|
|
45
|
+
airbyte_agent_mcp/_vendored/connector_sdk/schema/components.py,sha256=2ivMNhUAcovw88qvDkW221ILf1L63eXteztTDZL46us,7989
|
|
46
|
+
airbyte_agent_mcp/_vendored/connector_sdk/schema/connector.py,sha256=VFBOzIkLgYBR1XUTmyrPGqBkX8PP-zsG8avQcdJUqXs,3864
|
|
47
|
+
airbyte_agent_mcp/_vendored/connector_sdk/schema/extensions.py,sha256=LdoCuMLNdCj68O47qAL4v8xmqGz5tJgRiNZL5JnL9uw,3311
|
|
48
|
+
airbyte_agent_mcp/_vendored/connector_sdk/schema/operations.py,sha256=zInMjx9iOEVZo-CCWw06Uk2SFg7HtUAXXpO5kFGUwNk,5825
|
|
49
|
+
airbyte_agent_mcp/_vendored/connector_sdk/schema/security.py,sha256=Jtrhb58d1zssN5yR7LhLJi-QK0PsZKT7uIvPqanF0co,8114
|
|
50
|
+
airbyte_agent_mcp/_vendored/connector_sdk/telemetry/__init__.py,sha256=RaLgkBU4dfxn1LC5Y0Q9rr2PJbrwjxvPgBLmq8_WafE,211
|
|
51
|
+
airbyte_agent_mcp/_vendored/connector_sdk/telemetry/config.py,sha256=tLmQwAFD0kP1WyBGWBS3ysaudN9H3e-3EopKZi6cGKg,885
|
|
52
|
+
airbyte_agent_mcp/_vendored/connector_sdk/telemetry/events.py,sha256=NvqjlUbkm6cbGh4ffKxYxtjdwwgzfPF4MKJ2GfgWeFg,1285
|
|
53
|
+
airbyte_agent_mcp/_vendored/connector_sdk/telemetry/tracker.py,sha256=KacNdbHatvPPhnNrycp5YUuD5xpkp56AFcHd-zguBgk,5247
|
|
54
|
+
airbyte_agent_mcp-0.1.30.dist-info/METADATA,sha256=s8S_NKeiCnFDPz5m-BExQbyapXVoEQzuxEBlGhWMA5o,3009
|
|
55
|
+
airbyte_agent_mcp-0.1.30.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
56
|
+
airbyte_agent_mcp-0.1.30.dist-info/RECORD,,
|