Skip to main content
Glama
mitetenov

Bedolaga MCP Server

by mitetenov

Bedolaga MCP Server

MCP 服务器,用于通过 Telegram ID 或内部 user_idBedolaga Bot 获取用户事实。

该服务器为 只读:通过 Bedolaga MCP 无法更改余额、创建或续订订阅、使用促销码、办理退款、提取推荐奖励或代表用户执行任何其他操作。

破坏性迁移(1.0.0)

1.0.0 版本开始,工具的公共契约已更改,旧名称已被删除。请更新客户端配置:

旧工具

替代方案

bedolaga_balance

已替换为 bedolaga_user_get

bedolaga_transactions

已替换为 bedolaga_billing_get

bedolaga_subscription

在 Bedolaga MCP 中没有对应工具。实际订阅状态和 VPN 面板状态通过单独的 mcp-remnawave 检查,而不是通过此服务器

此外,1.0.0 移除了已废弃的 HTTP 路径 /mcp:sessionful Streamable HTTP 现在像 mcp-remnawave 一样在根端点 / 上提供服务。每次镜像发布都会获得三个标签::latest:{version}:{sha}

1.0.0 是第一个具有正确 API 路由、结构化结果以及与 Remnawave 明确责任边界的契约。

Related MCP server: Monobank MCP Server

工具(Tools)

服务器恰好提供八个可通过 MCP 协议使用的工具。所有工具均为 只读 — 不会修改数据。

身份契约

每个工具接受恰好一个以下两个字段:

  • telegram_id — 整数,用户的 Telegram ID(正数);

  • user_id — 整数,Bedolaga 中的内部用户 ID(正数),用于仅限邮箱的账户工单。

如果未传递任何字段,或同时传递了两个字段,工具将返回 invalid_input 错误。身份永远不会从模型获取:supportBot 始终固定实际发送者 — 来自经过身份验证的 Telegram update 的正数 telegram_id,或用于仅限邮箱工单的账户内部 user_id

bedolaga_user_get

获取当前 Bedolaga 用户的账户和余额。

参数:

参数

类型

必填

描述

telegram_id

int

恰好一个(二选一)

用户的 Telegram ID

user_id

int

恰好一个(二选一)

Bedolaga 内部用户 ID(仅限邮箱工单)

响应 JSON 字段(data):

字段

类型

描述

found

bool

是否找到用户的标志

telegram_id

int | null

用户的 Telegram ID

display_name

string | null

安全的显示名称

status

string | null

Bedolaga 账户状态

balance_kopeks

int | null

以戈比计的余额

balance_rubles

float | null

