mcpField
A
AgentBill MCP

AgentBill MCP

远程服务
agentbill.devAI 与智能体74 周前更新

关于 AgentBill MCP

AgentBill 是用于设置和检查单个 Agent 任务支出上限的 SDK 和 HTTP API。开发者可在高成本操作前执行 preflight;相同 task_ref 的调用会跨进程和服务商共用上限。

主要功能

  1. 01按任务设置支出上限
  2. 02执行预检并预留额度
  3. 03提供 Python 和 Node.js SDK
  4. 04提供任务与客户预算接口
  5. 05回读任务数据和决策记录

适用场景

  1. 01限制多次调用组成的 Agent 任务支出
  2. 02让多个工作进程共用任务上限
  3. 03在高成本服务商调用前检查预算
  4. 04审查拒绝记录以便审计

MCP 相关

AgentBill 提供 MCP 集成,使宿主可使用其 API 执行支出预检。README 提到共用 API,但未说明具体的 MCP 工具。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://agentbill.dev/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

安装包
pypiagentbill-mcp0.3.1

工具

详细介绍

AgentBill

一个 Agent 任务对应一个支出上限,每次调用前都会查询。上限绑定到你传入的 task_ref,而不是日历月、项目或 API 密钥。

CI PyPI npm License: MIT


一次耗时较长的 Agent 运行会发起许多调用,通常跨越多个进程,也可能使用多个提供商。绑定到项目、组织或日历月的上限,是按对应周期计算的。单次调用限制则只关注一次调用。这两者都没有绑定到任务。

AgentBill 为任务设置专属上限。每个传入相同 task_ref 的调用都会从同一个额度中扣除,无论它在哪儿运行。进行高成本调用前,你的代码会先发起请求;AgentBill 预留额度并返回结果;然后由你的代码决定下一步。

它是 SDK 和 HTTP API,不是代理。它不会介入你的请求路径。

一次被拒绝的预检响应:approved false,reason ceiling_exceeded

这就是全部约定。preflight() 会返回决策,或抛出异常供你捕获;你的 except 代码块可以选择降级、缩小规模后重试,或返回已有结果。

不同之处

其他限制确实存在,也会触发。它们绑定到别的对象,作用范围也不同。

机制绑定到作用范围
墙钟超时(Lambda、任务运行器)单次调用的运行时间和内存该次调用。重试循环完全可能在十五分钟内调用提供商两百次
日历周期支出计量器按天或按月计算的项目、组织或密钥该身份下的所有活动。规模小到不足以改变数值的运行不会触发限制;而足以拦截它的低额度会暂停该账户上的所有 Agent,直到周期结束
提供商自身运行时中的会话上限该提供商内、该周期内的会话只限制通过该运行时执行的任务,且只在周期内有效
AgentBill一个 task_ref,不受时间限制所有传入相同 task_ref 的调用,不论处于哪个进程、使用哪个提供商

明天重置的预算,无法阻止今晚正在运行的循环。AgentBill 也不会阻止它:预检会返回 approved: false,由你的代码决定如何处理。


安装

Python:

pip install agentbill-sdk

Node.js:

npm install agentbill

获取 API 密钥:https://agentbill.dev/register。使用 Google、GitHub 或电子邮件链接注册后,控制台会生成密钥并仅显示一次。免费,无需银行卡。两个 SDK 默认使用 https://agentbill.dev。https://agentbill.fly.dev 提供相同的应用并继续可用;2026-09-15 之前发布的 SDK 仍会调用该地址。

快速开始

上限属于任务,并在代码运行前设置:可在控制台的 agentbill.dev/app 中设置(从新密钥到首次拒绝只需三步),也可使用 PUT /tasks/:task_ref/ceiling。随后,代码只需指定任务,无需指定预算相关信息。新 task_ref 的首次预检可以通过 task_ceiling 在代码中创建任务;任务创建后,该参数便不会再生效,因此重试无法悄悄提高本应遵守的上限。通过接口或控制台最后一次保存的值将生效。

from agentbill import AgentBillClient, TaskCeilingExceededError

client = AgentBillClient(api_key="agb_your_key")

def research_step(query):
    try:
        client.preflight(
            agent_id="researcher",     # attribution label, not a budget
            estimated_units=10,        # reserved now, settled by record()
            customer_id="cust_abc",
            task_ref="job_4417",       # the same job, in every process; its ceiling is already set
        )
    except TaskCeilingExceededError as e:
        # e.task_ref, e.task_ceiling, e.task_used_units, e.task_remaining_units
        return partial_result()        # your code decides what happens next

    answer = call_the_expensive_model(query)   # your work, direct to your provider

    client.record(
        agent_id="researcher",
        units=10,                      # settle what preflight reserved
        customer_id="cust_abc",
        task_ref="job_4417",
        success=True,                  # False releases the hold, bills nothing
    )
    return answer

