AWS Cost Explorer & Bedrock Logs

Recupera datos de gasto de AWS desde Cost Explorer y datos de uso de Amazon Bedrock desde registros de CloudWatch.

Documentación

Servidor y Cliente MCP de AWS Cost Explorer y Registros de Invocación de Modelos de Amazon Bedrock

Un servidor MCP para obtener datos de gastos de AWS mediante Cost Explorer y datos de uso de Amazon Bedrock mediante Model invocation logs en Amazon Cloud Watch a través del MCP (Protocolo de Control de Modelos) de Anthropic. Consulta la sección sobre "servidor" MCP remoto seguro para ver cómo puedes ejecutar tu servidor MCP sobre HTTPS.

flowchart LR
    User([User]) --> UserApp[User Application]
    UserApp --> |Queries| Host[Host]
    
    subgraph "Claude Desktop"
        Host --> MCPClient[MCP Client]
    end
    
    MCPClient --> |MCP Protocol over HTTPS| MCPServer[AWS Cost Explorer MCP Server]
    
    subgraph "AWS Services"
        MCPServer --> |API Calls| CostExplorer[(AWS Cost Explorer)]
        MCPServer --> |API Calls| CloudWatchLogs[(AWS CloudWatch Logs)]
    end

Puedes ejecutar el servidor MCP localmente y acceder a él mediante Claude Desktop, o también puedes ejecutar un servidor MCP remoto en Amazon EC2 y acceder a él mediante un cliente MCP integrado en un Agente LangGraph.

🚨También puedes usar este servidor MCP para obtener información de gastos de AWS de otras cuentas siempre que el rol de IAM utilizado por el servidor MCP pueda asumir roles en esas otras cuentas🚨

Video de demostración

AWS Cost Explorer MCP Server Deep Dive

Descripción general

Esta herramienta proporciona una forma conveniente de analizar y visualizar datos de gastos en la nube de AWS utilizando el modelo Claude de Anthropic como interfaz interactiva. Funciona como un servidor MCP que expone la funcionalidad de la API de AWS Cost Explorer a Claude Desktop, permitiéndote hacer preguntas sobre tus gastos de AWS en lenguaje natural.

Características

  • Análisis de gastos de Amazon EC2: Consulta desgloses detallados de los gastos de EC2 del último día
  • Análisis de gastos de Amazon Bedrock: Consulta desgloses por región, usuarios y modelos de los últimos 30 días
  • Informes de gastos por servicio: Analiza los gastos en todos los servicios de AWS de los últimos 30 días
  • Desglose detallado de costos: Obtén datos de costos granulares por día, región, servicio y tipo de instancia
  • Interfaz interactiva: Usa Claude para consultar tus datos de costos mediante lenguaje natural

Requisitos

  • Python 3.12
  • Credenciales de AWS con acceso a Cost Explorer
  • Acceso a la API de Anthropic (para la integración con Claude)
  • [Opcional] Acceso a Amazon Bedrock (para el Agente LangGraph)
  • [Opcional] Amazon EC2 para ejecutar un servidor MCP remoto

Instalación

  1. Instala uv:

    # On macOS and Linux
    curl -LsSf https://astral.sh/uv/install.sh | sh
    
    # On Windows
    powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
    

    Las opciones de instalación adicionales están documentadas aquí

  2. Clona este repositorio: (asumiendo que esto se actualizará para apuntar a aws-samples)

    git clone https://github.com/aarora79/aws-cost-explorer-mcp.git
    cd aws-cost-explorer-mcp
    
  3. Configura el entorno virtual de Python e instala las dependencias:

    uv venv --python 3.12 && source .venv/bin/activate && uv pip install --requirement pyproject.toml
    
  4. Configura tus credenciales de AWS:

    mkdir -p ~/.aws
    # Set up your credentials in ~/.aws/credentials and ~/.aws/config
    

    Si usas AWS IAM Identity Center, sigue la documentación para configurar tus credenciales de corta duración

Uso

Requisitos previos

  1. Configura los registros de invocación de modelos en Amazon CloudWatch.
  2. Asegúrate de que el usuario/rol de IAM utilizado tenga acceso de solo lectura completo a Amazon Cost Explorer y Amazon CloudWatch; esto es necesario para que el servidor MCP recupere datos de estos servicios. Consulta aquí y aquí para ver ejemplos de políticas que puedes usar y modificar según tus requisitos.
  3. Para permitir que tu servidor MCP acceda a información de gastos de AWS de otras cuentas, establece el parámetro CROSS_ACCOUNT_ROLE_NAME al iniciar el servidor y ahora puedes proporcionar el ID de cuenta de AWS de otra cuenta al interactuar con tu agente, y el agente pasará el ID de cuenta al servidor.