以卢布计的余额(始终为 kopeks / 100

has_made_first_topup

bool | null

是否曾进行过首次充值

has_had_paid_subscription

bool | null

是否曾有过付费购买

referral_code

string | null

推荐码

was_referred

bool | null

用户是否通过邀请而来

promo_group

object | null

促销组名称和折扣百分比

created_at / last_activity

string | null

创建日期和最后活动日期

promo_group 字段仅包含 nameserver_discount_percenttraffic_discount_percentdevice_discount_percent

解释示例(合成数据): balance_kopeks: 350000balance_rubles: 3500.0 表示余额为 3 500 卢布。has_had_paid_subscription: false 表示还没有过付费购买。

bedolaga_billing_get

通过一次调用显示余额、最近的财务事件以及 Bedolaga 内部购买记录 — 以便区分充值和购买。

参数:

参数

类型

必填

描述

telegram_id

int

恰好一个(二选一)

用户的 Telegram ID

user_id

int

恰好一个(二选一)

Bedolaga 内部用户 ID(仅限邮箱工单)

limit

int

列表中的操作数量限制(默认 20,最大 50)

响应 JSON 字段(data):

字段

类型

描述

balance_kopeks / balance_rubles

int / float | null

当前余额

transactions

array

操作按从新到旧排列,不超过 limit

latest_completed_deposit

object | null

最近一次已完成充值的摘要

latest_completed_subscription_purchase

object | null

最近一次已完成订阅购买的摘要

purchased_after_latest_deposit

bool | null

在最近一次已完成充值之后是否有已完成的购买

bot_subscriptions

array

Bedolaga 内部订阅记录

meta

string

固定说明“deposit ≠ purchase”

transactions 中的每个操作:

字段

类型

描述

id

number | null

内部交易 ID

category

string

规范化类别:depositsubscription_purchasegift_purchasewithdrawalrefundfailed_refundreferral_rewardpoll_rewardunknown

direction

string

credit / debit / unknown

raw_type

string | null

原始安全类型名称

amount_kopeks / amount_rubles

int / float | null

绝对金额

payment_method

string | null

支付方式

is_completed

bool | null

操作是否已完成

description

string | null

描述

created_at / completed_at

string | null

创建和完成时间

bot_subscriptions 中的每条记录包含 idbot_record_statusbot_record_effective_statusis_trialtariff_idtariff_namestart_dateend_dateautopay_enabledautopay_days_before 以及固定的 note。服务器优先使用完整的 upstream subscriptions 列表,按 id 删除重复记录,并保留对单个 legacy 字段 subscription 的回退。该字段故意命名为 bot_record_status:这是 Bedolaga 的内部记录,而不是 VPN 面板状态。bot_record_effective_status 同样是机器人侧的有效状态(由机器人根据 statusend_date 计算),而不是面板状态。

解释示例(合成数据): latest_completed_deposit: {amount_kopeks: 350000}purchased_after_latest_deposit: false — 资金已计入余额,但充值之后没有单独的购买完成。

bedolaga_referrals_get

获取当前用户的推荐摘要。

参数:

参数

类型

必填

描述

telegram_id

int

恰好一个(二选一)

用户的 Telegram ID

user_id

int

恰好一个(二选一)

Bedolaga 内部用户 ID(仅限邮箱工单)

响应 JSON 字段(data):

字段

类型

描述

referral_code

string | null

账户所有者的推荐码

was_referred

bool | null

所有者是通过邀请来的

effective_referral_commission_percent

number | null

有效佣金

invited_count

int | null

总共邀请人数

active_referrals

int | null

活跃的受邀者

total_earned_kopeks / total_earned_rubles

int / float | null

历史总收益

month_earned_kopeks / month_earned_rubles

int / float | null

本月收益

recent_referral_rewards

array

所有者的最近入账

meta

string

固定说明

返回的统计信息仅限账户所有者。永远不会返回受邀用户的 Telegram ID、内部 ID、用户名、姓名、余额和活动情况。

bedolaga_subscription_get

获取机器人侧的订阅记录和生命周期日期(created_atstart_dateend_dateis_trialautopay_enabled)。

参数: telegram_iduser_id(恰好一个)。

返回 has_subscription_recordsactive_record_countsubscriptions 列表和固定的 metabot_record_status 字段是机器人的内部记录,而不是 VPN 面板状态(实际状态通过 Remnawave MCP 检查)。

bedolaga_tickets_get

获取自己的支持工单摘要(idtitlestatuspriority、创建/更新/关闭日期),不包含消息文本和媒体。

参数: telegram_iduser_id(恰好一个),limit(默认 10,最大 50)。

bedolaga_payment_status_get

获取机器人记账系统中的财务操作历史和完成状态(completed / not_completed / unknown)。

参数: telegram_iduser_id(恰好一个),limit(默认 5,最大 20)。

状态 not_completed 仅表示操作在机器人计费系统中未完成,而不是支付网关侧的故障或等待。

bedolaga_promocode_check

检查促销码的全局定义、有效期、活动状态、奖励和剩余使用次数。

参数: code(必填),telegram_iduser_id(恰好一个,用于固定身份)。

返回掩码后的代码(code_masked)、globally_valid 标志、reason_codenot_foundinactivenot_yet_validexpired_or_exhaustedlookup_incomplete)以及 user_eligibility: "unknown"

bedolaga_gifts_get

获取账户所有者的礼物购买历史。

参数: telegram_iduser_id(恰好一个),limit(默认 20,最大 50)。

仅显示礼物购买事实(记账);礼物令牌、接收者和激活状态不予披露。

Decision table

LLM(supportBot)应如何按场景使用 Bedolaga 和 Remnawave 数据:

场景

Bedolaga MCP 中可见的内容

LLM 操作

充值但未购买

deposit 存在,purchased_after_latest_deposit: false

说明资金已计入余额,但单独的购买尚未完成;引导用户从余额完成购买。不要声称订阅有故障

购买且面板正常

存在已完成的 subscription_payment

通过 Remnawave MCP 检查面板的实际状态

购买但面板无记录

存在已完成的 subscription_payment

作为已确认的差异升级处理,并附上简短的事实摘要

无充值

deposit 不存在

不要声称支付提供商未扣款(Bedolaga 仅确认其记账系统中没有入账);如果用户报告实际已扣款,则升级处理

推荐问题

bedolaga_referrals_get

仅路由到 Bedolaga MCP

关于节点 / HWID 的问题

