Repository navigation
fix(billing-cost-management-mcp-server): reject cost-explorer arguments an operation does not use - #4993
Open
finklen-amazon wants to merge 1 commit into
Open
fix(billing-cost-management-mcp-server): reject cost-explorer arguments an operation does not use#4993finklen-amazon wants to merge 1 commit into
finklen-amazon wants to merge 1 commit into
Conversation
…ts an operation does not use cost-explorer takes one argument list for all eight operations, and each handler sends only the arguments its API takes. Any other argument was dropped with no error, so an unnarrowed result came back as success and read as narrowed: search_string on getCostAndUsage, tag_key on getCostCategories, cost_category_name on getTagsOrValues, dimension and context outside getDimensionValues, max_items and next_token on the forecasts and getSavingsPlansUtilization, and metric on getCostAndUsage (which then used UnblendedCost). OPERATION_ARGUMENTS now lists the arguments each operation sends. Any other argument the caller sets returns a validation_error before the AWS client is created, and the message names, per argument, the operation or argument that does what the caller asked for. None, an empty string and empty JSON are not set. granularity and prediction_interval_level are not checked: an operation that does not list them has no periods or interval to misread, and callers commonly pass granularity to every operation. The table replaces OPERATIONS_WITHOUT_GROUP_BY and the getSavingsPlansUtilization billing_view_arn check. Behavior change: a call that passes such an argument, which used to succeed with it ignored, now fails with a validation_error naming it.
finklen-amazon
requested review from
a team,
Comusus,
Dinkie,
Rahul-1404,
anniewn,
bhatia-di,
callnmm,
chittev,
johnwangwyx,
junaidgirkar,
mattkelsey,
shsrams,
somsubhro,
wangyuhere and
yasmeenh11
as code owners
November 2, 2026 20:07
Comusus
approved these changes
Nov 2, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4993 +/- ##
=======================================
Coverage 93.79% 93.79%
=======================================
Files 1080 1080
Lines 94712 94734 +22
Branches 15442 15444 +2
=======================================
+ Hits 88833 88857 +24
Misses 3505 3505
+ Partials 2374 2372 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Changes
cost-explorertakes one argument list for all eight operations, but each handler sends only the arguments its API takes. Before this change, any other argument was dropped with no error. The result came back assuccessand read as if the argument had applied:search_stringon getCostAndUsage, getCostAndUsageWithResources, the forecasts and getSavingsPlansUtilizationtag_keyon getCostCategories, andcost_category_nameon getTagsOrValuesdimensionandcontextoutside getDimensionValuesmax_itemsandnext_tokenon the forecasts and getSavingsPlansUtilization (the description already said they "take neither")metricon getCostAndUsage, which then returned UnblendedCostWhat changes:
OPERATION_ARGUMENTSlists the arguments each operation sends.validation_errorbefore the AWS client is created.tag_keyon getCostCategories points to getTagsOrValues withtag_key, andmetricon getCostAndUsage points tometrics.hintis fixed text.None,'', and empty JSON forgroup_byormetrics([],null).granularityandprediction_interval_levelare not checked. An operation that does not list them has no periods or prediction interval to misread, and callers commonly passgranularityto every operation. The description says so.OPERATIONS_WITHOUT_GROUP_BYand the getSavingsPlansUtilizationbilling_view_arncheck. Both rejections stay, and the table makes them general.Interaction with #4990: that PR adds a
dimension_keyargument. The two merge without textual conflicts. Whichever merges second must adddimension_keyto the getDimensionValues entry inOPERATION_ARGUMENTS, plus a reason entry. Without that,dimension_keyis rejected everywhere.test_every_argument_the_operation_does_not_list_is_checkedandtest_documented_arguments_match_what_each_operation_acceptsfail until it is added. With it added (9 lines plus one test fixture line), the merged tree passes all cost-explorer tests.User experience
Before:
{"operation": "getCostCategories", "tag_key": "Environment"}returnedsuccesswith the cost category names, as if they were the values of theEnvironmenttag.{"operation": "getCostAndUsage", "metric": "AMORTIZED_COST"}returned UnblendedCost.After: both return
validation_error.tag_key is not supported for getCostCategories: it selects the tag key whose values getTagsOrValues lists. To list them, use operation=getTagsOrValues with tag_key; ...metric is not supported for getCostAndUsage: it is the single metric of getCostForecast and getUsageForecast. getCostAndUsage and getCostAndUsageWithResources take metrics instead (e.g. ["AmortizedCost"]).Testing
cost_explorer_tools.py. 129 new or rewritten tests cover:mainsource, 62 of the 129 fail and 67 pass as regression guards.next_tokenandmax_itemson getSavingsPlansUtilization now asserts the rejection instead.main: 5/15. The 10 that fail are this change's claims: each rejected case returnedsuccessonmainwith the argument ignored. The 5 that pass are controls:search_string,tag_keyandcost_category_namestill narrow where they apply, an empty argument is not rejected, andgranularitystays unchecked.metricsmessage gives a separate example for each forecast.Checklist
Is this a breaking change? (Y/N) N. Calls that pass an argument the operation does not use, and that used to succeed with the argument ignored, now return a
validation_errornaming it, the same waygroup_byis already rejected on those operations.RFC issue number:
Checklist:
Acknowledgment
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the project license.