amazon-ads-mcp 0.2.7__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.
Files changed (82) hide show
  1. amazon_ads_mcp/__init__.py +11 -0
  2. amazon_ads_mcp/auth/__init__.py +33 -0
  3. amazon_ads_mcp/auth/base.py +211 -0
  4. amazon_ads_mcp/auth/hooks.py +172 -0
  5. amazon_ads_mcp/auth/manager.py +791 -0
  6. amazon_ads_mcp/auth/oauth_state_store.py +277 -0
  7. amazon_ads_mcp/auth/providers/__init__.py +14 -0
  8. amazon_ads_mcp/auth/providers/direct.py +393 -0
  9. amazon_ads_mcp/auth/providers/example_auth0.py.example +216 -0
  10. amazon_ads_mcp/auth/providers/openbridge.py +512 -0
  11. amazon_ads_mcp/auth/registry.py +146 -0
  12. amazon_ads_mcp/auth/secure_token_store.py +297 -0
  13. amazon_ads_mcp/auth/token_store.py +723 -0
  14. amazon_ads_mcp/config/__init__.py +5 -0
  15. amazon_ads_mcp/config/sampling.py +111 -0
  16. amazon_ads_mcp/config/settings.py +366 -0
  17. amazon_ads_mcp/exceptions.py +314 -0
  18. amazon_ads_mcp/middleware/__init__.py +11 -0
  19. amazon_ads_mcp/middleware/authentication.py +1474 -0
  20. amazon_ads_mcp/middleware/caching.py +177 -0
  21. amazon_ads_mcp/middleware/oauth.py +175 -0
  22. amazon_ads_mcp/middleware/sampling.py +112 -0
  23. amazon_ads_mcp/models/__init__.py +320 -0
  24. amazon_ads_mcp/models/amc_models.py +837 -0
  25. amazon_ads_mcp/models/api_responses.py +847 -0
  26. amazon_ads_mcp/models/base_models.py +215 -0
  27. amazon_ads_mcp/models/builtin_responses.py +496 -0
  28. amazon_ads_mcp/models/dsp_models.py +556 -0
  29. amazon_ads_mcp/models/stores_brands.py +610 -0
  30. amazon_ads_mcp/server/__init__.py +6 -0
  31. amazon_ads_mcp/server/__main__.py +6 -0
  32. amazon_ads_mcp/server/builtin_prompts.py +269 -0
  33. amazon_ads_mcp/server/builtin_tools.py +962 -0
  34. amazon_ads_mcp/server/file_routes.py +547 -0
  35. amazon_ads_mcp/server/html_templates.py +149 -0
  36. amazon_ads_mcp/server/mcp_server.py +327 -0
  37. amazon_ads_mcp/server/openapi_utils.py +158 -0
  38. amazon_ads_mcp/server/sampling_handler.py +251 -0
  39. amazon_ads_mcp/server/server_builder.py +751 -0
  40. amazon_ads_mcp/server/sidecar_loader.py +178 -0
  41. amazon_ads_mcp/server/transform_executor.py +827 -0
  42. amazon_ads_mcp/tools/__init__.py +22 -0
  43. amazon_ads_mcp/tools/cache_management.py +105 -0
  44. amazon_ads_mcp/tools/download_tools.py +267 -0
  45. amazon_ads_mcp/tools/identity.py +236 -0
  46. amazon_ads_mcp/tools/oauth.py +598 -0
  47. amazon_ads_mcp/tools/profile.py +150 -0
  48. amazon_ads_mcp/tools/profile_listing.py +285 -0
  49. amazon_ads_mcp/tools/region.py +320 -0
  50. amazon_ads_mcp/tools/region_identity.py +175 -0
  51. amazon_ads_mcp/utils/__init__.py +6 -0
  52. amazon_ads_mcp/utils/async_compat.py +215 -0
  53. amazon_ads_mcp/utils/errors.py +452 -0
  54. amazon_ads_mcp/utils/export_content_type_resolver.py +249 -0
  55. amazon_ads_mcp/utils/export_download_handler.py +579 -0
  56. amazon_ads_mcp/utils/header_resolver.py +81 -0
  57. amazon_ads_mcp/utils/http/__init__.py +56 -0
  58. amazon_ads_mcp/utils/http/circuit_breaker.py +127 -0
  59. amazon_ads_mcp/utils/http/client_manager.py +329 -0
  60. amazon_ads_mcp/utils/http/request.py +207 -0
  61. amazon_ads_mcp/utils/http/resilience.py +512 -0
  62. amazon_ads_mcp/utils/http/resilient_client.py +195 -0
  63. amazon_ads_mcp/utils/http/retry.py +76 -0
  64. amazon_ads_mcp/utils/http_client.py +873 -0
  65. amazon_ads_mcp/utils/media/__init__.py +21 -0
  66. amazon_ads_mcp/utils/media/negotiator.py +243 -0
  67. amazon_ads_mcp/utils/media/types.py +199 -0
  68. amazon_ads_mcp/utils/openapi/__init__.py +16 -0
  69. amazon_ads_mcp/utils/openapi/json.py +55 -0
  70. amazon_ads_mcp/utils/openapi/loader.py +263 -0
  71. amazon_ads_mcp/utils/openapi/refs.py +46 -0
  72. amazon_ads_mcp/utils/region_config.py +200 -0
  73. amazon_ads_mcp/utils/response_wrapper.py +171 -0
  74. amazon_ads_mcp/utils/sampling_helpers.py +156 -0
  75. amazon_ads_mcp/utils/sampling_wrapper.py +173 -0
  76. amazon_ads_mcp/utils/security.py +630 -0
  77. amazon_ads_mcp/utils/tool_naming.py +137 -0
  78. amazon_ads_mcp-0.2.7.dist-info/METADATA +664 -0
  79. amazon_ads_mcp-0.2.7.dist-info/RECORD +82 -0
  80. amazon_ads_mcp-0.2.7.dist-info/WHEEL +4 -0
  81. amazon_ads_mcp-0.2.7.dist-info/entry_points.txt +3 -0
  82. amazon_ads_mcp-0.2.7.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,314 @@
