Skip to main content
Glama
motoraif

finops-mcp

by motoraif
README.md
# finops-mcp

A **multi-cloud FinOps [MCP](https://modelcontextprotocol.io) server**. It gives an
AI assistant read-only access to cloud cost and usage data through a single,
uniform set of tools — so you can ask questions like *"what did I spend on AWS
last month, broken down by service?"* or *"forecast next month's bill"* in plain
language.

Today **AWS is fully implemented** (Cost Explorer, Budgets, Cost Optimization
Hub). **Azure, GCP, and OCI** are registered as stubs behind the same interface,
ready to be built out next.

> **Read-only by design.** Every tool only *reads* cost data. Nothing in this
> server modifies, creates, or deletes cloud resources.

---

## Features

| Tool | What it does | AWS status |
|------|--------------|------------|
| `list_providers` | List known providers and whether each is implemented | ✅ |
| `get_cost_summary` | Grouped cost breakdown (by service, region, account, usage type, instance type) | ✅ |
| `get_cost_trend` | Cost time series (daily or monthly) | ✅ |
| `get_budgets` | Budgets with limit / actual / forecasted spend | ✅ |
| `get_forecast` | Forecasted cost for a future period | ✅ |
| `get_recommendations` | Cost-optimization recommendations (savings) | ✅ |
| `compare_providers` | Total spend across all implemented providers | ✅ |

All tools return a **normalized, provider-agnostic shape** (see `models.py`), so
the assistant gets consistent output no matter which cloud answered.

---

## Architecture

```
finops-mcp/
├── server.py            # MCP server; registers the tools
├── config.py            # Builds the provider registry from env vars
├── models.py            # Normalized, provider-agnostic data models
├── providers/
│   ├── base.py          # Abstract CostProvider interface (read-only)
│   ├── aws.py           # AWS: Cost Explorer + Budgets + Cost Optimization Hub
│   ├── azure.py         # STUB: Azure Cost Management (planned)
│   ├── gcp.py           # STUB: GCP BigQuery billing export (planned)
│   └── oci.py           # STUB: OCI Usage API (planned)
├── tests/               # Unit tests (no cloud creds needed; boto3 is faked)
├── requirements.txt
└── mcp.json.example     # Example MCP client configuration
```

**Design idea:** the tool layer is thin and dispatches to a `CostProvider`. Each
provider adapter translates its cloud's native API into the shared models. Adding
a cloud means implementing one class — the tools don't change.

### How each cloud exposes cost data

| Cloud | Data source | Auth |
|-------|-------------|------|
| **AWS** | Cost Explorer (`ce`), Budgets, Cost Optimization Hub via `boto3` | Named profile or default credential chain |
| **Azure** *(planned)* | Cost Management API | Service principal / `DefaultAzureCredential` |
| **GCP** *(planned)* | Billing export in BigQuery (requires export to be configured) | Service account |
| **OCI** *(planned)* | Usage API (`UsageapiClient`) | OCI config file / API key |

---

## Requirements

- Python 3.10+
- For AWS: credentials with read access to Cost Explorer / Budgets. A named
  profile works well (this project was developed against a profile called
  `tau-dev`).

### AWS IAM permissions (read-only)

The AWS provider needs these actions:

```
ce:GetCostAndUsage
ce:GetCostForecast
budgets:DescribeBudgets
cost-optimization-hub:ListRecommendations   (optional; account must be enrolled)
sts:GetCallerIdentity
```

> **Note on regions:** AWS Cost Explorer and Budgets are global services
> accessed through the **`us-east-1`** endpoint. The provider always calls
> `us-east-1` regardless of where your resources run.

---

## Setup

```bash
git clone <your-repo-url>
cd finops-mcp

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

---

## Configuration

Providers are configured entirely through **environment variables** — no
credentials are ever hardcoded.

| Env var | Purpose |
|---------|---------|
| `AWS_PROFILE` | Named AWS profile to use (optional; else default credential chain) |
| `FINOPS_AZURE_SUB_ID` | Azure subscription id *(stub)* |
| `FINOPS_GCP_BQ_TABLE` | GCP BigQuery billing export table *(stub)* |
| `FINOPS_OCI_TENANCY` | OCI tenancy OCID *(stub)* |

---

## Running

The server speaks MCP over **stdio**:

```bash
AWS_PROFILE=tau-dev python server.py
```

It's designed to be launched by an MCP client rather than run by hand.

### Connect it to an MCP client

Add it to your client's `mcp.json` (see `mcp.json.example`):

```json
{
  "mcpServers": {
    "finops": {
      "command": "python",
      "args": ["/absolute/path/to/finops-mcp/server.py"],
      "env": { "AWS_PROFILE": "tau-dev" },
      "timeout": 120000
    }
  }
}
```

Point `command` at your venv's Python (e.g. `.venv/bin/python`) if the MCP
dependencies are installed there.

---

## Example prompts

Once connected, you can ask the assistant:

- "List the cost of my AWS account this month, grouped by service."
- "Show me the monthly cost trend for AWS over the last 3 months."
- "What's the forecast for next month on AWS?"
- "Are there any AWS budgets, and how are we tracking against them?"
- "Any cost-optimization recommendations for AWS?"

---

## Testing

Unit tests fake the boto3 session, so they run with **no AWS credentials and no
network**:

```bash
source .venv/bin/activate
python -m pytest tests/ -v
```

To smoke-test against a real AWS account:

```bash
AWS_PROFILE=tau-dev python -c "
from config import get_provider
p = get_provider('aws')
s = p.get_cost_summary('2026-08-01', '2026-09-01', 'service')
print(f'{s.total} {s.currency} across {len(s.items)} services')
"
```

---

## Roadmap

- [x] AWS provider (cost summary, trend, budgets, forecast, recommendations)
- [ ] Azure provider (Cost Management API)
- [ ] GCP provider (BigQuery billing export)
- [ ] OCI provider (Usage API)
- [ ] Tag-based cost allocation and untagged-cost detection
- [ ] Reserved Instance / Savings Plan / commitment coverage & utilization
- [ ] Optional write actions (behind explicit opt-in), e.g. budget creation

---

## Notes & limitations

- **AWS forecast** requires at least ~14 days of historical usage, otherwise the
  API returns no data (handled gracefully with a clear error).
- **Cost Optimization Hub** must be enrolled for the account; if not, the
  recommendations tool returns an empty list rather than failing.
- Amounts use AWS **BlendedCost**. Other metrics (UnblendedCost, AmortizedCost)
  can be added as options later.

## License

MIT