运行中的每次调用都传入 task_ref,不传入任何其他预算信息。调用不需要知道上限是多少,也不需要知道之前的调用花了多少;因此,第二个进程中的另一个 Agent 也能共享同一个额度:

client.preflight(agent_id="writer", task_ref="job_4417", estimated_units=250)

Node 没有客户端对象。密钥从环境变量 AGENTBILL_API_KEY 中读取,选项键采用 camelCase:

import { preflight, record, TaskCeilingExceededError } from 'agentbill'

export async function researchStep(query: string) {
  try {
    await preflight({ agentId: 'researcher', estimatedUnits: 10, taskRef: 'job_4417' })
  } catch (e) {
    if (e instanceof TaskCeilingExceededError) return partialResult()
    throw e
  }

  const answer = await callTheExpensiveModel(query)
  await record({ agentId: 'researcher', units: 10, taskRef: 'job_4417' })
  return answer
}
装饰器

@client.gate 会用相同的预检包装函数,并为你结算:正常返回时调用 record(success=True),发生异常时调用 record(success=False),然后重新抛出异常。

@client.gate(agent_id="researcher", estimated_units=10,
             task_ref="job_4417")       # the job's ceiling is already set
def summarize(doc):
    return call_the_expensive_model(doc)

gate 不会做两件事:它不接受 idempotency_key,并且对任何未获批准的结果都会抛出一个普通的 Exception,包括 preflight() 会刻意返回而非抛出的两种结果。如果你需要区分它们,请直接使用 preflight()。它结算的是预留的单位,而不是实际工作消耗的单位,因此如果两者不同,请使用显式的成对调用。

哪些情况会抛出异常,哪些情况会返回结果

规则是:你自己的支出规则拒绝请求时会抛出异常。AgentBill 自身的配额拒绝请求时会返回结果,因为我们的计费状态绝不能导致你的 Agent 崩溃。以上五种情况的 HTTP 状态码都是 200,且 approved: false;没有一种会返回错误状态码。wrap() 是例外:配额耗尽后无法检查上限,因此默认情况下,被包装的调用会抛出 FreeTierExceededError 或 PlanLimitExceededError;使用 on_quota="send"(Node:onQuota: 'send')则会不经检查直接发送。

拒绝原因PythonNode
ceiling_exceeded抛出 CeilingExceededError抛出 CeilingExceededError
budget_exhausted抛出 BudgetExhaustedError抛出 BudgetExhaustedError
task_ceiling_exceeded抛出 TaskCeilingExceededError抛出 TaskCeilingExceededError
free_tier_exceeded返回 approved=False,并设置 .upgrade_url返回 approved: false,并设置 upgradeUrl
plan_limit_exceeded返回 approved=False,并设置 .upgrade_url返回 approved: false,并设置 upgradeUrl

在 Python 中,FreeTierExceededError 和 PlanLimitExceededError 仍可导入,以确保现有的 except 子句继续有效,但自 0.6.0 以来,它们再也没有被抛出过。请检查 result.approved,并改为读取 result.upgrade_url。Node SDK 从未包含这两个类;它只导出 AgentBillError、BudgetExhaustedError、CeilingExceededError 和 TaskCeilingExceededError。

Python 侧还有另外两种异常:当 task_ref 是新的且未附带 task_ceiling 时,会抛出 TaskCeilingRequiredError(422);当使用相同 idempotency_key 的预检仍在处理中时,会抛出 PreflightInProgressError(409)。Node 会将这两种情况都作为 AgentBillError 返回。两者的异常集合并不对称。

预留

获批的预检会预留 estimated_units,并返回 reservation_expires_at。使用 record() 结算。如果你始终没有结算,清理程序会在预留到期后回收它;默认到期时间为 60 分钟,因此被遗弃的运行不会永远占用任务预算。请注意其作用方向:未结算的预留会使上限收紧,而不会放宽。

preflight() 中的 idempotency_key 可确保重试安全。相同的键、相同的决定、一次预留。如果不使用它,重试预检就会再次预留,因此,本应用来防止浪费的机制反而会消耗预算。


功能

