Skip to content

Commit 8abaec6

Browse files
fix(billing-cost-management-mcp-server): map each service's bad-token code to invalid_next_token (#4861)
* fix(billing-cost-management-mcp-server): map each service's bad-token code to invalid_next_token Only Cost Explorer, Budgets and the Price List API report a rejected pagination token as InvalidNextTokenException. The other paged services use a generic code: ValidationException (Billing views, billing preferences, credits, enterprise support, Invoicing, Billing Conductor, Cost Optimization Hub, Free Tier, Savings Plans, Pricing Calculator) or InvalidParameterValueException (Compute Optimizer Automation). A bogus or expired next_token on those tools came back as the generic code with the "correct your arguments" hint instead of invalid_next_token and the "restart without next_token" hint. Each of those operations' PageSpec now names its service's code in caller_token_error_codes, the mechanism Compute Optimizer and the Billing Group cost report already use. The code is read as a rejected token only when the caller sent next_token, on the first request; elsewhere it stays the service's own error. * fix(billing-cost-management-mcp-server): require a generic bad-token code to name the token A generic code such as ValidationException also reports other invalid arguments. With a caller next_token, a service can still reject another argument first (ListBillingViews checks arns before the token), and the helper reported that as invalid_next_token. A caller_token_error_codes code now counts as a rejected token only when the error message names the token. GetBillingGroupCostReport keeps code-only matching, because its expired-token InternalServerException need not name the token.
1 parent ddee1bc commit 8abaec6

15 files changed

Lines changed: 416 additions & 3 deletions

‎src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/bcm_pricing_calculator_tools.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
token_key_in_response='nextToken',
5050
page_max=25,
5151
page_size_param='maxResults',
52+
# The service reports a bad caller next_token as ValidationException.
53+
caller_token_error_codes=frozenset({'ValidationException'}),
5254
)
5355
# ListWorkloadEstimateUsage returns up to 300 usage lines per page.
5456
LIST_WORKLOAD_ESTIMATE_USAGE_PAGE_SPEC = PageSpec(
@@ -57,6 +59,8 @@
5759
token_key_in_response='nextToken',
5860
page_max=300,
5961
page_size_param='maxResults',
62+
# The service reports a bad caller next_token as ValidationException.
63+
caller_token_error_codes=frozenset({'ValidationException'}),
6064
)
6165
PREFERENCES_NOT_CONFIGURED_ERROR = 'BCM Pricing Calculator preferences are not configured. Please configure preferences before using this service.'
6266

‎src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/billing_conductor_operations.py‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ def _bc_page_spec(result_key: str) -> PageSpec:
5555
token_key_in_response='NextToken',
5656
page_max=100,
5757
page_size_param='MaxResults',
58+
# Billing Conductor reports a bad caller next_token as ValidationException.
59+
caller_token_error_codes=frozenset({'ValidationException'}),
5860
)
5961

6062

