关于 warda
warda 是供 Agent 管理 Kaspa L1 授权额度的 MCP 服务,可检查授权操作并构建未签名交易;它不接触密钥、不访问链,也不负责广播。
主要功能
- 01查看钱包限额与可用额度
- 02检查支出和委托规则
- 03构建未签名支出及授权交易
- 04结算、撤销和恢复授权
适用场景
- 01购物前检查当前可用支出额度
- 02了解付款提案被拒的原因
- 03准备授权委托或结算交易
- 04从支出交易中恢复授权
MCP 相关
向 MCP 客户端提供授权查询、校验、交易构建、结算、撤销和恢复工具。它只构建未签名交易,不负责签名或广播。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://mcp.wardaprotocol.com/mcpclaude mcp add --transport http artykomarkets-warda https://mcp.wardaprotocol.com/mcp{"mcpServers":{"artykomarkets-warda":{"type":"http","url":"https://mcp.wardaprotocol.com/mcp"}}}在 Cursor 中打开{"servers":{"artykomarkets-warda":{"type":"http","url":"https://mcp.wardaprotocol.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"artykomarkets-warda":{"type":"http","url":"https://mcp.wardaprotocol.com/mcp"}}}{"mcpServers":{"artykomarkets-warda":{"serverUrl":"https://mcp.wardaprotocol.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
11| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| grant | object | 是 | 由 principal 签发的 grant。 |
| grant.nonce | string | 是 | |
| grant.state | object | 否 | |
| grant.state.epochIndex | string | 是 | |
| grant.state.reserveRoot | string | 否 | 对于存在未结清委托子项的 grant,需要提供 reserve root。它是 ADDRESS 的一部分:只有此 grant 从未进行过委托时才能省略。warda_build_delegation 会将其作为 parentReserveRootAfter 返回。 |
| grant.state.reservedKas | string | 是 | |
| grant.state.epochSpentKas | string | 是 | |
| grant.state.spentTotalKas | string | 是 | |
| grant.agentKey | string | 是 | |
| grant.budgetKas | string | 是 | |
| grant.expiresAt | string | 是 | |
| grant.notBefore | string | 是 | |
| grant.recipients | array | 是 | |
| grant.epochLength | string | 是 | |
| grant.principalKey | string | 是 | |
| grant.epochLimitKas | string | 是 | |
| grant.revocationKey | string | 是 | |
| grant.maxPerSpendKas | string | 是 | |
| grant.delegationDepth | number | 是 | |
| daaScore | string | 是 | 链的当前 DAA score。 |
详细介绍
@warda_protocol/mcp
一个 MCP 服务,让 Agent 框架能够推理自身的经济权限,并管理授权的整个生命周期——支出、委托、结算、撤销,以及记录过期时重新查找授权——无需集成 Kaspa。
无需安装任何内容,也无需拥有 Kaspa。将以下内容放入客户端配置中——Claude Desktop 对应 claude_desktop_config.json,Cursor 对应 .cursor/mcp.json——然后重启:
{
"mcpServers": {
"warda": { "command": "npx", "args": ["-y", "@warda_protocol/mcp"] }
}
}
在空的 npm 缓存下冷启动,大约需要 7 秒即可获得 11 个工具。
npx -y @warda_protocol/mcp # the same thing, by hand, speaking stdio
也可以直接从代码库检出目录启动:
node --experimental-strip-types src/server.ts # stdio
npm test # 34 tests, real transport
这最后两种方式过去是本节的全部内容,但这并不适合阅读此文件的唯一一群人:他们从 MCP 注册表进入,永远不会克隆任何内容。
它会构建,但不会签名,也不会强制执行。
warda_build_spend 会返回未签名的交易和待签名的摘要。**此服务永远不会接触密钥。**持有 Agent 密钥的人会在密钥所在的位置签署摘要,将 65 个字节填入固定宽度的槽位,然后广播。负责签名的 MCP 服务就成了托管方,而 Warda 的核心理念正是让任何人都不必成为托管方。
有一项测试会断言,每笔已构建交易中的签名槽仍是 65 个零字节,而且响应中任何位置都不会出现密钥材料。
它不会强制执行任何内容
Agent 可以完全无视此服务给出的所有答复,照样构建交易并广播。**Covenant 会拒绝该交易。**Warda 的安全性从来不依赖 Agent 先征求许可——这是整个设计的前提;暗示情况并非如此的服务,会与其所服务的协议相矛盾。
每个响应都会在名为 enforcement 的字段中说明这一点,并且有一项测试会断言该字段确实存在。
那么它有什么用
- **可用额度。**规划购买的 Agent 需要知道当前可支付的最大金额。这并非由某个单独字段决定,而是剩余预算、周期额度和单笔交易上限三者中的最小值。
warda_grant_authority会计算该值。 - **避免浪费交易。**Covenant 会拒绝的支出会耗费手续费,还要多一次往返。事先检查更省成本。
- **用文字说明拒绝原因。**在链上,每条失败规则都会归结为一个不透明的脚本错误。在这里,拒绝会指出具体规则,并说明该怎么做——“金额超过单笔交易上限;请拆分金额,或请委托方提高上限”,而不是
VerifyError。 - **发现服务。**使用 MCP 的框架无需自定义集成即可找到 Warda,这正是规范 §20 的意义所在。
规则集中在一处
所有判定都来自 @warda_protocol/core——用于验证 covenant 的同一套代码,并且共享同样的 45 项测试。此服务不包含协议规则的副本。
这是有意为之的约束。再实现一套规则会导致两者偏离,而无论朝哪个方向出错,后果都很严重:告诉 Agent 可以支出,但链上会拒绝,会浪费资金;告诉它不可以支出,但链上其实允许,则会让资金悄无声息地闲置。要么只有一个规则来源,要么就不要有。
工具
| 工具 | 解答的问题 |
|---|---|
warda_wallet | 完整的钱包视图:地址、限额、可支出额度、允许列表。 |
warda_grant_authority | 此 Agent 现在可以支出什么? |
warda_grant_address | 此授权位于何处? |
warda_check_spend | 这笔付款会被接受吗?如果不会,原因是什么? |
warda_check_delegation | 此子授权是否是合法的权限缩小? |
warda_build_spend | 此笔付款待签名的字节。 |
warda_build_delegation | 拆分此授权待签名的字节。 |
warda_build_settlement | 将子授权合并回父授权待签名的字节。 |
warda_build_exit | 撤销此授权,或在其过期后收回授权待签名的字节。 |
warda_recover_grant | 根据一笔使用过此授权的交易重新查找授权。 |
其中四个工具曾有一段时间缺失,值得说明一下这个缺口的具体情况:Agent 可以询问自己能支出什么,并构建一笔支出,但无法触及授权生命周期中的其他任何环节。发现违规行为的监控器可以提交报告,却无法采取行动。记录落后的调用方则无从重新找到授权。
它称自己为“钱包”,但也说明了它不是什么
warda_wallet 使用了开发者熟悉的词,而工具一旦这么做,下一个显而易见的字段就是余额。**此服务没有节点。**它返回的每个数值都来自收到的描述符,因此响应会明确说明没有链上余额,而不是悄悄将其省略——根据过时记录推导出的余额正是此协议一再遇到的问题,也是最容易被误认为成功的情况。
有一项测试会断言余额不存在,因此日后是否给此服务接入节点,必须由人来决定,而不能由自动补全替人决定。
它组合了 warda_grant_address 和 warda_grant_authority,并没有计算任何新内容。如果每个框架都要稍微不同地组合这两个调用,那就等于多写了一套账务实现。
授权位于何处,以及它为何不断变化
授权的地址是其状态的哈希,因此每次支出或委托后都会改变。昨天的地址今天已一无所有,而空地址与从未获得资金的授权无法区分。这是每种集成都容易踩到的关键事实,因此 warda_grant_address 专门用于直接回答这个问题,而且每个构建工具都会返回授权接下来所在的位置。
找回丢失的授权
Kaspa 的 P2SH 要求在每笔使用该授权的交易中,将 covenant 脚本明文放入签名脚本——否则网络无法验证哈希——而授权状态会按已知偏移量嵌入该脚本。因此每笔支出都会公开它使用的授权,无论支出者是否有意为之。warda_recover_grant 会将其读回,并沿着交易记录追踪到授权现在所在的位置。
没有此工具,授权只能通过某人磁盘上的记录来访问:记录丢失后,代币在链上依然完全有效,却无法再被找到。如果某个协议的论点是限额由共识保障,那么它的可恢复性就不该依赖文件系统。
结算,以及它为何不等同于等待
子授权到期后,其余额会退还给委托人——也就是人类。子授权若被结算,未花完的余额则会退还给父级 Agent 的预算,父级只需支付子级实际花费的金额。这正是结算存在的全部原因:任务进行到一半的 Agent 无法使用已经退还给所有者的资金。
warda_build_settlement 会返回两个摘要,并有意不将它们合并。父级的部分由父级的 Agent 密钥签名;子级的部分则由撤销密钥签名,因为合并授权等同于撤销授权,而且子 Agent 不得按自己选择的条件结束自己的授权。
它需要一个无法从链上任何数据推导出的数字:推送该子级之前的父级 reserve root。reserve 是哈希链,弹出一个值就意味着必须提供其原像。warda_build_delegation 会将其作为 parentReserveRootBefore 返回——请保留它。
即使建议性判定结果为否,warda_build_spend 仍会构建交易,并同时报告判定结果。这是有意为之:过于严格的本地规则不得阻止链上本会接受的付款。拒绝会损失手续费;阻止则会损失能力。
但它会直接拒绝一种情况——收款方不在允许列表中。没有证明能将其放入树中,因此不存在有效交易;伪造借来的证明,会让协定的拒绝看起来像是树有问题,而不是收款方不在列表中。
接入
{
"mcpServers": {
"warda": {
"command": "npx",
"args": ["-y", "@warda_protocol/mcp"]
}
}
}
字节的来源
warda_build_spend 通过 @warda_protocol/kaspa 组装交易,并使用 golden-spend.json 进行验证——这是由同一 Rust 路径生成的参考交易,该路径曾将一笔支出提交到 testnet-10。mcp/test/build.test.ts 补上了最后一处验证缺口:它以 Agent 框架会采用的方式描述同一笔授权,使用十进制 KAS 和具名收款方,并要求结果逐字节一致。
这很重要,因为两种表示之间隔着三个环节——十进制解析器、由不同于 SDK 的代码构建的 Merkle 树,以及按字段顺序布局的结构体。它们都不是规则,因此没有一个会错误地允许支出。但它们都可能生成链会拒绝的字节,而且这种拒绝不会有任何提示,只有在涉及真金白银时才会显现。
尚未实现
无法访问链。 服务无法查找授权当前的 UTXO——需要由你传入。每次支出后,授权地址都会变更,因此过时的 UTXO 将无法找到。(@warda_protocol/kaspa 可以替你查找:NodeClient.open 接受一个节点 URL、节点列表或 Kaspa Resolver,并会拒绝会错误响应的节点。)
不广播交易。 构建出的支出是一笔普通交易;请使用你已有的任意节点客户端提交。
模板有意不作为参数传入。 模板从磁盘加载(WARDA_TEMPLATE 可覆盖其路径)。调用方提供的模板是协议中最薄弱的攻击面:只要替换模板,每个地址都会出错,导致授权将资金付入无人能够支出的脚本。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。