Repository navigation
fix(billing-cost-management-mcp-server)!: request COH savings percentage, coerce boolean filters, fold summaries group_by - #4906
Open
finklen-amazon wants to merge 7 commits into
Conversation
finklen-amazon
requested review from
a team,
Comusus,
Rahul-1404,
anniewn,
bhatia-di,
callnmm,
chittev,
johnwangwyx,
junaidgirkar,
mattkelsey,
shsrams,
somsubhro,
wangyuhere and
yasmeenh11
as code owners
October 28, 2026 01:36
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4906 +/- ##
=======================================
Coverage 93.79% 93.79%
=======================================
Files 1080 1080
Lines 94586 94599 +13
Branches 15402 15404 +2
=======================================
+ Hits 88715 88728 +13
Misses 3498 3498
Partials 2373 2373 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
finklen-amazon
commented
Oct 28, 2026
finklen-amazon
force-pushed
the
fix/bcm-coh-summary-filters
branch
from
October 29, 2026 16:39
ddcefdf to
45a52eb
Compare
yasmeenh11
previously approved these changes
Oct 29, 2026
…age, coerce boolean filters, fold summaries group_by
- list_recommendation_summaries now sends metrics=['SavingsPercentage'].
Without it the service returns the placeholder "Percentage not
requested." in metrics.savingsPercentage, which the tool passed through
as a metric. A percentage value ('12%', '>=80%', '<=2%') is returned as
metrics.savings_percentage; any other text the service puts in that
field (before-discounts mode, unsupported filter, not calculable) is
returned as metrics.savings_percentage_unavailable_reason. A metrics
block without a string value gives no metrics key.
- restartNeeded / rollbackPossible filters given as "true"/"false"
strings are coerced to booleans instead of failing botocore parameter
validation.
- Summaries group_by fixed dimensions match case- and
underscore-insensitively (resource_type -> ResourceType), like filter
keys. The missing-group_by error lists the same values as the
invalid-group_by error, including TagKey:<tag key>. The unreachable
'RESOURCE_TYPE' fallback is removed.
- The description documents the savings percentage and its limits, the
resourceIds / resourceArns / recommendationIds filters (list only;
summaries reject them), that there is no
per-service resource type filter, and that summary fields are the same
on every page, including continuation calls (it said they were not
repeated).
No tool parameter is added, renamed, retyped or given a new default.
BREAKING CHANGE: cost-optimization list_recommendation_summaries no
longer returns the service's explanation text in
metrics.savings_percentage. When no percentage is computed,
metrics.savings_percentage is absent and the text is in
metrics.savings_percentage_unavailable_reason. Before this change the
field always held the "Percentage not requested." placeholder.
… excludes credits and refunds The service computes metrics.savingsPercentage against the last 30 days' net amortized cost with the Credit and Refund record types filtered out. Say so in the cost-optimization description and the CHANGELOG entry, so a caller comparing it to Cost Explorer's net amortized cost with no record-type filter knows why the figures differ. Also say that total_recommendation_count is not one of the summary fields repeated on every page, and drop the CHANGELOG clause about documenting the ID filters, which main already covers.
finklen-amazon
force-pushed
the
fix/bcm-coh-summary-filters
branch
from
October 30, 2026 01:47
45a52eb to
dd1f2c5
Compare
finklen-amazon
enabled auto-merge
October 30, 2026 17:30
wangyuhere
previously approved these changes
Oct 30, 2026
yasmeenh11
previously approved these changes
Oct 30, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Oct 30, 2026
finklen-amazon
enabled auto-merge
October 30, 2026 20:27
… case-insensitively only Fold only letter case in list_recommendation_summaries group_by, not underscores, so the legacy upper-snake spelling RESOURCE_TYPE (and resource_type) is rejected locally as an invalid dimension instead of being sent as ResourceType. resourcetype and ACCOUNTID still resolve. The description, the CHANGELOG entry and the tests say the same.
…len-amazon/mcp into fix/bcm-coh-summary-filters
finklen-amazon
dismissed stale reviews from yasmeenh11 and wangyuhere
via
October 30, 2026 20:36
594a769
scottschreckengaust
removed this pull request from the merge queue due to a manual request
Oct 30, 2026
wangyuhere
previously approved these changes
Oct 30, 2026
Open
4 of 6 tasks
# Conflicts: # src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/cost_optimization_hub_helpers.py # src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/cost_optimization_hub_tools.py # src/billing-cost-management-mcp-server/tests/tools/test_cost_optimization_hub_tools.py
wangyuhere
approved these changes
Oct 31, 2026
4 of 6 tasks
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.
Fixes
Summary
Changes
Savings percentage (
list_recommendation_summaries). The tool never sentmetrics, so the service always answeredmetrics.savingsPercentagewith the placeholder"Percentage not requested.", and the tool returned that string asmetrics.savings_percentage. The request now sendsmetrics=['SavingsPercentage']. A percentage value ('12%', or the clamped'>=80%'/'<=2%') is returned asmetrics.savings_percentage. When the service does not compute it, it puts an explanation in the same field; that text is now returned asmetrics.savings_percentage_unavailable_reason. The service gives an explanation in three cases: savings estimation mode BeforeDiscounts, a filter other thanaccountIds,regionsandtags, or a failed calculation. The description says what the value is: estimated deduplicated monthly savings as a percent of the last 30 days' net amortized cost, excluding credits and refunds (the service filters out the Credit and Refund record types), for the whole filtered result, not per group.Boolean filters.
restartNeeded/rollbackPossiblegiven as"true"/"false"strings failed botocore parameter validation. They are now coerced to booleans. Other values pass through unchanged.Summaries
group_by. Fixed dimensions now match case-insensitively (resourcetype->ResourceType). Underscores are not ignored, so the legacyRESOURCE_TYPEspelling is still rejected. The missing-group_byerror now lists the same values as the invalid-group_byerror, includingTagKey:<tag key>. The unreachable'RESOURCE_TYPE'fallback is removed.Filter docs.
DatabaseSavingsPlanssupport (folding andvalid_filter_values) now comes from main (#4948). The description now also covers three more things:resourceIds,resourceArnsandrecommendationIdsfilters are listed with the other filter parameters aslist_recommendationsonly (summaries reject them locally, since feat(billing-cost-management-mcp-server): add COH summaries total cou… #4934).No tool parameter is added, renamed, retyped or given a new default.
User experience
Before:
"metrics": {"savings_percentage": "Percentage not requested."}on every summaries call.filters='{"restartNeeded": "true"}'gave a parameter validation error.group_by='resourcetype'gave a validation error.After:
"metrics": {"savings_percentage": "12%"}, or{"savings_percentage_unavailable_reason": "<service text>"}when the service does not compute a percentage.group_by='resourcetype'is sent asResourceType;RESOURCE_TYPEis still rejected locally.Testing
Run from
src/billing-cost-management-mcp-server:uv run --frozen pytest: 3515 passed (after the latest rebase onto main); patch coverage 21/21 added executable lines.ruff format --check,ruff checkandpyrighton the changed files: clean.The new tests failed before the fix (16 failures) and pass after.
Live check (read-only): a harness started the server over stdio and read the description as served. It then made 4
list_recommendation_summariescalls and 2list_recommendationscalls (max_items=1).actionTypesfilter returns the service's incompatible-filter reason, not a metric;group_by='resourcetype'is accepted (an earlier revision folded underscores too; it now ignores letter case only);resourceIds;restartNeeded: "false"is accepted;DatabaseSavingsPlansis accepted as a filter value.resourceIdscheck expects the tool's localvalidation_error. On current main, the description checks pass 1/13.Merge conflict
After #4945 and #4946 merged, this branch conflicted with main in
cost_optimization_hub_helpers.py,cost_optimization_hub_tools.pyandtests/tools/test_cost_optimization_hub_tools.py. I merged main in (a merge commit, no rebase) and resolved it:ResourceType)".effective_group_by: both sides removed the legacy'RESOURCE_TYPE'fallback; kept a single copy.RESOURCE_TYPEcase. Dropped main's lowercaseresourcetypereject line, because this PR matches fixedgroup_bydimensions case-insensitively (underscores are not ignored, soRESOURCE_TYPEandresource_typestay rejected).After the merge: 4271 tests pass, ruff and pyright are clean, and the description checks pass 14/14.
Checklist
If your change doesn't seem to apply, please leave them unchecked.
Is this a breaking change? (Y/N) Y. When no percentage is computed,
metrics.savings_percentageis now absent and the service's text is inmetrics.savings_percentage_unavailable_reason. Before this change the field always held the"Percentage not requested."placeholder, never a percentage. This is recorded in CHANGELOG.md.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.