MCP - Model Context Protocol

Introducción

El servidor MCP de Bitnovo Pay permite a los agentes de IA interactuar con la API de Bitnovo Pay para crear y gestionar pagos con criptomonedas de forma autónoma. Esta integración facilita la automatización de pagos cripto en aplicaciones que utilizan modelos de lenguaje como ChatGPT, Claude, o Gemini.


¿Qué es MCP?

Model Context Protocol (MCP) es un protocolo estándar abierto que permite a los modelos de IA acceder a herramientas y servicios externos de forma estructurada y segura.

Conceptos clave de MCP

Concepto
Descripción

MCP Server

Proceso que expone capacidades (herramientas, recursos) a través del protocolo MCP vía stdio

MCP Tools

Funciones que el modelo de IA puede invocar (ej: create_payment_link)

MCP Resources

Datos que el servidor puede proveer al modelo (ej: catálogo de criptomonedas)

stdio Transport

Comunicación entre cliente y servidor MCP usando entrada/salida estándar

El servidor MCP de Bitnovo Pay implementa este protocolo para exponer 8 herramientas MCP que permiten gestión completa de pagos cripto desde cualquier cliente MCP compatible.

Especificación oficial: modelcontextprotocol.io


Inicio Rápido (5 minutos)

Paso 1: Obtén tus credenciales

  1. Crea cuenta en Bitnovo Pay

  2. Obtén tu Device ID desde el panel de Bitnovo

  3. (Opcional) Genera Device Secret para webhooks

Paso 2: Configura tu cliente MCP

Agrega esta configuración a tu cliente MCP (ejemplo para Claude Desktop):

{
  "mcpServers": {
    "bitnovo-pay": {
      "command": "npx",
      "args": ["-y", "@bitnovopay/mcp-bitnovo-pay"],
      "env": {
        "BITNOVO_DEVICE_ID": "tu_device_id_aqui",
        "BITNOVO_BASE_URL": "https://pos.bitnovo.com"
      }
    }
  }
}

Paso 3: Reinicia tu cliente MCP

Reinicia Claude Desktop, ChatGPT, o tu cliente MCP para cargar el servidor.

Paso 4: ¡Prueba!

Pregunta a tu asistente IA:

"Crea un pago de 10 euros"

✅ Deberías recibir una URL de pago lista para compartir.


Características principales

  • 8 herramientas MCP para gestión completa de pagos:

    • create_payment_onchain - Genera direcciones de criptomonedas para pagos directos

    • create_payment_link - Crea URLs de pago web con gestión de redirecciones

    • get_payment_status - Consulta el estado de un pago con información detallada

    • list_currencies_catalog - Obtiene las criptomonedas soportadas con filtrado

    • generate_payment_qr - Genera códigos QR personalizados desde pagos existentes

    • get_webhook_events - Consulta eventos de webhook recibidos en tiempo real

    • get_webhook_url - Obtiene la URL pública del webhook con instrucciones de configuración

    • get_tunnel_status - Diagnostica el estado de la conexión del túnel

  • Sistema de webhooks automático con 3 proveedores de túnel:

    • 🔗 ngrok: URL persistente gratuita (1 dominio estático por cuenta)

    • 🌐 zrok: Open-source 100% gratuito con URLs persistentes

    • 🏢 manual: Para servidores con IP pública (N8N, Opal, VPS)

  • Compatible con múltiples LLMs:

    • 🤖 OpenAI ChatGPT (GPT-5, GPT-4o, Responses API, Agents SDK)

    • 🧠 Google Gemini (Gemini 2.5 Flash/Pro Sept 2025, CLI, FastMCP)

    • 🔮 Claude (Claude Desktop, Claude Code)

  • Códigos QR de alta calidad (v1.1.0+):

    • 📱 Resolución por defecto de 512px (mejorada desde 300px) para pantallas modernas

    • 🖨️ Soporte hasta 2000px para impresión profesional

    • ✨ Bordes nítidos con algoritmos de interpolación optimizados

    • 🎨 Branding personalizado de Bitnovo Pay con escalado suave de logo

  • Seguridad y privacidad:

    • Comunicación HTTPS obligatoria

    • Validación de firmas HMAC para webhooks

    • Prevención de ataques de replay con caché de nonces

    • Datos sensibles enmascarados en logs

    • Sin almacenamiento local (operación stateless)

Requisitos previos

Antes de comenzar, asegúrate de tener:

Requisito
Descripción
Necesario para

Node.js 18+

Runtime de JavaScript

Ejecutar servidor MCP

Cuenta Bitnovo Pay

Registro en bitnovo.com/pay

Obtener credenciales

Device ID

Identificador de dispositivo del panel

Todas las operaciones

⚠️ Device Secret

Secret HMAC (opcional)

Webhooks con validación

Cliente MCP

Claude, ChatGPT, o Gemini

Interactuar con servidor

⚠️ ngrok/zrok (opcional)

Túnel para webhooks

Desarrollo local con webhooks

Instalación

Hay dos formas de instalar el servidor MCP de Bitnovo Pay:

Opción 1: Usar npx (Recomendado)

No requiere instalación previa, solo necesitas configurar tu cliente MCP (ver sección "Configuración por plataforma" más abajo) usando:

npx -y @bitnovopay/mcp-bitnovo-pay

✅ Ventajas:

  • Siempre obtienes la última versión publicada

  • No requiere clonar el repositorio

  • No requiere compilar el código

  • Actualización automática en cada ejecución

  • Perfecto para usuarios finales

Opción 2: Clonar el repositorio (Para desarrollo)

Si necesitas modificar el código o contribuir al proyecto:

# Clonar el repositorio
git clone https://github.com/bitnovo/mcp-bitnovo-pay.git
cd mcp-bitnovo-pay

