What nable is, in one minute
nable answers questions about your cloud and AI bill right inside Claude or Cursor. Ask why a bill went up, it finds the cause, drafts the fix, and proves the savings. No SQL, no dashboards.
- ✓Read-only access to one cloud account (AWS, Azure, or GCP) to start. nable only ever reads your bill.
- ✓Your credentials stay in your OS keyring, on your machine. Nothing reaches our servers.
- ✓It proposes, you approve. nable never changes anything in your cloud on its own.
One command, uvx nable, on your machine.
Point it at AWS, Azure, or GCP. The setup wizard walks you through it.
In Claude or Cursor, ask why the bill went up. Get the cause, the cost, and the fix.
An engineer installs nable and connects the read-only access once. The IAM, CloudFormation, and SSO pages below are for them. After that, anyone on the team just asks questions, no setup, no terminal.
Quickstart
Install nable, point it at your AI editor, then ask about your cloud spend. You only need one provider to start. Everything stays on your machine.
- ✓Python 3.11+ with pip. Check with
python3 --version. - ✓Claude Desktop or Cursor (or any MCP-compatible editor)
- ✓Read-only credentials for at least one cloud account (AWS, Azure, or GCP)
uvx nable
uv fetches a matching Python and runs the setup wizard. No PATH setup, no separate install step. Want a look first? uvx nable welcome --demo runs it on sample data. Already on Python 3.11+? pip install -U finops-mcp && finops welcome. No uv? brew install uv.
uv tool install finops-mcp && uv tool update-shell
Installs the finops commands on your PATH so you can run finops welcome, finops doctor, and the rest directly. Open a new terminal after update-shell, then fully quit and reopen your editor.
Prefer manual MCP setup? Add this to your editor's config:
// Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json
// Cursor: ~/.cursor/mcp.json
{
"mcpServers": {
"finops": { "command": "finops-mcp" }
}
}
Tip: replace finops-mcp with the full path from which finops-mcp. macOS GUI apps inherit a minimal PATH and may not find the command otherwise.
"What are my top 5 AWS cost drivers this month, and did anything spike unexpectedly?"
nable breaks down your spend by service, flags anomalies, and explains what changed. No SQL, no dashboards.
Detailed installation
The long version of the quickstart, with verification and the manual MCP path spelled out. Takes about five minutes including IAM setup.
uvx nableThe welcome command walks you through connecting Claude and your first cloud account, then shows your first cost number right in the terminal. uv fetches a matching Python automatically. Already on Python 3.11+? pip install -U finops-mcp && finops welcome works too.
# Scans this machine for credentials (env vars, gcloud, gh, ~/.modal.toml…)
# and connects everything it finds in one keystroke:
finops connect
# Or pick providers individually:
finops setup aws
finops setup gcp
finops setup azureAWS and GCP are detect-and-confirm: nable finds working credentials (profiles, SSO, gcloud ADC), auto-discovers the billing accounts, and connects on one keystroke. Every paste-a-key wizard links the exact page where the key lives. Credentials go to your OS keyring; nothing leaves the machine. You don't need all 30 connectors, one is enough to start.
{
"mcpServers": {
"finops": { "command": "finops-mcp" }
}
}Run finops setup to have this written automatically, or paste it manually. Then fully quit and reopen your editor , most clients only read config at startup.
finops doctor
✓ aws configured
✓ datadog configured
– azure not configuredIf a provider shows red, re-run finops setup <provider> or check the troubleshooting section.
Activate your Team license
After purchase, your license key is emailed to you. Keys start with FINOPS-2-. Run one command and it handles everything.
finops setup license FINOPS-2-your-key-hereThis validates the key, stores it in your OS keyring, and writes it directly into your Claude Desktop config. No manual JSON editing.
Team features turn on immediately on restart.
finops setup license-status.AI client setup
Add the MCP server to your AI client's config. You only need to do this once. If you ran finops setup, it was configured automatically with the correct path.
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"finops": { "command": "finops-mcp" }
}
}Cursor
Settings → MCP → Add server, or edit ~/.cursor/mcp.json
{ "mcpServers": { "finops": { "command": "finops-mcp" } } }Windsurf
Edit ~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "finops": { "command": "finops-mcp" } } }OpenAI Codex / other MCP clients
Run the server manually and point your client at the stdio transport.
finops-mcp # listens on stdiofinops-mcp with the full path from which finops-mcp. macOS GUI apps inherit a minimal PATH.AWS
Connects to Cost Explorer for spend data and CloudWatch for rightsizing metrics. Supports IAM keys, IAM Identity Center SSO, and cross-account role assumption.
Permission tiers
nable works with whatever you're comfortable giving it. Start with Cost Explorer read-only for cost queries, anomaly detection, and budgets. Add the audit permissions when you're ready for the deep waste scanner.
- Cost queries across all services
- Anomaly detection
- Budget alerts and soft checks
- Savings Plan coverage
- Forecasting
- Deep waste audit (16 scanners)
- CloudWatch rightsizing per instance
- Idle NAT / EIP / EBS detection
- Lambda memory analysis
- S3 storage class optimization
ce:GetCostAndUsage
ce:GetSavingsPlans*
ce:GetReservation*
sts:GetCallerIdentity# everything on the left, plus:
cloudwatch:GetMetricData
ec2:Describe{Instances,Volumes,
Snapshots,Addresses,NatGateways}
rds:Describe{DBInstances,DBSnapshots}
lambda:ListFunctions
logs:DescribeLogGroups
s3:ListAllMyBuckets
compute-optimizer:Get*logs:PutRetentionPolicy, for optional auto-remediation of infinite-retention log groups. Destructive cleanup requires explicitly setting FINOPS_CLEANUP_ENABLED=true. Run finops setup aws --iam-template to generate a least-privilege CloudFormation policy. Full policy in Least-privilege IAM.Setup
Create an IAM user with the permissions above, or use an existing SSO role.
finops setup awsEnter your Access Key ID and Secret Access Key when prompted. For SSO, enter your profile name.
Manual env vars
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=your-secret
AWS_DEFAULT_REGION=us-east-1 # CE requires us-east-1Azure
Connects to the Azure Cost Management API. Supports a Service Principal (recommended for automation) and device-code flow (interactive login).
- ✓Cost Management Reader , scoped to your Subscription or Management Group
Setup
Create a Service Principal:
az ad sp create-for-rbac --name finops-mcp \
--role "Cost Management Reader" \
--scopes /subscriptions/YOUR_SUB_IDfinops setup azureEnter Tenant ID, Client ID, Client Secret, and Subscription ID when prompted.
Manual env vars
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
AZURE_SUBSCRIPTION_ID=your-subscription-idGCP
Primary path: BigQuery billing export (recommended, richer data). Fallback: Cloud Billing API. Both use a service-account JSON key stored encrypted in your vault.
- ✓roles/billing.viewer , Billing API access
- ✓roles/bigquery.dataViewer , only if using BigQuery export
- ✓roles/bigquery.jobUser , only if using BigQuery export
Setup
Create a service account in GCP Console → IAM → Service Accounts. Assign the roles above, then download the JSON key file.
(Recommended) Enable billing export to BigQuery: Billing → Billing export → BigQuery export.
finops setup gcpPaste the path to your JSON key file and your GCP Project ID when prompted.
Manual env vars
GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json
GCP_PROJECT_ID=my-project-123
GCP_BIGQUERY_DATASET=billing_export # if using BQ export
GCP_PROJECT_IDS=my-prod,my-staging # enables the GCP waste auditCost guardrail for agents
One command wires nable into an AI coding agent so it checks every infrastructure-mutating command against your policy before it runs. No prompt engineering. It is advisory and propose-only: nable pauses or blocks an action and shows why, but it never executes anything itself. Read the agent cost controls overview for the why.
Install
In your project (or add --global for every repo), run:
finops guard install
This writes a Claude Code PreToolUse hook to .claude/settings.json. Restart Claude Code so it picks up the hook. Uses uvx nable? The hook is finops guard hook either way. Check status with finops guard status, remove with finops guard uninstall.
What it does
Before your agent runs an infrastructure command, nable classifies it and applies your policy:
terraform destroy, kubectl delete, aws ec2 terminate-instances, a commitment purchaseterraform apply, helm upgrade, stopping an instanceTry any command against your policy without an agent:
finops guard check --command "terraform destroy"
Policy knobs
- ·
FINOPS_POLICY_MAX_AUTO_USD— a monthly-dollar threshold; a cost increase above it escalates. Default 500. - ·
FINOPS_POLICY_ALLOWED_ACTIONS— comma-separated action types a human can apply (e.g.rightsizing,tag_fix,stop_idle). Anything else is denied. - ·
FINOPS_GUARD_STRICT=1— also pause on reversible mutations (terraform apply,helm upgrade) with a nudge to cost the change first.
Safety
The guard never executes a command; it only returns ask, deny, or nothing. It fails open, any internal error exits cleanly so a guard bug can never break your agent, and it adds about 80ms per command. Propose-only stays fully intact: nable does not auto-execute infrastructure. Outside Claude Code (Cursor, Windsurf, your own loop), point the agent at the same gate with a one-line system-prompt instruction, see the adoption paths.
Security & permissions
nable is not SaaS. It runs on your machine, holds credentials in your OS keyring, queries your cloud providers directly, and has no backend that receives your data. It reads your cloud bill. It cannot change your cloud. Full detail on the security page and the access scope page.
What nable can and cannot do
There is exactly one optional write permission in the whole footprint: logs:PutRetentionPolicy, used only if you explicitly ask nable to fix a CloudWatch Log Group that has no retention policy. You can omit it and lose nothing but that one auto-fix. Destructive cleanup is off entirely unless you set FINOPS_CLEANUP_ENABLED=true yourself.
Where things live
- ·Credentials: your OS keyring (macOS Keychain, Windows Credential Manager, libsecret on Linux), encrypted at rest with Fernet. Never written to config files in plaintext, never transmitted to nable.
- ·Cost data: cached in a local SQLite database on your machine (Postgres in team mode, hosted by you). nable has no data lake; there is nothing of yours on our side to breach.
- ·License verification: offline. Keys are Ed25519-signed and verified against a public key bundled in the package. No license server, no phone-home check.
- ·The website and billing are the only nable-operated systems. They never see cloud credentials or cost data.
Verify before you trust
You do not have to take this on faith. nable ships the tools to generate a scoped credential and prove it is read-only:
- ·
finops setup aws --iam-templateprints the exact CloudFormation policy - ·
finops setup aws --iam-terraformprints it as a Terraform snippet - ·
finops setup aws --check-scopeinspects a credential and confirms it has no write permissions
Because nable runs entirely on your machine with no backend, you can watch the wire yourself: run it behind a packet capture (tcpdump, Little Snitch, your egress firewall) and confirm the only outbound destinations are your own cloud provider APIs. Two exceptions, both yours to disable: anonymous opt-out usage telemetry (no cost figures, account IDs, or credentials; off with NABLE_NO_TELEMETRY=1); and, only if you opt into peer benchmarking which is off by default, anonymized differentially-private cost ratios. FINOPS_AIRGAP=1 forbids all non-provider traffic including both.
AI exposure, stated plainly
When you ask a question in Claude, Cursor or another MCP editor, the cost figures nable returns are sent to that editor's AI model to compose the answer, the same as anything else in the chat. nable itself sends nothing to any model. For zero model exposure, use the local dashboard or CLI, which never touch one. Enterprises routing AI through private endpoints (Bedrock, Azure OpenAI) keep that boundary too.
Team mode
- ·RBAC: viewer, analyst and admin roles with team scoping; API keys stored as SHA-256 hashes.
- ·SSO: OIDC with strict validation (algorithm allowlist, issuer, audience, expiry and CSRF state all enforced).
- ·Audit log: every tool call recorded with duration and outcome.
- ·Remediation approvals: drafted actions require a second-person approval by default (analyst or above, 24-hour expiry, replay-proof).
Least-privilege IAM
The exact, least-privilege read-only permissions nable needs on each provider. Hand the policy below to your platform team, or run finops setup aws --iam-template to generate it. Every action is a Get, List, Describe, or read.
AWS least-privilege read-only policy
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "NableReadOnlyFinOps",
"Effect": "Allow",
"Action": [
"ce:GetCostAndUsage", "ce:GetCostForecast",
"ce:GetReservationUtilization", "ce:GetReservationCoverage",
"ce:GetSavingsPlansPurchaseRecommendation",
"ce:GetSavingsPlansUtilization", "ce:GetSavingsPlansCoverage",
"ce:GetRightsizingRecommendation", "ce:ListCostAllocationTags",
"compute-optimizer:GetEC2InstanceRecommendations",
"compute-optimizer:GetLambdaFunctionRecommendations",
"compute-optimizer:GetRDSDatabaseRecommendations",
"compute-optimizer:GetECSServiceRecommendations",
"compute-optimizer:GetEnrollmentStatus",
"cloudwatch:GetMetricData", "cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics",
"ec2:DescribeInstances", "ec2:DescribeRegions", "ec2:DescribeVolumes",
"ec2:DescribeSnapshots", "ec2:DescribeAddresses",
"ec2:DescribeNatGateways", "ec2:DescribeImages",
"elasticloadbalancing:DescribeLoadBalancers",
"rds:DescribeDBInstances", "rds:DescribeDBSnapshots",
"lambda:ListFunctions", "lambda:GetFunctionConfiguration",
"ecr:DescribeRepositories", "ecr:DescribeImages",
"ecs:ListClusters", "ecs:ListServices",
"ecs:DescribeServices", "ecs:DescribeTaskDefinition",
"logs:DescribeLogGroups", "logs:DescribeLogStreams",
"logs:PutRetentionPolicy", // the one optional write, omit to be pure read-only
"cloudtrail:DescribeTrails", "cloudtrail:GetTrailStatus",
"cloudtrail:GetEventSelectors",
"s3:ListAllMyBuckets", "s3:GetBucketLocation",
"s3:GetBucketIntelligentTieringConfiguration",
"s3:ListBucketMultipartUploads",
"organizations:ListAccounts", "organizations:DescribeAccount",
"organizations:DescribeOrganization",
"sts:GetCallerIdentity", "sts:AssumeRole"
],
"Resource": "*"
}]
}Every action is a Get, List, Describe, or read. There is no Create, Delete, Modify, Run, Terminate, or Put anywhere except the single annotated log-retention line.
One optional, separate backend: if you turn on the detailed CUR-via-Athena cost path (off by default, not part of this policy), it also needs read access to Athena and Glue plus a scoped s3:PutObject to its own Athena query-results bucket. That is the only write outside log retention, it is opt-in, and it is scoped to a bucket you designate.
Google Cloud roles to grant the service account
- ·
roles/billing.vieweron the billing account, to read cost - ·
roles/bigquery.dataVieweron the billing-export dataset - ·
roles/bigquery.jobUseron the project, to run the export queries - ·
roles/compute.vieweron each audited project (optional, for the GCP waste audit) - ·
roles/monitoring.vieweron each audited project (optional, for the GCP waste audit) - ·
roles/recommender.vieweron each project (optional, to pull Google's native Recommender API: rightsizing, committed-use, Cloud SQL, idle resources)
All are read and query roles. nable reads your Cloud Billing export in BigQuery and, for the optional waste audit, lists Compute resources and reads Monitoring metrics. It writes to nothing. Set GCP_PROJECT_IDS to turn the resource audit on.
Azure RBAC roles per subscription
- ·Cost Management Reader, for cost and usage queries
- ·Reader, for Advisor cost recommendations and the VM list
- ·Monitoring Reader, for VM CPU metrics used in rightsizing
All three are Reader-tier roles. nable performs no write operation on Azure.
finops setup aws --iam-template), they create a scoped read-only credential in minutes, and nable runs on your machine with that. Read the full write-up on the access scope page.Enterprise SSO (OIDC)Enterprise
Lets your whole team sign in with their company credentials via Okta, Azure AD, Google Workspace, Auth0, or any OIDC-compatible IdP. IdP groups automatically map to nable RBAC roles, with no manual API key distribution.
admin / analyst / viewer → user receives a Team license key automatically.Setup
Create an OAuth2 app in your IdP. Set the redirect URI to https://getnable.com/api/sso/oidc-callback. Request scopes openid email profile groups.
Enable the groups claim in the ID token. Steps vary by IdP: Okta (Authorization Server → Claims), Azure AD / Entra ID (Token configuration → groups claim, set OIDC_GROUPS_CLAIM=roles), Google Workspace (custom claim via Admin SDK), Auth0 (Action or Rule).
Run the wizard to configure and store credentials:
finops setup ssoAdd the env vars to your deployment (or wherever nable runs). Test by visiting /api/sso/oidc-start.
Role mapping example
OIDC_ISSUER=https://yourcompany.okta.com
OIDC_CLIENT_ID=0oa1abc...
OIDC_CLIENT_SECRET=your-client-secret
OIDC_GROUPS_CLAIM=groups
OIDC_ROLE_MAP={"finops-admins":"admin","engineering":"analyst","finance":"viewer"}
OIDC_DEFAULT_ROLE=viewer # fallback for users not in any mapped groupRBAC roles
| Role | Can do |
|---|---|
| admin | All queries, set budgets, manage API keys, create tickets, view all teams |
| analyst | All queries and recommendations, cannot manage keys or budgets |
| viewer | Read-only: cost summaries, anomalies, rightsizing. Cannot set budgets or create tickets |
All environment variables
Every variable nable reads. The setup wizard writes these for you; this table is for manual config, CI, and containerized runs.
Click any row to copy the variable name. Or skip the table entirely: finops connect detects credentials already on your machine and connects everything it finds.
finops setup <provider> and the wizard writes them for you.Troubleshooting
The usual suspects, and how to clear them fast.
Editor can't find finops-mcp
macOS GUI apps inherit a minimal PATH. Use the absolute path from which finops-mcp in your MCP config, or install with uv tool install finops-mcp && uv tool update-shell.
AWS returns empty cost data
Cost Explorer isn't enabled yet, or it's still warming up (up to 24h on new accounts). Confirm under Billing → Cost Explorer, make sure your region is us-east-1, and check the IAM user has ce:GetCostAndUsage. Run aws sts get-caller-identity to confirm which account you're reading.
Tools don't appear after config
Most MCP clients only read config at startup. Fully quit and reopen the editor , not just close the window. Then run finops doctor to confirm each provider.
Credentials not persisting after restart
Install the keyring extra: pip install finops-mcp[keyring]. Without it, credentials fall back to a local encrypted file. Re-run finops setup after installing.
Snowflake: "Object does not exist"
The user needs IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE granted to its role. Run as ACCOUNTADMIN: GRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE your_role;
command not found: finops after pip install
pip installed the package but the executable isn't on your PATH, common on macOS with system or Homebrew Python. Find and add the pip bin directory, or use pipx install finops-mcp which handles PATH automatically.
# Find where pip puts executables
python3 -m site --user-base
# Add /bin to that path, e.g.:
export PATH="$HOME/Library/Python/3.11/bin:$PATH"Still stuck?
Email us with your finops doctor output and we'll debug with you: hello@getnable.com.