仅路由到 Remnawave MCP(Bedolaga 不知道节点和设备的状态)

结果格式

每个工具都以统一的包装结构返回文本 MCP content 中的 JSON:

  • 成功:ok: truesource: "bedolaga-mcp"tooldatameta

  • 错误:ok: falsesourcetoolerror.code、安全的 error.messageerror.retryable

不返回 Bedolaga API 的原始响应体和 Python 模型异常。工具不返回电子邮件、订阅链接、crypto link、密钥、外部支付 ID、receipt 标识符、Remnawave 标识符以及推荐人的个人数据。

Error codes

代码

Retryable

何时发生

invalid_input

同时传入了两个或未传入任何 identity 字段;值无效

not_configured

环境配置缺失/不正确

identity_unavailable

无法将身份与 Bedolaga 用户匹配

user_not_found

未找到用户(upstream 404)

unauthorized

API 凭据错误/缺失(upstream 401/403)

rate_limited

达到速率限制(upstream 429)

upstream_timeout

响应前超时或网络故障

upstream_unavailable

Upstream 不可用(5xx 或不可恢复的错误)

invalid_upstream_response

响应体不是有效 JSON 或不是对象

internal_error

意外的内部错误

用户消息仅由安全的 error.message 构成,绝不透露 HTTP body 或内部 URL。

传输方式

服务器在同一个 server factory 和同一个工具注册表上支持两种传输方式:

传输方式

Launcher

端口

协议

Streamable HTTP(主要)

http_server.py

默认 3100

位于 / 的双时代 MCP(见下文)、GET /healthDELETE /(仅 legacy 会话)

Stdio

bedolaga_server.py

MCP stdio 握手(同一 factory)

端点 / 是唯一的,但同时服务两个协议时代;SDK v2 根据 MCP-Protocol-Version 头自行判断每个请求属于哪个时代:

  • 现代协议 2026-07-28 — 无状态/无会话。每个对 / 的 POST 都是自包含的:服务器从不发出 Mcp-Session-Id,也不在请求之间存储状态。官方 MCP SDK v2 客户端(见下文「官方 SDK v2 客户端」)自动使用此模式。

  • 使用 initialize 握手的 Legacy 客户端(直至 2025-11-25 的协议,包括 2024-11-05)会在 initialize 响应中获得 Mcp-Session-Id 头,并且必须在所有后续请求中传递该头。带有此头的 DELETE / 仅结束该会话;不影响其他会话和现代客户端。

GET /health 返回进程存活状态和服务器版本,不透露配置和机密。

版本兼容性

组件

版本

Bedolaga Bot API (upstream)

commit 49b05d5,应用 4.1.0

bedolaga-mcp

1.2.0

Python MCP SDK (mcp)

2.0.0

支持的 MCP 协议

2026-07-28(现代,无状态)+ 直至 2025-11-25 的 legacy initialize 握手

supportBot

2.0.1

mcp-remnawave

v3.2.1

工具契约已针对指定的 upstream 提交和 mcp-remnawave v3.2.1 基准进行验证。

要求

  • Python 3.11+

  • Docker(可选)

  • 已部署带 Web API 的 Bedolaga Bot

  • Bedolaga 的 API 密钥(在机器人管理面板中发放)

快速开始

1. 克隆

git clone https://github.com/mitetenov/bedolaga-mcp.git
cd bedolaga-mcp

2. 配置

cp .env.example .env
# Заполнить BEDOLAGA_API_URL и BEDOLAGA_API_KEY

3. 运行

Streamable HTTP(推荐):

# Установить зависимости
pip install -r requirements.txt

# Запустить HTTP-сервер
BEDOLAGA_API_URL=https://your-bot.example.com \
BEDOLAGA_API_KEY=your-key \
python3 http_server.py

服务器将监听 http://0.0.0.0:3100,MCP 端点为根路径 /

Stdio:

BEDOLAGA_API_URL=https://your-bot.example.com \
BEDOLAGA_API_KEY=your-key \
python3 bedolaga_server.py

通过 Docker:

docker compose up -d

Docker 镜像默认在 3100 端口启动 Streamable HTTP 服务器。

作为 MCP 服务器连接

Streamable HTTP

服务器可通过 HTTP 在 3100 端口访问,端点为根路径 /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"
    }
  }
}

通过 curl 检查(legacy 兼容性检查)

通过 curl 的原始 JSON-RPC 使用 legacy initialize 握手(协议 2024-11-05)——这是手动检查向后兼容性,而不是现代客户端的通信方式。现代 MCP SDK v2 客户端会自动协商协议 2026-07-28,并且不会收到 Mcp-Session-Id(见下文「官方 SDK v2 客户端(现代协议)」)。