# Instalar dependencias
npm install

# Compilar el proyecto
npm run build

# Ejecutar en modo desarrollo
npm run dev

✅ Ventajas:

  • Control total del código fuente

  • Permite modificaciones y desarrollo local

  • Ideal para contribuir al proyecto

Configuración de credenciales

Obtén tus credenciales desde el panel de Bitnovo Pay:

  • Device ID: Identificador único de tu comercio

  • Device Secret: (Requerido para webhooks) Para validación de firmas HMAC

  • Base URL: URL del entorno (desarrollo o producción)

Configuración por plataforma

OpenAI ChatGPT

Para integrar con ChatGPT (GPT-4o, GPT-5), crea o edita tu archivo de configuración:

Ubicación: ~/.config/openai/mcp-config.json

Opción A: Usando npx (Recomendado)

{
  "mcpServers": {
    "bitnovo-pay": {
      "command": "npx",
      "args": ["@bitnovopay/mcp-bitnovo-pay"],
      "env": {
        "BITNOVO_DEVICE_ID": "tu_device_id_aqui",
        "BITNOVO_BASE_URL": "https://pos.bitnovo.com.com",
        "BITNOVO_DEVICE_SECRET": "tu_device_secret_hex"
      }
    }
  }
}

Con webhooks habilitados (desarrollo local con ngrok):

{
  "mcpServers": {
    "bitnovo-pay": {
      "command": "npx",
      "args": ["-y", "@bitnovopay/mcp-bitnovo-pay"],
      "env": {
        "BITNOVO_DEVICE_ID": "tu_device_id_aqui",
        "BITNOVO_BASE_URL": "https://pos.bitnovo.com.com",
        "BITNOVO_DEVICE_SECRET": "tu_device_secret_hex",
        "WEBHOOK_ENABLED": "true",
        "TUNNEL_ENABLED": "true",
        "TUNNEL_PROVIDER": "ngrok",
        "NGROK_AUTHTOKEN": "tu_token_ngrok",
        "NGROK_DOMAIN": "bitnovo-dev.ngrok-free.app"
      }
    }
  }
}

Soportado desde: Marzo 2025 (GPT-5 desde Agosto 2025)

Google Gemini

Para integrar con Gemini 2.5, configura el archivo de FastMCP:

Ubicación: ~/.config/gemini/mcp-config.json

Opción A: Usando npx (Recomendado)

{
  "mcpServers": {
    "bitnovo-pay": {
      "command": "npx",
      "args": ["@bitnovopay/mcp-bitnovo-pay"],
      "env": {
        "BITNOVO_DEVICE_ID": "tu_device_id_aqui",
        "BITNOVO_BASE_URL": "https://pos.bitnovo.com.com",
        "BITNOVO_DEVICE_SECRET": "tu_device_secret_hex"
      }
    }
  }
}

Soportado desde: Abril 2025 (Modelos Sept 2025)

Claude (Anthropic)

Para integrar con Claude Desktop o Claude Code:

Ubicación macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Ubicación Windows: %APPDATA%\Claude\claude_desktop_config.json

Configuración básica (sin webhooks)

{
  "mcpServers": {
    "bitnovo-pay": {
      "command": "npx",
      "args": ["@bitnovopay/mcp-bitnovo-pay"],
      "env": {
        "BITNOVO_DEVICE_ID": "tu_device_id_aqui",
        "BITNOVO_BASE_URL": "https://pos.bitnovo.com.com",
        "BITNOVO_DEVICE_SECRET": "tu_device_secret_hex"
      }
    }
  }
}

Configuración con webhooks (desarrollo local con ngrok)

{
  "mcpServers": {
    "bitnovo-pay": {
      "command": "npx",
      "args": ["@bitnovopay/mcp-bitnovo-pay"],
      "env": {
        "BITNOVO_DEVICE_ID": "tu_device_id_aqui",
        "BITNOVO_BASE_URL": "https://pos.bitnovo.com.com",
        "BITNOVO_DEVICE_SECRET": "tu_device_secret_hex",
        "WEBHOOK_ENABLED": "true",
        "TUNNEL_ENABLED": "true",
        "TUNNEL_PROVIDER": "ngrok",
        "NGROK_AUTHTOKEN": "tu_token_ngrok",
        "NGROK_DOMAIN": "bitnovo-dev.ngrok-free.app"
      }
    }
  }
}

Configuración para N8N/Opal/Servidor

{
  "mcpServers": {
    "bitnovo-pay": {
      "command": "npx",
      "args": ["@bitnovopay/mcp-bitnovo-pay"],
      "env": {
        "BITNOVO_DEVICE_ID": "tu_device_id_aqui",
        "BITNOVO_BASE_URL": "https://pos.bitnovo.com.com",
        "BITNOVO_DEVICE_SECRET": "tu_device_secret_hex",
        "WEBHOOK_ENABLED": "true",
        "TUNNEL_ENABLED": "false",
        "WEBHOOK_PUBLIC_URL": "https://n8n.empresa.com"
      }
    }
  }
}

Soportado desde: 2025

Referencia de herramientas MCP

Herramientas de Pago (5)

1. create_payment_onchain

Crea un pago con dirección de criptomoneda específica para transacciones directas en blockchain.

Usar cuando: El usuario especifica una criptomoneda concreta (Bitcoin, ETH, USDC, etc.)

Parámetros:

{
  "amount_eur": 50.0,
  "input_currency": "BTC",
  "fiat": "EUR",
  "notes": "Pago por café",
  "include_qr": true
}

Respuesta:

