You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 9a53397
Browse filesBrowse the repository at this point in the historyBrowse files
fix(billing-cost-management-mcp-server): name INSTANCE_TYPE_FAMILY for SP coverage, document SP filters, add sort_by (#4901)
* fix(billing-cost-management-mcp-server): name INSTANCE_TYPE_FAMILY for SP coverage, document SP filters, add sort_by
The sp-performance description told callers to use INSTANCE_FAMILY for
GetSavingsPlansCoverage group_by and filter. The service rejects that key;
it accepts INSTANCE_TYPE_FAMILY, the same key the utilization operations use.
Name INSTANCE_TYPE_FAMILY everywhere and drop the note contrasting the two.
Also document what the description left out:
- get_savings_plans_utilization filter dimensions, and that only Dimensions,
And and Not are allowed (Or, Tags and CostCategories are rejected). The
filter text no longer says "And/Or", since Or is not accepted.
- SAVINGS_PLANS_TYPE is not a coverage dimension.
- The exact PAYMENT_OPTION and SAVINGS_PLANS_TYPE value spellings; any other
spelling returns a DataUnavailableException with no service message rather
than a ValidationException, so check the spelling before moving the window.
Add an optional sort_by (JSON string, passed through as SortBy) for coverage
and utilization details, with each operation's sort keys. The API sorts
before paging, so sort_by plus max_items gives a top N. Utilization ignores
it: sorting there reorders the time periods out of date order.
* fix(billing-cost-management-mcp-server): list all SP utilization details filters; note coverage sort needs group_by
get_savings_plans_utilization_details also filters on SAVINGS_PLANS_TYPE and
on the plan end-date bounds AGREEMENT_END_DATE_TIME_AFTER and
AGREEMENT_END_DATE_TIME_BEFORE (YYYY-MM-DD). The description listed only five
dimensions and scoped SAVINGS_PLANS_TYPE to utilization, steering callers
away from a filter details accepts.
Sorting coverage by InstanceFamily, Region or Service needs that dimension
in group_by; otherwise the API returns "SortKey=[Region] should be in
groupBy list to provide sorting". Say so next to the coverage sort keys.
* docs(billing-cost-management-mcp-server): say sp-performance sorts before max_items
State the order of operations for sort_by and max_items: the API sorts
every matching item by the key first and then pages, and max_items=N keeps
the first N of that order. sort_by plus max_items=N is therefore the top N
by the key, not N arbitrary items sorted afterwards. Checked live: with
group_by INSTANCE_TYPE_FAMILY and sort_by OnDemandCost DESCENDING,
max_items=3 returned exactly the first 3 groups of the full sorted list,
while the same request without sort_by returned a different 3.
Copy file name to clipboardExpand all lines: src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/sp_performance_tools.py
+62-12Lines changed: 62 additions & 12 deletions
Original file line number
Diff line number
Diff line change
@@ -51,11 +51,12 @@
51
51
3. get_savings_plans_utilization_details: Shows detailed per-Savings Plan utilization
52
52
53
53
COVERAGE grouping and filtering (get_savings_plans_coverage):
54
-
- group_by accepts ONLY INSTANCE_FAMILY, REGION, or SERVICE. LINKED_ACCOUNT is
54
+
- group_by accepts ONLY INSTANCE_TYPE_FAMILY, REGION, or SERVICE. LINKED_ACCOUNT is
55
55
NOT a valid group_by attribute — grouping by it returns a ValidationException.
56
-
- filter accepts LINKED_ACCOUNT, REGION, SERVICE, INSTANCE_FAMILY. To see coverage
56
+
- filter accepts LINKED_ACCOUNT, REGION, SERVICE, INSTANCE_TYPE_FAMILY. To see coverage
57
57
per member account, FILTER by one LINKED_ACCOUNT and call once per account; do
58
-
not try to group_by LINKED_ACCOUNT.
58
+
not try to group_by LINKED_ACCOUNT. SAVINGS_PLANS_TYPE is not a coverage dimension
59
+
(ValidationException).
59
60
- Each group_by entry is a GroupDefinition with Type and Key, e.g.
60
61
`[{"Type": "DIMENSION", "Key": "REGION"}]`. There is no "Value" field in a
61
62
group_by entry — a `{Key, Value}` shape is rejected (seen as a boto
@@ -77,14 +78,46 @@
77
78
utilization or coverage) and do NOT resend the identical request. Correct an unknown
78
79
filter value; query an earlier window only if the question allows it.
- get_savings_plans_utilization ignores sort_by and returns its periods in date order.
88
121
89
122
RESPONSE PERIODS (all three operations):
90
123
- `requested_time_period` echoes the start_date/end_date that were sent.
@@ -99,7 +132,7 @@
99
132
IMPORTANT: For get_savings_plans_coverage, `granularity` and `group_by` are mutually
100
133
exclusive. If `group_by` is provided, `granularity` is ignored (the Cost Explorer
101
134
GetSavingsPlansCoverage API does not allow both). Valid `group_by` dimensions for
102
-
coverage are SERVICE, REGION, or INSTANCE_FAMILY.
135
+
coverage are SERVICE, REGION, or INSTANCE_TYPE_FAMILY.
103
136
104
137
PAGINATION (get_savings_plans_coverage, where an item is one period x group entry, and
105
138
get_savings_plans_utilization_details, where an item is one Savings Plan;
@@ -125,6 +158,7 @@ async def sp_performance(
125
158
filter: Optional[str] =None,
126
159
max_items: Optional[int] =None,
127
160
next_token: Optional[str] =None,
161
+
sort_by: Optional[str] =None,
128
162
) ->Dict[str, Any]:
129
163
"""Tool that retrieves AWS Savings Plans coverage and utilization data.
130
164
@@ -135,12 +169,17 @@ async def sp_performance(
135
169
end_date: End date in YYYY-MM-DD format (exclusive). Defaults to today if not provided. Savings Plans data for the last 2-3 days (counting today) is not processed yet: a start_date in those days returns a DataUnavailableException, and a window reaching into them leaves them out.
136
170
granularity: Time granularity of the data (DAILY or MONTHLY). Defaults to DAILY. For coverage, ignored when group_by is provided (granularity and group_by are mutually exclusive).
137
171
metrics: List of metrics to retrieve as a JSON string. For coverage, only 'SpendCoveredBySavingsPlans' is valid.
138
-
group_by: Optional grouping of results as a JSON string. For coverage, supports SERVICE, REGION, or INSTANCE_FAMILY (NOT LINKED_ACCOUNT). Each entry is {"Type": ..., "Key": ...}; there is no "Value" field.
139
-
filter: Optional filter to apply to the results as a JSON string. Coverage filter dimensions: LINKED_ACCOUNT, REGION, SERVICE, INSTANCE_FAMILY. And/Or need >=2 operands; for one condition pass the leaf object directly.
172
+
group_by: Optional grouping of results as a JSON string. For coverage, supports SERVICE, REGION, or INSTANCE_TYPE_FAMILY (NOT LINKED_ACCOUNT). Each entry is {"Type": ..., "Key": ...}; there is no "Value" field.
173
+
filter: Optional filter to apply to the results as a JSON string. Coverage filter dimensions: LINKED_ACCOUNT, REGION, SERVICE, INSTANCE_TYPE_FAMILY. And needs >=2 operands; for one condition pass the leaf object directly. Values are case-sensitive; see FILTER VALUES in the tool description.
140
174
max_items: Total number of items to return across all pages. Omit it to fetch every
141
-
page. Coverage and utilization details only.
175
+
page. Coverage and utilization details only. With sort_by, these are the first N
176
+
items in the requested SortOrder (the top N), not N items sorted afterwards.
142
177
next_token: The pagination.next_token from a previous response; continue with otherwise
143
178
identical parameters. Coverage and utilization details only.
179
+
sort_by: Optional sort as a JSON string, e.g. {"Key": "CoveragePercentage", "SortOrder": "ASCENDING"}.
180
+
Applied before max_items, so sort_by + max_items=N returns the top N.
181
+
Coverage and utilization details only (ignored by get_savings_plans_utilization);
182
+
the valid keys differ per operation (see SORTING).
144
183
145
184
Returns:
146
185
Dict containing the savings plans coverage/utilization information
0 commit comments