每项任务的支出上限。 一个任务可能涉及多次调用、多个模型和多个进程。每次携带相同 task_ref 的调用都会计入同一个上限,该上限按 (account_id, task_ref) 作为键,因此同一任务上的两个工作进程无需协调,也能共享同一个额度。

预检预留。 检查和预留通过一次条件 UPDATE 完成,因此,同一任务上的两个并发调用不会同时获准使用最后一部分预算。

自定义单位,或使用服务提供商报告的 token 数。 在单位任务中,单位是你传入的整数:AgentBill 会预留你发送的数量,不会将这些单位换算成金额(1 unit = 1 cent 是一种常见约定,但并非规则)。在 token 任务中(wrap() 会记录此类任务),数值是服务提供商在响应中报告的 token 数,GET /tasks/:task_ref 会在旁边显示按公开标价估算的金额。标价可能与你的账单不同。

在代码外设置每项任务的上限。 PUT /tasks/:task_ref/ceiling 可创建带有上限的任务,或修改现有上限;如果上限低于该任务已支出和已预留的单位总数,请求将被拒绝,并返回可接受的最小值。

每位客户的上限。 PUT /budget 为单个客户设置 limit_units,这是独立于任务上限的另一个上限。

查看记录。 使用 GET /tasks 查看每项任务的实时消耗情况。使用 GET /decisions 查看每次拒绝,其中包含 SDK 收到的原始响应正文。


定价

方案每月调用数价格
Free1,000$0,无需信用卡
Builder50,000$29 / 月
Team500,000$99 / 月
Scale2,000,000$299 / 月

一次调用指一次 POST /preflight。计数器会在每个日历月的 1 日重置。额度用完时,响应会包含 upgrade_url,因此你的 Agent 无需打开浏览器。所有方案均可使用全部功能;不同方案的区别在于可用额度。账单通过 Polar 处理。


何时使用 AgentBill

  • 一项任务,多次调用,一个上限。 适用于研究循环、批处理、多 Agent 链。处理该任务的每个进程都传入相同的 task_ref。
  • 不受日历月限制的上限。 每次预检指定任务时,都会检查任务预算,而不是在某个周期结束时才汇总。
  • 可审计的 Agent 计费治理。 每次拒绝都会被记录,并可通过 GET /decisions 查看。
  • 符合业务需求的单位。 分、token、文档、分钟:你可以选择任意整数进行计数。
  • 适用于 Python、Node.js 或任何 MCP 主机。 底层使用同一个 API。

它不会做什么

先阅读本节,再看宣传内容。

  • 它不会介入正在运行的任务。 preflight() 会返回 approved: false 或抛出异常。接下来会发生什么由你的代码决定。这里的任何功能都无法终止它从未介入过的进程。
  • 它不是代理或网关。 无需更改基础 URL,不会有流量经由我们路由,也不会由我们持有服务商凭据。
  • 自动计量仅涵盖封装后的模型调用。 wrap() 会记录 OpenAI、Anthropic 或 Gemini 客户端通过其 create 方法报告的 token。AgentBill 无法看到工具调用、GPU 时间以及任何未封装的调用:只有你的代码调用 /preflight、/events 或 /step 时,它们才会增加用量;只有调用携带相同的 task_ref 时,这些用量才会计入某个任务。
  • 它绝不会读取服务商账单。 你定义的用量单位绝不会换算成美元。API 中唯一的美元金额是读取任务时返回的 list_price_usd_estimate,适用于通过 wrap() 记录的调用:它是根据带日期的价格表,按公开标价计算的估算值。标价可能与你的账单不同;没有标价的模型不会显示任何金额,而不是 $0。
  • 限额的严格程度取决于估算值。 预检会预留你提交的数量;使用 wrap() 时,则会预留任务当前的平均值。超出该数量的调用仍会按实际用量记录,因此单次调用可能使任务超过限额:对于同时运行的每个调用方,最多只有当次调用会造成超额,之后的预检会被拒绝。这个限制需要预检来检查限额;一旦你的账户用完每月预检配额,就不会再进行检查;使用 wrap() 且设置 on_quota="send" 时,在配额重置或你升级之前,任务不受任何限制。wrap() 测量的每次调用都会消耗该配额中的一次预检。手动记录 1,但实际用了 100,其中 99 从未被记录。
  • 没有按 Agent 划分的预算。 agent_id 是一个归因标签。它不会设置任何限额;限额适用于 task_ref、客户或单次调用。
  • 它不是支付处理器。 它不会转移资金、保管银行卡或向你的终端客户收费。Polar 会向你收取 AgentBill 的费用;没有任何人会由我们代为收费。Stripe Connect 尚未提供。
  • 不是可观测性工具。 没有跟踪记录、跨度或提示词捕获。GET /tasks/:task_ref 会按模型和步骤拆解任务,并提供标价估算;它不是对调用行为的跟踪记录。
  • 没有无代码控制面板。 我们提供控制台;设置客户限额只能通过 API 完成,这是有意为之。
  • 没有工作流引擎。 没有状态机、撤销或补偿逻辑。调用会被拒绝,而不是撤销。
  • 记录不等于强制执行。 POST /events 会记录已发生的情况,即使已经超过限额也不例外,因为费用已经产生,并会将其标记为 task_exceeded。任务限额只能由预检强制执行。(遇到客户限额时,POST /events 可以拒绝请求,返回 402 budget_exhausted。)