{
  "identifier": "abc-123-def",
  "payment_uri": "bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?amount=0.001",
  "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
  "qr_address": "data:image/png;base64,...",
  "qr_payment_uri": "data:image/png;base64,...",
  "expected_output_amount": "0.001",
  "currency_id": "BTC",
  "fiat_amount": "50.00",
  "status": "PE"
}

Ejemplos de uso:

  • "Crear un pago en Bitcoin por 50 euros"

  • "Generar dirección ETH para 100 euros"

  • "Necesito un QR de USDC para 25 euros"


2. create_payment_link

Crea una URL de pago web donde el cliente puede elegir su criptomoneda preferida.

Usar cuando: Solicitud de pago genérica sin criptomoneda específica mencionada (OPCIÓN POR DEFECTO)

Parámetros:

{
  "amount_eur": 50.0,
  "fiat": "EUR",
  "url_ok": "https://mitienda.com/exito",
  "url_ko": "https://mitienda.com/cancelado",
  "notes": "Pedido #1234",
  "include_qr": true
}

Respuesta:

{
  "identifier": "abc-123-def",
  "web_url": "https://payments.bitnovo.com/pay/abc-123-def",
  "qr_web_url": "data:image/png;base64,...",
  "fiat_amount": "50.00",
  "fiat_currency": "EUR",
  "status": "PE"
}

Ejemplos de uso:

  • "Crear un pago de 50 euros"

  • "Generar QR para cobrar 100 euros"

  • "Dame el link de pago para 25 euros"


3. get_payment_status

Consulta el estado actual de un pago con información detallada.

Parámetros:

{
  "identifier": "abc-123-def"
}

Respuesta:

{
  "identifier": "abc-123-def",
  "status": "CO",
  "status_description": "Completed",
  "fiat_amount": "50.00",
  "crypto_amount": "0.001",
  "currency_id": "BTC",
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:35:00Z"
}

Estados posibles:

  • NR (Not Ready): Pre-pago creado, sin cripto asignada

  • PE (Pending): Esperando pago del cliente

  • AC (Awaiting Completion): Cripto detectada en mempool

  • CO (Completed): Pago confirmado en blockchain

  • EX (Expired): Tiempo límite de pago excedido

  • CA (Cancelled): Pago cancelado

  • FA (Failed): Transacción falló al confirmar

Ejemplos de uso:

  • "¿Cuál es el estado del pago abc-123-def?"

  • "¿Se completó el pago?"

  • "Verificar estado de pago"


4. list_currencies_catalog

Obtiene el catálogo de criptomonedas disponibles con filtrado opcional por importe.

Parámetros:

{
  "filter_by_amount": 25.0
}

Respuesta:

{
  "currencies": [
    {
      "symbol": "BTC",
      "name": "Bitcoin",
      "blockchain": "Bitcoin",
      "min_amount": "0.0001",
      "max_amount": "10.0",
      "decimals": 8
    },
    {
      "symbol": "ETH",
      "name": "Ethereum",
      "blockchain": "Ethereum",
      "min_amount": "0.001",
      "max_amount": "100.0",
      "decimals": 18
    }
  ]
}

Ejemplos de uso:

  • "¿Qué criptomonedas están disponibles?"

  • "¿Qué monedas aceptan pagos de 50 euros?"

  • "Mostrar catálogo de criptos"


5. generate_payment_qr

Genera códigos QR personalizados desde pagos existentes.

Parámetros:

{
  "identifier": "abc-123-def",
  "qr_type": "both",
  "size": 512,
  "style": "branded",
  "branding": true
}

Opciones de qr_type:

  • address: Solo dirección cripto (cliente ingresa importe manualmente)

  • payment_uri: Dirección + importe incluido (recomendado)

  • both: Genera ambos tipos (recomendado)

  • gateway_url: QR de la URL del gateway de pago

Respuesta:

{
  "qr_address": "data:image/png;base64,...",
  "qr_payment_uri": "data:image/png;base64,...",
  "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
  "payment_uri": "bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?amount=0.001"
}

Ejemplos de uso:

  • "Generar QR más grande para el pago"

  • "Crear QR sin branding"

  • "Necesito un QR de 500px"


Herramientas de Webhook (3)

6. get_webhook_events

Consulta eventos de webhook recibidos en tiempo real desde Bitnovo Pay API.

Disponible cuando: WEBHOOK_ENABLED=true

Parámetros:

{
  "identifier": "abc-123-def",
  "limit": 50,
  "validated_only": true
}

Respuesta:

{
  "events": [
    {
      "event_id": "abc-123:1234567890",
      "identifier": "abc-123-def",
      "status": "CO",
      "received_at": "2025-09-30T10:30:00.000Z",
      "validated": true,
      "payload": {
        "identifier": "abc-123-def",
        "status": "CO",
        "confirmed_amount": 0.0012,
        "crypto_amount": 0.0012
      }
    }
  ],
  "total_count": 1
}

Ejemplos de uso:

  • "¿Ha llegado algún webhook del pago abc-123?"

  • "Mostrar todos los eventos de webhook"

  • "¿Se recibió confirmación de pago?"


7. get_webhook_url

Obtiene la URL pública del webhook con instrucciones de configuración para el panel de Bitnovo.

Disponible cuando: WEBHOOK_ENABLED=true

Parámetros:

{
  "validate": true
}

Respuesta:

{
  "webhook_url": "https://bitnovo-dev.ngrok-free.app/webhook/bitnovo",
  "provider": "ngrok",
  "validated": true,
  "instructions": "✅ ngrok tunnel activo con URL persistente.\n\nPasos de configuración:\n1. Copiar esta URL: https://bitnovo-dev.ngrok-free.app/webhook/bitnovo\n2. Entrar en https://pay.bitnovo.com\n3. Ir a: Configuración → Comercio → Dispositivos\n4. Seleccionar dispositivo\n5. Configurar 'notification_url' con la URL\n\nNota: Esta URL es persistente y no cambiará entre reinicios."
}