Configuración local

Usa stdio como transporte para MCP; tanto el servidor MCP como el cliente se ejecutan en tu máquina local.

Iniciar el servidor (local)

Ejecuta el servidor usando:

export MCP_TRANSPORT=stdio
export BEDROCK_LOG_GROUP_NAME=YOUR_BEDROCK_CW_LOG_GROUP_NAME
export CROSS_ACCOUNT_ROLE_NAME=ROLE_NAME_FOR_THE_ROLE_TO_ASSUME_IN_OTHER_ACCOUNTS # can be ignored if you do not want AWS spend info from other accounts
python server.py

Configuración de Claude Desktop

Hay dos formas de configurar esta herramienta con Claude Desktop:

Opción 1: Usando Docker

Agrega lo siguiente a tu archivo de configuración de Claude Desktop. El archivo se puede encontrar en estas rutas según tu sistema operativo.

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json.
  • Windows: %APPDATA%\Claude\claude_desktop_config.json.
  • Linux: ~/.config/Claude/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" ],
      "env": {
        "AWS_ACCESS_KEY_ID": "YOUR_ACCESS_KEY_ID",
        "AWS_SECRET_ACCESS_KEY": "YOUR_SECRET_ACCESS_KEY",
        "AWS_REGION": "us-east-1",
        "BEDROCK_LOG_GROUP_NAME": "YOUR_CLOUDWATCH_BEDROCK_MODEL_INVOCATION_LOG_GROUP_NAME",
        "CROSS_ACCOUNT_ROLE_NAME": "ROLE_NAME_FOR_THE_ROLE_TO_ASSUME_IN_OTHER_ACCOUNTS",
        "MCP_TRANSPORT": "stdio"
      }
    }
  }
}

IMPORTANTE: Reemplaza YOUR_ACCESS_KEY_ID y YOUR_SECRET_ACCESS_KEY con tus credenciales reales de AWS. Nunca envíes credenciales reales al control de versiones.

Opción 2: Usando UV (sin Docker)

Si prefieres ejecutar el servidor directamente sin Docker, puedes usar UV:

{
  "mcpServers": {
    "aws_cost_explorer": {
      "command": "uv",
      "args": [
          "--directory",
          "/path/to/aws-cost-explorer-mcp-server",
          "run",
          "server.py"
      ],
      "env": {
        "AWS_ACCESS_KEY_ID": "YOUR_ACCESS_KEY_ID",
        "AWS_SECRET_ACCESS_KEY": "YOUR_SECRET_ACCESS_KEY",
        "AWS_REGION": "us-east-1",
        "BEDROCK_LOG_GROUP_NAME": "YOUR_CLOUDWATCH_BEDROCK_MODEL_INVOCATION_LOG_GROUP_NAME",
        "CROSS_ACCOUNT_ROLE_NAME": "ROLE_NAME_FOR_THE_ROLE_TO_ASSUME_IN_OTHER_ACCOUNTS",
        "MCP_TRANSPORT": "stdio"
      }
    }
  }
}

Asegúrate de reemplazar la ruta del directorio con la ruta real a tu repositorio en tu sistema.

Configuración remota

Usa sse como transporte para MCP; los servidores MCP están en EC2 y el cliente se ejecuta en tu máquina local. Ten en cuenta que Claude Desktop no admite servidores MCP remotos en este momento (consulta este problema de GitHub).

Iniciar el servidor (remoto)

Puedes iniciar un servidor MCP remoto en Amazon EC2 siguiendo las mismas instrucciones que arriba. Asegúrate de establecer MCP_TRANSPORT como sse (eventos del lado del servidor) como se muestra a continuación. Ten en cuenta que MCP usa JSON-RPC 2.0 como formato de transmisión; por lo tanto, el protocolo en sí no incluye autorización ni autenticación (consulta este problema de GitHub); no envíes ni recibas datos sensibles a través de MCP.

Ejecuta el servidor usando:

export MCP_TRANSPORT=sse
export BEDROCK_LOG_GROUP_NAME=YOUR_BEDROCK_CW_LOG_GROUP_NAME
export CROSS_ACCOUNT_ROLE_NAME=ROLE_NAME_FOR_THE_ROLE_TO_ASSUME_IN_OTHER_ACCOUNTS # can be ignored if you do not want AWS spend info from other accounts
python server.py
  1. El servidor MCP comenzará a escuchar en el puerto TCP 8000.
  2. Configura una regla de entrada en el grupo de seguridad asociado con tu instancia EC2 para permitir el acceso al puerto TCP 8000 desde tu máquina local (donde ejecutas el cliente MCP/aplicación basada en LangGraph) a tu instancia EC2.