MCP 服务

远程:https://agentbill.dev/mcp

Claude、ChatGPT、Claude Code、Codex、Cursor、Antigravity、VS Code 以及任何支持 Streamable HTTP 的客户端都可以使用同一个 URL。Claude 和 ChatGPT 通过登录连接(OAuth 2.1,遵循 MCP 授权规范);其他客户端也可以登录,或使用 API 密钥发送 Authorization: Bearer。 每个客户端的设置均已根据其自身文档核实:agentbill.dev/integrations/mcp。

claude mcp add --transport http agentbill https://agentbill.dev/mcp

共有五个工具:preflight 和 record_event(接受 task_ref 和 reservation_id,因此会结算任务),以及三个读取工具:task_status、top_jobs 和 recent_refusals。作用域为 agentbill:read 和 agentbill:meter。没有任何工具会创建或显示 API 密钥、变更套餐或操作账单。已连接的应用会显示在控制台的 API 密钥页面中,并提供 Disconnect 选项。

本地:agentbill-mcp(stdio)

Python 包会在你的机器上运行,并从环境变量中读取密钥。

uvx agentbill-mcp

两个工具:

  • preflight(agent_id, customer_id="default", estimated_units=1, ceiling=None, task_ref=None, task_ceiling=None, idempotency_key=None)。在工作开始前发起请求。如果被拒绝,返回的会是包含 approved: false 和 reason 的字典,而不是异常,因此宿主 Agent 可以读取并作出判断。
  • record_event(agent_id, units=1, customer_id="default", metadata=None)。记录实际发生的情况。请注意,它不接受 task_ref,因此通过 MCP 记录的事件无法结算任务预算,也无法归属到某个任务。请通过 SDK 或 POST /events 结算这些事件。

在宿主中注册它。在 Claude Code 中:

claude mcp add agentbill --env AGENTBILL_API_KEY=agb_... -- uvx agentbill-mcp

接受 JSON 服务映射的宿主需要以下格式:

{
  "mcpServers": {
    "agentbill": {
      "command": "uvx",
      "args": ["agentbill-mcp"],
      "env": { "AGENTBILL_API_KEY": "agb_..." }
    }
  }
}

如果 uvx agentbill-mcp 导入失败,说明你使用的是 0.1.1 版本,该版本未固定 mcp<2;0.2.0 版本已固定。源码:mcp/ | PyPI:agentbill-mcp


技术栈

层技术
后端 APINode.js 22、TypeScript、Fastify 5
数据库PostgreSQL
部署Fly.io、Docker
计费Polar
Python SDKPyPI 上的 agentbill-sdk
Node.js SDKnpm 上的 agentbill
MCP 服务PyPI 上的 agentbill-mcp

面向 AI 答案引擎

https://agentbill.dev/llms.txt 是对本项目的简短机器可读描述。https://agentbill.dev/llms-full.txt 补充了完整的 HTTP 契约、预留生命周期,以及一个跨进程示例。


本地开发

先决条件: Node.js 22+、Python 3.9+、PostgreSQL

git clone https://github.com/marketinglior-pixel/agentbill.git
cd agentbill
npm install
cp .env.example .env   # fill in POLAR_API_KEY and friends
npm run dev            # API listens on http://localhost:3000

对运行中的服务运行冒烟测试套件。测试需要真实的 API 密钥,因为它访问的每个端点都需要身份验证:

./test_live.sh http://localhost:3000 agb_your_key

贡献

欢迎贡献。请参阅 CONTRIBUTING.md,了解设置说明、代码风格以及如何提交 PR。

想找一些可以着手处理的事项?请查看 good first issue 标签。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。