Ejemplos de uso:

  • "¿Cuál es mi URL de webhook?"

  • "Dame la URL para configurar en Bitnovo"

  • "¿Cómo configuro los webhooks?"


8. get_tunnel_status

Diagnostica el estado de la conexión del túnel (ngrok, zrok o manual).

Disponible cuando: WEBHOOK_ENABLED=true

Parámetros: Ninguno

Respuesta:

{
  "enabled": true,
  "provider": "ngrok",
  "status": "connected",
  "public_url": "https://bitnovo-dev.ngrok-free.app",
  "connected_at": "2025-09-30T10:30:00.000Z",
  "last_error": null,
  "reconnect_attempts": 0,
  "health_check_enabled": true,
  "context_detected": {
    "execution_context": "local",
    "confidence": 0.7,
    "suggested_provider": "ngrok",
    "indicators": ["Local development environment detected"]
  }
}

Estados de conexión:

  • disconnected: Túnel no iniciado

  • connecting: Túnel inicializando

  • connected: Túnel activo y saludable

  • reconnecting: Conexión perdida, intentando reconectar

  • error: Falló después de máximo de reintentos

Ejemplos de uso:

  • "¿Está funcionando el túnel de webhooks?"

  • "¿Cuál es el estado de la conexión?"

  • "Diagnosticar problemas de túnel"


Sistema de Webhooks y Túneles

Arquitectura Dual-Server

El servidor MCP puede ejecutar dos servidores simultáneamente:

┌─────────────────────────────────────────────────────────┐
│             MCP Bitnovo Pay Server                      │
│                                                         │
│  ┌──────────────┐  ┌──────────────────┐ ┌────────────┐│
│  │ MCP Server   │  │ Webhook Server   │ │  Tunnel    ││
│  │ (stdio)      │  │ (HTTP :3000)     │ │  Manager   ││
│  └──────┬───────┘  └────────┬─────────┘ └──────┬─────┘│
│         │                   │                   │      │
│         │    Event Store    │     Public URL    │      │
│         │   (in-memory)     │   (ngrok/zrok)    │      │
│         └──────────┬────────┴──────────┬────────┘      │
└────────────────────┼───────────────────┼───────────────┘
                     │                   │
            ┌────────┴────────┐  ┌───────┴────────┐
            │                 │  │                │
       Claude Desktop   Bitnovo API    Tunnel Provider
       (MCP Tools)      (Webhooks)    (ngrok/zrok/manual)

Proveedores de Túnel

Comparación de Proveedores

Proveedor
Costo
URL Persistente
Mejor Para
Estabilidad

ngrok

Gratis (1 dominio estático)

✅ Sí

Desarrollo local

~99% uptime

zrok

100% Gratis

✅ Sí (reserved shares)

Preferencia open-source

Media-alta

manual

Depende del hosting

✅ Sí

Servidores con IP pública

Dependiente del servidor

1. ngrok (Recomendado para Desarrollo Local)

Características:

  • Dominio estático gratuito (1 por cuenta desde 2023)

  • URL persistente (no cambia en reinicios)

  • Alta confiabilidad (~99% uptime)

  • Timeout de 24 horas (auto-reconexión maneja esto)

Configuración:

TUNNEL_ENABLED=true
TUNNEL_PROVIDER=ngrok
NGROK_AUTHTOKEN=tu_token_ngrok
NGROK_DOMAIN=bitnovo-dev.ngrok-free.app  # Tu dominio estático gratuito

Setup:

  1. Crear cuenta en ngrok.com

  2. Obtener authtoken del dashboard

  3. Reclamar dominio estático gratuito en domains

2. zrok (Alternativa Open-Source)

Características:

  • 100% Gratuito (sin límites en reserved shares)

  • URL persistente con unique-name

  • Open-source (construido sobre OpenZiti)

  • Estabilidad media-alta (mejorando con cada release)

Configuración:

TUNNEL_ENABLED=true
TUNNEL_PROVIDER=zrok
ZROK_TOKEN=tu_token_zrok
ZROK_UNIQUE_NAME=bitnovo-webhooks  # Tu nombre de share reservado

# Resulta en URL persistente:
# https://bitnovo-webhooks.share.zrok.io/webhook/bitnovo

Setup:

  1. Crear cuenta en myzrok.io

  2. Instalar zrok CLI: brew install openziti/zrok/zrok

  3. Habilitar cuenta: zrok enable TU_TOKEN

  4. Reservar share: zrok reserve public --unique-name bitnovo-webhooks 3000

3. manual (Servidores con IP Pública)

Mejor Para:

  • Instancias de N8N

  • Despliegues de Opal

  • Servidores VPS/cloud

  • Docker con ingress

  • Kubernetes con LoadBalancer

Auto-detección de Entornos:

El sistema detecta automáticamente estos entornos:

Entorno
Método de Detección

N8N

Variables N8N_HOST o N8N_PROTOCOL

Opal

Variables OPAL_WEBHOOK_URL o OPAL_HOST

Kubernetes

Variable KUBERNETES_SERVICE_HOST

Docker

Archivo /.dockerenv o DOCKER_HOST

VPS/Server

Múltiples indicadores (systemd, PM2, etc.)

Configuración:

WEBHOOK_ENABLED=true
TUNNEL_ENABLED=false  # o TUNNEL_PROVIDER=manual
WEBHOOK_PUBLIC_URL=https://n8n.empresa.com  # URL pública del servidor

Seguridad de Webhooks

Validación HMAC-SHA256

Todos los webhooks se validan usando:

signature = hex(hmac_sha256(device_secret, nonce + raw_body))