# 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>"

官方 SDK v2 客户端(现代协议)

来自 Python MCP SDK v2(mcp==2.0.0)的官方客户端会自动协商协议——如果服务器支持则使用 2026-07-28,否则使用 legacy 握手——无需手动构造 _meta 或请求头:

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" 与 supportBot 使用的协商机制相同:客户端自行判断面前的是现代服务器还是 legacy 服务器,并且不要求调用方代码预先知道协议时代。

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

添加到 .cursor/mcp.jsonsettings.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"
      }
    }
  }
}

会话管理

Streamable HTTP 传输是 dual-era 的,会话仅适用于两个时代之一:

  • Legacy initialize-handshake(直到 2025-11-25 的协议):在 initialize 之后,服务器返回 Mcp-Session-Id 头,客户端必须在所有后续请求中传递该头。带有此头的 DELETE / 仅终止指定的会话;一个客户端不能终止或重用其他客户端的会话。

  • 现代协议 2026-07-28:stateless/sessionless——服务器从不发出 Mcp-Session-Id,并且对于此类客户端,DELETE / 既不需要也不适用。

环境变量

变量

用途

BEDOLAGA_API_URL

URL Bedolaga Web API

BEDOLAGA_API_KEY

Bedolaga API 密钥(通过 X-API-Key 传递给 upstream)

MCP_HTTP_HOST

绑定地址(默认:0.0.0.0

MCP_HTTP_PORT

HTTP 服务器端口(默认:3100

BEDOLAGA_TIMEOUT_MS

upstream 超时(毫秒)(默认:10000)

为了兼容性,如果未设置 MCP_HTTP_HOST/MCP_HTTP_PORT,则接受 legacy 变量 HOST/PORT

Upstream API

Bedolaga Web API:X-API-Key 位于请求头中。使用的路由:

  • GET /users/by-telegram-id/{telegram_id} — 按 Telegram ID 查找用户;

  • GET /users/{user_id} — 按内部 ID 查找用户(仅电子邮件工单);

  • GET /transactions?user_id=... — 带筛选和分页的交易记录;

  • GET /partners/referrers/{user_id} — 推荐人卡片。

更多信息:https://docs.bedolagam.ru

第一版的限制

  • 没有 provider-specific 的支付尝试。 Bedolaga 只返回已成为 transactions 总表中记录的操作。未成为记录的支付提供商的原始尝试不可用。

  • 无法读取用户的 Redis 购物车。 当前的 Web API 不为此提供安全的 read-only 端点。当前的问题“充值了但没有购买”可以通过 depositsubscription_payment 之间的差异可靠地诊断(参见 decision table)。

  • 支持 Email-only lookup。 对于没有 Telegram ID 的账户工单,服务器接受内部 user_id(正整数)并通过 GET /users/{user_id} 解析它。supportBot 固定(pin)账户的内部 user_id(负的 synthetic conversation key 的绝对值)——对于此类工单,Bedolaga 数据可用,而 Remnawave 工具返回 identity_unavailable,因为此类用户没有 Telegram 身份,也没有面板中经过验证的记录。

回滚(rollback)

在 supportBot 中设置 BEDOLAGA_MCP_ENABLED=false 会将其恢复到 Remnawave-only 模式:Bedolaga MCP 不连接,其工具从 allowlist 中消失,而 webhook/poller 的工单处理(BEDOLAGA_ENABLED)保持独立。回滚不会影响用户数据库和财务数据——Bedolaga MCP 是 read-only 的,不存储状态。

bedolaga-mcp 镜像回滚到标签 1.1.0(迁移到 MCP SDK v2 之前的最后一个版本,仅支持 legacy 时代的 Streamable HTTP)也是安全的:基于 MCP SDK v2 的 supportBot 客户端会在服务器不响应现代协议 2026-07-28 时自动回退(auto-fallback)到 legacy initialize-handshake,因此 Bedolaga MCP 工具无需额外配置即可继续使用。

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Provides user balance information by connecting to a backend service through the users_balance tool. Built with TypeScript and Express for retrieving financial data.
    -
  • A
    license
    A
    quality
    A
    maintenance
    Enables integration with Monobank API to check currency exchange rates, view account balances, and retrieve transaction statements through natural language queries.
    3
    29 npm
    9
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with Telegram Bot API for sending messages, photos, editing messages, answering callbacks, and fetching updates.
    MIT