@@ -188,6 +190,8 @@ def _format_billing_groups(billing_groups: List[Dict[str, Any]]) -> List[Dict[st
188190
token_param='NextToken',
189191
token_key_in_response='NextToken',
190192
page_max=100,
193+
# The service reports a bad caller next_token as ValidationException.
194+
caller_token_error_codes=frozenset({'ValidationException'}),
191195
)
192196

193197

@@ -315,7 +319,8 @@ async def list_billing_group_cost_reports(
315319
# A changed parameter or a malformed token fails with ValidationException, and an expired token
316320
# can fail with ValidationException or InternalServerException. Either code on a call that
317321
# carried a next_token means that token is unusable, so the helper maps it to
318-
# invalid_next_token only then.
322+
# invalid_next_token only then. The expired-token InternalServerException need not name the
323+
# token, so this spec does not require the message to.
319324
BC_GET_BILLING_GROUP_COST_REPORT = PageSpec(
320325
result_key='BillingGroupCostReportResults',
321326
token_param='NextToken',
@@ -324,6 +329,7 @@ async def list_billing_group_cost_reports(
324329
page_size_param='MaxResults',
325330
page_min=200,
326331
caller_token_error_codes=frozenset({'ValidationException', 'InternalServerException'}),
332+
caller_token_message_required=False,
327333
)
328334

329335

‎src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/billing_preferences_operations.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ def _create_billing_client() -> Any:
5454
token_key_in_response='nextToken',
5555
page_max=50,
5656
page_size_param='maxResults',
57+
# The service reports a bad caller next_token as ValidationException.
58+
caller_token_error_codes=frozenset({'ValidationException'}),
5759
)
5860

5961

‎src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/bvs_operations.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ async def get_billing_view(
9494
token_key_in_response='nextToken',
9595
page_max=100,
9696
page_size_param='maxResults',
97+
# The service reports a bad caller next_token as ValidationException.
98+
caller_token_error_codes=frozenset({'ValidationException'}),
9799
)
98100

99101

@@ -144,6 +146,8 @@ async def list_source_views_for_billing_view(
144146
token_key_in_response='nextToken',
145147
page_max=100,
146148
page_size_param='maxResults',
149+
# The service reports a bad caller next_token as ValidationException.
150+
caller_token_error_codes=frozenset({'ValidationException'}),
147151
)
148152

149153

@@ -295,6 +299,8 @@ async def get_resource_policy(
295299
token_key_in_response='nextToken',
296300
page_max=100,
297301
page_size_param='maxResults',
302+
# The service reports a bad caller next_token as ValidationException.
303+
caller_token_error_codes=frozenset({'ValidationException'}),
298304
)
299305

300306

‎src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/compute_optimizer_automation_operations.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,55 +381,71 @@ async def get_enrollment_configuration(
381381
token_key_in_response='nextToken',
382382
page_max=100,
383383
page_size_param='maxResults',
384+
# The service reports a bad caller next_token as InvalidParameterValueException.
385+
caller_token_error_codes=frozenset({'InvalidParameterValueException'}),
384386
)
385387
COA_LIST_AUTOMATION_EVENT_STEPS = PageSpec(
386388
result_key='automationEventSteps',
387389
token_param='nextToken',
388390
token_key_in_response='nextToken',
389391
page_max=100,
390392
page_size_param='maxResults',
393+
# The service reports a bad caller next_token as InvalidParameterValueException.
394+
caller_token_error_codes=frozenset({'InvalidParameterValueException'}),
391395
)
392396
COA_LIST_AUTOMATION_EVENT_SUMMARIES = PageSpec(
393397
result_key='automationEventSummaries',
394398
token_param='nextToken',
395399
token_key_in_response='nextToken',
396400
page_max=100,
397401
page_size_param='maxResults',
402+
# The service reports a bad caller next_token as InvalidParameterValueException.
403+
caller_token_error_codes=frozenset({'InvalidParameterValueException'}),
398404
)
399405
COA_LIST_AUTOMATION_RULES = PageSpec(
400406
result_key='automationRules',
401407
token_param='nextToken',
402408
token_key_in_response='nextToken',
403409
page_max=100,
404410
page_size_param='maxResults',
411+
# The service reports a bad caller next_token as InvalidParameterValueException.
412+
caller_token_error_codes=frozenset({'InvalidParameterValueException'}),
405413
)
406414
COA_LIST_RECOMMENDED_ACTIONS = PageSpec(
407415
result_key='recommendedActions',
408416
token_param='nextToken',
409417
token_key_in_response='nextToken',
410418
page_max=100,
411419
page_size_param='maxResults',
420+
# The service reports a bad caller next_token as InvalidParameterValueException.
421+
caller_token_error_codes=frozenset({'InvalidParameterValueException'}),
412422
)
413423
COA_LIST_RECOMMENDED_ACTION_SUMMARIES = PageSpec(
414424
result_key='recommendedActionSummaries',
415425
token_param='nextToken',
416426
token_key_in_response='nextToken',
417427
page_max=100,
418428
page_size_param='maxResults',
429+
# The service reports a bad caller next_token as InvalidParameterValueException.
430+
caller_token_error_codes=frozenset({'InvalidParameterValueException'}),
419431
)
420432
COA_LIST_AUTOMATION_RULE_PREVIEW = PageSpec(
421433
result_key='previewResults',
422434
token_param='nextToken',
423435
token_key_in_response='nextToken',
424436
page_max=100,
425437
page_size_param='maxResults',
438+
# The service reports a bad caller next_token as InvalidParameterValueException.
439+
caller_token_error_codes=frozenset({'InvalidParameterValueException'}),
426440
)
427441
COA_LIST_AUTOMATION_RULE_PREVIEW_SUMMARIES = PageSpec(
428442
result_key='previewResultSummaries',
429443
token_param='nextToken',
430444
token_key_in_response='nextToken',
431445
page_max=100,
432446
page_size_param='maxResults',
447+
# The service reports a bad caller next_token as InvalidParameterValueException.
448+
caller_token_error_codes=frozenset({'InvalidParameterValueException'}),
433449
)
434450

435451

‎src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/cost_optimization_hub_helpers.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,26 @@
5454
token_key_in_response='nextToken',
5555
page_max=1000,
5656
page_size_param='maxResults',
57+
# The service reports a bad caller next_token as ValidationException.
58+
caller_token_error_codes=frozenset({'ValidationException'}),
5759
)
5860
COH_LIST_RECOMMENDATION_SUMMARIES = PageSpec(
5961
result_key='items',
6062
token_param='nextToken',
6163
token_key_in_response='nextToken',
6264
page_max=1000,
6365
page_size_param='maxResults',
66+
# The service reports a bad caller next_token as ValidationException.
67+
caller_token_error_codes=frozenset({'ValidationException'}),
6468
)
6569
COH_LIST_EFFICIENCY_METRICS = PageSpec(
6670
result_key='efficiencyMetricsByGroup',
6771
token_param='nextToken',
6872
token_key_in_response='nextToken',
6973
page_max=1000,
7074
page_size_param='maxResults',
75+
# The service reports a bad caller next_token as ValidationException.
76+
caller_token_error_codes=frozenset({'ValidationException'}),
7177
)
7278
# Performance ranking's internal fetch: EFFICIENCY_PARETO_PAGE_SIZE groups per page, highest
7379
# spend first, up to EFFICIENCY_PARETO_MAX_PAGES pages (a cap of pages x page size groups).

‎src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/credits_operations.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@
6464
token_key_in_response='nextToken',
6565
page_max=500,
6666
page_size_param='maxResults',
67+
# The service reports a bad caller next_token as ValidationException.
68+
caller_token_error_codes=frozenset({'ValidationException'}),
6769
)
6870

6971
# IAM action required by each operation, used to build an actionable message

‎src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/enterprise_support_operations.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
token_key_in_response='nextToken',
5757
page_max=100,
5858
page_size_param='maxResults',
59+
# The service reports a bad caller next_token as ValidationException.
60+
caller_token_error_codes=frozenset({'ValidationException'}),
5961
)
6062

6163

‎src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/free_tier_usage_tools.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
token_key_in_response='nextToken',
3838
page_max=1000,
3939
page_size_param='maxResults',
40+
# The service reports a bad caller next_token as ValidationException.
41+
caller_token_error_codes=frozenset({'ValidationException'}),
4042
)
4143

4244
free_tier_usage_server = FastMCP(

‎src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/invoice_units_operations.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
token_key_in_response='NextToken',
4444
page_max=500,
4545
page_size_param='MaxResults',
46+
# The service reports a bad caller next_token as ValidationException.
47+
caller_token_error_codes=frozenset({'ValidationException'}),
4648
)
4749

4850

0 commit comments

Comments
 (0)