Consulta también la sección sobre cómo ejecutar un "servidor" MCP remoto seguro, es decir, un servidor al que tus clientes MCP puedan conectarse a través de HTTPS.

Pruebas con un cliente MCP CLI

Puedes probar tu servidor MCP remoto con el script mcp_sse_client.py. Ejecutar este script imprimirá la lista de herramientas disponibles del servidor MCP y una salida para la herramienta get_bedrock_daily_usage_stats.

# set the hostname for your MCP server
MCP_SERVER_HOSTNAME=YOUR_MCP_SERVER_EC2_HOSTNAME
# or localhost if your MCP server is running locally
# MCP_SERVER_HOSTNAME=localhost 
AWS_ACCOUNT_ID=AWS_ACCOUNT_ID_TO_GET_INFO_ABOUT # if set to empty or if the --aws-account-id switch is not specified then it gets the info about the AWS account MCP server is running in
python mcp_sse_client.py --host $MCP_SERVER_HOSTNAME --aws-account-id $AWS_ACCOUNT_ID

Pruebas con la aplicación Chainlit

El archivo app.py en este repositorio proporciona una aplicación Chainlit (chatbot) que crea un agente LangGraph que usa LangChain MCP Adapter para importar las herramientas proporcionadas por el servidor MCP como herramientas en un Agente LangGraph. El agente puede usar un LLM para responder preguntas de los usuarios y usar las herramientas disponibles según sea necesario. Así, si el usuario hace una pregunta como "¿Cómo fue mi uso de Bedrock en la última semana?", el agente usará las herramientas disponibles a través del servidor MCP remoto para responder esa pregunta. Usamos el modelo Claude 3.5 Haiku disponible a través de Amazon Bedrock para impulsar este agente.

Ejecuta la aplicación Chainlit usando:

chainlit run app.py --port 8080 

Se debería abrir una ventana del navegador en localhost:8080 y deberías poder usar el chatbot para obtener detalles sobre tus gastos de AWS.

Herramientas disponibles

El servidor expone las siguientes herramientas que Claude puede usar:

  1. get_ec2_spend_last_day(): Recupera datos de gastos de EC2 del día anterior
  2. get_detailed_breakdown_by_day(days=7): Entrega un análisis completo de costos por región, servicio y tipo de instancia
  3. get_bedrock_daily_usage_stats(days=7, region='us-east-1', log_group_name='BedrockModelInvocationLogGroup'): Entrega un desglose diario del uso de modelos por región y usuarios.
  4. get_bedrock_hourly_usage_stats(days=7, region='us-east-1', log_group_name='BedrockModelInvocationLogGroup'): Entrega un desglose diario y por hora del uso de modelos por región y usuarios.

Consultas de ejemplo

Una vez conectado a Claude a través de una interfaz habilitada para MCP, puedes hacer preguntas como:

  • "Ayúdame a entender mis gastos de Bedrock en las últimas semanas"
  • "¿Cuál fue mi gasto de EC2 ayer?"
  • "Muéstrame mis 5 principales servicios de AWS por costo del último mes"
  • "Analiza mis gastos por región de los últimos 14 días"
  • "¿Qué tipos de instancia me están costando más?"
  • "¿Qué servicios tuvieron el mayor aumento de costos mes a mes?"

Soporte de Docker

Se incluye un Dockerfile para implementación en contenedores:

docker build -t aws-cost-explorer-mcp .
docker run -v ~/.aws:/root/.aws aws-cost-explorer-mcp

Desarrollo

Estructura del proyecto

  • server.py: Implementación principal del servidor con herramientas MCP
  • pyproject.toml: Dependencias del proyecto y metadatos
  • Dockerfile: Definición del contenedor para implementaciones

Agregar nuevas herramientas de análisis de costos

Para ampliar la funcionalidad:

  1. Agrega nuevas funciones a server.py
  2. Anótalas con @mcp.tool()
  3. Implementa las llamadas a la API de AWS Cost Explorer
  4. Formatea los resultados para facilitar su lectura

Servidor MCP "remoto" seguro