1
+ """Structured exception classes for Amazon Ads MCP."""
2
+
3
+ import json
4
+ from typing import Any, Dict, Optional
5
+
6
+
7
+ class AmazonAdsMCPError(Exception):
8
+ """Base exception for all Amazon Ads MCP errors.
9
+
10
+ This exception serves as the parent class for all Amazon Ads MCP
11
+ specific exceptions, providing a consistent interface for error
12
+ handling across the application.
13
+
14
+ :param message: Human-readable error message
15
+ :param code: Optional error code for programmatic handling
16
+ :param details: Optional dictionary containing additional error context
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ message: str,
22
+ code: Optional[str] = None,
23
+ details: Optional[Dict[str, Any]] = None,
24
+ ):
25
+ """Initialize the exception with message, code, and details."""
26
+ super().__init__(message)
27
+ self.message = message
28
+ self.code = code or self.__class__.__name__
29
+ self.details = details or {}
30
+
31
+ def to_dict(self) -> Dict[str, Any]:
32
+ """Convert exception to dictionary format.
33
+
34
+ :return: Dictionary containing error code, message, and details
35
+ """
36
+ return {
37
+ "error": self.code,
38
+ "message": self.message,
39
+ "details": self.details,
40
+ }
41
+
42
+ def to_json(self) -> str:
43
+ """Convert exception to JSON string.
44
+
45
+ :return: JSON-encoded string representation of the exception
46
+ """
47
+ return json.dumps(self.to_dict())
48
+
49
+
50
+ class AuthenticationError(AmazonAdsMCPError):
51
+ """Raised when authentication fails.
52
+
53
+ This exception is raised when authentication operations fail,
54
+ including token validation, credential verification, and
55
+ provider initialization errors.
56
+
57
+ :param message: Description of the authentication failure
58
+ :param details: Optional additional context about the failure
59
+ """
60
+
61
+ def __init__(self, message: str, details: Optional[Dict[str, Any]] = None):
62
+ """Initialize authentication error with message and optional details."""
63
+ super().__init__(message=message, code="AUTHENTICATION_ERROR", details=details)
64
+
65
+
66
+ class OAuthError(AuthenticationError):
67
+ """Raised for OAuth-specific errors.
68
+
69
+ This exception is raised when OAuth-related operations fail,
70
+ such as authorization code exchange, token refresh, or
71
+ OAuth flow validation.
72
+
73
+ :param message: Description of the OAuth error
74
+ :param error_code: Optional OAuth error code from the provider
75
+ """
76
+
77
+ def __init__(self, message: str, error_code: Optional[str] = None):
78
+ """Initialize OAuth error with message and optional error code."""
79
+ details = {}
80
+ if error_code:
81
+ details["oauth_error"] = error_code
82
+ super().__init__(message=message, details=details)
83
+ self.code = "OAUTH_ERROR"
84
+
85
+
86
+ class OAuthStateError(OAuthError):
87
+ """Raised when OAuth state validation fails.
88
+
89
+ This exception is raised when the OAuth state parameter
90
+ validation fails during the authorization flow, indicating
91
+ a potential security issue or tampering.
92
+
93
+ :param message: Description of the state validation failure
94
+ """
95
+
96
+ def __init__(self, message: str):
97
+ """Initialize OAuth state error with message."""
98
+ super().__init__(message)
99
+ self.code = "OAUTH_STATE_ERROR"
100
+
101
+
102
+ class TokenError(AuthenticationError):
103
+ """Raised for token-related errors.
104
+
105
+ This exception is raised when token operations fail,
106
+ including token validation, refresh, or parsing errors.
107
+
108
+ :param message: Description of the token error
109
+ :param token_type: Optional type of token that caused the error
110
+ """
111
+
112
+ def __init__(self, message: str, token_type: Optional[str] = None):
113
+ """Initialize token error with message and optional token type."""
114
+ details = {}
115
+ if token_type:
116
+ details["token_type"] = token_type
117
+ super().__init__(message=message, details=details)
118
+ self.code = "TOKEN_ERROR"
119
+
120
+
121
+ class APIError(AmazonAdsMCPError):
122
+ """Raised for API-related errors.
123
+
124
+ This exception is raised when Amazon Ads API operations fail,
125
+ including HTTP errors, invalid responses, and API-specific
126
+ error conditions.
127
+
128
+ :param message: Description of the API error
129
+ :param status_code: Optional HTTP status code from the API response
130
+ :param response_body: Optional response body from the failed request
131
+ """
132
+
133
+ def __init__(
134
+ self,
135
+ message: str,
136
+ status_code: Optional[int] = None,
137
+ response_body: Optional[str] = None,
138
+ ):
139
+ """Initialize API error with message and optional response details."""
140
+ details: Dict[str, Any] = {}
141
+ if status_code:
142
+ details["status_code"] = status_code
143
+ if response_body:
144
+ details["response_body"] = response_body
145
+ super().__init__(message=message, code="API_ERROR", details=details)
146
+ self.status_code = status_code
147
+ self.response_body = response_body
148
+
149
+
150
+ class TimeoutError(APIError):
151
+ """Raised when an API request times out.
152
+
153
+ This exception is raised when an API request exceeds the
154
+ configured timeout duration, indicating network or server
155
+ performance issues.
156
+
157
+ :param message: Description of the timeout error
158
+ :param operation: Optional name of the operation that timed out
159
+ """
160
+
161
+ def __init__(self, message: str, operation: Optional[str] = None):
162
+ """Initialize timeout error with message and optional operation."""
163
+ details = {}
164
+ if operation:
165
+ details["operation"] = operation
166
+ super().__init__(message=message, status_code=None, response_body=None)
167
+ self.code = "TIMEOUT_ERROR"
168
+ self.details.update(details)
169
+
170
+
171
+ class RateLimitError(APIError):
172
+ """Raised when API rate limits are exceeded.
173
+
174
+ This exception is raised when API requests exceed the
175
+ configured rate limits, requiring backoff or retry logic.
176
+
177
+ :param message: Description of the rate limit error
178
+ :param retry_after: Optional seconds to wait before retrying
179
+ :param limit: Optional rate limit that was exceeded
180
+ """
181
+
182
+ def __init__(
183
+ self,
184
+ message: str,
185
+ retry_after: Optional[int] = None,
186
+ limit: Optional[int] = None,
187
+ ):
188
+ """Initialize rate limit error with message and optional limits."""
189
+ details = {}
190
+ if retry_after:
191
+ details["retry_after"] = retry_after
192
+ if limit:
193
+ details["limit"] = limit
194
+ super().__init__(message=message, status_code=429, response_body=None)
195
+ self.code = "RATE_LIMIT_ERROR"
196
+ self.details.update(details)
197
+
198
+
199
+ class ConfigurationError(AmazonAdsMCPError):
200
+ """Raised for configuration-related errors.
201
+
202
+ This exception is raised when configuration validation fails
203
+ or when required configuration settings are missing or invalid.
204
+
205
+ :param message: Description of the configuration error
206
+ :param setting: Optional name of the problematic setting
207
+ """
208
+
209
+ def __init__(self, message: str, setting: Optional[str] = None):
210
+ """Initialize configuration error with message and optional setting."""
211
+ details = {}
212
+ if setting:
213
+ details["setting"] = setting
214
+ super().__init__(message=message, code="CONFIGURATION_ERROR", details=details)
215
+
216
+
217
+ class ToolExecutionError(AmazonAdsMCPError):
218
+ """Raised when tool execution fails.
219
+
220
+ This exception is raised when MCP tool execution fails,
221
+ wrapping the original error with additional context.
222
+
223
+ :param message: Description of the tool execution error
224
+ :param tool_name: Optional name of the tool that failed
225
+ :param original_error: Optional original exception that caused the failure
226
+ """
227
+
228
+ def __init__(
229
+ self,
230
+ message: str,
231
+ tool_name: Optional[str] = None,
232
+ original_error: Optional[Exception] = None,
233
+ ):
234
+ """Initialize tool execution error with message and optional context."""
235
+ details = {}
236
+ if tool_name:
237
+ details["tool"] = tool_name
238
+ if original_error:
239
+ details["original_error"] = str(original_error)
240
+ details["error_type"] = type(original_error).__name__
241
+ super().__init__(message=message, code="TOOL_EXECUTION_ERROR", details=details)
242
+ self.tool_name = tool_name
243
+ self.original_error = original_error
244
+
245
+
246
+ class SamplingError(AmazonAdsMCPError):
247
+ """Raised when sampling operations fail.
248
+
249
+ This exception is raised when data sampling operations fail,
250
+ such as when sampling configuration is invalid or when
251
+ sampling cannot be performed on the requested data.
252
+
253
+ :param message: Description of the sampling error
254
+ :param fallback_available: Whether a fallback sampling method is available
255
+ """
256
+
257
+ def __init__(self, message: str, fallback_available: bool = False):
258
+ """Initialize sampling error with message and fallback availability."""
259
+ details = {"fallback_available": fallback_available}
260
+ super().__init__(message=message, code="SAMPLING_ERROR", details=details)
261
+
262
+
263
+ class TransformError(AmazonAdsMCPError):
264
+ """Raised when data transformation fails.
265
+
266
+ This exception is raised when data transformation operations
267
+ fail, such as when transforming API responses or converting
268
+ data between different formats.
269
+
270
+ :param message: Description of the transformation error
271
+ :param transform_type: Optional type of transformation that failed
272
+ :param data_path: Optional path to the data that caused the error
273
+ """
274
+
275
+ def __init__(
276
+ self,
277
+ message: str,
278
+ transform_type: Optional[str] = None,
279
+ data_path: Optional[str] = None,
280
+ ):
281
+ """Initialize transform error with message and optional context."""
282
+ details = {}
283
+ if transform_type:
284
+ details["transform_type"] = transform_type
285
+ if data_path:
286
+ details["data_path"] = data_path
287
+ super().__init__(message=message, code="TRANSFORM_ERROR", details=details)
288
+
289
+
290
+ class ValidationError(AmazonAdsMCPError):
291
+ """Raised when validation fails.
292
+
293
+ This exception is raised when data validation fails,
294
+ such as when input parameters don't meet required
295
+ constraints or when data format validation fails.
296
+
297
+ :param message: Description of the validation error
298
+ :param field: Optional name of the field that failed validation
299
+ :param value: Optional value that caused the validation failure
300
+ """
301
+
302
+ def __init__(
303
+ self,
304
+ message: str,
305
+ field: Optional[str] = None,
306
+ value: Optional[Any] = None,
307
+ ):
308
+ """Initialize validation error with message and optional field/value."""
309
+ details = {}
310
+ if field:
311
+ details["field"] = field
312
+ if value is not None:
313
+ details["value"] = str(value)
314
+ super().__init__(message=message, code="VALIDATION_ERROR", details=details)
@@ -0,0 +1,11 @@
1
+ """Middleware module for Amazon Ads MCP.
2
+
3
+ This module provides middleware components for the Amazon Ads MCP
4
+ server, including authentication middleware and request/response
5
+ processing.
6
+
7
+ The module provides:
8
+ - Authentication middleware for request processing
9
+ - Request/response transformation
10
+ - Error handling and validation
11
+ """