Proceso de validación:

  1. Extraer nonce y signature de headers X-NONCE y X-SIGNATURE

  2. Calcular signature esperada usando device_secret

  3. Comparar usando comparación timing-safe

  4. Rechazar si las signatures no coinciden (401 Unauthorized)

Prevención de Ataques de Replay

  • Caché de nonces: Almacena nonces usados por 5 minutos

  • Detección de duplicados: Rechaza webhooks con nonces ya utilizados

  • Deduplicación de eventos: Mismo evento recibido múltiples veces se almacena una vez

¿Por qué las URLs Públicas son Seguras?

Pregunta: "¿No enviarán actores maliciosos webhooks falsos a mi URL pública?"

Respuesta: No, porque:

  1. Validación HMAC asegura que solo Bitnovo (con tu device_secret) puede crear signatures válidas

  2. Sin el device_secret, atacantes no pueden generar signatures válidas

  3. Todas las requests sin signatures válidas son rechazadas (401 Unauthorized)

  4. Prevención de replay de nonces detiene reutilización de requests válidas capturadas

Modelo de Seguridad:

Atacante envía webhook falso → Signature faltante/inválida → 401 Rechazado ✅
Atacante replica webhook capturado → Nonce ya usado → 401 Rechazado ✅
Bitnovo envía webhook → Signature válida + nonce fresco → 200 Aceptado ✅

Árbol de decisión para selección de herramienta

REGLA CRÍTICA: ¿El usuario menciona explícitamente una criptomoneda?

Usuario menciona cripto específica (Bitcoin, BTC, Ethereum, ETH, USDC, etc.)

Usar create_payment_onchain con ese input_currency específico

Usuario NO menciona cripto específica

Usar create_payment_link (OPCIÓN POR DEFECTO)

Tabla comparativa de métodos de pago

Característica
create_payment_onchain
create_payment_link

Retorna

Dirección cripto + QR

URL web

Cliente elige cripto?

No (fijo)

Sí (en gateway)

Mejor para

Pagos cripto específicos

Pagos genéricos (DEFECTO)

Método de compartir

Mostrar QR/dirección

Enviar link

Redirecciones

N/A

Sí (url_ok/url_ko)

Usar cuando

Usuario especifica cripto

NO se menciona cripto

Ejemplos

"Pago en Bitcoin", "Dirección ETH"

"Pago de 24 euros", "Generar QR"

Ejemplos de uso

Ejemplo 1: Pago genérico (sin cripto específica)

Solicitud del usuario:

"Necesito crear un pago de 50 euros"

Herramienta a usar: create_payment_link

Comando:

{
  "amount_eur": 50.0,
  "notes": "Pago genérico"
}

Resultado: URL web donde el cliente puede elegir cualquier criptomoneda disponible.


Ejemplo 2: Pago con Bitcoin específicamente

Solicitud del usuario:

"Crear un pago en Bitcoin por 100 euros"

Herramienta a usar: create_payment_onchain

Comando:

{
  "amount_eur": 100.0,
  "input_currency": "BTC",
  "notes": "Pago en Bitcoin"
}

Resultado: Dirección Bitcoin específica + QR con el importe incluido.


Ejemplo 3: Verificar pago con webhooks

Solicitud del usuario:

"¿Se completó el pago abc-123-def?"

Herramienta 1: get_webhook_events

Comando:

{
  "identifier": "abc-123-def",
  "validated_only": true
}

Resultado: Lista de eventos webhook recibidos mostrando estado actualizado en tiempo real.

Alternativa - Herramienta 2: get_payment_status

Comando:

{
  "identifier": "abc-123-def"
}

Resultado: Estado actual del pago consultado a la API.


Ejemplo 5: Casos de uso por industria

🛒 E-commerce: Pago en checkout

Escenario: Cliente completa compra de €150, necesita flexibilidad de criptomoneda

Herramienta: create_payment_link

{
  "amount_eur": 150.0,
  "url_ok": "https://tienda.com/pedido/12345/confirmado",
  "url_ko": "https://tienda.com/pedido/12345/cancelado",
  "notes": "Pedido #12345 - Auriculares Bluetooth"
}

Flujo:

  1. Cliente confirma pedido → AI genera payment link

  2. Cliente elige criptomoneda preferida en gateway

  3. Realiza pago con wallet

  4. Gateway redirige a url_ok tras confirmación

  5. Sistema procesa pedido automáticamente


☕ Café/Restaurante: Propinas en Bitcoin

Escenario: Cliente quiere dejar €5 de propina en Bitcoin

Herramienta: create_payment_onchain

{
  "amount_eur": 5.0,
  "input_currency": "BTC",
  "notes": "Propina - Mesa 7"
}

Flujo:

  1. Mesero solicita QR de propina → AI genera dirección BTC

  2. Cliente escanea QR con wallet Bitcoin

  3. Pago se confirma en minutos

  4. Sistema notifica via webhook al mesero


💼 Freelance: Factura internacional en stablecoins

Escenario: Freelancer cobra $500 USD por proyecto, prefiere USDC

Herramienta: create_payment_onchain

{
  "amount_eur": 500.0,
  "input_currency": "USDC_ERC20",
  "fiat": "USD",
  "notes": "Factura #2025-001 - Desarrollo web"
}

Flujo:

  1. Cliente internacional recibe dirección USDC

  2. Transfiere desde exchange o wallet

  3. Confirmación en blockchain

  4. Freelancer recibe fondos sin intermediarios


🎮 Gaming: Compras in-game

Escenario: Jugador compra skin de €25, elige criptomoneda

Herramienta: create_payment_link

{
  "amount_eur": 25.0,
  "notes": "Compra in-game - Dragon Skin Legendary",
  "include_qr": true
}

