Skip to content

Add MCP usage server and richer spend analytics - #87

Merged
tsouth89 merged 4 commits into
mainfrom
sou-276-278-mcp-spend-metrics
Jul 20, 2026
Merged

Add MCP usage server and richer spend analytics#87
tsouth89 merged 4 commits into
mainfrom
sou-276-278-mcp-spend-metrics

Conversation

@tsouth89

@tsouth89 tsouth89 commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add codexbar mcp stdio MCP server (list_providers, get_usage, get_spend, get_status) and persist widget snapshots on desktop refresh so cache-only quota tools work (SOU-276).
  • Enrich per-model spend breakdown with cache-read %, cost/call, and output tokens/call (SOU-278).
  • Show dollar period-over-period on the estimated API value card (Today vs yesterday, 30d vs prior 30d).

Test plan

  • cargo test --manifest-path rust/Cargo.toml --lib cli::mcp
  • cargo test --manifest-path apps/desktop-tauri/src-tauri/Cargo.toml model_breakdown
  • pnpm --dir apps/desktop-tauri test -- run src/lib/apiValueCard.test.ts src/components/TotalApiValueCard.test.tsx
  • codexbar mcp --help then configure Claude Code/Cursor MCP to codexbar mcp and call get_status
  • Open desktop app, refresh providers, confirm model breakdown metrics and API value card PoP labels
  • CodeRabbit review

Summary by CodeRabbit

  • New Features

    • Added a local MCP command exposing provider quotas, spend estimates, and combined status over stdio.
    • Added per-model usage metrics, including cache-read percentage, cost per call, output tokens per call, and call counts.
    • Added prior-30-day comparisons and period-change labels to API value cards.
    • Provider refreshes now save a local widget snapshot for offline usage data.
  • Improvements

    • Expanded token accounting to include cache activity and usage calls.
    • Updated usage breakdown layouts and styling for improved metric readability.

tsouth89 added 2 commits July 19, 2026 23:24
Expose quota and estimated spend over stdio via `codexbar mcp`, and persist the widget snapshot on desktop refresh so cache-only tools work.
Show cache-read %, cost/call, and output/call on the model breakdown, and surface Today/30d dollar deltas on the estimated API value card.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ceiling 910c8b1 Commit Preview URL

Branch Preview URL
Jul 20 2026, 04:04 AM

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 35 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 95e8296f-90dd-47fc-809b-8e2aa0d937ba

📥 Commits

Reviewing files that changed from the base of the PR and between 020bf00 and 910c8b1.

📒 Files selected for processing (4)
  • apps/desktop-tauri/src-tauri/src/commands/chart.rs
  • apps/desktop-tauri/src-tauri/src/commands/providers.rs
  • rust/src/cli/mcp.rs
  • rust/src/cost_scanner.rs
📝 Walkthrough

Walkthrough

The changes add cache and call-based usage metrics, four-period API value comparisons, richer model-breakdown rendering, provider snapshot persistence, and a local MCP stdio server exposing quota and spend tools.

Changes

Local usage analytics

Layer / File(s) Summary
Token and model metrics
rust/src/cost_scanner.rs, rust/src/codex_costs.rs, apps/desktop-tauri/src-tauri/src/commands/chart.rs, apps/desktop-tauri/src/types/bridge.ts
Token aggregation now tracks cache buckets and calls, while model breakdown data includes cache-read percentage, cost per call, output tokens per call, and call counts.
Four-period API value comparisons
apps/desktop-tauri/src-tauri/src/commands/chart.rs, apps/desktop-tauri/src/lib/apiValueCard.ts, apps/desktop-tauri/src/components/TotalApiValueCard.tsx, apps/desktop-tauri/src/lib/apiValueCard.test.ts, apps/desktop-tauri/src/components/TotalApiValueCard.test.tsx
Local API totals include a prior 30-day window, and the card computes and formats comparisons for today and 30-day periods.
Model breakdown presentation
apps/desktop-tauri/src/surfaces/settings/providers/sections/charts/ChartsSection.tsx, apps/desktop-tauri/src/styles.css
Model rows display optional cache and per-call metrics using updated layout and styling.

Local MCP access

Layer / File(s) Summary
Provider snapshot persistence
apps/desktop-tauri/src-tauri/src/commands/providers.rs
Provider refreshes persist successful cached provider data and parsed quota rate windows to a widget snapshot.
MCP tools and CLI wiring
rust/Cargo.toml, rust/src/cli/mcp.rs, rust/src/cli/mod.rs, rust/src/main.rs
A stdio MCP server exposes provider listing, cached usage, local spend, and combined status tools, with provider selection and structured error payloads.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPClient
  participant CeilingMcp
  participant WidgetSnapshotStore
  participant CostScanner
  MCPClient->>CeilingMcp: call get_status
  CeilingMcp->>WidgetSnapshotStore: load provider snapshot
  WidgetSnapshotStore-->>CeilingMcp: return cached quota
  CeilingMcp->>CostScanner: scan local spend
  CostScanner-->>CeilingMcp: return spend summary
  CeilingMcp-->>MCPClient: return combined JSON status
Loading

Possibly related PRs

  • tsouth89/ceiling#55: Adds the earlier local model cost breakdown foundation extended by these metrics.
  • tsouth89/ceiling#57: Establishes the local API value totals extended here with the prior 30-day period.
  • tsouth89/ceiling#58: Adds the API value card extended here with period-change computation and rendering.

Suggested reviewers: finesssee

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main changes: a new MCP usage server and richer spend analytics.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sou-276-278-mcp-spend-metrics

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/desktop-tauri/src-tauri/src/commands/chart.rs (1)