Podemos usar nginx como proxy inverso para que proporcione un endpoint HTTPS para conectarse al servidor MCP. Los clientes MCP remotos pueden conectarse a nginx a través de HTTPS y luego puede enviar tráfico internamente a http://localhost:8000. Los siguientes pasos describen cómo hacer esto.

  1. Habilita el acceso al puerto TCP 443 desde la dirección IP de tu cliente MCP (tu computadora portátil o cualquier lugar) en las reglas de entrada del grupo de seguridad asociado con tu instancia EC2.

  2. Necesitarás un certificado HTTPS y una clave privada para continuar. Digamos que usas your-mcp-server-domain-name.com como dominio para tu servidor MCP; entonces necesitarás un certificado SSL para your-mcp-server-domain-name.com y será accesible para los clientes MCP como https://your-mcp-server-domain-name.com/sse. Si bien puedes usar un certificado autofirmado, requeriría deshabilitar la verificación SSL en el cliente MCP; NO recomendamos que hagas eso. Si alojas tu servidor MCP en EC2, puedes generar un certificado SSL usando no-ip o Let' Encrypt u otros servicios similares. Coloca los archivos del certificado SSL y la clave privada en las carpetas /etc/ssl/certs y /etc/ssl/privatekey respectivamente en tu máquina EC2.

  3. Instala nginx en tu máquina EC2 usando los siguientes comandos.

    sudo apt-get install nginx
    sudo nginx -t
    sudo systemctl reload nginx
    
  4. Obtén el nombre de host de tu instancia EC2; esto será necesario para configurar el proxy inverso nginx.

    TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") && curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/public-hostname
    
  5. Copia el siguiente contenido en un nuevo archivo /etc/nginx/conf.d/ec2.conf. Reemplaza YOUR_EC2_HOSTNAME, /etc/ssl/certs/cert.pem y /etc/ssl/privatekey/privkey.pem con valores apropiados para tu configuración.

    server {
     listen 80;
     server_name YOUR_EC2_HOSTNAME;
    
     # Optional: Redirect HTTP to HTTPS
     return 301 https://$host$request_uri;
     }
    
     server {
         listen 443 ssl;
         server_name YOUR_EC2_HOSTNAME;
    
         # Self-signed certificate paths
         ssl_certificate     /etc/ssl/certs/cert.pem;
         ssl_certificate_key /etc/ssl/privatekey/privkey.pem; 
    
         # Optional: Good practice
         ssl_protocols       TLSv1.2 TLSv1.3;
         ssl_ciphers         HIGH:!aNULL:!MD5;
    
         location / {
             # Reverse proxy to your local app (e.g., port 8000)
             proxy_pass http://127.0.0.1:8000;
             proxy_http_version 1.1;
             proxy_set_header Host $host;
             proxy_set_header X-Real-IP $remote_addr;
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         }
     }
    
    
  6. Reinicia nginx.

    sudo systemctl start nginx
    
  7. Inicia tu servidor MCP como de costumbre, como se describe en la sección de configuración remota.

  8. Tu servidor MCP ahora es accesible a través de HTTPS como https://your-mcp-server-domain-name.com/sse para tu cliente MCP.

  9. En el lado del cliente (por ejemplo, en tu computadora portátil o en tu Agente), configura tu cliente MCP para comunicarse con tu servidor MCP de la siguiente manera.

    MCP_SERVER_HOSTNAME=YOUR_MCP_SERVER_DOMAIN_NAME
    AWS_ACCOUNT_ID=AWS_ACCOUNT_ID_TO_GET_INFO_ABOUT # if set to empty or if the --aws-account-id switch is not specified then it gets the info about the AWS account MCP server is running in
    python mcp_sse_client.py --host $MCP_SERVER_HOSTNAME --port 443 --aws-account-id $AWS_ACCOUNT_ID
    

    De manera similar, puedes ejecutar la aplicación Chainlit para hablar con el servidor MCP remoto a través de HTTPS.

    export MCP_SERVER_URL=YOUR_MCP_SERVER_DOMAIN_NAME
    export MCP_SERVER_PORT=443
    chainlit run app.py --port 8080
    

    De manera similar, puedes ejecutar el Agente LangGraph para hablar con el servidor MCP remoto a través de HTTPS.

    python langgraph_agent_mcp_sse_client.py --host $MCP_SERVER_HOSTNAME --port 443 --aws-account-id $AWS_ACCOUNT_ID
    

Licencia

Licencia MIT

Agradecimientos

  • Esta herramienta utiliza el marco MCP de Anthropic
  • Impulsado por la API de AWS Cost Explorer
  • Construido con FastMCP para la implementación del servidor
  • El README se generó proporcionando un volcado de texto del repositorio a través de GitIngest a Claude