Flujo:

  1. Jugador selecciona skin → AI genera QR + link

  2. Paga con su crypto preferida (BTC, ETH, etc.)

  3. Sistema detecta pago via webhook

  4. Unlock automático de item en cuenta


🏨 Hotel: Reserva con depósito

Escenario: Reserva de habitación con depósito de €200

Herramienta: create_payment_link

{
  "amount_eur": 200.0,
  "url_ok": "https://hotel.com/reservas/confirm/789",
  "url_ko": "https://hotel.com/reservas/cancel/789",
  "notes": "Depósito reserva - Suite Presidencial 15-20 Octubre"
}

Flujo:

  1. Cliente reserva → AI genera payment link

  2. Cliente paga depósito en criptomoneda preferida

  3. Confirmación automática de reserva

  4. Check-in sin fricción


Ejemplo 6: Monitoreo de pagos en tiempo real

Escenario: Sistema de punto de venta monitoring payments

Flujo completo:

// 1. Crear pago
create_payment_link({
  amount_eur: 50.0,
  notes: "POS Sale #4567"
})
// → Identifier: "abc-123-def"

// 2. Monitorear con webhooks (recomendado)
get_webhook_events({
  identifier: "abc-123-def",
  validated_only: true
})
// → Recibe eventos en tiempo real

// 3. Verificar estado manualmente (alternativa)
get_payment_status({
  identifier: "abc-123-def"
})
// → Status: "CO" (Completed)

// 4. Confirmar pago completado
// → Sistema actualiza inventario, imprime recibo

Ejemplo 4: Configurar webhooks

Solicitud del usuario:

"¿Cómo configuro los webhooks en Bitnovo?"

Herramienta: get_webhook_url

Comando:

{
  "validate": true
}

Resultado: URL del webhook + instrucciones paso a paso para configurar en panel de Bitnovo.

Arquitectura técnica

Capas del sistema

┌─────────────────┐
│   MCP Tools     │ ← 8 herramientas: 5 de pago + 3 de webhook
│ (src/tools/)    │
├─────────────────┤
│   Services      │ ← Lógica de negocio: PaymentService, CurrencyService
│ (src/services/) │
├─────────────────┤
│   API Client    │ ← Integración con API de Bitnovo con retry logic
│ (src/api/)      │
├─────────────────┤
│ Webhook Server  │ ← Servidor HTTP Express + Event Store + Tunnel Manager
│ (src/webhook-*) │
├─────────────────┤
│   Utilities     │ ← Logging, validación, manejo de errores, crypto
│ (src/utils/)    │
└─────────────────┘

Flujo de datos

Pagos:

  1. Solicitud de herramienta → Validación → Capa de servicio → Cliente API → API de Bitnovo

  2. Respuesta → Manejo de errores → Transformación de datos → Respuesta JSON

  3. Logging: Todas las operaciones registradas con enmascaramiento de datos sensibles

Webhooks:

  1. Bitnovo envía webhook → Túnel (ngrok/zrok) → Webhook Server (HTTP :3000)

  2. Validación HMAC → Verificación de nonce → Almacenamiento en Event Store

  3. Consulta via MCP → get_webhook_events → Datos del Event Store

Variables de entorno

Variables Requeridas

BITNOVO_DEVICE_ID=tu_device_id_aqui        # Requerido
BITNOVO_BASE_URL=https://pos.bitnovo.com.com  # Requerido

Variables de Webhook (Opcionales)

# Habilitar webhooks
WEBHOOK_ENABLED=true
WEBHOOK_PORT=3000
WEBHOOK_HOST=0.0.0.0
WEBHOOK_PATH=/webhook/bitnovo

# Seguridad
BITNOVO_DEVICE_SECRET=tu_device_secret_hex   # Requerido para webhooks

# Event store
WEBHOOK_MAX_EVENTS=1000
WEBHOOK_EVENT_TTL_MS=3600000  # 1 hora

Variables de Túnel (Opcionales)

# Configuración de túnel
TUNNEL_ENABLED=true
TUNNEL_PROVIDER=ngrok  # Opciones: ngrok, zrok, manual

# ngrok específico
NGROK_AUTHTOKEN=tu_token_ngrok
NGROK_DOMAIN=bitnovo-dev.ngrok-free.app  # Opcional: dominio estático gratuito

# zrok específico
ZROK_TOKEN=tu_token_zrok
ZROK_UNIQUE_NAME=bitnovo-webhooks  # Tu nombre de share reservado

# manual provider
WEBHOOK_PUBLIC_URL=https://n8n.empresa.com  # Para provider manual

# Monitoreo de salud y reconexión
TUNNEL_HEALTH_CHECK_INTERVAL=60000       # 60 segundos (default)
TUNNEL_RECONNECT_MAX_RETRIES=10          # Máximo intentos de reintento
TUNNEL_RECONNECT_BACKOFF_MS=5000         # Delay inicial de backoff

🔒 Seguridad

La seguridad es una prioridad fundamental del servidor MCP de Bitnovo Pay. Implementamos múltiples capas de protección para garantizar transacciones seguras.

🛡️ Principios de Seguridad Implementados

1. Comunicación Segura

  • HTTPS obligatorio: Todas las llamadas a la API usan HTTPS exclusivamente

  • No HTTP: Requests HTTP son rechazadas automáticamente

  • TLS 1.2+: Comunicación cifrada con protocolos modernos

2. Validación de Webhooks HMAC-SHA256

Los webhooks están protegidos con firmas criptográficas HMAC:

signature = hex(hmac_sha256(device_secret, nonce + raw_body))

Proceso de validación:

  1. Bitnovo envía webhook con headers X-NONCE y X-SIGNATURE

  2. Servidor calcula signature esperada usando BITNOVO_DEVICE_SECRET

  3. Comparación timing-safe entre signatures

  4. Rechazo inmediato si no coinciden (401 Unauthorized)

