Install
$ agentstack add mcp-mbanderas-costguard ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
CostGuard
CostGuard audits your repos and cloud providers for CI and infrastructure cost leaks. It is built for developers who run several projects across GitHub Actions, Vercel, Supabase, Railway, Netlify, Neon, Cloudflare, and more, and want a single command that surfaces what is being wasted and exactly how to fix it. On repositories that have never been optimized, the static audit alone typically reduces CI spend by 60–80%.
Install
CostGuard installs three ways. The plugin paths are zero-build and zero-npm (they ship a prebuilt, self-contained bundle); the npm package gives you the CLI and the MCP server anywhere.
Claude Code
/plugin marketplace add mbanderas/costguard
/plugin install costguard@costguard
Adds /costguard-audit, /costguard-fix, /costguard-live, and the full costguard skill (scan, providers, registry, report, digest). No build step, no npm install.
Codex
codex plugin marketplace add mbanderas/costguard
codex plugin add costguard@costguard
Adds the bundled costguard skill to Codex CLI and Desktop.
npm / any MCP host
Run the MCP server directly — no install:
npx -y @costguard/costguard-mcp
Install the MCP server and the costguard CLI globally (both bins):
npm i -g @costguard/costguard-mcp
Run the CLI ad-hoc without installing:
npx -y -p @costguard/costguard-mcp costguard
npx -y @costguard/costguard-mcp launches the MCP server directly because the package name matches its bin entry point — drop it straight into any MCP host's server config.
> Other CLIs / Desktop apps — one command drops a thin /costguard adapter > into Cursor, Gemini CLI, Cline, Windsurf, or a Codex project: > > ``sh > npx -y -p @costguard/costguard-mcp costguard install --target > ` > > --target auto detects the host; the adapter is no-clobber and idempotent. Run > costguard install --help` for the full target list.
What it finds
Static half (zero credentials). Reads .github/workflows/*.yml and application code to detect redundant CI triggers (push + pull_request on the same branch), missing timeout-minutes, missing concurrency cancellation, paths-ignore gaps that run CI on doc-only commits, and over-scheduled crons. No API call, no token needed — always safe to run.
Billing half (read-only, opt-in). When a provider token is present, reconciles live billed resources against a declared allowlist and flags orphaned resources (billed but not listed) and over-provisioned resources (larger or more capable than declared), each with a best-effort estimated monthly cost. Covers thirteen providers: GitHub, Vercel, Supabase, Railway, Netlify, Neon, Cloudflare, Fly, Render, Sentry, Upstash, MongoDB Atlas, and Datadog.
Proof
Tested on production repositories. Patterns found and fixed across repositories like my-app, web-app, and api-service:
- Redundant CI triggers. A workflow wired to both
pushandpull_request
on the same branch runs CI twice per commit. Dropping the redundant trigger halves runner-minute consumption for every push.
- Missing timeouts. Jobs without
timeout-minutesburn minutes up to
GitHub's 6-hour cap on hung runs. Adding a sane timeout is a one-line fix with no functional impact.
- Missing concurrency cancellation. Without a
concurrencyblock, rapid
pushes queue up and run sequentially instead of cancelling superseded runs. Adding cancel-in-progress: true eliminates the queue.
paths-ignoregaps. Workflows withoutpaths-ignorefor documentation
paths run full CI on commit-message and README edits. Excluding **.md and docs/** removes a class of runs entirely.
- Orphaned preview branches. A Supabase preview branch left running after a
feature ships keeps accruing compute cost each billing cycle.
On repositories that have accumulated these patterns over time, fixing all of them has reduced observed CI spend by up to 80%. The typical range on repositories never previously optimized is 60–80%. Results vary by workflow structure and push cadence; these are observed, directional outcomes, not a guarantee.
Using CostGuard
Every host drives the same read-only engine — reach for it the native way. Each block below is self-contained; use the one for your host.
Claude Code
Three slash commands plus the full costguard skill (scan, providers, registry, report, digest):
/costguard-audit— audit a workspace for CI/cron and cloud-spend waste./costguard-fix— preview or apply the safe in-repo CI fixes (dry-run first)./costguard-live— opt-in, consent-gated live billing read for a provider.
Codex
Invoke the bundled costguard skill by name, then say what you want:
- "Use the costguard skill to audit my-app for CI waste."
- "With costguard, show a dry-run fix for web-app's workflows."
- "Run a costguard provider billing check across api-service."
Cursor / Gemini CLI / Cline / Windsurf
Install the /costguard adapter once for your host:
costguard install --target cursor
costguard install --target gemini
costguard install --target cline
costguard install --target windsurf
Then drive it with any costguard arguments:
/costguard audit my-app
/costguard fix my-app --apply
(If costguard is not yet on your PATH, prefix the install command with npx -y -p @costguard/costguard-mcp .)
Any MCP host
Copy-paste CostGuard's MCP server into your host's config — no checkout:
{
"mcpServers": {
"costguard": {
"command": "npx",
"args": ["-y", "@costguard/costguard-mcp"],
"env": {
"GITHUB_TOKEN": "…",
"SUPABASE_ACCESS_TOKEN": "…",
"RAILWAY_TOKEN": "…",
"NETLIFY_AUTH_TOKEN": "…",
"NEON_API_KEY": "…"
}
}
}
}
Every token is optional and read-only; a provider with no token is skipped. See [Environment variables](#environment-variables) for the full list and aliases.
npx -y @costguard/costguard-mcp (no -p, no subcommand) starts the MCP server for this config; npx -y -p @costguard/costguard-mcp costguard runs the CLI.
Environment variables
Provider tokens are read only from the process environment or a gitignored .env in the CostGuard workspace. They are never printed, logged, or committed. Each provider module runs only when one of its tokens is present; offline, the modules are fully exercised by fixtures. All tokens are used read-only.
| Variable (any one of) | Provider | Used for | |-----------------------|----------|----------| | GITHUB_TOKEN / GH_TOKEN | github | Actions usage per repo (read-only billing PAT) | | SUPABASE_ACCESS_TOKEN / SUPABASE_TOKEN | supabase | Projects, compute size, PITR, branches | | RAILWAY_TOKEN / RAILWAY_API_TOKEN | railway | Services, deploys, usage (read-only GraphQL) | | NETLIFY_AUTH_TOKEN / NETLIFY_TOKEN | netlify | Sites, build minutes, bandwidth | | NEON_API_KEY / NEON_API_TOKEN | neon | Projects, branches, compute hours | | VERCEL_TOKEN / VERCEL_API_TOKEN | vercel | Team deploying seats vs deploy activity | | SENTRY_AUTH_TOKEN / SENTRY_TOKEN | sentry | Monthly error events vs plan quota | | UPSTASH_API_KEY / UPSTASH_TOKEN | upstash | Redis DB commands + storage | | ATLAS_API_KEY / MONGODB_ATLAS_TOKEN | atlas | Cluster tiers + data size | | CLOUDFLARE_API_TOKEN / CF_API_TOKEN | cloudflare | R2 buckets, storage, class A/B ops | | FLY_API_TOKEN / FLY_ACCESS_TOKEN | fly | Apps + dedicated IPv4 addresses | | RENDER_API_KEY / RENDER_TOKEN | render | Service instance plans | | DD_API_KEY / DATADOG_API_KEY | datadog | Enables the module (declaration-only; APM host counts read from config) | | COSTGUARD_DIGEST_WEBHOOK | — | Optional digest --post destination (inert in this build) |
Use providers --check to confirm which tokens the environment exposes without revealing any value.
Provider modules
CostGuard ships thirteen read-only, opt-in provider modules, and the roster is actively expanding. Each reads live billed resources, reconciles them against the registry active{} allowlist, and emits orphaned and over-provisioned findings with a best-effort $/mo.
| Module | Reads | Flags | |--------|-------|-------| | github | Actions usage per repo | top minute-burners; repos over budget | | supabase | Projects, compute size, PITR/add-ons, branches | running preview branches; compute/PITR drift vs registry | | railway | Services, deploys, usage (read-only GraphQL queries) | idle services; deploys never torn down | | netlify | Sites, build minutes, bandwidth | build-minute spend; runaway bandwidth | | neon | Projects, branches, compute hours | idle branches; orphaned (defunct but billed) projects | | vercel | Team deploying seats vs deploy activity | idle paid deploying seats | | sentry | Monthly error events | error-event overage vs plan quota | | upstash | Redis DB commands + storage | pay-as-you-go cost above a fixed plan | | atlas | Cluster tiers + data size | oversized cluster for its data | | cloudflare | R2 buckets, storage, class A/B ops | operation-heavy R2 spend | | fly | Apps + dedicated IPv4 addresses | dedicated IPv4 on non-critical apps | | render | Service instance plans | oversized instance for its environment | | datadog | APM host counts (declared in config) | excess provisioned APM hosts |
All live provider access is HTTP GET; the railway module uses GraphQL queries only, guarded against mutations. The datadog module is declaration-only — it reconciles operator-declared host counts offline and makes no network call. No module ever issues a write or delete call. A module activates only when its token (above) is present; otherwise it is skipped.
More providers are on the way — coverage is expanding as new billing surfaces are researched and sourced.
Security / read-only posture
CostGuard is built to be safe to run anywhere, including on a schedule:
- Read-only provider access only. No write or mutating API call is ever issued. Provider tokens are read-only and are never printed, logged, or committed.
- Secrets stay out of the repo. Tokens are read from the environment or a gitignored
.env*only.providers --checkreports presence by variable name, never by value. - The static half needs no credentials.
audit(without--providers) andscanread only local files and are always safe to run. fixis in-repo and dry-run by default. It edits only.github/workflows/*files in the target workspace, never provider or cloud state, and writes nothing until--apply.- Outward actions are inert and gated.
fix --open-pranddigest --postrefuse to act without an explicit opt-in flag and the matching credential, and even then perform no git push or network post in this build.
How workspaces.json works
workspaces.json is the registry of projects CostGuard tracks. registry --init scans workspacesRoot (default: ~/Workspaces) and writes a fresh file with auto-detected providers arrays (GitHub, Netlify, Supabase, etc.) and blank active{} blocks. A starter [workspaces.example.json](workspaces.example.json) ships with this repo.
{
"root": "~/Workspaces",
"workspaces": {
"my-app": {
"providers": ["github", "netlify"],
"active": {}
}
}
}
The active{} block is the allowlist used by the provider checks: any live resource not listed there is flagged as orphaned, and any resource larger or more capable than declared is flagged as over-provisioned. Leave it empty if you only run the static half; the provider modules then have nothing to reconcile against.
Configuration
Create costguard.config.json in the project root to override defaults:
{
"workspacesRoot": "~/Workspaces",
"defaults": {
"cronThresholdMinutes": 15,
"ciMinuteRate": 0.008,
"assumedPushesPerDay": 10,
"assumedMinutesPerRun": 5
},
"perWorkspace": {
"my-app": {
"cronThresholdMinutes": 30
}
}
}
| Key | Default | Description | |-----|---------|-------------| | cronThresholdMinutes | 15 | Crons running more often than this threshold are flagged | | ciMinuteRate | 0.008 | USD per runner-minute (GitHub-hosted Linux) | | assumedPushesPerDay | 10 | Estimated daily push cadence for cost projection | | assumedMinutesPerRun | 5 | Assumed wasted minutes per redundant CI run |
Per-workspace overrides in perWorkspace merge on top of defaults.
Scheduler template
A monthly digest can be wired to GitHub Actions via the documented, inert scheduler template templates/costguard-digest.yml.
- It lives under
templates/— not.github/workflows/— so it never runs automatically and is not enabled by this project. - To activate: a human copies it into
.github/workflows/in the target repo and supplies the required secrets (e.g.COSTGUARD_DIGEST_WEBHOOK). - To roll back: delete the copy from
.github/workflows/.
Activating the template is a deliberate human action outside CostGuard's own runtime.
CLI reference
These flags apply to the costguard CLI, available via npm i -g @costguard/costguard-mcp or npx -y -p @costguard/costguard-mcp costguard .
All commands operate on the workspaces.json registry in the project root. Workspace selection is by directory name; --all selects every registered workspace. Examples use the global costguard command; from a checkout you can equivalently run node dist/cli/index.js .
audit
Run the static CI/cron audit, optionally adding read-only provider billing checks, and print a report to stdout.
# Audit a single workspace (static checks only)
costguard audit my-app
# Audit everything at once
costguard audit --all
# CI-minutes check only
costguard audit my-app --ci-only
# Cron check only, JSON output
costguard audit my-app --crons-only --json
# Add provider billing checks for specific providers (only those whose token is present)
costguard audit --all --providers github,supabase
# Add provider checks for every provider whose token is present
costguard audit --all --providers all
| Option | Effect | |--------|--------| | --all | Audit all registered workspaces | | --ci-only | Run only the CI-minute checks | | --crons-only | Run only the cron-frequency checks | | --site | Also run read-only live-site checks for workspaces whose registry entry has a site URL (see [site](#site)) | | --substitutions | Add cross-tool /cheaper-alternative suggestions (e.g. a static Vercel/Netlify Pro site → Cloudflare Pages), each with a sourced saving, migration effort, and lock-in caveat | | --providers | Add read-only provider billing checks. Comma-separated ids (github,supabase,railway,netlify,neon) or all. A provider is only contacted when its token is present (see [Environment variables](#environment-variables)); others are silently skipped. | | --json | Emit JSON instead of Markdown |
scan
Static-only audit across all workspaces. A convenience alias intended for a single catch-all CI step; it never touches provider credentials.
costguard scan
costguard scan --ci # CI minutes only
costguard scan --crons # Cron schedules only
providers
Report which provider tokens are present in the environment, by environment-variable name only. Secret values are never read into output, printed, or logged.
costguard providers --check
--check is the default action.
discover
Detect which providers a repo actually uses — from config files, package.json dependencies, and environment-variable names (never values, never secrets). Covers all 13 wired providers plus inngest, so you don'
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mbanderas
- Source: mbanderas/costguard
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.