Bedolaga MCP Server
Bedolaga MCP Server
Servidor MCP para obtener datos de usuario de Bedolaga Bot por Telegram ID o por user_id interno.
El servidor es de solo lectura: a través de Bedolaga MCP no se puede cambiar el saldo, crear o renovar suscripciones, aplicar códigos promocionales, procesar reembolsos, retirar fondos de referidos ni realizar otras acciones en nombre del usuario.
Migración importante (1.0.0)
A partir de la versión 1.0.0, el contrato público de las herramientas ha cambiado y los nombres antiguos se han eliminado. Actualice la configuración del cliente:
Herramienta antigua | Qué la reemplaza |
| reemplazada por |
| reemplazada por |
| no tiene equivalente en Bedolaga MCP. El estado real de la suscripción y el estado del panel VPN se verifican a través de un mcp-remnawave independiente, no a través de este servidor |
También en 1.0.0 se eliminó la ruta HTTP obsoleta /mcp: el Streamable HTTP con sesión ahora se sirve en el endpoint raíz /, como en mcp-remnawave. Cada publicación de imagen recibe tres etiquetas: :latest, :{version} y :{sha}.
La versión 1.0.0 es el primer contrato con rutas de API correctas, resultados estructurados y un límite de responsabilidad explícito con Remnawave.
Related MCP server: Monobank MCP Server
Herramientas (Tools)
El servidor proporciona exactamente ocho herramientas disponibles a través del protocolo MCP. Todas las herramientas son de solo lectura: los datos no se modifican.
Contrato de identidad
Cada herramienta acepta exactamente uno de dos campos:
telegram_id— número entero, Telegram ID del usuario (positivo);user_id— número entero, ID interno del usuario en Bedolaga (positivo), utilizado para tickets de oficina solo por correo electrónico.
Si no se envía ningún campo o se envían ambos, la herramienta devuelve un error invalid_input. La identidad nunca se toma del modelo: supportBot siempre fija al remitente real: un telegram_id positivo del update de Telegram autenticado, o el user_id interno de la oficina para un ticket solo por correo electrónico.
bedolaga_user_get
Obtener la cuenta y el saldo del usuario actual de Bedolaga.
Parámetros:
Parámetro | Tipo | Obligatorio | Descripción |
|
| exactamente uno de los dos | Telegram ID del usuario |
|
| exactamente uno de los dos | ID interno del usuario de Bedolaga (ticket solo por correo electrónico) |
Campos JSON de la respuesta (data):
Campo | Tipo | Descripción |
|
| Indica si el usuario fue encontrado |
|
| Telegram ID del usuario |
|
| Nombre para mostrar seguro |
|
| Estado de la cuenta Bedolaga |
|
| Saldo en kopeks |
|
| Saldo en rublos (siempre |
|
| Indica si hubo un primer depósito en el pasado |
|
| Indica si hubo una compra de pago en el pasado |
|
| Código de referido |
|
| El usuario llegó por invitación |
|
| Nombre del grupo promocional y porcentajes de descuento |
|
| Fechas de creación y última actividad |
El campo promo_group contiene solo name, server_discount_percent, traffic_discount_percent, device_discount_percent.
Ejemplo de interpretación (sintético): balance_kopeks: 350000 y balance_rubles: 3500.0 significan un saldo de 3 500 rublos. has_had_paid_subscription: false significa que aún no ha habido compras de pago.
bedolaga_billing_get
Mostrar de una sola llamada el saldo, los eventos financieros recientes y los registros internos de compras de Bedolaga, para distinguir un depósito de una compra.
Parámetros:
Parámetro | Tipo | Obligatorio | Descripción |
|
| exactamente uno de los dos | Telegram ID del usuario |
|
| exactamente uno de los dos | ID interno del usuario de Bedolaga (ticket solo por correo electrónico) |
|
| No | Límite de operaciones en la lista (por defecto 20, máximo 50) |
Campos JSON de la respuesta (data):
Campo | Tipo | Descripción |
|
| Saldo actual |
|
| Operaciones de más recientes a más antiguas, no más de |
|
| Resumen del último depósito completado |
|
| Resumen de la última compra de suscripción completada |
|
| Compra completada después del último depósito completado |
|
| Registros internos de suscripciones de Bedolaga |
|
| Explicación fija «deposit ≠ purchase» |
Cada operación en transactions:
Campo | Tipo | Descripción |
|
| ID interno de la transacción |
|
| Categoría normalizada: |
|
|
|
|
| Nombre de tipo original seguro |
|
| Importe absoluto |
|
| Método de pago |
|
| Si la operación está completada |
|
| Descripción |
|
| Hora de creación y de finalización |
Cada registro en bot_subscriptions contiene id, bot_record_status, bot_record_effective_status, is_trial, tariff_id, tariff_name, start_date, end_date, autopay_enabled, autopay_days_before y una note fija. El servidor prefiere la lista upstream completa subscriptions, elimina los registros duplicados por id y conserva un fallback al campo legacy único subscription. El campo se llama bot_record_status a propósito: es un registro interno de Bedolaga, no el estado del panel VPN. bot_record_effective_status también es un estado efectivo del lado del bot (calculado por el bot a partir de status y end_date), no el estado del panel.
Ejemplo de interpretación (sintético): latest_completed_deposit: {amount_kopeks: 350000} y purchased_after_latest_deposit: false — el dinero se ha acreditado en el saldo, pero no se ha completado una compra separada después del depósito.
bedolaga_referrals_get
Obtener el resumen de referidos del usuario actual.
Parámetros:
Parámetro | Tipo | Obligatorio | Descripción |
|
| exactamente uno de los dos | Telegram ID del usuario |
|
| exactamente uno de los dos | ID interno del usuario de Bedolaga (ticket solo por correo electrónico) |
Campos JSON de la respuesta (data):
Поле | Тип | Описание |
|
| Código de referencia del propietario de la cuenta |
|
| El propietario fue referido |
|
| Comisión efectiva |
|
| Total invitados |
|
| Invitados activos |
|
| Ganancias de todo el tiempo |
|
| Ganancias del mes actual |
|
| Últimas recompensas por referidos del propietario |
|
| Explicación fija |
Se devuelven estadísticas solo del propietario de la cuenta. Telegram ID, IDs internos, username, nombres, saldo y actividad de los usuarios invitados nunca se devuelven.
bedolaga_subscription_get
Obtener los registros de suscripciones del lado del bot y las fechas del ciclo de vida (created_at, start_date, end_date, is_trial, autopay_enabled).
Parámetros: telegram_id o user_id (exactamente uno).
Devuelve has_subscription_records, active_record_count, la lista subscriptions y un meta fijo. El campo bot_record_status es un registro interno del bot, no el estado del panel VPN (el estado real se comprueba a través de Remnawave MCP).
bedolaga_tickets_get
Obtener un resumen de las propias solicitudes de soporte (id, title, status, priority, fechas de creación/actualización/cierre) sin los textos de los mensajes ni los medios.
Parámetros: telegram_id o user_id (exactamente uno), limit (por defecto 10, máximo 50).
bedolaga_payment_status_get
Obtener el historial de operaciones financieras y el estado de finalización en el sistema de contabilidad del bot (completed / not_completed / unknown).
Parámetros: telegram_id o user_id (exactamente uno), limit (por defecto 5, máximo 20).
El estado not_completed solo significa que la operación no se ha completado en la facturación del bot, no un fallo o una espera por parte de la pasarela de pago.
bedolaga_promocode_check
Comprobar la definición global del código promocional, la fecha de caducidad, la actividad, el bonus y el saldo de usos restantes.
Parámetros: code (obligatorio), telegram_id o user_id (exactamente uno para fijar la identidad).
Devuelve el código enmascarado (code_masked), el indicador globally_valid, reason_code (not_found, inactive, not_yet_valid, expired_or_exhausted, lookup_incomplete) y user_eligibility: "unknown".
bedolaga_gifts_get
Obtener el historial de compras de regalos del propietario de la cuenta.
Parámetros: telegram_id o user_id (exactamente uno), limit (por defecto 20, máximo 50).
Muestra solo el hecho de la compra de regalos (contabilidad); los tokens de los regalos, los destinatarios y el estado de activación no se revelan.
Decision table
Cómo debe usar el LLM (supportBot) los datos de Bedolaga y Remnawave según los escenarios:
Escenario | Qué se ve en Bedolaga MCP | Acción del LLM |
Depósito sin compra |
| Explicar que el dinero se ha abonado al saldo, pero la compra por separado no se ha completado; indicar que complete la compra desde el saldo. No afirmar que la suscripción está defectuosa |
Compra con panel operativo | Existe | Comprobar el estado real del panel a través de Remnawave MCP |
Compra sin registro en el panel | Existe | Escalar como una discrepancia confirmada con un breve resumen factual |
Sin depósito | No hay | No afirmar que el proveedor de pagos no ha cobrado el dinero (Bedolaga solo confirma la ausencia de abono en su sistema de contabilidad); escalar si el usuario informa de un cobro real |
Consulta sobre referidos |
| Enrutar solo a Bedolaga MCP |
Consulta sobre nodo / HWID | — | Enrutar solo a Remnawave MCP (Bedolaga no conoce el estado de los nodos ni de los dispositivos) |
Formato del resultado
Cada herramienta devuelve JSON en el content de MCP en texto con una envoltura común:
éxito:
ok: true,source: "bedolaga-mcp",tool,data,meta;error:
ok: false,source,tool,error.code,error.messageseguro,error.retryable.
El cuerpo bruto de la respuesta de la API de Bedolaga y las excepciones de Python del modelo no se devuelven. Las herramientas no devuelven email, enlace de suscripción, crypto link, claves, IDs de pago externos, identificadores de receipt, identificadores de Remnawave ni datos personales de los referidos.
Error codes
Código | Reintentable | Cuándo ocurre |
| no | Se han pasado ambos campos de identidad o ninguno; valor no válido |
| no | Falta o es incorrecta la configuración del entorno |
| no | La identidad no se puede asociar con un usuario de Bedolaga |
| no | Usuario no encontrado (upstream 404) |
| no | Credenciales de API incorrectas o ausentes (upstream 401/403) |
| sí | Se ha alcanzado el rate limit (upstream 429) |
| sí | Tiempo de espera agotado o fallo de red antes de la respuesta |
| sí | Upstream no disponible (5xx o error irrecuperable) |
| no | El cuerpo de la respuesta no es un JSON válido o no es un objeto |
| no | Error interno inesperado |
El mensaje de usuario se construye únicamente a partir del error.message seguro y nunca revela el body HTTP ni la URL interna.
Transportes
El servidor admite dos transportes en un mismo server factory y un mismo registro de herramientas:
Transporte | Launcher | Puerto | Protocolo |
Streamable HTTP (principal) |
| 3100 por defecto | MCP de doble era en |
Stdio |
| — | Handshake MCP stdio (el mismo factory) |
El endpoint / es único, pero atiende dos eras del protocolo a la vez; el SDK v2 determina por sí mismo a qué era pertenece cada solicitud mediante la cabecera MCP-Protocol-Version:
Protocolo moderno
2026-07-28— stateless/sessionless. Cada POST a/es autosuficiente: el servidor nunca emiteMcp-Session-Idni almacena estado entre solicitudes. Los clientes oficiales de MCP SDK v2 (ver «Cliente oficial de SDK v2» más abajo) usan este modo automáticamente.Clientes legacy con initialize-handshake (protocolos hasta
2025-11-25, incluido2024-11-05) reciben la cabeceraMcp-Session-Iden respuesta ainitializey deben enviarla en todas las solicitudes posteriores.DELETE /con esa cabecera finaliza exactamente esa sesión; no afecta a otras sesiones ni a los clientes modernos.
GET /health devuelve el liveness del proceso y la versión del servidor, sin revelar la configuración ni los secretos.
Compatibilidad de versiones
Componente | Versión |
Bedolaga Bot API (upstream) | commit |
bedolaga-mcp |
|
Python MCP SDK ( |
|
Protocolos MCP compatibles |
|
supportBot |
|
mcp-remnawave |
|
El contrato de las herramientas se ha verificado contra el commit upstream indicado y el estándar de mcp-remnawave v3.2.1.
Requisitos
Python 3.11+
Docker (opcional)
Bedolaga Bot desplegado con Web API
Clave de API de Bedolaga (se entrega en el panel de administración del bot)
Inicio rápido
1. Clonar
git clone https://github.com/mitetenov/bedolaga-mcp.git
cd bedolaga-mcp2. Configurar
cp .env.example .env
# Заполнить BEDOLAGA_API_URL и BEDOLAGA_API_KEY3. Ejecutar
Streamable HTTP (recomendado):
# Установить зависимости
pip install -r requirements.txt
# Запустить HTTP-сервер
BEDOLAGA_API_URL=https://your-bot.example.com \
BEDOLAGA_API_KEY=your-key \
python3 http_server.pyEl servidor escuchará en http://0.0.0.0:3100, el endpoint MCP es la raíz /.
Stdio:
BEDOLAGA_API_URL=https://your-bot.example.com \
BEDOLAGA_API_KEY=your-key \
python3 bedolaga_server.pyMediante Docker:
docker compose up -dLa imagen de Docker por defecto ejecuta el servidor Streamable HTTP en el puerto 3100.
Conexión como servidor MCP
Streamable HTTP
El servidor está disponible por HTTP en el puerto 3100, el endpoint es la raíz / (http://localhost:3100).
Hermes Agent
# ~/.hermes/config.yaml
mcp_servers:
bedolaga:
transport: streamable-http
url: "http://localhost:3100"
env:
BEDOLAGA_API_URL: "https://your-bot.example.com"
BEDOLAGA_API_KEY: "your-api-key"Claude Desktop
{
"mcpServers": {
"bedolaga": {
"type": "streamableHttp",
"url": "http://localhost:3100"
}
}
}Cursor / VS Code
{
"mcpServers": {
"bedolaga": {
"transport": "streamable-http",
"url": "http://localhost:3100"
}
}
}Comprobación mediante curl (legacy compatibility check)
El JSON-RPC crudo mediante curl usa legacy initialize-handshake (protocolo 2024-11-05): es una comprobación manual de compatibilidad inversa, no la forma en que se comunican los clientes modernos. Los clientes modernos de MCP SDK v2 negocian el protocolo 2026-07-28 automáticamente y no reciben Mcp-Session-Id (ver «Cliente oficial de SDK v2 (protocolo moderno)» más abajo).
# Liveness
curl -s http://localhost:3100/health
# Legacy initialize handshake (получить session ID; работает для протоколов вплоть до 2025-11-25)
curl -s -X POST http://localhost:3100/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}},"id":1}' \
-D - | grep -i mcp-session-id
# Список инструментов (с session ID)
curl -s -X POST http://localhost:3100/ \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: <SESSION_ID>" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":2}'
# Вызов инструментов
# Пользователь и баланс
curl -s -X POST http://localhost:3100/ \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: <SESSION_ID>" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"bedolaga_user_get","arguments":{"telegram_id":123456789}},"id":3}'
# Биллинг (операции и внутренние записи покупок)
curl -s -X POST http://localhost:3100/ \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: <SESSION_ID>" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"bedolaga_billing_get","arguments":{"telegram_id":123456789,"limit":20}},"id":4}'
# Реферальная сводка
curl -s -X POST http://localhost:3100/ \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: <SESSION_ID>" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"bedolaga_referrals_get","arguments":{"telegram_id":123456789}},"id":5}'
# Завершение legacy-сессии (для современного протокола 2026-07-28 не требуется и не применяется)
curl -s -X DELETE http://localhost:3100/ \
-H "Mcp-Session-Id: <SESSION_ID>"Cliente oficial de SDK v2 (protocolo moderno)
El cliente oficial de Python MCP SDK v2 (mcp==2.0.0) negocia el protocolo por sí mismo — 2026-07-28 si el servidor lo soporta, de lo contrario legacy-handshake — sin construir manualmente _meta ni cabeceras:
import asyncio
from mcp.client.client import Client
async def main() -> None:
async with Client("http://localhost:3100/", mode="auto") as client:
print("negotiated protocol:", client.protocol_version) # "2026-07-28" against this server
tools = await client.list_tools()
print([tool.name for tool in tools.tools])
result = await client.call_tool(
"bedolaga_user_get", {"telegram_id": 123456789}
)
print(result.content)
asyncio.run(main())mode="auto" — es la misma negociación que utiliza supportBot: el cliente decide por sí mismo si tiene delante un servidor moderno o legacy, y no exige que el código llamante conozca la era del protocolo de antemano.
Transporte Stdio
Hermes Agent
# ~/.hermes/config.yaml
mcp_servers:
bedolaga:
command: "python3"
args: ["/path/to/bedolaga-mcp/bedolaga_server.py"]
env:
BEDOLAGA_API_URL: "https://your-bot.example.com"
BEDOLAGA_API_KEY: "your-api-key"Claude Desktop
{
"mcpServers": {
"bedolaga": {
"command": "python3",
"args": ["/path/to/bedolaga-mcp/bedolaga_server.py"],
"env": {
"BEDOLAGA_API_URL": "https://your-bot.example.com",
"BEDOLAGA_API_KEY": "your-api-key"
}
}
}
}Cursor / VS Code
Añadir a .cursor/mcp.json o settings.json:
{
"mcpServers": {
"bedolaga": {
"command": "python3",
"args": ["/path/to/bedolaga-mcp/bedolaga_server.py"],
"env": {
"BEDOLAGA_API_URL": "https://your-bot.example.com",
"BEDOLAGA_API_KEY": "your-api-key"
}
}
}
}Gestión de sesiones
El transporte Streamable HTTP es dual-era, y las sesiones solo se aplican a una de las dos eras:
Legacy initialize-handshake (protocolos hasta
2025-11-25): después deinitialize, el servidor devuelve la cabeceraMcp-Session-Id, que el cliente debe enviar en todas las solicitudes posteriores.DELETE /con esta cabecera finaliza solo la sesión indicada; un cliente no puede finalizar ni reutilizar la sesión de otro.Protocolo moderno
2026-07-28: stateless/sessionless — el servidor nunca emiteMcp-Session-Id, yDELETE /no es necesario ni se aplica para tales clientes.
Variables de entorno
Variable | Descripción |
| URL de Bedolaga Web API |
| Clave API de Bedolaga (se transmite upstream en |
| Dirección para bind (por defecto: |
| Puerto del servidor HTTP (por defecto: |
| Timeout upstream en milisegundos (por defecto: 10000) |
Por compatibilidad, se aceptan las variables legacy HOST/PORT si MCP_HTTP_HOST/MCP_HTTP_PORT no están definidas.
API Upstream
Bedolaga Web API: X-API-Key en la cabecera. Rutas utilizadas:
GET /users/by-telegram-id/{telegram_id}— usuario por Telegram ID;GET /users/{user_id}— usuario por ID interno (tickets email-only);GET /transactions?user_id=...— operaciones con filtros y paginación;GET /partners/referrers/{user_id}— tarjeta de referido.
Más información: https://docs.bedolagam.ru
Limitaciones de la primera versión
No hay intentos de pago provider-specific. Bedolaga solo devuelve operaciones que se han convertido en registros en la tabla común transactions. Los intentos brutos del proveedor de pagos que no se convirtieron en un registro no están disponibles.
No hay lectura de la cesta de Redis del usuario. El Web API actual no proporciona un endpoint read-only seguro para esto. El problema actual de «recargó, pero no hay compra» se diagnostica de manera fiable por la diferencia entre
depositysubscription_payment(ver decision table).La búsqueda email-only es compatible. Para tickets de la cuenta sin Telegram ID, el servidor acepta el
user_idinterno (entero positivo) y lo resuelve medianteGET /users/{user_id}. supportBot fija eluser_idinterno de la cuenta (valor absoluto de la clave de conversación sintética negativa) — para estos tickets, los datos de Bedolaga están disponibles, y las herramientas de Remnawave devuelvenidentity_unavailable, porque ese usuario no tiene identidad de Telegram ni un registro probado en el panel.
Reversión (rollback)
Desactivar BEDOLAGA_MCP_ENABLED=false en supportBot lo devuelve al modo Remnawave-only: Bedolaga MCP no se conecta, sus herramientas desaparecen de la allowlist, y el procesamiento de tickets por webhook/poller (BEDOLAGA_ENABLED) sigue siendo independiente. La reversión no toca la base de usuarios ni los datos financieros — Bedolaga MCP es read-only y no almacena estado.
Reversión de la imagen bedolaga-mcp a la etiqueta 1.1.0 (la última versión antes de la migración al MCP SDK v2, solo la era legacy de Streamable HTTP) también es segura: el cliente supportBot en MCP SDK v2 cambia automáticamente (auto-fallback) al legacy initialize-handshake si el servidor no responde al protocolo moderno 2026-07-28, por lo que las herramientas de Bedolaga MCP siguen disponibles sin configuración adicional.
This server cannot be deployed
Maintenance
Related MCP Connectors
Non-custodial crypto payments for AI assistants: balances, payments, and create payment links.
Accept crypto payments via the TgPay Merchant API — invoices, subscriptions, webhooks.
Pay-per-use web extract, token prices, and wallet balances via x402 USDC micropayments.
Telegram bridge for your MCP-compatible agent. Bidirectional, no LLM in our stack.
Related MCP Servers
FlicenseNot gradedqualityNot gradedmaintenanceProvides user balance information by connecting to a backend service through the users_balance tool. Built with TypeScript and Express for retrieving financial data.-- AlicenseAqualityAmaintenanceEnables integration with Monobank API to check currency exchange rates, view account balances, and retrieve transaction statements through natural language queries.329 npm9MIT
- AlicenseNot gradedqualityDmaintenanceEnables interaction with Telegram Bot API for sending messages, photos, editing messages, answering callbacks, and fetching updates.MIT
- AlicenseNot gradedqualityBmaintenanceEnables sending Telegram messages, photos, and documents, and retrieving bot information through the Telegram Bot API.23 npm1MIT