From 61521915893ac893ae500b07dc91c25c6181ae1d Mon Sep 17 00:00:00 2001 From: William Grant Date: Thu, 29 Oct 2026 17:44:37 +1100 Subject: [PATCH 1/4] fix: correct AssetDB cost guidance on current months and AI providers Agents misread `current` on the monthly cost tables as "the valid row for this month" and filtered on it, so past months came back empty. They also searched service names for "anthropic" instead of filtering by provider, finding nothing, because Anthropic services are model names. Explain both in sql_info.md, document the cost table joins, and mention non-cloud providers in the server instructions. Co-Authored-By: Claude Opus 5.5 --- NEWS.md | 6 ++++++ stacklet/mcp/assetdb/sql_info.md | 9 +++++++++ stacklet/mcp/mcp_info.md | 1 + 3 files changed, 16 insertions(+) diff --git a/NEWS.md b/NEWS.md index 78d59ea..2e72692 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,10 +2,16 @@ ### Features +- **Ask about AI spend**: your AI assistant can now find spend from AI providers such as + Anthropic. + ### Changes ### Fixes +- **Past months' costs**: your AI assistant no longer reports past months as having no + cost data. + --- ## October 26, 2026 diff --git a/stacklet/mcp/assetdb/sql_info.md b/stacklet/mcp/assetdb/sql_info.md index 3a39370..2842735 100644 --- a/stacklet/mcp/assetdb/sql_info.md +++ b/stacklet/mcp/assetdb/sql_info.md @@ -21,12 +21,21 @@ Many AssetDB tables are extremely large. Always use LIMIT and indexed column fil | `cost_source` | Lookup table for cost sources | Very Small | Sources of ingested cost data | | `account_id` | Lookup table for accounts | Small | Bridge between cost tables and account/provider detail | | `resource_id` | Lookup table for resources | Medium | Bridge between cost tables and resource detail | +| `cloud_service` | Lookup table for services | Small | Bridge between cost tables and service/provider names | +| `cloud_region` | Lookup table for regions | Small | Bridge between cost tables and region names | ### **Special Considerations** - Most table columns are commented. When investigating table structure, these are valuable. - Foreign key constraints do not tell the whole story; there are many implicit foreign relations. +### **Cost Data** + +- Do not filter on `current` to pick a month; filter on `date`. `current` marks each account's (`account_cost_monthly`) or resource's (`resource_cost_monthly`) own latest month, not the latest calendar month, and a resource that has stopped costing has no current row. Rows are never superseded, so filtering `current = true` silently drops past months, and any account or resource whose latest data is older. +- A month's row may be partial while its data is still arriving: compare `source_date` or `last_date` with the month end. +- Providers are not only clouds: `account_id.provider` and `cloud_service.provider` also include AI vendors such as `anthropic`, whose services are model names (e.g. `claude-sonnet-4-6`) and items such as `web_search`, never containing the vendor name. Find providers with `SELECT DISTINCT provider FROM account_id`, and filter on provider, never by matching service names. +- `account_cost_monthly.account`, `.service` and `.region` are integer ids; join them to `account_id`, `cloud_service` and `cloud_region` on `id`. `resource_cost_monthly` has only `account` and `resource_id`, with no service or region. + ### **Safe Querying Process** 1. **Query table sizes:** diff --git a/stacklet/mcp/mcp_info.md b/stacklet/mcp/mcp_info.md index 281c5ae..3a72637 100644 --- a/stacklet/mcp/mcp_info.md +++ b/stacklet/mcp/mcp_info.md @@ -14,6 +14,7 @@ Always call these info tools first - they contain essential guidance and best pr ### 🔍 Cloud Asset Discovery & Analytics Analyze your entire multi-cloud estate with a continuously-updated PostgreSQL warehouse: - Query resource inventories, costs, and relationships across AWS, GCP, Azure, Tencent +- Analyze spend from other providers, such as Anthropic, alongside cloud costs - Perform complex analytics on resource usage patterns and cost optimization - Track resource changes and lifecycle management - Build custom reports with SQL From 3dfac4d36ff06f27e99dd2f85932826786a35cbe Mon Sep 17 00:00:00 2001 From: William Grant Date: Thu, 29 Oct 2026 17:45:42 +1100 Subject: [PATCH 2/4] fix: keep preview Anthropic provider low-key in guidance Co-Authored-By: Claude Opus 5.5 --- NEWS.md | 3 --- stacklet/mcp/assetdb/sql_info.md | 2 +- stacklet/mcp/mcp_info.md | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index 2e72692..4bed06a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,9 +2,6 @@ ### Features -- **Ask about AI spend**: your AI assistant can now find spend from AI providers such as - Anthropic. - ### Changes ### Fixes diff --git a/stacklet/mcp/assetdb/sql_info.md b/stacklet/mcp/assetdb/sql_info.md index 2842735..4f93c63 100644 --- a/stacklet/mcp/assetdb/sql_info.md +++ b/stacklet/mcp/assetdb/sql_info.md @@ -33,7 +33,7 @@ Many AssetDB tables are extremely large. Always use LIMIT and indexed column fil - Do not filter on `current` to pick a month; filter on `date`. `current` marks each account's (`account_cost_monthly`) or resource's (`resource_cost_monthly`) own latest month, not the latest calendar month, and a resource that has stopped costing has no current row. Rows are never superseded, so filtering `current = true` silently drops past months, and any account or resource whose latest data is older. - A month's row may be partial while its data is still arriving: compare `source_date` or `last_date` with the month end. -- Providers are not only clouds: `account_id.provider` and `cloud_service.provider` also include AI vendors such as `anthropic`, whose services are model names (e.g. `claude-sonnet-4-6`) and items such as `web_search`, never containing the vendor name. Find providers with `SELECT DISTINCT provider FROM account_id`, and filter on provider, never by matching service names. +- Filter on `account_id.provider` or `cloud_service.provider`, not by matching service names: a provider's services need not contain its name. Some deployments have non-cloud providers (e.g. `anthropic`, in preview, whose services are model names); `SELECT DISTINCT provider FROM account_id` lists them. - `account_cost_monthly.account`, `.service` and `.region` are integer ids; join them to `account_id`, `cloud_service` and `cloud_region` on `id`. `resource_cost_monthly` has only `account` and `resource_id`, with no service or region. ### **Safe Querying Process** diff --git a/stacklet/mcp/mcp_info.md b/stacklet/mcp/mcp_info.md index 3a72637..281c5ae 100644 --- a/stacklet/mcp/mcp_info.md +++ b/stacklet/mcp/mcp_info.md @@ -14,7 +14,6 @@ Always call these info tools first - they contain essential guidance and best pr ### 🔍 Cloud Asset Discovery & Analytics Analyze your entire multi-cloud estate with a continuously-updated PostgreSQL warehouse: - Query resource inventories, costs, and relationships across AWS, GCP, Azure, Tencent -- Analyze spend from other providers, such as Anthropic, alongside cloud costs - Perform complex analytics on resource usage patterns and cost optimization - Track resource changes and lifecycle management - Build custom reports with SQL From 6984c4c54f2dcf8cd17028b74ad80105227a6ce8 Mon Sep 17 00:00:00 2001 From: William Grant Date: Thu, 29 Oct 2026 18:06:03 +1100 Subject: [PATCH 3/4] fix: explain cost row tags, SKUs and Anthropic principals in AssetDB guidance Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01UowzEucGd9196yo8RmhMMA --- stacklet/mcp/assetdb/sql_info.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stacklet/mcp/assetdb/sql_info.md b/stacklet/mcp/assetdb/sql_info.md index 4f93c63..f50811b 100644 --- a/stacklet/mcp/assetdb/sql_info.md +++ b/stacklet/mcp/assetdb/sql_info.md @@ -35,6 +35,8 @@ Many AssetDB tables are extremely large. Always use LIMIT and indexed column fil - A month's row may be partial while its data is still arriving: compare `source_date` or `last_date` with the month end. - Filter on `account_id.provider` or `cloud_service.provider`, not by matching service names: a provider's services need not contain its name. Some deployments have non-cloud providers (e.g. `anthropic`, in preview, whose services are model names); `SELECT DISTINCT provider FROM account_id` lists them. - `account_cost_monthly.account`, `.service` and `.region` are integer ids; join them to `account_id`, `cloud_service` and `cloud_region` on `id`. `resource_cost_monthly` has only `account` and `resource_id`, with no service or region. +- `resource_focus_cost` and `resource_cost_monthly` have `tags`, an array of `resource_tags.id`s: unnest and join them to see whose cost it is, even for resources that aren't in `resources`. Only `resource_focus_cost` has `sku`: join it to `sku.id` for `sku_id`, which encodes the pricing dimensions. +- Anthropic (preview): the cost row's `resource_id` joins `resource_id.id`, whose `r_id` is a user (`user_…`, Claude Code usage included), an API key (`apikey_…`) or a service account (untagged). Users are tagged `anthropic:user_email`/`anthropic:user_name` (or `anthropic:claude_code_user` for users who've left), keys `anthropic:api_key_name`/`anthropic:owner_*`. `sku_id` is `model:token_type:context_window:service_tier:inference_geo:speed` (e.g. `…:200k-1M:…` for long context), or `web_search`. Some cost (Console usage, code execution, small shares) has no principal, so is only in account-level cost; resource rows sum to less. ### **Safe Querying Process** From 30c7a2ec7bfa441f119b1ec280138d66ebb6528c Mon Sep 17 00:00:00 2001 From: William Grant Date: Thu, 29 Oct 2026 10:04:02 +0000 Subject: [PATCH 4/4] fix: filter AssetDB cost by account provider, and say when cost row tags are empty Every cost table has account, but resource_cost_monthly has no service, so cloud_service.provider can't filter it. AWS's legacy CUR reports no tags on cost rows, and CUR 2.0 prefixes user tag keys with user_, so an agent filtering cost rows' tags on the inventory key finds nothing. --- stacklet/mcp/assetdb/sql_info.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stacklet/mcp/assetdb/sql_info.md b/stacklet/mcp/assetdb/sql_info.md index f50811b..c27ae77 100644 --- a/stacklet/mcp/assetdb/sql_info.md +++ b/stacklet/mcp/assetdb/sql_info.md @@ -33,9 +33,9 @@ Many AssetDB tables are extremely large. Always use LIMIT and indexed column fil - Do not filter on `current` to pick a month; filter on `date`. `current` marks each account's (`account_cost_monthly`) or resource's (`resource_cost_monthly`) own latest month, not the latest calendar month, and a resource that has stopped costing has no current row. Rows are never superseded, so filtering `current = true` silently drops past months, and any account or resource whose latest data is older. - A month's row may be partial while its data is still arriving: compare `source_date` or `last_date` with the month end. -- Filter on `account_id.provider` or `cloud_service.provider`, not by matching service names: a provider's services need not contain its name. Some deployments have non-cloud providers (e.g. `anthropic`, in preview, whose services are model names); `SELECT DISTINCT provider FROM account_id` lists them. +- Filter on `account_id.provider`, through the cost row's `account`, not by matching service names: every cost table has `account`, and a provider's services need not contain its name. Some deployments have non-cloud providers (e.g. `anthropic`, in preview, whose services are model names); `SELECT DISTINCT provider FROM account_id` lists them. - `account_cost_monthly.account`, `.service` and `.region` are integer ids; join them to `account_id`, `cloud_service` and `cloud_region` on `id`. `resource_cost_monthly` has only `account` and `resource_id`, with no service or region. -- `resource_focus_cost` and `resource_cost_monthly` have `tags`, an array of `resource_tags.id`s: unnest and join them to see whose cost it is, even for resources that aren't in `resources`. Only `resource_focus_cost` has `sku`: join it to `sku.id` for `sku_id`, which encodes the pricing dimensions. +- `resource_focus_cost` and `resource_cost_monthly` have `tags`, an array of `resource_tags.id`s: unnest and join them to see whose cost it is, even for resources that aren't in `resources`. They are the tags the cost source reported, so for cloud resources they can be empty (AWS legacy CUR) or have `user_`-prefixed keys (AWS CUR 2.0: `team` is `user_team`); `resources._tags` has the inventory tags. Only `resource_focus_cost` has `sku`: join it to `sku.id` for `sku_id`, which encodes the pricing dimensions. - Anthropic (preview): the cost row's `resource_id` joins `resource_id.id`, whose `r_id` is a user (`user_…`, Claude Code usage included), an API key (`apikey_…`) or a service account (untagged). Users are tagged `anthropic:user_email`/`anthropic:user_name` (or `anthropic:claude_code_user` for users who've left), keys `anthropic:api_key_name`/`anthropic:owner_*`. `sku_id` is `model:token_type:context_window:service_tier:inference_geo:speed` (e.g. `…:200k-1M:…` for long context), or `web_search`. Some cost (Console usage, code execution, small shares) has no principal, so is only in account-level cost; resource rows sum to less. ### **Safe Querying Process**