Repository navigation
Commit 4937c97
fix(billing-cost-management-mcp-server): scope rec-details Cost Explorer calls to the recommendation's account (#4931)
* fix(billing-cost-management-mcp-server): scope rec-details Cost Explorer calls to the recommendation's account
rec-details looked up the Cost Explorer purchase recommendation behind a
Cost Optimization Hub RI or Savings Plans recommendation without the
recommendation's scope. The RI call sent no AccountScope, so Cost
Explorer answered at its default (payer) scope with rows for other
accounts, instance types and Regions. The Savings Plans call sent the
scope but no account, so a Linked recommendation came back with every
member account's rows and a summary that totals all of them.
- RI: send AccountScope from the recommendation, and for EC2 the
offering class (ServiceSpecification.EC2Specification.OfferingClass,
'Standard' -> 'STANDARD', 'Convertible' -> 'CONVERTIBLE').
- RI and SP, Linked: narrow the call with a LINKED_ACCOUNT filter.
AccountId is not used: Cost Explorer rejects any AccountId other than
the caller's own account ("Request account should not be different
from user account"), so a management account cannot name a member
account there.
- Keep only the rows for the recommendation's account and, for EC2 RIs,
its instance type and Region (Cost Explorer returns Region names such
as 'US East (Ohio)' and 'EU (Paris)'; codes are mapped through the
botocore endpoint descriptions). A "note" counts dropped rows, a
"warning" says when no row matched.
- The tool description states that the summary is Cost Explorer's own
total for every row it returned and is not recomputed.
* fix(billing-cost-management-mcp-server): note unmatched non-EC2 RI rows and keep the SP page token
- Savings Plans: GetSavingsPlansPurchaseRecommendation returns NextPageToken
beside SavingsPlansPurchaseRecommendation, so the no-match warning's
"Only the first page was read" hint could never fire. The token is now
copied into additional_details.
- Non-EC2 RIs (RDS, ElastiCache, Redshift, OpenSearch, MemoryDB, DynamoDB):
rows are matched on account only and can span other instance types and
regions. The note and the tool description now say so instead of implying
the kept rows are the recommendation's own.
- constants: note that Cost Explorer accepts only upper-case OfferingClass
in requests while its responses echo 'Standard'.
* fix(billing-cost-management-mcp-server): keep rec-details RI rows when only the Region name misses
- An EC2 RI whose Region name matches no row no longer loses its account
and instance-type matches: the rows are kept unfiltered by Region and the
note says so, instead of a no-row warning.
- The non-EC2 RI note and the tool description say rows are not matched on
instance type or region (accurate for Payer scope too), and point
DynamoDB at ReservedCapacityDetails.
- Page hints say this tool cannot fetch later pages, and the dropped-rows
note now mentions unread pages when NextPageToken is set.
- Type hints for commitment_config and keep_matching_rows.
* fix(billing-cost-management-mcp-server): match rec-details RI Regions per row, not by response-wide fallback
The previous fallback kept every account and instance-type match whenever
no row's Region name matched, so a row for a genuinely different Region
(a regenerated Cost Explorer recommendation) was kept and the no-row
warning was lost; it was also decided once for the whole response.
Now each row is matched on its own: a row is kept when its Region name is
one of the recommendation's Region names, or when it is not the name of any
Region botocore knows (a new spelling), and the note names those. A row for
another known Region is dropped. The page hint is added whenever rows were
kept and NextPageToken is set, even when none were dropped.
* test(billing-cost-management-mcp-server): align rec-details tests that #4929, #4956 and this PR each changed the premise of
- test_reserved_instances_coh_terms_reach_cost_explorer (from #4929)
expected PARTIAL_UPFRONT for a three-year DynamoDB reserved capacity
recommendation; #4956 sends HEAVY_UTILIZATION for DynamoDB, so the test
failed on main. It now expects HEAVY_UTILIZATION.
- test_dynamodb_reserved_capacity_requests_heavy_utilization (from #4956)
asserts the exact Cost Explorer request; this PR also sends the
recommendation's AccountScope, so the expected request gains
AccountScope=PAYER.
* fix(billing-cost-management-mcp-server): say which rec-details warning sits where after the ThreeYears merge
- The description used "top-level" both for the response and for
additional_details. It now says "a note/warning key in additional_details"
and "no response-level warning".
- The empty-lookup sentence no longer promises an inner warning for every
empty commitment answer: the inner warning is added when Cost Explorer
returns rows but none for this recommendation.
- New test: a Savings Plans lookup whose rows are all for another account
leaves the response without a warning and puts one in additional_details.
---------
Co-authored-by: Som Chatterjee <5313130+somsubhro@users.noreply.github.com>1 parent 24fa5e5 commit 4937c97
3 files changed
Lines changed: 743 additions & 8 deletions
File tree
- src/billing-cost-management-mcp-server
- awslabs/billing_cost_management_mcp_server
- tools
- utilities
- tests/tools
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
20 | 22 | | |
21 | 23 | | |
22 | 24 | | |
| |||
27 | 29 | | |
28 | 30 | | |
29 | 31 | | |
| 32 | + | |
30 | 33 | | |
31 | 34 | | |
32 | 35 | | |
| |||
40 | 43 | | |
41 | 44 | | |
42 | 45 | | |
43 | | - | |
| 46 | + | |
44 | 47 | | |
45 | 48 | | |
46 | 49 | | |
| |||
62 | 65 | | |
63 | 66 | | |
64 | 67 | | |
65 | | - | |
66 | | - | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
67 | 79 | | |
68 | 80 | | |
69 | 81 | | |
70 | | - | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
71 | 85 | | |
72 | 86 | | |
73 | 87 | | |
| |||
204 | 218 | | |
205 | 219 | | |
206 | 220 | | |
207 | | - | |
| 221 | + | |
| 222 | + | |
208 | 223 | | |
209 | 224 | | |
210 | | - | |
| 225 | + | |
| 226 | + | |
211 | 227 | | |
212 | 228 | | |
213 | 229 | | |
214 | 230 | | |
215 | 231 | | |
216 | 232 | | |
217 | 233 | | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
218 | 410 | | |
219 | 411 | | |
220 | 412 | | |
| |||
289 | 481 | | |
290 | 482 | | |
291 | 483 | | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
292 | 488 | | |
293 | 489 | | |
294 | 490 | | |
295 | | - | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
296 | 496 | | |
297 | 497 | | |
298 | 498 | | |
| |||
347 | 547 | | |
348 | 548 | | |
349 | 549 | | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
350 | 566 | | |
351 | 567 | | |
352 | 568 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
231 | 231 | | |
232 | 232 | | |
233 | 233 | | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
234 | 238 | | |
235 | 239 | | |
236 | 240 | | |
| |||
0 commit comments