Skip to content

Commit 25bc2f5

Browse files
somsubhrosomsubhr
andauthored
docs(billing-cost-management-mcp-server): warn that summing Cost Opti… (#4946)
* docs(billing-cost-management-mcp-server): warn that summing Cost Optimization Hub savings double-counts The cost-optimization tool description said to focus on the highest estimated savings but never said that list_recommendations items overlap, so an agent that adds them up reports an inflated total. Commitment savings overlap with rightsizing and idle actions on the same usage, Auto Scaling groups overlap with their instances, Payer and Linked copies repeat, and include_all_recommendations returns one row per term, payment option and scope. Add a SAVINGS TOTALS block that points to estimated_total_deduped_savings from list_recommendation_summaries as the only de-duplicated total, and says it stays comparable only with no filter or with accountIds and regions filters. Filters on actionTypes, resourceTypes, implementationEfforts, restartNeeded and rollbackPossible change how overlap is netted out, so filtered totals do not sum to the portfolio total. Note the multi-row behavior in the include_all_recommendations argument text, and add a test for the new text. * docs(billing-cost-management-mcp-server): note summaries omit DatabaseSavingsPlans in savings totals guidance list_recommendation_summaries totals and groups do not include DatabaseSavingsPlans recommendations, while list_recommendations returns them. Tell the model to add their savings from the list to the summary total, so a reported portfolio total is not understated, and cover it in the description test. --------- Co-authored-by: Som Chatterjee🤖 <somsubhr@amazon.com>
1 parent 737ca13 commit 25bc2f5

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,22 @@ def _validate_order_by(
447447
key is case-sensitive; recommendations without the tag, or for a key that does not exist,
448448
are grouped under 'NoTagKey'.
449449
450+
SAVINGS TOTALS:
451+
- For a portfolio total, use list_recommendation_summaries estimated_total_deduped_savings
452+
with no filter, or with only accountIds and/or regions. Never add up list_recommendations
453+
estimated_monthly_savings: items overlap (commitment purchases and rightsizing or idle
454+
actions on the same usage, Auto Scaling groups and their instances, Payer and Linked copies).
455+
- Filters other than accountIds and regions (actionTypes, resourceTypes, implementationEfforts,
456+
restartNeeded, rollbackPossible) change how overlap is netted out, so a filtered total is
457+
not that slice's share of the portfolio total, and filtered totals do not sum to it.
458+
- list_recommendation_summaries totals and groups do not include DatabaseSavingsPlans
459+
recommendations. list_recommendations returns them, so add their estimated_monthly_savings
460+
to the summary total and say that the total was built that way.
461+
- Commitment (Savings Plans/Reserved Instance) savings assume current usage; implementing
462+
rightsizing or idle recommendations reduces them.
463+
- With include_all_recommendations=true, the same purchase appears once per term, payment
464+
option, and Payer/Linked scope, so a sum is inflated further.
465+
450466
CRITICAL PARAMETER REQUIREMENTS:
451467
- 'filters' parameter must be passed as JSON string format
452468
- 'max_items' must be integer (not string)
@@ -598,8 +614,9 @@ async def cost_optimization_hub(
598614
omitted (default): one deduplicated recommendation per resource, and
599615
one Savings Plans/Reserved Instances purchase option per covered usage,
600616
chosen first by the account's commitment preference; Cost Optimization Hub
601-
hides the alternatives. True: every recommendation,
602-
including alternatives whose savings must not be added together.
617+
hides the alternatives. True: every recommendation, including one row per
618+
term, payment option, and Payer/Linked scope for the same purchase, so do
619+
not sum their estimated_monthly_savings to get a total.
603620
next_token: Pagination token to resume from a previous response.
604621
Applies to list_recommendations, list_recommendation_summaries, and
605622
list_efficiency_metrics.

‎src/billing-cost-management-mcp-server/tests/tools/test_cost_optimization_hub_tools.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,28 @@ async def test_coh_validation_exception_adds_valid_filter_values(mock_context, o
18511851
assert 'Ec2Instance' in res['valid_filter_values']['resourceTypes']
18521852

18531853

1854+
@pytest.mark.asyncio
1855+
async def test_description_warns_that_summing_recommendation_savings_double_counts():
1856+
"""The description names the one de-duplicated total and the filters that change it."""
1857+
from awslabs.billing_cost_management_mcp_server.tools import (
1858+
cost_optimization_hub_tools as coh_mod,
1859+
)
1860+
1861+
# Other tests reload the module with an identity decorator, which leaves no tool registered.
1862+
importlib.reload(coh_mod)
1863+
tool = await coh_mod.cost_optimization_hub_server.get_tool('cost-optimization')
1864+
assert tool is not None
1865+
description = ' '.join((tool.description or '').split())
1866+
1867+
assert 'SAVINGS TOTALS:' in description
1868+
assert 'estimated_total_deduped_savings' in description
1869+
assert 'Never add up list_recommendations estimated_monthly_savings' in description
1870+
for filter_name in ('actionTypes', 'resourceTypes', 'implementationEfforts'):
1871+
assert filter_name in description.split('SAVINGS TOTALS:')[1].split('CRITICAL')[0]
1872+
assert 'include_all_recommendations=true' in description
1873+
assert 'do not include DatabaseSavingsPlans' in description
1874+
1875+
18541876
@pytest.mark.parametrize(
18551877
'filters,expected',
18561878
[

0 commit comments

Comments
 (0)