关于 Budgetary: estimate token spend
@budgetary/mcp 是一个 MCP 服务,可在编码任务执行前估算 Token 开销,并在主机提供可靠数据时记录实际用量。它面向希望区分概率预测与实际 Token 计数的开发者和编码 Agent 用户。
主要功能
- 01任务前概率性 Token 估算
- 02缺乏依据时不作预测
- 03支持时记录实际 Token 数
- 04可选主机与语言标签
- 05doctor 命令检查自动提交
适用场景
- 01编码任务开始前估算 Token 开销
- 02比较预测与测得的用量
- 03按主机或声明的语言追踪估算
MCP 相关
该服务向支持 MCP 的主机提供一个 `estimate` 工具,并连接托管的 Budgetary API。实际用量提交取决于主机支持;Claude Code 自动提交需要随附插件。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @budgetary/mcpBUDGETARY_API_KEY密钥Budgetary API key (bg_live_ or bg_test_ prefix). Get one at https://budgetary.tools.BUDGETARY_HOSTOptional tag naming the MCP host this server runs under — e.g. claude-code, cursor, codex, copilot. It labels each estimate with where it came from, and an explicit value overrides the host name the MCP handshake reports. Free-form; defaults to "mcp" when unset.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
1收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| model | string | 否 | 可选的目标模型标识符(例如 claude-opus-4-7)。省略则使用账户默认模型。 |
| query | string | 是 | 要估算的编码任务的自然语言描述。 |
详细介绍
@budgetary/mcp
一个 Model Context Protocol 服务,可为任何支持 MCP 的宿主——Claude Code、Cursor、GitHub Copilot、Codex 等——在运行编码任务前提供概率性的Token 花费预估,并尽最大努力以绝不捏造的方式测量任务的实际花费。预测是概率;测量是计数。若没有可靠依据来预测某项具体任务,它会如实说明,而不是猜测。只需构建一次,即可随处添加。它取代了此前计划的各宿主专用扩展。
该服务只公开一个可由模型调用的工具 estimate。它会与托管的 Budgetary API https://api.budgetary.tools 通信。
安装——每个宿主只需一条命令
将密钥作为 BUDGETARY_API_KEY 传入,并使用 BUDGETARY_HOST 标记宿主,以便账本条目区分预估的来源。使用 npx 时务必带上 -y,以免启动时被安装提示阻塞。
Claude Code
claude mcp add budgetary \
--env BUDGETARY_API_KEY=bg_test_... \
--env BUDGETARY_HOST=claude-code \
-- npx -y @budgetary/mcp
自动记录实际花费需要安装插件,光运行此命令不够。
claude mcp add只会接入 estimate 工具。提交实际花费的会话结束钩子由捆绑的 Claude Code 插件(通过其清单)接入。因此,只运行claude mcp add时,你能获得预估,但与其他宿主一样,必须手动记录实际花费。安装插件即可启用自动流程——或者自行添加钩子(见下文)。无需读到这里才能了解情况:
npx @budgetary/mcp doctor会报告此机器上是否曾运行过自动会话结束提交,并在尚未配置时打印要添加的确切钩子。对于标记为BUDGETARY_HOST=claude-code的安装(如上述命令所示),该服务也会在首次预估时提示一次。这两种方式都不会写入你的 Claude Code 配置——此软件包中的任何内容都不会读取或编辑该配置。
若要不通过插件接入钩子,请自行将以下内容添加到 ~/.claude/settings.json:
{
"hooks": {
"SessionEnd": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "npx -y @budgetary/mcp on-session-end",
"timeout": 30
}
]
}
]
}
}
请将密钥放入 ~/.budgetary/config.json(见 API 密钥设置),不要将其插入命令中,以免出现在进程列表里。
该钩子会在使用时证明其有效:下次会话结束后,运行 npx @budgetary/mcp doctor,即可在 Last auto: 下看到该次运行。在此之前,doctor 仍会报告尚未记录自动提交——这是预期行为,并不意味着编辑失败。此软件包中的任何内容都不会读取你的 Claude Code 配置,因此无法更早确认钩子是否生效。
Cursor — .cursor/mcp.json(项目级)或 ~/.cursor/mcp.json(全局)
{
"mcpServers": {
"budgetary": {
"command": "npx",
"args": ["-y", "@budgetary/mcp"],
"env": {
"BUDGETARY_API_KEY": "bg_test_...",
"BUDGETARY_HOST": "cursor"
}
}
}
}
GitHub Copilot(VS Code)— .vscode/mcp.json
VS Code 使用 servers 键(而非 mcpServers),并可通过 inputs 提示输入密钥:
{
"inputs": [
{ "id": "budgetary-key", "type": "promptString", "description": "Budgetary API key", "password": true }
],
"servers": {
"budgetary": {
"command": "npx",
"args": ["-y", "@budgetary/mcp"],
"env": {
"BUDGETARY_API_KEY": "${input:budgetary-key}",
"BUDGETARY_HOST": "copilot"
}
}
}
}
Codex
codex mcp add budgetary \
--env BUDGETARY_API_KEY=bg_test_... \
--env BUDGETARY_HOST=codex \
-- npx -y @budgetary/mcp
……或者写入 ~/.codex/config.toml:
[mcp_servers.budgetary]
command = "npx"
args = ["-y", "@budgetary/mcp"]
[mcp_servers.budgetary.env]
BUDGETARY_API_KEY = "bg_test_..."
BUDGETARY_HOST = "codex"
从 MCP 注册表安装(单击即可)
此服务已作为 io.github.thriftell/budgetary 列入 MCP 注册表。该条目仅列出上述 npm 软件包,不包含其他内容。通过该条目安装的宿主会提示你填写条目声明的字段——必填的 BUDGETARY_API_KEY 和可选的 BUDGETARY_HOST。
无论如何都请设置 BUDGETARY_HOST。 它用于标记预估的来源宿主;显式设置的值始终优先于服务自行检测到的任何值。即使留空,宿主仍会记录为 mcp——不过,关于未提交运行的单次提示不再依赖此变量:MCP 握手已包含宿主自身的名称,因此即使 Claude Code 安装从未设置该变量,只要没有任何机制在此提交已完成的运行,也仍会收到一次提示。如果客户端读取的条目版本较旧、没有提供此字段,请按上述各节所示,将其添加到宿主自己的 MCP 配置中对应的服务条目里。
远程端点(仅限手动配置)
https://api.budgetary.tools/mcp 上提供了一个 Streamable-HTTP 端点。注册表条目不再宣传此端点,因为条目只能包含 URL,除此之外别无他物:没有字段可填写 tools/call 所需的 API 密钥,也没有空间在你选择它时告知你以下任何信息。请手动配置,否则就不要使用。
它只能估算。 此路径上没有本地进程——没有待处理存储、没有会话结束钩子,也没有可读取的转录——因此无法衡量一次运行的实际成本。该端点也刻意不提供接受计数的工具,因为那样就必须由你提供计数,而不是进行测量。通过此端点作出的估算,无论通过何种途径,都不会由实际成本结算。如果你希望统计运行成本,请安装上面的 npm 包。
通过 Authorization: Bearer bg_… 进行身份验证;没有密钥时,initialize 和 tools/list 仍会正常响应,而 tools/call 会返回 authentication_failed。如果你的宿主缓存了较旧版本的条目,远程服务可能仍显示为安装选项——撤下仅适用于当前条目。
API 密钥设置
服务按以下顺序解析密钥:
- 服务环境中的
BUDGETARY_API_KEY(通过上面的宿主配置设置)。 ~/.budgetary/config.json→{ "api_key": "bg_...", "base_url"? }。
如果两处都未设置,estimate 工具会返回简短的密钥配置指引,而不是报错——它绝不会抛出异常,也不会导致宿主崩溃。
mkdir -p ~/.budgetary
# Write the key with an EDITOR so it never lands in your shell history:
"${EDITOR:-nano}" ~/.budgetary/config.json # add: { "api_key": "bg_test_..." }
chmod 600 ~/.budgetary/config.json # owner-only
建议使用文本编辑器,而不是
echo '{...}' > config.json,后者会将密钥记录在 shell 历史记录中;还应对文件执行chmod 600,避免其他用户读取。
密钥前缀表示环境:
bg_test_— 免费测试层级,可立即用于开发。bg_live_— 生产环境。生产密钥必须对应一个有效方案;否则,API 会返回 403,工具会显示 "Your Budgetary key isn't on an active plan."(这与 401 不同,后者表示密钥本身未通过验证。)
API 密钥绝不会出现在工具结果、pending.json 或任何日志行中。
可选:标记你正在使用的语言
你可以选择为每次估算标记所用语言,以便按语言归类估算历史记录。在服务环境中设置:
--env BUDGETARY_LANGUAGE=TypeScript
或者在 ~/.budgetary/config.json 中添加 language 字段(如果两者都设置,以环境变量为准):
{ "api_key": "bg_test_...", "language": "TypeScript" }
这是一个自由格式的显示名称,例如 TypeScript、Python、Go 等,服务会对其进行规范化;无需完全匹配特定拼写。与 BUDGETARY_HOST 一样,它是你在环境中声明的无害标签:语言模型不会设置它,也不会根据任务描述猜测。estimate 工具刻意不提供 language 参数。如果你不设置,估算记录中就不会包含语言——它从来都不是必需的,也不会改变估算结果本身。
纯 stdio MCP 服务只能看到宿主发送给它的消息,无法知道你打开了哪个文件,因此它只能依赖这个声明值(每个宿主/会话一个)。无法提供语言信息的宿主只会记录不带语言的估算。
可选:BUDGETARY_SOURCE — 操作员为一批运行添加的标签
普通用户无需在此设置任何内容,不设置也不会有任何变化。 这是为操作员准备的:他们通过自动化测试框架(基准测试、负载测试、脚本化评估)驱动此客户端,并希望给这些运行添加标签,以便之后与真实运行区分开来。
在启动该批次的进程的环境中设置此变量,使其生命周期与该批次一致:
BUDGETARY_SOURCE=my-harness-run <the command your harness runs>
不要在 MCP 主机配置中设置此变量。 与
BUDGETARY_HOST和BUDGETARY_LANGUAGE不同,此标签不应放入claude mcp add --env、~/.claude.json或.mcp.json。这些配置是全机器范围且永久生效的:你为某一批次在那里设置的标签会悄无声息地持续生效,在该批次结束后,机器上的每个普通会话都会带上这个标签——而且无法察觉,因为记录看起来仍然完全正常。此变量也不会从~/.budgetary/config.json中读取,这是有意为之——这三个变量中,只有BUDGETARY_LANGUAGE有config.json回退值。描述一次运行的标签,不应在运行结束后继续生效。
每次实际用量提交都会附带此标签。默认值为 mcp_client。它是一个不透明字符串——客户端不会赋予它任何含义,只会验证其格式(最多 64 个字符,且仅限 A–Z a–z 0–9 . _ -),并忽略格式错误的值;此时会回退到默认值,而不会导致提交失败。(使用 BUDGETARY_DEBUG=1 运行时,如果标签被拒绝,客户端会在 stderr 中说明;否则,拼写错误不会有提示。)
有两点需要特别说明,它并非:
- 它不会改变数据的处理方式。 它是标签,不是设置。设置或不设置它都不会授予权限、解锁任何内容,也不会改变记录的内容或数据的使用方式。
- 它不是单任务字段,模型也不会设置它。 与
BUDGETARY_HOST和BUDGETARY_LANGUAGE一样,它是在环境中声明的。因此,estimate工具特意不提供source参数。
此标签会在生成估算时解析一次,并存储在该估算的待处理条目中——因此,如果之后需要重试提交(从不同会话、使用不同环境),提交的仍是实际发生的那次运行所对应的标签。
实际用量——能自动记录的自动记录,否则手动记录;绝不捏造
运行前估算只完成了整个流程的一半;校准需要运行后的实际令牌数。记录方式取决于主机提供的功能:
-
Claude Code(使用插件)——自动。 此主机会写入真实的会话记录。插件的会话结束钩子会读取真实的
tokens_in + tokens_out(不包括缓存读取令牌),并提交这些数据,以及一份简短的行为跟踪:此次运行使用了哪些工具(Read、Edit、Bash……)、每个工具大致用了多少令牌,以及每个步骤的两项原始测量数据——运行的命令(一个已脱敏的描述:常见程序名称,例如pytest或go test,以及其余部分经过加盐处理、不可逆的摘要——绝不包含原始路径、参数或命令)和是否成功。此跟踪基于会话记录测得,绝不由模型提供;任何无法可靠读取的字段都会直接省略,而总用量仍会提交。无需人工操作。 -
Claude Code(直接使用
claude mcp add,不安装插件)——根据会话记录手动提交。 没有插件就没有会话结束钩子,因此不会自动为你提交数据——但 Claude Code 无论是否安装插件,都会写入相同的真实会话记录,所以你无需手动输入令牌数。会话结束后,使用以下命令提交测得的总用量(以及相同的行为跟踪):npx @budgetary/mcp on-session-end --transcript ~/.claude/projects/<project>/<session-id>.jsonl请从你进行估算的目录运行,并指定一个已完成的会话——仍在写入的转录内容并不完整,而且估算的首次提交才会生效。添加
--success或--failed,声明运行结果;若两者都不添加,则结果会保持未报告状态(见下文)。更好的做法是接入上文所述的钩子,不再手动操作。 -
Codex — 手动提交,数据来自 rollout。 Codex 不提供会话结束钩子,但会写入 rollout 转录内容。会话结束后,提交实际统计数据:
npx @budgetary/mcp on-session-end --transcript ~/.codex/sessions/rollout-<ts>-<uuid>.jsonl请从你进行估算的目录运行。
声明运行结果是可选的,且没有默认值。
--success/--failed用于说明运行是否达成目标,并会原样转发;但只有实际检查过的调用方才有内容可声明,因此若两个标志都未指定,该字段就会省略,服务器会将运行结果记录为未观察到。这是第三种状态:不表示运行失败,也不表示运行成功。不要朝任何方向猜测——错误的判定无法更改(每项估算只存储首次提交的数据,且没有更新调用),而你测得的 token 数量无论如何都会提交。自行启动会话、因而观察到运行如何结束的执行框架,也可以通过
--censoring <category>声明这一点:值必须且只能是natural、harness_watchdog、operative_cap、kill_switch之一(这是 API 契约中封闭的取值范围)。系统会对值进行精确匹配并原样转发;其他任何值都会从提交内容中省略,不会被归一化为某个类别,也不会报错。对于你未观察到结束方式的运行,不要传入此参数:字段缺失能如实记录“未知”,而猜测为natural则是服务器无法检测的虚假声明。 -
Cursor / Copilot / 其他宿主 — 手动提交。 这些宿主不会把已完成 Agent 运行的 token 总数交给第三方服务器,大模型也不知道这些数据。因此,有空时请自行记录:
npx @budgetary/mcp report-actual此命令会显示本项目最近一项待补充实际数据的估算,并提示你输入输入和输出 token 数量(从宿主的用量界面读取,
48,000这样的分组数字也可以)、任务是否成功、可选的持续时间,以及——如果你观察到了——运行是如何结束的(达到上限、看门狗触发、主动中止,还是自然结束)。在最后一个问题处按 Enter 不会记录任何内容:“不确定”是一个有效答案;未观察到的结束方式绝不会被转换为某个值。
要随时查看哪些估算仍在等待实际数据(只读,不调用服务器):
npx @budgetary/mcp pending
模型不会提供 token 数量。 模型唯一可调用的工具是
estimate。实际数据只会通过以下两种方式提交:(a) 会话结束钩子读取真实转录内容,或 (b) 用户输入report-actual命令。编造实际数据会污染校准结果,因此特意不提供模型可调用的数量写入工具。
录制运行后你会看到什么
录制一次运行后,会返回一份实测明细,显示令牌的使用去向——exploration、generation、testing、retries、other,以及各项占实测总量的比例——还会返回 API 对“像这样的任务,这样的情况是否正常?”的回答。两者均由 API 计算并报告,并按收到的内容原样打印;如果 API 报告没有数据,就不会打印任何内容,而不会进行猜测。这份明细是对该次运行自身计数的测量,因此结果准确,无需与其他数据进行比较;判定结果也可能如实显示为 insufficient_data,这代表 API 如实回答了这个问题,并非错误。
内容的显示位置取决于运行的提交方式:
report-actual/on-session-end --transcript— 打印在终端中,紧接在提交确认信息下方。- 会话结束钩子 — 钩子的输出不会传回给你(宿主会将其发送到调试日志),因此摘要会缓存在本地,并显示在你下次运行
estimate的结果下方,同时标注其测量的运行 ID。只显示一次,不会重复。
仪表板
如需使用预测值与实际值校准仪表板,请从 Open VSX 安装 Budgetary(budgetary.budgetary-vscode)——它可在 Cursor 和其他 VS Code 分支中直接运行,无需任何改动。本服务不会重新实现该功能。
隐私
你在某台机器上首次成功调用 estimate 后,会追加一条指向此处的一次性说明;npx @budgetary/mcp doctor 每次运行时也会重复显示其简短版本。这条说明会晚一次调用,并且会明确说明这一点:在任何内容能够显示之前,estimate 已经发送了任务文本。这是一项披露和指引——它不索取任何内容、不设置任何门槛,也不授予任何权限。本节就是它所指向的说明。
只有以下内容会离开你的机器,并且只会发送到 https://api.budgetary.tools:
- 你传给
estimate的任务描述,原样发送。 - 如果模型提供了目标模型标识符,则发送其标识符(例如
claude-opus-4-7)——这是estimate工具的可选model参数,未提供时则省略。 - 主机标签——如果你设置了
BUDGETARY_HOST,则使用该值,否则使用常量mcp。它只说明此次调用来自哪个 MCP 主机,不包含其他信息。 - 每次调用对应的请求 ID,每次
estimate都会生成一个新的随机 UUID,确保重试的调用不会被重复计数。它不会根据任何与你、你的机器或任务相关的信息生成。 - 如果你设置了语言标签,则发送你声明的标签(例如
TypeScript)——这是无害的标签,与主机名称类似。只有你通过BUDGETARY_LANGUAGE或配置中的language字段主动选择加入后,才会发送。 - 运行结束后,会发送令牌数(
tokens_in、tokens_out)和持续时间;只有在实际观察到结果时,才会发送success标志,否则绝不发送;如果声明过运行结束方式,则会发送运行结束方式——仅限natural、harness_watchdog、operative_cap、kill_switch其中之一,不会发送其他值。 - 固定的客户端标签——除非操作人员通过
BUDGETARY_SOURCE覆盖它(见上文),否则为mcp_client。它只说明是哪一个客户端发送了这条记录,不包含其他信息:这是固定字符串,不会根据与你、你的机器或任务相关的任何信息生成。 - 在 Claude Code 中,会发送行为轨迹:逐步记录主机工具名称(例如
Read、Bash)、令牌数、对操作对象的脱敏描述符,以及操作是否成功。描述符仅在程序名称属于常见且非敏感工具时才会以明文显示(例如pytest、npm run)——粘贴的凭据或私有脚本名称绝不会显示,只会记录其加盐摘要;程序之后的所有内容(路径、参数、命令其余部分)始终只包含在摘要中;对于文件工具,则只记录裸路径摘要。自定义或内部工具名称(例如组织的私有 MCP 工具)会以通用名称mcp:other报告,绝不原样发送。任何文件内容、绝对路径、命令参数或输出都不会离开机器——只会发送允许列表中的程序名称和不透明键。设置BUDGETARY_TRACE_TARGET=off可完全移除描述符(轨迹将退化为仅包含工具名称和令牌数);任何不是明确的1/true/on/yes的值都会视为关闭。
不会传输其他任何内容。描述符摘要和附加到每次估算的 project_id 都是加盐、不可逆的哈希(HMAC-SHA256):描述符摘要使用每次提交时新生成的盐,project_id 使用保存在 ~/.budgetary/install-salt 的机器本地安装盐。盐绝不会离开机器,因此服务端只会获得无法还原为命令或路径的稳定键。待处理存储位于 ~/.budgetary/pending.json,与官方 Claude Code 和 Codex 客户端逐字节共享,因此配置一次即可覆盖所有主机。API 为已提交运行返回的测量摘要会缓存在本地 ~/.budgetary/measured.json,直到 estimate 显示它为止——最多保留少量近期记录,一周后删除;它只是你已经收到的响应副本,其中任何内容都不会发送到其他地方。
参考
关于 v1 API 契约——端点、错误代码和场景标签——请参阅 docs/api-contract.md。
根据 Apache-2.0 许可。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。