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,215 @@
1
+ """Shared Pydantic models for the Amazon Ads MCP project.
2
+
3
+ This module contains all the data models used throughout the Amazon Ads MCP
4
+ server, including authentication tokens, identity management, API responses,
5
+ and OpenBridge integration models.
6
+
7
+ The models provide type safety and validation for:
8
+ - Authentication and token management
9
+ - Identity and profile management
10
+ - API request/response handling
11
+ - OpenBridge integration
12
+ """
13
+
14
+ from datetime import datetime
15
+ from typing import Any, Dict, List, Optional
16
+
17
+ from pydantic import BaseModel, Field
18
+
19
+
20
+ # Auth Models
21
+ class Token(BaseModel):
22
+ """Authentication token model for Amazon Ads API access.
23
+
24
+ Represents an OAuth2 access token with expiration and metadata.
25
+ Used for authenticating requests to the Amazon Advertising API.
26
+
27
+ :param value: The actual token string value
28
+ :type value: str
29
+ :param expires_at: When the token expires
30
+ :type expires_at: datetime
31
+ :param token_type: Type of token (default: "Bearer")
32
+ :type token_type: str
33
+ :param scope: Optional scope string for the token
34
+ :type scope: Optional[str]
35
+ :param metadata: Additional token metadata
36
+ :type metadata: Dict[str, Any]
37
+ """
38
+
39
+ value: str
40
+ expires_at: datetime
41
+ token_type: str = "Bearer"
42
+ scope: Optional[str] = None
43
+ metadata: Dict[str, Any] = Field(default_factory=dict)
44
+
45
+
46
+ class Identity(BaseModel):
47
+ """Simplified identity model - passthrough from Openbridge.
48
+
49
+ Represents a remote identity from OpenBridge with all
50
+ attributes and relationships preserved.
51
+
52
+ :param id: Unique identifier for the identity
53
+ :type id: str
54
+ :param type: Type of identity (default: "RemoteIdentity")
55
+ :type type: str
56
+ :param attributes: All attributes from Openbridge
57
+ :type attributes: Dict[str, Any]
58
+ :param relationships: All relationships from Openbridge
59
+ :type relationships: Optional[Dict[str, Any]]
60
+ """
61
+
62
+ id: str
63
+ type: str = "RemoteIdentity"
64
+ attributes: Dict[str, Any]
65
+ relationships: Optional[Dict[str, Any]] = None
66
+
67
+
68
+ class AuthCredentials(BaseModel):
69
+ """Credentials for API access.
70
+
71
+ Contains all necessary authentication information for making
72
+ authenticated requests to the Amazon Advertising API.
73
+
74
+ :param identity_id: ID of the identity these credentials belong to
75
+ :type identity_id: str
76
+ :param access_token: OAuth2 access token for API authentication
77
+ :type access_token: str
78
+ :param token_type: Type of token (default: "Bearer")
79
+ :type token_type: str
80
+ :param expires_at: When the access token expires
81
+ :type expires_at: datetime
82
+ :param base_url: Base URL for API requests (default: Amazon API URL)
83
+ :type base_url: str
84
+ :param headers: Additional headers to include in requests
85
+ :type headers: Dict[str, str]
86
+ """
87
+
88
+ identity_id: str
89
+ access_token: str
90
+ token_type: str = "Bearer"
91
+ expires_at: datetime
92
+ base_url: str = "https://advertising-api.amazon.com"
93
+ headers: Dict[str, str] = Field(default_factory=dict)
94
+
95
+
96
+ # API Models
97
+ class AccountInfo(BaseModel):
98
+ """Account information model.
99
+
100
+ Represents account information returned by the Amazon Advertising API.
101
+ Contains marketplace details and account status information.
102
+
103
+ :param marketplace_string_id: Marketplace identifier string
104
+ :type marketplace_string_id: str
105
+ :param id: Account ID
106
+ :type id: str
107
+ :param type: Type of account
108
+ :type type: str
109
+ :param name: Account name
110
+ :type name: str
111
+ :param valid_payment_method: Whether account has valid payment method
112
+ :type valid_payment_method: Optional[bool]
113
+ """
114
+
115
+ marketplace_string_id: str = Field(alias="marketplaceStringId")
116
+ id: str
117
+ type: str
118
+ name: str
119
+ valid_payment_method: Optional[bool] = Field(
120
+ alias="validPaymentMethod", default=None
121
+ )
122
+
123
+
124
+ class Profile(BaseModel):
125
+ """Amazon Ads Profile model.
126
+
127
+ Represents an Amazon Advertising profile with location, currency,
128
+ and budget information. Profiles are used to organize campaigns
129
+ and manage advertising accounts.
130
+
131
+ :param profile_id: Unique profile identifier
132
+ :type profile_id: int
133
+ :param country_code: ISO country code for the profile
134
+ :type country_code: str
135
+ :param currency_code: ISO currency code for the profile
136
+ :type currency_code: str
137
+ :param timezone: Timezone for the profile
138
+ :type timezone: str
139
+ :param daily_budget: Optional daily budget limit
140
+ :type daily_budget: Optional[float]
141
+ :param account_info: Associated account information
142
+ :type account_info: AccountInfo
143
+ """
144
+
145
+ profile_id: int = Field(alias="profileId")
146
+ country_code: str = Field(alias="countryCode")
147
+ currency_code: str = Field(alias="currencyCode")
148
+ timezone: str
149
+ daily_budget: Optional[float] = Field(alias="dailyBudget", default=None)
150
+ account_info: AccountInfo = Field(alias="accountInfo")
151
+
152
+ model_config = {"populate_by_name": True}
153
+
154
+
155
+ # Request/Response Models
156
+ class IdentityListResponse(BaseModel):
157
+ """Response model for identity list.
158
+
159
+ Represents a paginated response containing a list of available
160
+ identities that can be used for Amazon Ads API access.
161
+
162
+ :param identities: List of available identities
163
+ :type identities: List[Identity]
164
+ :param total: Total number of identities available
165
+ :type total: int
166
+ :param has_more: Whether there are more identities to fetch
167
+ :type has_more: bool
168
+ """
169
+
170
+ identities: List[Identity]
171
+ total: int
172
+ has_more: bool = False
173
+
174
+
175
+ class SetActiveIdentityRequest(BaseModel):
176
+ """Request model for setting active identity.
177
+
178
+ Used when requesting to set a specific identity as the active
179
+ identity for Amazon Ads API operations.
180
+
181
+ :param identity_id: ID of the identity to activate
182
+ :type identity_id: str
183
+ :param persist: Whether to persist this choice across sessions
184
+ :type persist: bool
185
+ """
186
+
187
+ identity_id: str
188
+ persist: bool = False
189
+
190
+
191
+ class SetActiveIdentityResponse(BaseModel):
192
+ """Response model for setting active identity.
193
+
194
+ Response indicating the result of setting an identity as active,
195
+ including whether credentials were successfully loaded.
196
+
197
+ :param success: Whether the operation was successful
198
+ :type success: bool
199
+ :param identity: The identity that was set as active
200
+ :type identity: Identity
201
+ :param credentials_loaded: Whether credentials were loaded for identity
202
+ :type credentials_loaded: bool
203
+ :param message: Optional message about the operation result
204
+ :type message: Optional[str]
205
+ """
206
+
207
+ success: bool
208
+ identity: Identity
209
+ credentials_loaded: bool = False
210
+ message: Optional[str] = None
211
+
212
+
213
+ # OpenBridge API Models
214
+ # OpenbridgeIdentity is now just an alias for Identity since we're passing through
215
+ OpenbridgeIdentity = Identity
@@ -0,0 +1,496 @@
1
+ """Response models for builtin MCP tools.
2
+
3
+ This module defines structured Pydantic response models for all builtin tools
4
+ in the Amazon Ads MCP server. These models enable:
5
+ - Client-side validation of tool responses
6
+ - IDE autocompletion and type hints
7
+ - Automatic JSON schema generation for MCP clients
8
+ - Self-documenting API responses
9
+
10
+ All models inherit from BaseModel with consistent patterns:
11
+ - `success: bool` field for operation status
12
+ - Optional `message: str` for human-readable feedback
13
+ - Typed fields for all response data
14
+ """
15
+
16
+ from typing import Any, Dict, List, Literal, Optional
17
+
18
+ from pydantic import BaseModel, Field
19
+
20
+
21
+ # ============================================================================
22
+ # Region Tool Responses
23
+ # ============================================================================
24
+
25
+
26
+ class RegionInfo(BaseModel):
27
+ """Information about a single Amazon Ads region.
28
+
29
+ :param name: Human-readable region name
30
+ :param api_endpoint: API endpoint URL for this region
31
+ :param oauth_endpoint: OAuth token endpoint URL
32
+ :param marketplaces: List of marketplace codes in this region
33
+ :param sandbox: Whether this is a sandbox endpoint
34
+ """
35
+
36
+ name: str
37
+ api_endpoint: str
38
+ oauth_endpoint: str
39
+ marketplaces: List[str]
40
+ sandbox: bool = False
41
+
42
+
43
+ class SetRegionResponse(BaseModel):
44
+ """Response from set_region tool.
45
+
46
+ :param success: Whether the operation succeeded
47
+ :param previous_region: Region before the change
48
+ :param new_region: Region after the change
49
+ :param region_name: Human-readable name of new region
50
+ :param api_endpoint: API endpoint URL for new region
51
+ :param oauth_endpoint: OAuth endpoint URL (if available)
52
+ :param message: Human-readable status message
53
+ :param error: Error code if operation failed
54
+ :param identity: Identity name if region is identity-controlled
55
+ """
56
+
57
+ success: bool
58
+ previous_region: Optional[str] = None
59
+ new_region: Optional[str] = None
60
+ region_name: Optional[str] = None
61
+ api_endpoint: Optional[str] = None
62
+ oauth_endpoint: Optional[str] = None
63
+ message: Optional[str] = None
64
+ error: Optional[str] = None
65
+ identity: Optional[str] = None
66
+ current_identity: Optional[str] = None
67
+ identity_region: Optional[str] = None
68
+ requested_region: Optional[str] = None
69
+ region: Optional[str] = None
70
+
71
+
72
+ class GetRegionResponse(BaseModel):
73
+ """Response from get_region tool.
74
+
75
+ :param success: Whether the operation succeeded
76
+ :param region: Current region code (na/eu/fe)
77
+ :param region_name: Human-readable region name
78
+ :param api_endpoint: API endpoint URL
79
+ :param oauth_endpoint: OAuth endpoint URL (if using direct auth)
80
+ :param sandbox_mode: Whether sandbox mode is enabled
81
+ :param auth_method: Authentication method (direct/openbridge)
82
+ :param source: Where region setting comes from (identity/config)
83
+ :param identity_region: Region from active identity (if applicable)
84
+ """
85
+
86
+ success: bool
87
+ region: str
88
+ region_name: str
89
+ api_endpoint: str
90
+ oauth_endpoint: Optional[str] = None
91
+ sandbox_mode: bool = False
92
+ auth_method: Literal["direct", "openbridge"] = "openbridge"
93
+ source: Literal["identity", "config"] = "config"
94
+ identity_region: Optional[str] = None
95
+
96
+
97
+ class ListRegionsResponse(BaseModel):
98
+ """Response from list_regions tool.
99
+
100
+ :param success: Whether the operation succeeded
101
+ :param current_region: Currently active region code
102
+ :param sandbox_mode: Whether sandbox mode is enabled
103
+ :param regions: Map of region code to region info
104
+ """
105
+
106
+ success: bool
107
+ current_region: str
108
+ sandbox_mode: bool = False
109
+ regions: Dict[str, RegionInfo]
110
+
111
+
112
+ # ============================================================================
113
+ # Profile Tool Responses
114
+ # ============================================================================
115
+
116
+
117
+ class SetProfileResponse(BaseModel):
118
+ """Response from set_active_profile tool.
119
+
120
+ :param success: Whether the operation succeeded
121
+ :param profile_id: The profile ID that was set
122
+ :param message: Human-readable status message
123
+ """
124
+
125
+ success: bool
126
+ profile_id: str
127
+ message: str
128
+
129
+
130
+ class GetProfileResponse(BaseModel):
131
+ """Response from get_active_profile tool.
132
+
133
+ :param success: Whether the operation succeeded
134
+ :param profile_id: Current active profile ID (None if not set)
135
+ :param source: Where profile setting comes from (explicit/environment/default)
136
+ :param message: Human-readable status message (when no profile set)
137
+ """
138
+
139
+ success: bool
140
+ profile_id: Optional[str] = None
141
+ source: Optional[str] = None
142
+ message: Optional[str] = None
143
+
144
+
145
+ class ClearProfileResponse(BaseModel):
146
+ """Response from clear_active_profile tool.
147
+
148
+ :param success: Whether the operation succeeded
149
+ :param message: Human-readable status message
150
+ :param fallback_profile_id: Profile ID that will be used after clearing
151
+ """
152
+
153
+ success: bool
154
+ message: str
155
+ fallback_profile_id: Optional[str] = None
156
+
157
+
158
+ # ============================================================================
159
+ # Identity Tool Responses
160
+ # ============================================================================
161
+
162
+
163
+ class GetActiveIdentityResponse(BaseModel):
164
+ """Response from get_active_identity tool.
165
+
166
+ :param success: Whether the operation succeeded
167
+ :param identity: Active identity details (None if not set)
168
+ :param message: Human-readable status message
169
+ """
170
+
171
+ success: bool
172
+ identity: Optional[Dict[str, Any]] = None
173
+ message: Optional[str] = None
174
+
175
+
176
+ class ProfileSelectorResponse(BaseModel):
177
+ """Response from select_profile interactive tool.
178
+
179
+ :param success: Whether the operation succeeded
180
+ :param action: User action (accept/decline/cancel)
181
+ :param profile_id: Selected profile ID (if accepted)
182
+ :param profile_name: Selected profile name/description (if accepted)
183
+ :param message: Human-readable status message
184
+ """
185
+
186
+ success: bool
187
+ action: Literal["accept", "decline", "cancel"]
188
+ profile_id: Optional[str] = None
189
+ profile_name: Optional[str] = None
190
+ message: str
191
+
192
+
193
+ # ============================================================================
194
+ # Profile Listing Tool Responses
195
+ # ============================================================================
196
+
197
+
198
+ class ProfileListItem(BaseModel):
199
+ """Normalized profile list item used by wrapper tools.
200
+
201
+ :param profile_id: Amazon Ads profile ID
202
+ :param name: Account name or advertiser name
203
+ :param country_code: Marketplace country code
204
+ :param type: Account type (seller/vendor/agency)
205
+ """
206
+
207
+ profile_id: str
208
+ name: str
209
+ country_code: str
210
+ type: str
211
+
212
+
213
+ class ProfileSummaryResponse(BaseModel):
214
+ """Response from summarize_profiles tool.
215
+
216
+ :param total_count: Total profiles available
217
+ :param by_country: Counts by country code
218
+ :param by_type: Counts by account type
219
+ :param message: Optional guidance or status message
220
+ :param stale: Whether cached data was used after a refresh failure
221
+ """
222
+
223
+ total_count: int
224
+ by_country: Dict[str, int]
225
+ by_type: Dict[str, int]
226
+ message: Optional[str] = None
227
+ stale: bool = False
228
+
229
+
230
+ class ProfileSearchResponse(BaseModel):
231
+ """Response from search_profiles tool.
232
+
233
+ :param items: Matching profile items
234
+ :param total_count: Total matches available
235
+ :param returned_count: Number of items returned
236
+ :param has_more: Whether more matches are available
237
+ :param message: Optional guidance or status message
238
+ :param stale: Whether cached data was used after a refresh failure
239
+ """
240
+
241
+ items: List[ProfileListItem]
242
+ total_count: int
243
+ returned_count: int
244
+ has_more: bool
245
+ message: Optional[str] = None
246
+ stale: bool = False
247
+
248
+
249
+ class ProfilePageResponse(BaseModel):
250
+ """Response from page_profiles tool.
251
+
252
+ :param items: Page of profile items
253
+ :param total_count: Total profiles available for this filter
254
+ :param returned_count: Number of items returned
255
+ :param has_more: Whether more items are available
256
+ :param next_offset: Offset for the next page (if available)
257
+ :param message: Optional guidance or status message
258
+ :param stale: Whether cached data was used after a refresh failure
259
+ """
260
+
261
+ items: List[ProfileListItem]
262
+ total_count: int
263
+ returned_count: int
264
+ has_more: bool
265
+ next_offset: Optional[int] = None
266
+ message: Optional[str] = None
267
+ stale: bool = False
268
+
269
+
270
+ class ProfileCacheRefreshResponse(BaseModel):
271
+ """Response from refresh_profiles_cache tool.
272
+
273
+ :param success: Whether the refresh succeeded
274
+ :param total_count: Total profiles cached
275
+ :param cache_timestamp: Timestamp of the cached data (epoch seconds)
276
+ :param stale: Whether cached data was returned after refresh failure
277
+ :param message: Optional guidance or status message
278
+ """
279
+
280
+ success: bool
281
+ total_count: int
282
+ cache_timestamp: Optional[float] = None
283
+ stale: bool = False
284
+ message: Optional[str] = None
285
+
286
+
287
+ # ============================================================================
288
+ # Download Tool Responses
289
+ # ============================================================================
290
+
291
+
292
+ class DownloadExportResponse(BaseModel):
293
+ """Response from download_export tool.
294
+
295
+ :param success: Whether the download succeeded
296
+ :param file_path: Local path where file was saved
297
+ :param export_type: Type of export (campaigns/adgroups/ads/targets/general)
298
+ :param message: Human-readable status message
299
+ """
300
+
301
+ success: bool
302
+ file_path: str
303
+ export_type: str
304
+ message: str
305
+
306
+
307
+ class DownloadedFile(BaseModel):
308
+ """Information about a downloaded file.
309
+
310
+ :param filename: Name of the file
311
+ :param path: Full path to the file
312
+ :param size: File size in bytes
313
+ :param modified: Last modified timestamp
314
+ :param resource_type: Type of resource (report/export/etc)
315
+ """
316
+
317
+ filename: str
318
+ path: str
319
+ size: int
320
+ modified: str
321
+ resource_type: Optional[str] = None
322
+
323
+
324
+ class ListDownloadsResponse(BaseModel):
325
+ """Response from list_downloads tool.
326
+
327
+ :param success: Whether the operation succeeded
328
+ :param files: List of downloaded files
329
+ :param count: Total number of files
330
+ :param download_dir: Directory where downloads are stored
331
+ """
332
+
333
+ success: bool
334
+ files: List[DownloadedFile]
335
+ count: int
336
+ download_dir: str
337
+
338
+
339
+ class GetDownloadUrlResponse(BaseModel):
340
+ """Response from get_download_url tool.
341
+
342
+ :param success: Whether the URL was generated successfully
343
+ :param download_url: HTTP URL to download the file
344
+ :param file_name: Name of the file
345
+ :param size_bytes: File size in bytes
346
+ :param profile_id: Profile ID the file belongs to
347
+ :param instructions: Instructions for using the download URL
348
+ :param error: Error message if failed
349
+ :param hint: Helpful hint for resolving issues
350
+ """
351
+
352
+ success: bool
353
+ download_url: Optional[str] = None
354
+ file_name: Optional[str] = None
355
+ size_bytes: Optional[int] = None
356
+ profile_id: Optional[str] = None
357
+ instructions: Optional[str] = None
358
+ error: Optional[str] = None
359
+ hint: Optional[str] = None
360
+
361
+
362
+ # ============================================================================
363
+ # Reporting Tool Responses
364
+ # ============================================================================
365
+
366
+
367
+ class AsyncReportResponse(BaseModel):
368
+ """Response from request_async_report tool.
369
+
370
+ :param success: Whether the report was generated successfully
371
+ :param report_id: Amazon Ads report ID
372
+ :param report_type: Type of report requested
373
+ :param file_path: Local path where report was saved (if successful)
374
+ :param status: Final report status
375
+ :param error: Error message if operation failed
376
+ :param download_url: Report download URL (if available but download failed)
377
+ :param message: Human-readable status message
378
+ """
379
+
380
+ success: bool
381
+ report_id: Optional[str] = None
382
+ report_type: Optional[str] = None
383
+ file_path: Optional[str] = None
384
+ status: Optional[str] = None
385
+ error: Optional[str] = None
386
+ download_url: Optional[str] = None
387
+ message: Optional[str] = None
388
+
389
+
390
+ # ============================================================================
391
+ # OAuth Tool Responses
392
+ # ============================================================================
393
+
394
+
395
+ class OAuthFlowResponse(BaseModel):
396
+ """Response from start_oauth_flow tool.
397
+
398
+ :param success: Whether the flow started successfully
399
+ :param authorization_url: URL to redirect user for authorization
400
+ :param state: OAuth state parameter for CSRF protection
401
+ :param message: Human-readable status message
402
+ """
403
+
404
+ success: bool
405
+ authorization_url: Optional[str] = None
406
+ state: Optional[str] = None
407
+ message: Optional[str] = None
408
+
409
+
410
+ class OAuthStatusResponse(BaseModel):
411
+ """Response from check_oauth_status tool.
412
+
413
+ :param success: Whether the check succeeded
414
+ :param authenticated: Whether user is authenticated
415
+ :param token_valid: Whether current token is valid
416
+ :param expires_at: Token expiration timestamp
417
+ :param scopes: Granted OAuth scopes
418
+ :param message: Human-readable status message
419
+ """
420
+
421
+ success: bool
422
+ authenticated: bool = False
423
+ token_valid: bool = False
424
+ expires_at: Optional[str] = None
425
+ scopes: Optional[List[str]] = None
426
+ message: Optional[str] = None
427
+
428
+
429
+ class OAuthRefreshResponse(BaseModel):
430
+ """Response from refresh_oauth_token tool.
431
+
432
+ :param success: Whether the refresh succeeded
433
+ :param message: Human-readable status message
434
+ :param expires_at: New token expiration timestamp
435
+ """
436
+
437
+ success: bool
438
+ message: str
439
+ expires_at: Optional[str] = None
440
+
441
+
442
+ class OAuthClearResponse(BaseModel):
443
+ """Response from clear_oauth_tokens tool.
444
+
445
+ :param success: Whether the clear succeeded
446
+ :param message: Human-readable status message
447
+ """
448
+
449
+ success: bool
450
+ message: str
451
+
452
+
453
+ # ============================================================================
454
+ # Routing State Response
455
+ # ============================================================================
456
+
457
+
458
+ class RoutingStateResponse(BaseModel):
459
+ """Response from get_routing_state tool.
460
+
461
+ :param region: Current region code
462
+ :param host: API host URL
463
+ :param headers: Current routing headers
464
+ :param sandbox: Whether sandbox mode is enabled
465
+ """
466
+
467
+ region: str
468
+ host: str
469
+ headers: Dict[str, str] = Field(default_factory=dict)
470
+ sandbox: bool = False
471
+
472
+
473
+ # ============================================================================
474
+ # Sampling Tool Responses
475
+ # ============================================================================
476
+
477
+
478
+ class SamplingTestResponse(BaseModel):
479
+ """Response from test_sampling tool.
480
+
481
+ :param success: Whether sampling executed successfully
482
+ :param message: Human-readable status message
483
+ :param response: Response from the sampled model
484
+ :param sampling_enabled: Whether sampling is enabled in settings
485
+ :param used_fallback: Note about fallback usage
486
+ :param error: Error message if operation failed
487
+ :param note: Additional notes about configuration
488
+ """
489
+
490
+ success: bool
491
+ message: Optional[str] = None
492
+ response: Optional[str] = None
493
+ sampling_enabled: bool = False
494
+ used_fallback: Optional[str] = None
495
+ error: Optional[str] = None
496
+ note: Optional[str] = None