SE

Secure Anthropic MCP Server for AWS Cost Explorer

Deploy a secure MCP server to retrieve AWS Cost Explorer spend and Amazon Bedrock usage from CloudWatch model invocation logs over HTTPS.

Quick Install
npx -y @aarora79/aws-cost-explorer-mcp-server

Overview

This project provides a secure Model Context Protocol (MCP) server that exposes AWS Cost Explorer and Amazon Bedrock model-invocation data (from CloudWatch Logs) over HTTPS. It lets an MCP client — for example, Claude Desktop or a LangGraph agent — query AWS spend and Bedrock usage in natural language via Anthropic’s MCP. The server can run locally (stdio transport) for desktop integrations or as a remote HTTPS service for multi-user or agent-based workflows.

Typical uses include interactive spend exploration, automated reporting, and feeding model-driven agents with contextual cost data. The server supports cross-account access via IAM role assumption so you can analyze spend across multiple AWS accounts if your service role is permitted.

Features

  • Exposes AWS Cost Explorer APIs through the MCP protocol
  • Reads Amazon Bedrock model invocation logs in CloudWatch to report Bedrock usage
  • Supports local (stdio) and remote (HTTPS) MCP transports
  • Optional cross-account cost access via assumed IAM roles
  • Granular breakdowns (by service, region, day, instance type, Bedrock model/region/user)
  • Compatible with Anthropic MCP clients (Claude Desktop) and LangGraph agents

Installation / Configuration

Prerequisites:

  • Python 3.12
  • AWS credentials with Cost Explorer and CloudWatch read permissions
  • (Optional) Bedrock access for model invocation logs
  • (Optional) A domain + TLS cert (for HTTPS remote deployment)

Clone and install:

git clone https://github.com/aarora79/aws-cost-explorer-mcp-server.git
cd aws-cost-explorer-mcp-server

# Create virtual environment and install (uses `uv` helper like in repo)
uv venv --python 3.12
source .venv/bin/activate
uv pip install --requirement pyproject.toml

Environment variables

VariablePurposeExample
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEYAWS credentials (or use instance/role credentials)-
AWS_REGIONDefault AWS Region for API callsus-east-1
BEDROCK_LOG_GROUP_NAMECloudWatch Log Group for model invocation logs/aws/bedrock/invocations
MCP_TRANSPORTTransport mode: “stdio” (local) or “https” (remote)stdio
CROSS_ACCOUNT_ROLE_NAMEOptional IAM role name to assume in other accountsCrossAccountReadOnly
TLS_CERT_PATHPath to TLS certificate (PEM) when using HTTPS/etc/ssl/fullchain.pem
TLS_KEY_PATHPath to TLS private key when using HTTPS/etc/ssl/privkey.pem

Local run (stdio transport)

export MCP_TRANSPORT=stdio
export BEDROCK_LOG_GROUP_NAME=YOUR_BEDROCK_CW_LOG_GROUP_NAME
export AWS_REGION=us-east-1
python server.py

This runs the MCP server using stdin/stdout, suitable for local Claude Desktop setups.

Secure remote server (HTTPS)

  • Option A: Run the server with TLS directly (if the server supports binding to TLS).
  • Option B (recommended): Put an HTTPS reverse proxy (nginx, Traefik) or a load balancer in front of the Python process.

Example systemd / direct TLS run (if TLS flags/env are supported):

export MCP_TRANSPORT=https
export TLS_CERT_PATH=/etc/letsencrypt/live/your-domain/fullchain.pem
export TLS_KEY_PATH=/etc/letsencrypt/live/your-domain/privkey.pem
export BEDROCK_LOG_GROUP_NAME=/aws/bedrock/invocations
export AWS_REGION=us-east-1

# Bind to 0.0.0.0:443 - use a reverse proxy if you prefer
python server.py --host 0.0.0.0 --port 443

Reverse proxy (nginx) example snippet

server {
    listen 443 ssl;
    server_name cost.example.com;
    ssl_certificate /etc/letsencrypt/live/cost.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cost.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

IAM permissions At minimum the server role needs read permissions for Cost Explorer and CloudWatch Logs. Example managed policies:

  • AWSBillingReadOnlyAccess or equivalent custom Cost Explorer policy
  • CloudWatchLogsReadOnlyAccess

If using cross-account role assumption, the MCP server’s role must have sts:AssumeRole permission to the target role(s).

Available Tools / Resources

  • GitHub repository: https://github.com/aarora79/aws-cost-explorer-mcp-server
  • Anthropic MCP spec and docs (for MCP client integration)
  • AWS Cost Explorer API reference
  • Amazon Bedrock model invocation logging docs (CloudWatch setup)
  • Typical MCP clients:
    • Claude Desktop (local MCP client integration)
    • LangGraph agents (MCP client integrated into agents)

Use Cases

  1. Interactive spend exploration with a model

    • Connect Claude Desktop to the local MCP server (stdio). Ask natural-language questions like “Show EC2 spend by instance type for the last 7 days” and receive structured breakdowns.
  2. Bedrock usage tracking

    • Surface Bedrock model invocation counts and cost by region/model/user for the last 30 days by parsing model-invocation CloudWatch Logs and correlating with Cost Explorer.
  3. Cross-account cost reporting

    • From a centralized MCP server, assume roles in other AWS accounts (CROSS_ACCOUNT_ROLE_NAME) to aggregate and compare spend across multiple accounts for chargeback or FinOps workflows.
  4. Agent-enabled automation

    • Deploy the server on EC2 with HTTPS and let a LangGraph agent call it to fetch fresh cost context before making provisioning or remediation decisions.

Example Claude Desktop config (Docker option)

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "aws-cost-explorer": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "AWS_ACCESS_KEY_ID", "-e", "AWS_SECRET_ACCESS_KEY",
        "-e", "AWS_REGION", "-e", "BEDROCK_LOG_GROUP_NAME",
        "-e", "MCP_TRANSPORT", "-e", "CROSS_ACCOUNT_ROLE_NAME",
        "aws-cost-explorer-mcp:latest"
      ]
    }
  }
}