Get up and running in 5 minutes
Install nable, connect a provider, then ask Claude about your cloud costs in plain English. You don't need all 18 connectors. Start with the one you care about most.
Installation
Install and run the setup wizard
finops setup
Note the hyphen: finops-mcp, not finops mcp. The setup wizard connects your providers and writes the Claude Desktop config automatically.
On Anaconda? Skip pip and run: uvx finops-mcp setup
Check your setup
✓ aws configured
✓ datadog configured
– azure not configured
Restart Claude Desktop and ask
"What did we spend on AWS last month?"
"Any anomalies in our Datadog costs this week?"
"Show me rightsizing opportunities for EC2."
Activate your Team license
After purchasing a Team plan, you receive a license key by email and on your account page at nable.sh/account. Keys start with FINOPS-1-. Here is how to activate it.
Copy your license key from the email or account page.
It looks like: FINOPS-1-your-key-here
Open your Claude Desktop config file.
On Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
On Windows: %APPDATA%\Claude\claude_desktop_config.json
Add the key to the env block for the finops server:
"FINOPS_LICENSE_KEY": "FINOPS-1-your-key-here"
}
Restart Claude Desktop. Team features unlock immediately.
AI client setup
Add the MCP server to your AI client's config. You only need to do this once.
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json
"mcpServers": {
"finops": {
"command": "finops-mcp"
}
}
}
Note: if you used finops setup, this was configured automatically with the correct path. If editing manually, use the full path from which finops-mcp instead of the bare command name.
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.
Cloud Providers
aws 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.
nable works with whatever permissions you're comfortable giving it. Start with Cost Explorer read-only and you get cost queries, anomaly detection, and budget tracking. Add the audit permissions when you're ready and you unlock the deep waste scanner.
FINOPS_CLEANUP_ENABLED=true. Run finops setup aws --iam-template to generate a least-privilege CloudFormation policy for either tier.Create an IAM user with the permissions above, or use an existing SSO role.
Enter your Access Key ID and Secret Access Key when prompted. For SSO, enter your profile name.
Manual env vars (alternative to wizard)
AWS_SECRET_ACCESS_KEY=your-secret
AWS_DEFAULT_REGION=us-east-1 # CE requires us-east-1
az Azure
Connects to Azure Cost Management API. Supports Service Principal (recommended for automation) and device code flow (interactive login).
Required Azure role
Create a Service Principal: az ad sp create-for-rbac --name finops-mcp --role "Cost Management Reader" --scopes /subscriptions/YOUR_SUB_ID
Enter Tenant ID, Client ID, Client Secret, and Subscription ID when prompted.
Manual env vars
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
AZURE_SUBSCRIPTION_ID=your-subscription-id
gcp GCP
Primary path: BigQuery billing export (recommended, richer data). Fallback: Cloud Billing API. Both use a service account JSON key stored encrypted in your vault.
Required IAM roles
Create a service account in GCP Console → IAM → Service Accounts. Assign roles above. Download the JSON key file.
(Recommended) Enable billing export to BigQuery: Billing → Billing export → BigQuery export.
Paste the path to your JSON key file and your GCP Project ID when prompted.
Manual env vars
GCP_PROJECT_ID=my-project-123
GCP_BIGQUERY_DATASET=billing_export # if using BQ export
SaaS Tools
dd Datadog
Real cost data via the Usage Metering API v2. Returns host counts, APM hosts, log ingestion, and dollar amounts where available. Supports EU site.
Go to Organization Settings → API Keys → New Key. Name it finops-mcp.
Go to Organization Settings → Application Keys → New Key.
DATADOG_APP_KEY=your-app-key
DATADOG_SITE=datadoghq.com # or datadoghq.eu
sf Snowflake
Queries ACCOUNT_USAGE.METERING_HISTORY for real credit consumption. Set your contract credit price to convert to USD.
Required privilege
Create a read-only role and user: GRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE finops_role;
SNOWFLAKE_USER=finops_user
SNOWFLAKE_PASSWORD=your-password
SNOWFLAKE_WAREHOUSE=COMPUTE_WH
SNOWFLAKE_CREDIT_PRICE=3.00 # your contract rate per credit
SNOWFLAKE_ROLE=ACCOUNTADMIN # optional, defaults to ACCOUNTADMIN
gh GitHub
Returns paid Actions minutes used and Copilot seat counts. Requires org-level access.
Go to Settings → Developer settings → Personal access tokens → Fine-grained tokens. Select your org. Set permissions: read:billing, read:org.
GITHUB_ORGS=your-org-name
str Stripe
Returns actual fees paid to Stripe via the Balance Transactions API. Use a restricted key with no write permissions needed.
Go to Stripe Dashboard → Developers → API Keys → Create restricted key. Enable: Balance → Read only.
tw Twilio
Paginated usage records with real billing amounts. Uses your main Account SID and Auth Token.
Find your Account SID and Auth Token on the Twilio Console homepage.
TWILIO_AUTH_TOKEN=your-auth-token
mg MongoDB Atlas
Invoice API with line-item breakdown. Uses Digest Auth with an org-level API key.
Go to Atlas → Access Manager → Organization Access → API Keys → Create API Key. Role: Organization Billing Viewer.
MONGODB_ATLAS_PRIVATE_KEY=your-private-key
MONGODB_ATLAS_ORG_IDS=your-org-id
cf Cloudflare
Billing history and active subscriptions via the Cloudflare API.
Go to Cloudflare Dashboard → My Profile → API Tokens → Create Token. Use the "Read billing info" template.
CLOUDFLARE_ACCOUNT_ID=your-account-id
vcl Vercel
Invoice API, requires a Vercel Enterprise plan. Returns invoices with line items. Returns a descriptive message if no invoice data is available.
Go to Vercel Dashboard → Settings → Tokens → Create. Scope: Full Account.
VERCEL_TEAM_ID=team_xxxxxxx # optional, for team accounts
pd PagerDuty
Returns seat count and user data. For actual dollar amounts, use the Invoice email parser, as PagerDuty doesn't expose billing amounts via API.
Go to My Profile → User Settings → Create API User Token. Read-only access is sufficient.
Set the env var manually or run finops setup (interactive mode) and select PagerDuty.
nr New Relic
Returns data ingest (GB) and full platform user counts. Set your contract ingest price to convert to USD.
Go to New Relic → API Keys → Create key. Type: User key.
Set the env vars manually or run finops setup (interactive mode) and select New Relic.
NEW_RELIC_ACCOUNT_ID=1234567
NEW_RELIC_INGEST_PRICE_PER_GB=0.35 # your contract rate
lf Langfuse
Tracks LLM observability costs via the Langfuse Daily Metrics API. Returns model cost, token usage, and trace volume so you can see how much each model and project is actually costing you.
Go to Langfuse → Settings → API Keys and create a new key pair. Copy the public and secret keys.
LANGFUSE_SECRET_KEY=sk-lf-...
LANGFUSE_HOST=https://cloud.langfuse.com # optional, defaults to cloud.langfuse.com
Invoice email parsing
For vendors with no billing API (PagerDuty, New Relic, GitHub Enterprise, etc.), nable can connect to your billing inbox via IMAP, parse PDF and HTML invoices, and extract real dollar amounts automatically.
Enable IMAP access on your mailbox (Gmail: Settings → See all settings → Forwarding and POP/IMAP).
If using Gmail, create an App Password (requires 2FA): Google Account → Security → App passwords.
Set the env vars below in your Claude Desktop MCP config or shell environment. Run finops setup to store them securely in the vault.
FINOPS_IMAP_PORT=993
FINOPS_IMAP_USER=billing@yourcompany.com
FINOPS_IMAP_PASSWORD=your-app-password
Alerts & Automation
sl Slack alerts
Sends anomaly alerts and daily digests to a Slack channel. Uses an incoming webhook, no bot scopes needed.
Go to api.slack.com/apps → Create app → Incoming Webhooks → Add webhook to workspace. Select your #finops channel.
Copy the webhook URL and add to your env:
ms Microsoft Teams alerts
Sends anomaly alerts and daily digests via an Incoming Webhook connector.
In Teams, go to your channel → ⋯ → Connectors → Incoming Webhook → Configure. Copy the webhook URL.
Weekly email digest Team
Sends a standalone HTML email every Monday at 09:00 UTC with last week's spend, anomalies, and rightsizing recommendations. No AI client session required. Fires from the scheduler.
FINOPS_SMTP_PORT=587
FINOPS_SMTP_USER=you@yourcompany.com
FINOPS_SMTP_PASSWORD=your-app-password
FINOPS_DIGEST_TO=team@yourcompany.com
FINOPS_WEEKLY_CRON="0 9 * * 1" # optional - default Mon 09:00 UTC
Auto-ticketing Team
When a high or medium-severity anomaly is detected, nable automatically creates a ticket in your tracker. Configure one or more. The first configured is used by default.
Jira
Create an API token at id.atlassian.com → Security → API tokens.
JIRA_EMAIL=you@yourcompany.com
JIRA_API_TOKEN=your-api-token
JIRA_PROJECT_KEY=FINOPS
Linear
Create an API key at Linear → Settings → API → Personal API keys.
LINEAR_TEAM_ID=your-team-id
GitHub Issues
Needs a fine-grained token with issues: write on the target repo.
GITHUB_ISSUES_REPO=yourorg/finops-alerts
sl Slack bot
A persistent bot you can talk to directly in Slack. Just DM @nable or mention it in any channel. It calls the same nable tools under the hood and responds with cost analysis, anomaly summaries, rightsizing recommendations, and more. Different from the webhook alerts above: this is conversational.
pip install finops-mcp[slack]
Go to api.slack.com/apps → Create app → From scratch. Name it nable.
Under OAuth & Permissions, add bot token scopes: app_mentions:read, chat:write, im:history, im:read. Install the app to your workspace and copy the Bot User OAuth Token.
Under Socket Mode, enable it and generate an App-Level Token with the connections:write scope. Copy that token too.
Under Event Subscriptions, enable events and subscribe to app_mention and message.im.
Set your env vars and start the bot:
SLACK_APP_TOKEN=xapp-...
ANTHROPIC_API_KEY=sk-ant-...
SLACK_DAILY_CHANNEL=#finops # optional - sends daily digest at 09:00 UTC
Uses Socket Mode, no public URL or reverse proxy needed. Keep it running in the background (systemd, screen, or Docker).
gh PR cost comments
Automatically posts a cost estimate on GitHub pull requests when infrastructure files change (Terraform, CloudFormation, CDK, Helm). The comment is updated, not duplicated, on each push. Only fires if the estimated impact exceeds your configured threshold.
pip install finops-mcp[pr-comments]
Create a GitHub fine-grained personal access token with pull_requests: write on the target repos.
Set your env vars and start the webhook server:
GITHUB_WEBHOOK_SECRET=your-secret # recommended - validates webhook payloads
PR_COST_THRESHOLD_USD=10 # skip comment if impact is under $10/mo
PR_WEBHOOK_PORT=8080 # optional - default 8080
In your GitHub repo, go to Settings → Webhooks → Add webhook. Set the payload URL to http://your-host:8080/webhook/github, content type to application/json, and choose the Pull requests event.
Idle resource cleanup
Scans for AWS resources that are running but not being used: unattached EBS volumes, unassociated Elastic IPs, stale snapshots, stopped EC2 instances, and load balancers with no healthy targets. Cleanup actions are opt-in and always dry-run by default.
FINOPS_CLEANUP_ENABLED=true to enable delete/terminate actions. Without it, the scan tool works but cleanup returns a dry-run preview only.
Example workflow in Claude / Cursor
list_idle_resources(resource_types=["ebs","eip"], min_idle_days=90)
# Step 2 - preview what cleanup would do (dry_run=True by default)
cleanup_idle_resources(resource_ids=["vol-abc123","vol-def456"], dry_run=True)
# Step 3 - actually clean up
cleanup_idle_resources(resource_ids=["vol-abc123","vol-def456"], dry_run=False)
Protected resource tags
Resources tagged with any of the following are never touched, regardless of idle status:
Override the default protected tag set via env:
FINOPS_PROTECTED_TAGS=env=prod,protected=true,keep=yes # comma-separated key=value pairs
~/.finops-mcp/cleanup_audit.jsonl for auditing.What nable actually does
nable isn't just a connector that pipes your billing data into Claude. It runs active analysis (anomaly detection, CloudWatch-based rightsizing, waste pattern scanning, and commitment modeling) and surfaces the output as MCP tools your AI client can query, reason about, and act on.
AWS deep audit
The intent here is to give you two tools side by side: AWS Compute Optimizer for standard rightsizing, and nable's audit for the deeper layer underneath it. Optimizer will tell you to downsize an instance. nable will also tell you the EBS volume attached to it is gp2, the snapshot from 6 months ago is still accruing charges, and the CloudTrail trail recording data events in every region is costing you $400/mo nobody noticed.
The patterns below are just what ships out of the box. The audit engine is built to be extended, and the tools are designed to be composed: ask Claude to "find every dollar of waste in us-east-1" and it will pull Compute Optimizer, run the deep audit, and cross-reference both.
Usage in Claude / Cursor
audit_aws_waste()
# Target specific checks and region
audit_aws_waste(regions=["us-east-1"], checks=["ebs","nat","rds_backups"])
# Deep CloudWatch analysis for a specific instance
get_instance_deep_analysis(instance_id="i-0abc123", lookback_days=14)
# Scan all log groups for missing retention policies
scan_cloudwatch_waste()
Anomaly detection
Multi-signal detection using z-score, CUSUM drift, and day-of-week seasonal normalisation. When something spikes, nable drills into Cost Explorer by tag and tells you which team, environment, or service drove it, and by how much.
SLACK_WEBHOOK_URL or TEAMS_WEBHOOK_URL to enable.Rightsizing
Combines AWS Compute Optimizer recommendations with nable's own CloudWatch analysis. Surfaces instances where actual CPU / memory / connection utilization is consistently below the provisioned level, with a specific recommended type and estimated savings.
Commitment analysis Team
Models Savings Plans and Reserved Instance coverage against your actual usage patterns. Shows your current effective discount rate, coverage gaps, and what you'd save by purchasing additional commitments, with ROI projections by term length.
Savings Plan showback by team
Savings Plans are purchased at the payer account level. By default there is no way to know which team benefited from a discount. Your bill shows one blended rate and tools like CloudHealth, Apptio, and AWS Cost Explorer all approximate the allocation. nable reads two fields from CUR that most tools ignore:
The difference is the real dollar savings that resource captured from the SP. Grouped by a resource tag
(e.g. team),
this gives each team their effective discount rate and savings captured. No tool below the $50K/yr tier offers this at line-item granularity.
Like CloudHealth and Apptio, this is an approximation. AWS applies SP discounts using internal logic that is not fully exposed in the CUR. Specifically: family-based SP allocation order (AWS picks which resources to cover first) is not deterministic from CUR data alone, and SP amortization timing can shift costs across billing periods by a few percent. Results will be within ~2–5% of the true allocation for most workloads, and significantly more accurate than tools that rely solely on Cost Explorer blended rates. Treat showback figures as a strong signal for team accountability, not an accounting-grade ledger entry.
Requires CUR delivery to S3 + Athena. Set CUR_S3_BUCKET, CUR_ATHENA_DATABASE, CUR_ATHENA_TABLE, CUR_ATHENA_RESULTS_BUCKET.
Enterprise SSO (OIDC)
Enterprise plan. 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 needed.
admin / analyst / viewer → user receives a Team license key automatically.
Create an OAuth2 app in your IdP. Set the redirect URI to https://nable.sh/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 → Add → set Name=groups, Token type=ID, Filter=Matches regex
.* - Azure AD / Entra ID: App registration → Token configuration → Add groups claim → select "Security groups". Use
OIDC_GROUPS_CLAIM=rolesand add App Roles in the manifest. - Google Workspace: Configure a custom claim via the Admin SDK. Set
OIDC_GROUPS_CLAIMto match your claim name. - Auth0: Add an Action or Rule to include groups/roles in the ID token.
Run the wizard to configure and store credentials:
Add the env vars to your Vercel project (or wherever nable runs). Test by visiting /api/sso/oidc-start.
Role mapping example
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 group
RBAC 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
Full reference. The wizard sets these for you. Use this table if you're deploying in CI/CD or Docker.
| Variable | Provider | Required |
|---|---|---|
| AWS_ACCESS_KEY_ID | AWS | Required |
| AWS_SECRET_ACCESS_KEY | AWS | Required |
| AWS_DEFAULT_REGION | AWS | Optional |
| AZURE_TENANT_ID | Azure | Required |
| AZURE_CLIENT_ID | Azure | Required |
| AZURE_CLIENT_SECRET | Azure | Required |
| AZURE_SUBSCRIPTION_ID | Azure | Required |
| GOOGLE_APPLICATION_CREDENTIALS | GCP | Required |
| GCP_PROJECT_ID | GCP | Required |
| GCP_BIGQUERY_DATASET | GCP | Optional |
| DATADOG_API_KEY | Datadog | Required |
| DATADOG_APP_KEY | Datadog | Required |
| DATADOG_SITE | Datadog | Optional |
| SNOWFLAKE_ACCOUNT | Snowflake | Required |
| SNOWFLAKE_USER | Snowflake | Required |
| SNOWFLAKE_PASSWORD | Snowflake | Required |
| SNOWFLAKE_WAREHOUSE | Snowflake | Required |
| SNOWFLAKE_CREDIT_PRICE | Snowflake | Optional |
| SNOWFLAKE_ROLE | Snowflake | Optional |
| GITHUB_TOKEN | GitHub | Required |
| LANGFUSE_PUBLIC_KEY | Langfuse | Required |
| LANGFUSE_SECRET_KEY | Langfuse | Required |
| LANGFUSE_HOST | Langfuse | Optional |
| STRIPE_SECRET_KEY | Stripe | Required |
| SLACK_WEBHOOK_URL | Slack | Optional |
| TEAMS_WEBHOOK_URL | Teams | Optional |
| FINOPS_DIGEST_TO | Optional | |
| JIRA_URL | Jira | Optional |
| LINEAR_API_KEY | Linear | Optional |
| GITHUB_ISSUES_REPO | GitHub Issues | Optional |
| Slack bot | ||
| SLACK_BOT_TOKEN | Slack bot | Required |
| SLACK_APP_TOKEN | Slack bot | Required |
| ANTHROPIC_API_KEY | Slack bot | Required |
| SLACK_DAILY_CHANNEL | Slack bot | Optional |
| PR cost comments | ||
| GITHUB_WEBHOOK_SECRET | PR comments | Optional |
| PR_COST_THRESHOLD_USD | PR comments | Optional |
| PR_WEBHOOK_PORT | PR comments | Optional |
| Idle resource cleanup | ||
| FINOPS_CLEANUP_ENABLED | Cleanup | Optional |
| FINOPS_PROTECTED_TAGS | Cleanup | Optional |
| Rate detection (CUR / Athena) | ||
| CUR_ATHENA_DATABASE | Rate detection | Optional |
| CUR_ATHENA_TABLE | Rate detection | Optional |
| Enterprise SSO (OIDC) | ||
| OIDC_ISSUER | SSO | Required |
| OIDC_CLIENT_ID | SSO | Required |
| OIDC_CLIENT_SECRET | SSO | Required |
| OIDC_REDIRECT_URI | SSO | Optional |
| OIDC_GROUPS_CLAIM | SSO | Optional |
| OIDC_ROLE_MAP | SSO | Optional |
| OIDC_DEFAULT_ROLE | SSO | Optional |
| License | ||
| FINOPS_LICENSE_KEY | Your Team license key. Set this in the env block of your Claude Desktop MCP config to unlock Team features. | Optional |
Troubleshooting
"Cost Explorer must be enabled"
Go to AWS Console → Billing → Cost Explorer → Enable Cost Explorer. Takes up to 24 hours. This is required even if you have an active account.
MCP server not showing in Claude / Cursor
Fully quit and reopen the app after editing the config file. Most clients only read config at startup. Run finops-mcp manually in terminal to confirm there are no Python errors.
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 their role. Run as ACCOUNTADMIN: GRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE your_role;