569-628: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Off-by-one: the "30 days" window is actually 31 days, while "prior 30 days" is exactly 30 days.

thirty_start = today - 30 days combined with thirty_end = today + 1 day yields a half-open window [today-30, today+1) spanning 31 calendar dates (today-30 … today inclusive). Meanwhile prior_start = today - 60 days combined with the same thirty_start as the end yields [today-60, today-30), which is exactly 30 dates. Comparing a 31-day window against an adjacent 30-day window for "30d vs prior 30d" dollar period-over-period skews the reported percent change (the current period always has one extra day of activity baked in).

Shift both boundaries back by one day so both windows are exactly 30 days:

🐛 Proposed fix to align both 30-day windows
-    let thirty_start = local_midnight_utc(today - chrono::Duration::days(30));
+    let thirty_start = local_midnight_utc(today - chrono::Duration::days(29));
     let thirty_end = local_midnight_utc(today + chrono::Duration::days(1));
-    let prior_start = local_midnight_utc(today - chrono::Duration::days(60));
+    let prior_start = local_midnight_utc(today - chrono::Duration::days(59));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop-tauri/src-tauri/src/commands/chart.rs` around lines 569 - 628,
Update load_local_api_value_totals so the thirty-day window is exactly 30
calendar days: set thirty_start to today minus 30 days and thirty_end to today
(not tomorrow), while retaining prior_start at today minus 60 days and the
adjacent [prior_start, thirty_start) prior_thirty window.
🧹 Nitpick comments (1)
rust/src/cost_scanner.rs (1)

101-118: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding local unit tests for processed()/merge_from().

These are new, non-trivial aggregation helpers; today they're only exercised indirectly via chart.rs tests (model_breakdown_orders_priced_first_and_keeps_unpriced, etc.). A focused #[cfg(test)] module here would pin down behavior (e.g., merge_from summing all buckets, processed() excluding cached_tokens) independent of the UI-facing consumer.

Also note: Rust tests could not be executed in this review environment, so this suggestion is unverified against cargo test.

As per path instructions, "rust/src/**/*.rs: Add or extend focused Rust tests near the changed module, commonly using #[cfg(test)] unit tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rust/src/cost_scanner.rs` around lines 101 - 118, Add a focused #[cfg(test)]
module near ModelTokenCounts with unit tests for processed() and merge_from().
Verify processed() sums input, output, cache-read, and cache-write tokens while
excluding cached_tokens, and verify merge_from() accumulates every token bucket
and calls field.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop-tauri/src-tauri/src/commands/providers.rs`:
- Around line 534-563: The widget snapshot mapper function
widget_entry_from_usage_snapshot must also populate token_usage from snap.cost
so provider-refresh snapshots emit the session cost value. Extend the existing
cost-handling block to set token_usage using the appropriate cost value while
preserving the current credits_remaining mapping.

In `@rust/src/cli/mcp.rs`:
- Around line 282-331: Update the get_status flow around choose_status_provider
and status_payload to distinguish an explicitly supplied but unrecognized
provider from an absent provider. Return the same clear “Unknown provider
'{name}'” error used by usage_payload and spend_payload instead of producing a
status payload with ok: false; preserve existing provider selection for
recognized or omitted names.

---

Outside diff comments:
In `@apps/desktop-tauri/src-tauri/src/commands/chart.rs`:
- Around line 569-628: Update load_local_api_value_totals so the thirty-day
window is exactly 30 calendar days: set thirty_start to today minus 30 days and
thirty_end to today (not tomorrow), while retaining prior_start at today minus
60 days and the adjacent [prior_start, thirty_start) prior_thirty window.

---

Nitpick comments:
In `@rust/src/cost_scanner.rs`:
- Around line 101-118: Add a focused #[cfg(test)] module near ModelTokenCounts
with unit tests for processed() and merge_from(). Verify processed() sums input,
output, cache-read, and cache-write tokens while excluding cached_tokens, and
verify merge_from() accumulates every token bucket and calls field.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bbc2da87-e44b-4cb8-a075-d8ccc6920948

📥 Commits

Reviewing files that changed from the base of the PR and between c560f09 and 020bf00.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • apps/desktop-tauri/src-tauri/src/commands/chart.rs
  • apps/desktop-tauri/src-tauri/src/commands/providers.rs
  • apps/desktop-tauri/src/components/TotalApiValueCard.test.tsx
  • apps/desktop-tauri/src/components/TotalApiValueCard.tsx
  • apps/desktop-tauri/src/lib/apiValueCard.test.ts
  • apps/desktop-tauri/src/lib/apiValueCard.ts
  • apps/desktop-tauri/src/styles.css
  • apps/desktop-tauri/src/surfaces/settings/providers/sections/charts/ChartsSection.tsx
  • apps/desktop-tauri/src/types/bridge.ts
  • rust/Cargo.toml
  • rust/src/cli/mcp.rs
  • rust/src/cli/mod.rs
  • rust/src/codex_costs.rs
  • rust/src/cost_scanner.rs
  • rust/src/main.rs

Comment thread apps/desktop-tauri/src-tauri/src/commands/providers.rs
Comment thread rust/src/cli/mcp.rs
tsouth89 added 2 commits July 20, 2026 00:03
Align 30d windows, persist session cost in widget snapshots, reject unknown providers in get_status, and add ModelTokenCounts unit tests.
@tsouth89
tsouth89 merged commit 4fc1eeb into main Jul 20, 2026
10 of 11 checks passed
@tsouth89
tsouth89 deleted the sou-276-278-mcp-spend-metrics branch July 20, 2026 04:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant