收费站DPYC
 ](https://pypi.org/project/tollbooth-dpyc/) 
不要骚扰你的客户 --MCP服务器的比特币闪电微支付。
专利申请中 --美国临时申请64/045999
*这个项目中的隐喻来自* 幻象天堂 *诺顿·贾斯特,朱尔斯·费弗(1961)插图。Milo、Tock、Tollboot、Dictionopolis和Digitopolis是Juster先生非凡想象力的创造。我们刚刚建立了支付基础设施。*
______________________________________________________________________
问题
成千上万的开发商正在建设 主控程序 服务器——让人工智能代理与世界互动的服务。知识图谱、财务数据、社交媒体、医疗记录。每一个都是地图上的一个城市。但是他们之间的收费公路呢?大开。没有收费员。没有可持续的经济。
每个MCP操作员都面临着同样的问题: *我该如何保持灯亮着?*
传统的API密钥按月计费?你现在正在经营一家SaaS公司。L402——闪电原生按需付费?每一个API调用都需要进行支付协商。米洛的玩具车在每个十字路口都停下来,摸索着找零。
解决方案
Tollboot DPYC采取了一种不同的方法——尊重每个人的时间:
米洛开车到收费站一次,用一张闪电发票买了一卷代币,然后开车。 没有停止。没有谈判。没有按要求摩擦。令牌在后台悄然递减。当价格下跌时,他又买了一个。收费公路保持快速。
通过比特币闪电网络预付的信用额度,在工具级别进行门控,立即结算,没有订阅管理,也没有第三方支付处理商收取费用。
______________________________________________________________________
快速入门:在5分钟内建立一个操作员
规范引用运算符是 收费亭样品每个生产操作员都遵循这种模式。
1.安装
pip install "tollbooth-dpyc[nostr]" fastmcp2.定义你的工具
from fastmcp import FastMCP
from tollbooth.tool_identity import ToolIdentity, STANDARD_IDENTITIES, capability_uuid
from tollbooth.runtime import OperatorRuntime, register_standard_tools
from tollbooth.credential_templates import CredentialTemplate, FieldSpec
from tollbooth.slug_tools import make_slug_tool
mcp = FastMCP("My Service")
# Domain tools — what your service actually does
_DOMAIN_TOOLS = [
ToolIdentity(capability="get_weather", category="read", intent="Current weather data"),
ToolIdentity(capability="get_forecast", category="read", intent="5-day forecast"),
]
TOOL_REGISTRY = {t.id: t for t in _DOMAIN_TOOLS}3.创建运行时
runtime = OperatorRuntime(
tool_registry={**STANDARD_IDENTITIES, **TOOL_REGISTRY},
operator_credential_template=CredentialTemplate(
service="my-operator",
fields={
"btcpay_host": FieldSpec(required=True, sensitive=False, description="BTCPay Server URL"),
"btcpay_api_key": FieldSpec(required=True, sensitive=True, description="BTCPay API key"),
"btcpay_store_id": FieldSpec(required=True, sensitive=True, description="BTCPay store ID"),
},
),
service_name="My Weather Service",
)4.注册标准工具+域工具
# This single call registers all 26+ standard DPYC tools
register_standard_tools(mcp, "weather", runtime,
service_name="my-weather-service",
service_version="1.0.0",
)
# Domain tools use the paid_tool decorator
tool = make_slug_tool(mcp, "weather")
@tool
@runtime.paid_tool(capability_uuid("get_weather"))
async def get_weather(city: str, npub: str = "", proof: str = "") -> dict:
"""Get current weather for a city. Costs 1 api_sat."""
# Your domain logic here
return {"city": city, "temp": 72, "conditions": "sunny"}5.部署
设置一个环境变量并部署:
export TOLLBOOTH_NOSTR_OPERATOR_NSEC=nsec1...
fastmcp run server.py就是这样。运行时通过加密的Nostr DM从权威机构引导其他所有内容。
______________________________________________________________________
运作原理
部署流程
- 集
TOLLBOOTH_NOSTR_OPERATOR_NSEC--运营商的Nostr私钥。这是开机时唯一需要的秘密。 - 来自权威机构的运行时训练带 --从上游权威机构签名的Nostr中继上的加密DM中发现其Neon Postgres URL。
- 保险库初始化 --AES-256-GCM加密凭证和分类账存储在Neon Postgres上,按操作员隔离模式(
op_{hash}). - 通过Secure Courier交付操作员凭据 --BTCPay连接详细信息通过加密的Nostr DM(人在循环中,从不在env变量中)到达。
- 配置定价 --通过pricing Studio iOS应用程序或
set_pricing_model工具。 - 服务 --顾客通过Lightning购买积分,使用工具,积分自动递减。
信贷生命周期
- 顾客来电
purchase_credits--操作员获得权威证书(Schnorr签名的Nostr事件)并创建Lightning发票。 - 赞助人付费 闪电发票和任何钱包。
- 顾客来电
check_payment--在结算时,信用作为一部分添加,可选择到期(TrancheLifetime). - Patron使用工具 —
debit_or_deny盖茨每次付费工具调用:验证身份、证明、约束、定价,并借记余额。FIFO部分消耗。 - 余额不足 --赞助人购买了更多的信用额度。无订阅,无中断。
认证费阶梯
当用户购买信用额度时,运营商的上游管理机构会从运营商的预融资储备中扣除一小部分认证费(默认2%,最低10 sats)。顾客总是得到他们支付的信用额度——费用是运营商做生意的成本。
每个管理局本身都是其上游管理局的运营商,相同的费用通过链条逐级传递到主管理局。
______________________________________________________________________
标准工具
register_standard_tools(mcp, slug, runtime) 注册这些工具,前缀为操作员的slug(例如。, weather_check_balance):
信用和账单(始终注册)
| 工具 | 成本 | 目的 |
|---|---|---|
check_balance | 自由 | 当前信用余额、批次、使用情况摘要 |
purchase_credits | 免费 | 为信用购买创建闪电发票 |
check_payment | 自由 | 轮询发票状态;结算信用余额 |
check_price | 免费 | 预览工具调用的有效成本(在约束后) |
restore_credits | 免费 | 从因缓存问题而丢失的已付款发票中恢复信用 |
account_statement | 免费 | 30天购买和使用历史记录 |
account_statement_infographic | 1 sat | 账户对账单的SVG可视化 |
身份和生命周期
| 工具 | 成本 | 目的 |
|---|---|---|
service_status | 免费 | 操作员健康状况、生命周期状态、版本信息 |
session_status | 免费 | 操作员准备就绪:就绪/预热/未注册/无身份 |
get_operator_onboarding_status | 免费 | 配置了哪些操作员凭据,缺少哪些凭据 |
get_patron_onboarding_status | 免费 | 配置了哪些用户凭据,缺少哪些凭据 |
安全快递(凭证交换)
| 工具 | 成本 | 目的 |
|---|---|---|
request_credential_channel | 免费 | 向用户或操作员发送凭证模板DM |
receive_credentials | 免费 | 从保管库(即时)或中继(DM)获取凭证 |
forget_credentials | 免费 | 删除服务的保险存储凭据 |
Npub证明
| 工具 | 成本 | 目的 |
|---|---|---|
request_npub_proof | 免费 | 向赞助人发送证明挑战DM |
receive_npub_proof | 免费 | 验证顾客的Schnorr签名证明回复 |
权限平衡
| 工具 | 成本 | 目的 |
|---|---|---|
check_authority_balance | 免费 | 上游管理局的运营商证书余额 |
Oracle委派
| 工具 | 成本 | 目的 |
|---|---|---|
oracle_* | 免费 | 委托致电DPYC Oracle(社区信息、税率、会员资格) |
定价模型
| 工具 | 成本 | 目的 |
|---|---|---|
get_pricing_model | 免费 | 具有工具注册表和约束的当前定价模型 |
set_pricing_model | 免费 | 更新定价模型(受运营商限制,需要证明) |
list_constraint_types | 自由 | 可用约束类型及其参数 |
开放时间戳(当 ots_enabled=True)
| 工具 | 成本 | 目的 |
|---|---|---|
notarize_ledger | 免费 | 通过Merkle树+OTS将所有分类账状态锚定到比特币 |
get_notarization_proof | 免费 | 为特定赞助人提供Merkle收录证明 |
list_notarizations | 免费 | 所有以比特币为锚的分类账快照 |
条件工具
| 工具 | 条件 | 目的 |
|---|---|---|
request_patron_credentials | patron_credential_template set | 打开Courier频道以获取特定于用户的凭据 |
receive_patron_credentials | patron_credential_template set | 提取用户凭据 |
begin_oauth | oauth_provider set | 启动OAuth2授权流 |
check_oauth_status | oauth_provider set | 浏览器授权后完成OAuth2流 |
update_patron_credential | patron_credential_template set | 添加或更新单个用户凭据字段 |
delete_patron_credential | patron_credential_template set | 删除单个用户凭据字段 |
get_patron_credential_fields | patron_credential_template set | 列出存储的用户凭据字段名称 |
______________________________________________________________________
操作员运行时间
OperatorRuntime 是核心协议引擎。所有DPYC操作——引导、计费、凭证、定价、约束——都委托给它。
构造函数参数
OperatorRuntime(
# Required
tool_registry={**STANDARD_IDENTITIES, **YOUR_TOOLS}, # UUID-keyed ToolIdentity map
# Credential templates
operator_credential_template=CredentialTemplate(...), # BTCPay + operator secrets
patron_credential_template=CredentialTemplate(...), # Per-patron API keys (optional)
operator_credential_greeting="Welcome message...",
patron_credential_greeting="Welcome message...",
credential_validator=validate_fn, # Called on credential receipt
# Identity & network
nsec_env_var="TOLLBOOTH_NOSTR_OPERATOR_NSEC", # Env var name (default)
service_name="My Service",
relays=["wss://relay.damus.io"], # Override default relays
# Billing
purchase_mode="certified", # "certified" (default) or "direct" (trust-root only)
operator_settings={}, # Arbitrary operator config dict
# Constraints
constraint_gate=None, # Legacy — use pricing model pipeline instead
# OpenTimestamps
ots_enabled=True,
ots_calendars=["https://a.pool.opentimestamps.org"],
# Npub proof
proven_npub_ttl_seconds=3600, # Default proof cache TTL
npub_proof_field="confirm", # Field name in proof DM
npub_proof_greeting="...",
on_npub_proven=async_callback, # Called when proof verified
# OAuth2
oauth_provider=OAuthProviderConfig(...), # Enables begin_oauth / check_oauth_status
# Lifecycle
on_forget=callback, # Called when credentials are forgotten
)关键方法
| 方法 | 返回 | 目的 | |
|---|---|---|---|
debit_or_deny(tool_id, npub, *, proof, tool_kwargs) | int (成本)或 dict (拒绝) | 通过身份、证明、约束、定价和计费来阻止工具调用 | |
paid_tool(tool_id) | 装饰师 | 包裹的装饰师 debit_or_deny 围绕工具功能 | |
vault() | NeonVault | 启动并返回霓虹灯保险库(懒惰) | |
ledger_cache() | LedgerCache | 返回写后分类账缓存(懒惰) | |
courier() | SecureCourierService | 返回安全信使(懒惰) | |
operator_npub() | str | 从nsec导出运算符的npub | |
resolve_npub(npub) | str | 验证npub(bech32解码) | |
resolve_tranche_lifetime() | `int \ | None` | 从定价模型中读取批次生命周期 |
load_credentials(fields) | dict | 从保管库加载操作员凭据 | |
graceful_shutdown() | -- | 刷新缓存并关闭连接 |
______________________________________________________________________
定价和限制
工具定价
每个工具都有一个 ToolIdentity 声明其定价:
ToolIdentity(
capability="get_weather",
category="read", # read, write, heavy, free
intent="Current weather",
pricing_hint_type="ad_valorem", # fixed or ad_valorem
pricing_hint_value=1, # base cost in sats
pricing_hint_param="symbols", # parameter for ad valorem scaling
pricing_hint_min=1, # minimum cost
)这 ToolPricing 引擎计算最终成本: fixed + ceil(percentage * param_value),夹紧 [min, max].
约束管道
操作员在定价模型中配置约束 pipeline 阵列。每一步都通过以下方式在每次付费工具调用中运行 debit_or_deny有效成本(折扣、免费试用、激增后)是顾客支付的。
| 约束 | 目的 |
|---|---|
free_trial | 每位用户前N次免费调用 |
happy_hour | 时间窗口免费/折扣,可重复使用 |
surge_pricing | 通过全球计数器进行需求弹性定价 |
temporal_window | 一天中的时间/一周中的某一天访问窗口 |
finite_supply | 总呼叫配额(每位用户或全球) |
periodic_refresh | ISO-8601刷新窗口的速率限制 |
coupon | 基于代码的过期折扣 |
loyalty_discount | 基于支出的分层折扣 |
bulk_bonus | 信用购买的批量奖金 |
patron_proof | 高价值工具需要每次通话的Schnorr证明 |
json_expression | 自定义布尔逻辑规则 |
范围界定: 每个管道步骤都可以针对特定的工具(tool_ids)和/或特定顾客(patron_npubs,最多10个)。未处理的步骤适用于所有工具和用户。
TrancheLifetime
信用到期是货币的属性,而不是每个工具的约束。 TrancheLifetime 在定价模型中,设置购买的信用额度的有效期。每次购买都会产生一部分;FIFO消耗。
______________________________________________________________________
凭证传递
所有机密-BTCPay密钥、API令牌、OAuth凭据-都通过 安全快递,而不是环境变量。这是一个使用NIP-44加密的Nostr DM的人在循环流:
- AI代理调用
request_credential_channel(sender_npub=..., service=...) - 操作员/顾客在其Nostr客户端中收到带有凭证模板的DM
- 他们填写字段并手动回复
- AI代理调用
receive_credentials(sender_npub=..., service=...) - 凭证经过验证、加密(AES-256-GCM和AAD),并存储在Neon保险库中
Vault首次查找意味着返回的用户可以立即激活,无需中继I/O。
在第一次中继接收时,服务发送 ncred1... 通过DM返回凭证卡。顾客可以扫描或粘贴此卡以稍后重新激活。
______________________________________________________________________
x402上游封装
消费的运营商 Coinbase x402-受保护的API可以透明地吸收402支付仪式。顾客永远不会看到402握手——运营商支付上游USDC费用作为COGS,就像服务器租赁一样。
from tollbooth.x402_client import X402Client
# Wallet credentials delivered via Secure Courier (service "x402-wallet")
creds = await runtime.load_credentials(["wallet_private_key", "wallet_address"])
x402 = X402Client(
wallet_private_key=creds["wallet_private_key"],
wallet_address=creds["wallet_address"],
)
@runtime.paid_tool(tool_id)
async def fetch_upstream(query: str, npub: str = "", proof: str = "") -> dict:
resp = await x402.get(f"https://x402-api.example.com/data?q={query}")
return resp.json() # patron sees data, never sees 402根据工具选择加入:只有达到x402上游的工具处理程序才能使用客户端。需要 pip install tollbooth-dpyc[x402]不退款,不回扣——运营商对其工具进行定价,以弥补上游成本。
______________________________________________________________________
身份和证明
每个参与者都由一个 笔记 键盘。这 npub 是您在DPYC荣誉链上的身份。这 nsec 和你在一起——从不分享,从不发送到服务。
接受的每一个工具 npub 还要求 proof --一个JSON序列化的Schnorr签名的kind-27235 Nostr事件,证明所有权。没有证据,就没有服务。
# Proof format (kind 27235, NIP-98 style)
{
"pubkey": "",
"kind": 27235,
"content": "",
"created_at": 1713000000,
"tags": [["u", ""]],
"sig": ""
}内联证明必须小于60秒。缓存的证明(通过 ProvenNpubCache)支持顾客选择TTL长达24小时。跟踪已消耗的事件ID以防止重播。
毒药密钥验证令牌: 对于非限制性工具,证明是 毒药短语(例如。, bold-hawk-42)返回由 request_npub_proof / receive_npub_proof调用应用程序会记住此令牌 将其作为 proof 每个后续付费工具调用的参数。 MCP仅存储 sha256(poison):npub 在保险库里——从不生吃 毒药。证明在MCP无限制重启后仍然有效;持续时间由用户选择 (最多7天)。
______________________________________________________________________
建筑
tollbooth-authority tollbooth-dpyc (this wheel) your-mcp-server
================================ ================================ ================================
Schnorr signing + tax ledger OperatorRuntime OperatorRuntime(tool_registry=...)
certify_purchase -> Nostr cert register_standard_tools(mcp, ...) register_standard_tools(mcp, ...)
Authority BTCPay debit_or_deny (gate + billing) @runtime.paid_tool(uuid)
Secure Courier + vault Domain-specific tools
Pricing resolver + constraints
DPYCRegistry (service discovery)依赖关系单向流动: your-mcp-server --> tollbooth-dpyc权威是网络对等体,而不是代码依赖关系。
生态系统资源库
| 代表 | 角色 |
|---|---|
| 收费亭样品 | 规范参考运算符 --从这里开始 |
| 收费站管理局 | 税收征收、Schnorr签署、采购订单认证 |
| dpyc社区 | 成员注册、治理、服务发现 |
| dpyc预言机 | 社区礼宾服务——入职、税率、会员资格 |
| 蒂巴因mcp | 生产操作员——人脑知识图谱 |
| excalibur mcp | 生产运营商——社交媒体发帖 |
| 施瓦布mcp | 生产操作员——使用OAuth2的经纪数据 |
| tollbooth-oauth2-收集器 | 社区实用程序--OAuth2回调邮箱 |
______________________________________________________________________
安装
# Standard install — includes Nostr relay support (Secure Courier, audit trail)
pip install tollbooth-dpyc[nostr]
# With QR code rendering for credential cards
pip install tollbooth-dpyc[nostr,qr]核心依赖关系(httpx, pynostr)处理身份、证明和HTTP。这 [nostr] 额外添加 websocket-client 用于Nostr中继I/O——自Secure Courier凭证传递、审计发布和引导都使用中继DM以来,每个实际操作员都需要它。这 [qr] 额外添加 segno 用于凭证卡二维码渲染 [x402] 额外添加 x402 + eth-account 用于透明的Coinbase x402上游封装。
# With x402 upstream encapsulation (for operators consuming x402-protected APIs)
pip install tollbooth-dpyc[nostr,x402]______________________________________________________________________
环境变量
| 变量 | 必需 | 目的 |
|---|---|---|
TOLLBOOTH_NOSTR_OPERATOR_NSEC | 是 | 单个引导键。身份、安全快递、审计签名。 |
NEON_DATABASE_URL | 仅信任root | Neon Postgres URL。仅适用于 purchase_mode="direct" (权威)。 |
TOLLBOOTH_NOSTR_RELAYS | 否 | 逗号分隔的中继URL(覆盖默认值)。 |
认证操作员(默认) 不 集 NEON_DATABASE_URL。他们在引导过程中通过加密的Nostr DM从权威机构发现它。
所有其他秘密(BTCPay、API密钥、OAuth令牌)都会通过Secure Courier-never env vars流动。
______________________________________________________________________
保险库和持久性
霓虹灯Postgres
NeonVault 通过以下方式提供具有AES-256-GCM加密(带AAD)、乐观并发性和模式限定表名的ACID分类账存储 _t().
NeonCredentialVault 在模式隔离的Postgres中存储加密的凭据(一个 op_{hash} 每个操作员的架构,由配置 register_operator).
架构隔离
管理局使用 authority 模式。每个经过认证的操作员都会收到一个隔离的模式(op_{hash})拥有专门的Postgres登录角色。 NeonCredentialVault 是否通过以下方式感知模式 _t().
______________________________________________________________________
Nostr集成
审计跟踪
NostrAuditPublisher 在每次跳马写作时发布kind-30078 NIP-78事件。内容是NIP-44v2加密的,只有用户的nsec才能读取。用 AuditedVault 以透明方式添加轨迹。
低余额通知
NotificationManager 当用户的余额超过阈值或部分接近到期时,发送主动NIP-44 DM。即发即弃-永远不会阻止工具路径。
凭证卡
ncred1... bech32编码的凭证卡将加密凭证打包成可扫描的二维码。基于带有NIP-44v2加密的kind-21420 Nostr事件构建。
______________________________________________________________________
开放时间戳比特币锚定
将分类账状态锚定到比特币区块链,以获得无可辩驳的、有时间戳的证明。 MerkleTree 全面构建SHA-256树 (npub, ledger_json) 条目。 OTSCalendarClient 将根哈希提交给公共OTS日历服务器(不需要API密钥)。
______________________________________________________________________
发展
git clone https://github.com/lonniev/tollbooth-dpyc.git
cd tollbooth-dpyc
python -m venv venv
source venv/bin/activate
pip install -e ".[dev,nostr,qr]"
pytest tests/ -q进一步阅读
闪电收费公路上的幻影收费站 --我们如何将AI API货币化,然后逐渐淡出人们的视线。
商标
DPYC、Tollbooth DPYC和Don't Pester Your Customer是Lonnie VanZandt的商标。请参阅 商标.md 在dpyc社区存储库中获取使用指南。
许可证
Apache 2.0——请参阅 许可证.
______________________________________________________________________
*因为最终,收费站从来都不是目的地。这总是旅程的开始。*