¿Necesito webhooks? Solo si requieres notificaciones en tiempo real. Para consultas manuales de estado, usa get_payment_status.

3. Prevención de Ataques de Replay

  • Caché de nonces: Almacena nonces usados por 5 minutos

  • Detección de duplicados: Rechaza webhooks con nonces ya utilizados

  • Deduplicación de eventos: Mismo evento recibido múltiples veces se almacena una vez

Ejemplo de ataque rechazado:

Atacante replica webhook válido → Nonce ya usado → 401 Rechazado ✅

4. Privacidad de Datos

  • Logs enmascarados: Device IDs, secrets, y direcciones cripto parcialmente ocultas

  • Sin exchange rates: No se exponen tasas de cambio para prevenir inexactitudes

  • Diseño stateless: Sin persistencia local, consultas en tiempo real a la API

  • Datos mínimos: Solo se solicitan datos necesarios para operación

Ejemplo de log enmascarado:

[INFO] Payment created for device: 12345678-****-****-****-********90ab
[INFO] Webhook validated with signature: a3f2c1...******

5. Resiliencia y Disponibilidad

  • Timeouts: 5 segundos máximo por operación API

  • Reintentos inteligentes: Máximo 2 reintentos con backoff exponencial

  • Auto-reconexión de túneles: Backoff exponencial hasta 10 reintentos

  • Health monitoring: Verificación cada 60 segundos de conexión de túnel

🔐 Configuración Segura de Credenciales

Permisos recomendados para archivo de configuración:

# Claude Desktop config (macOS)
chmod 600 ~/Library/Application\ Support/Claude/claude_desktop_config.json

# OpenAI ChatGPT config
chmod 600 ~/.config/openai/mcp-config.json

🌐 Seguridad de Túneles Públicos

Pregunta frecuente: "¿No es inseguro exponer una URL pública para webhooks?"

Respuesta: No, gracias a la validación HMAC:

Escenario
Resultado

Atacante envía webhook falso

❌ Signature inválida → 401 Rechazado

Atacante replica webhook capturado

❌ Nonce ya usado → 401 Rechazado

Bitnovo envía webhook legítimo

✅ Signature válida + nonce fresco → 200 Aceptado

Conclusión: Solo Bitnovo (con tu BITNOVO_DEVICE_SECRET) puede generar webhooks válidos.

📋 Checklist de Seguridad

Antes de usar en producción, verifica:



🔧 Solución de Problemas

Problemas Comunes y Soluciones

Consejo: Revisa los logs del servidor MCP para diagnósticos detallados. Los logs incluyen información enmascarada de seguridad.

❌ Error: "MCP server not found" o "Server failed to start"

Causa: El servidor MCP no puede inicializarse.

Soluciones:

  1. Verifica que Node.js 18+ esté instalado: node --version

  2. Prueba ejecutar manualmente: npx -y @bitnovopay/mcp-bitnovo-pay

  3. Revisa que las variables de entorno estén correctamente configuradas

  4. Busca errores en logs de tu cliente MCP (Claude Desktop: ~/Library/Logs/Claude/)

Ejemplo de configuración correcta:

{
  "mcpServers": {
    "bitnovo-pay": {
      "command": "npx",
      "args": ["-y", "@bitnovopay/mcp-bitnovo-pay"],
      "env": {
        "BITNOVO_DEVICE_ID": "12345678-abcd-...",
        "BITNOVO_BASE_URL": "https://pos.bitnovo.com"
      }
    }
  }
}

❌ Error: INVALID_DEVICE_ID

Causa: Device ID incorrecto o no válido.

Soluciones:

  1. Copia el Device ID desde el panel de Bitnovo Pay

  2. Verifica que sea un UUID válido (formato: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)

  3. Asegúrate de no incluir espacios antes/después del ID

  4. Confirma que estás usando el dispositivo correcto para el entorno (dev/prod)


❌ Error: CURRENCY_NOT_SUPPORTED

Causa: Criptomoneda solicitada no disponible.

Soluciones:

  1. Usa list_currencies_catalog para ver opciones disponibles

  2. Verifica el símbolo exacto (ej: BTC, no Bitcoin o btc)

  3. Confirma que la moneda esté activa en tu cuenta de Bitnovo

Ejemplo:

// ❌ Incorrecto
{ "input_currency": "Bitcoin" }

// ✅ Correcto
{ "input_currency": "BTC" }

❌ Error: AMOUNT_TOO_LOW / AMOUNT_TOO_HIGH

Causa: Importe fuera de los límites de la criptomoneda.

Soluciones:

  1. Consulta límites con list_currencies_catalog

  2. Ajusta el importe dentro del rango permitido

  3. Para pagos grandes, considera dividir en múltiples transacciones

Ejemplo de consulta de límites:

// Request
{ "filter_by_amount": 50.0 }

// Response muestra min_amount y max_amount
[
  {
    "symbol": "BTC",
    "min_amount": 0.01,
    "max_amount": null  // Sin límite superior
  }
]

❌ Error: PAYMENT_EXPIRED

Causa: El pago superó el tiempo límite de expiración.

Soluciones:

  1. Crea un nuevo pago con create_payment_onchain o create_payment_link

  2. Avisa a tu cliente sobre el tiempo límite antes de que expire

  3. Usa get_payment_status para monitorear el campo expires_at


❌ Error: WEBHOOK_NOT_ENABLED

Causa: Intentas usar herramientas de webhook sin habilitarlos.

Soluciones:

  1. Agrega "WEBHOOK_ENABLED": "true" a la configuración

  2. (Opcional) Configura túnel con TUNNEL_ENABLED y proveedor

  3. Reinicia el servidor MCP

Configuración mínima de webhooks:

{
  "env": {
    "BITNOVO_DEVICE_ID": "...",
    "BITNOVO_BASE_URL": "...",
    "BITNOVO_DEVICE_SECRET": "...",
    "WEBHOOK_ENABLED": "true"
  }
}

❌ Error: TUNNEL_CONNECTION_FAILED

Causa: Fallo al conectar con ngrok o zrok.

Soluciones ngrok:

  1. Verifica tu authtoken: ngrok config check

  2. Confirma que tu dominio estático esté reclamado en ngrok dashboard

  3. Prueba manualmente: ngrok http --domain=tu-dominio.ngrok-free.app 3000

Soluciones zrok:

  1. Verifica que zrok esté habilitado: zrok status

  2. Confirma que el share reservado exista: zrok share reserved

  3. Prueba conexión: zrok share reserved tu-share-name


❌ Error: INVALID_SIGNATURE (webhooks)

Causa: Firma HMAC del webhook no coincide.

Soluciones:

  1. Verifica que BITNOVO_DEVICE_SECRET sea correcto (64 caracteres hex)

  2. Confirma que sea el mismo secret configurado en el panel de Bitnovo

  3. No modifiques el body del webhook antes de validar

  4. Asegúrate de usar el secret del dispositivo correcto (dev/prod)


Códigos de Error Completos

Código
Descripción
Acción Recomendada

INVALID_DEVICE_ID

Device ID no válido

Verificar credenciales en panel de Bitnovo

INVALID_DEVICE_SECRET

Device Secret incorrecto

Verificar formato hex de 64 caracteres

CURRENCY_NOT_SUPPORTED

Criptomoneda no soportada

Usar list_currencies_catalog

AMOUNT_TOO_LOW

Importe por debajo del mínimo

Aumentar el importe del pago

AMOUNT_TOO_HIGH

Importe por encima del máximo

Reducir el importe o dividir pago

PAYMENT_NOT_FOUND

Pago no encontrado

Verificar el identifier

PAYMENT_EXPIRED

Pago expiró

Crear un nuevo pago

WEBHOOK_NOT_ENABLED

Webhooks no habilitados

Configurar WEBHOOK_ENABLED=true

TUNNEL_CONNECTION_FAILED

Fallo de conexión de túnel

Verificar credenciales de ngrok/zrok

INVALID_SIGNATURE

Firma HMAC inválida

Verificar BITNOVO_DEVICE_SECRET

Formato de Respuesta de Error

Todos los errores siguen el siguiente formato estándar:

{
  "error": {
    "code": "CURRENCY_NOT_SUPPORTED",
    "message": "The specified currency is not supported",
    "details": {
      "input_currency": "INVALID_COIN",
      "supported_currencies": ["BTC", "ETH", "USDC", "..."]
    }
  }
}

Desarrollo

Comandos disponibles

npm run build        # Compilar TypeScript a JavaScript
npm run dev          # Servidor de desarrollo con hot reload
npm start            # Iniciar servidor de producción

Rendimiento

Event Store

  • Almacenamiento: In-memory (rápido, sin persistencia)

  • Capacidad: 1000 eventos (configurable)

  • TTL: 1 hora (configurable)

  • Limpieza: Automática cada 5 minutos

  • Indexación: Búsqueda rápida por payment identifier

Túneles

  • ngrok: ~99% uptime, ~10-50ms latencia añadida

  • zrok: Uptime medio-alto, ~20-100ms latencia añadida

  • manual: Dependiente del servidor, sin overhead de túnel

Uso de Memoria

Event Store:

  • Memoria estimada por evento: ~2KB

  • 1000 eventos ≈ 2MB

  • 10000 eventos ≈ 20MB

Tunnel Manager:

  • ngrok: ~5-10MB overhead

  • zrok: ~10-20MB overhead (incluye OpenZiti)

  • manual: ~0MB (sin proceso de túnel)

Soporte y recursos

Limitaciones conocidas

  • Operación single-tenant: Un Device ID por instancia del servidor

  • Sin persistencia local: Todas las consultas son en tiempo real a la API

  • Sin tasas de cambio: Por privacidad y exactitud, no se exponen exchange rates

  • Timeouts: 5 segundos máximo por operación API

  • Reintentos: Máximo 2 reintentos con backoff exponencial

  • Event Store: In-memory (se pierde en reinicio)

  • Túneles gratuitos: Limitaciones de cada proveedor aplican

Changelog

v1.1.0 (2025-09-30) - Sistema de Túneles

  • Gestión automática de túneles con 3 proveedores (ngrok, zrok, manual)

  • Auto-detección de contexto (N8N, Opal, Docker, Kubernetes, VPS, local)

  • URLs persistentes con dominios estáticos gratuitos de ngrok y reserved shares de zrok

  • Auto-reconexión con backoff exponencial (hasta 10 reintentos)

  • Monitoreo de salud cada 60 segundos con recuperación automática

  • Nuevas herramientas MCP: get_webhook_url, get_tunnel_status

  • Configuración cero para escenarios de despliegue comunes

v1.0.0 (2025-09-28) - Implementación Inicial de Webhooks

  • ✅ Implementación inicial de webhooks

  • ✅ Event store (in-memory)

  • ✅ Validación de signatures HMAC

  • ✅ Prevención de ataques de replay

  • ✅ Modo dual-server (stdio + HTTP)

  • ✅ Nueva herramienta MCP: get_webhook_events

  • ✅ Endpoints de health check y stats

Licencia

Este proyecto está licenciado bajo la Licencia MIT - ver el archivo LICENSE para más detalles.

Última actualización: 30 de septiembre de 2025 Versión del servidor: v1.1.0

Última actualización