
Sato Kit
ai.satohub由 satohub.ai 发布v0.1.0更新于 Oct 24, 2026
Prepare -> execute for onchain agent actions: policy pre-flight, simulation, receipt log.
概览
一个本地 stdio MCP 服务器,用于在 EVM 各链和 Solana 上准备、策略预检、模拟并执行链上代理操作,并留下哈希链审计记录。
- 可以做什么
- 读取链上状态、代币授权、Safe 信息、ERC-8004 记录和 Solana 账户,并获取 EVM 各链与 Solana 的兑换和跨链报价,默认标注 Sato Swap 并同时给出无 Sato 手续费的报价。为兑换、跨链、x402 支付、撤销代币授权、ERC-8004 注册、Safe 提案和 Solana 转账准备未签名意图,每个意图都先经策略文件检查并模拟。通过已配置的签名器按 intent_id 执行已准备的意图,完成签名和广播,并追加一条哈希链收据。用 status、actions_search 和 actions_describe 查看工具清单,并了解哪条策略规则拒绝了某个意图及原因。
- 适用场景
- 适合需要带护栏进行链上操作的代理:报价和准备兑换或跨链、检查授权、提出 Safe 交易或支付 x402 资源,同时把签名放在策略预检和显式执行步骤之后。适合在本地运行代理、希望在资金变动前获得模拟结果和审计记录的开发者。
- 运行要求
- 通过 stdio 运行的本地进程,用 npx 从 npm 包启动;需要 Node 20 或更高版本,viem 为 peer 依赖。配置从工作目录读取:policy.json(缺失时使用 fork 网络上的默认策略)、存放意图、意图 HMAC 密钥和收据的 .sato/ 目录、按链设置的 SATO_RPC_URL_ ,以及用于本地 fork 签名器的 SATO_SIGNER。Solana 操作需要 Solana RPC 和 @solana/kit 8 或更高版本。执行需要签名器(本地、OWS、CDP 或 Solana devnet);Safe 托管网关需要 SAFE_API_KEY。
安装
在 SourceWeft 中
- 打开 控制台中的 Sato Kit,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
@satohub/kit
0.1.1 preview.
Sato Kit wraps the tools agents already use (viem, signers, x402) with a prepare -> execute
contract: an action prepares an unsigned intent, a policy pre-flight explains any refusal,
the transaction is simulated, and execute({ intent_id }) hands it to your signer and appends
a hash-chained sato.receipt/v1 line.
What it is not: not a wallet, not a custodian, not an agent framework, and not a guarantee. It never holds funds and ships no keys.
- Fork by default. A policy's
networkdefaults tofork; mainnet needs an explicit opt-in. - Pre-flight vs enforcement. The kit's policy check runs before an intent is returned and says which rule refused and why. It does not enforce anything once a key is in play. Enforcement lives in the signer (e.g. a CDP policy compiled from the same file).
scan.payto_changed. Thescanblock ofpolicy.jsonrecordspayto_changed(caution|refuse|off), but it is enforced only by hosts that implement it. The offline guard insatohub-core(scanRecipient) does not enforce it today: a changed x402 payTo needs the payee's earlier value, which the offline check is not given.- Swaps are venue-neutral. Any venue is accepted. Sato Swap is the labelled default and its fee is
disclosed on every response, with a no-Sato-fee quote alongside;
venue: "direct"skips Sato entirely.
Contracts (sato.action/v1, sato.policy/v1, sato.receipt/v1) live in src/spec (see VENDORED.md).
Install
Node 20 or later. viem is a peer; every framework SDK below is an optional peer, installed only
if you use its subpath.
Honest limits
- Pre-flight, not enforcement.
evaluatePreflightruns before an intent is returned and names each refused rule with its limit and the observed value. Once a key is in play the kit enforces nothing: enforcement is the signer's (a CDP, Privy or Turnkey policy compiled from the samepolicy.json, OWS's policy engine, or a Safe's owners).viemLocalSignerenforces only its mainnet refusal. - x402 execution scope.
x402.preparereads what an x402 resource asks to be paid and returns a priced, policy-checked intent.executedoes not send x402 payments: it sends EVM transactions, EIP-712 typed data (Safe proposals) and Solana transactions only. Pay through your x402 client. - AgentKit's own analytics call. AgentKit's
@CreateActiondecorator posts an invocation event tocca-lite.coinbase.comon every invoke. Actions consumed throughfromAgentKitProviderstill make that call; the kit neither blocks nor adds to it. - Unknown prices refuse. When a USD value cannot be read, a
max_usd_*rule refuses withunknown_pricerather than guessing. - Simulation is not a promise. A passing simulation says what the chain answered at that block.
Action reference
Generated from the registered descriptors by node scripts/gen-actions-doc.mjs (after
npm run build); test/readme-actions.test.ts fails when this table drifts from the registry.
"custody" is the descriptor's own answer to three sato.custody/v1 questions. toolset says
whether the tool is in the default MCP profile or only under --toolsets all.
Registered actions
Meta tools
Default MCP profile, in order: chain_read, swap_quote, swap_prepare, x402_prepare, execute, status, actions_search, actions_describe.
Actions consumed from an AgentKit provider (fromAgentKitProvider) are not in this table: they
are built at runtime from the provider you pass, and appear under toolset all.
Entry points
Signers
viemLocalSigner— a key in this process. Fork/testnet by default; refuses mainnet chain ids unlessallowMainnet: true(not recommended).generate: truemakes a throwaway in-memory key.owsSigner— a structural adapter over an Open Wallet Standard account; OWS's policy engine enforces. Seesrc/signers/OWS.md.cdpSigner— a structural adapter over a Coinbase CDP server account; CDP enforces its policies. Pass a compiled policy asnativePolicyto carry it with the signer (the adapter does not register it).solanaLocalSigner— local Solana signing for devnet and tests only; refuses any non-devnet payload and a mainnet-beta RPC, with no mainnet switch.humanApprove(signer, approve)— wraps any signer so a person approves each summary before it signs.
Policy compilers
compileCdpPolicy, compilePrivyPolicy and compileTurnkeyPolicy turn one sato.policy/v1 into
the provider's native policy document. Each result lists what did not compile (not_compiled) with
the reason, so a rule the provider cannot express is never silently dropped.
CLI
Config comes from the working directory: policy.json (absent means the default policy, network
fork), .sato/ (intents, intent secret, receipts), SATO_RPC_URL_<CHAIN> per chain, and
SATO_SIGNER=viem-local-fork (fork network only) for a local signer.
MCP server
npx -y @satohub/[email protected] mcp runs a stdio MCP server (registry name ai.satohub/kit). The default
profile is the eight tools listed above; --toolsets all adds every other registered action.
Tools that sign carry anthropic/requiresUserInteraction in _meta.
Sato Status
status and sato-kit doctor read the nightly per-action results (sato.action-status/v1)
published by the templates repo. When that file cannot be read, the answer says so; nothing is
filled in.
Recommended .gitignore
The file intent store and the intent HMAC secret live under .sato/ by default
(intents/, intent.key, mode 0600). Keep them out of version control:
License: MIT. The bundled Onchain Action Descriptor code (dist/spec) is Apache-2.0, copyright 2026 Prime Signal LLC: see LICENSE-ODA and NOTICE.
sato-kit doctor: template drift
In a repo made by create-sato-agent (one with sato.create.json), doctor
also sends sato.create.json and sato.lock.json to
https://satohub.ai/api/create/drift (3 s timeout) and prints the changes it
returns: a newer template version that passed its checks, a custody change in
a stored Sato Check profile for a pinned package, or a pinned package version
that fails the template checks upstream. It is read-only and opens no issues
(the generated sato-drift.yml workflow does that). With --json the answer
is under result.drift, with state checked, unavailable (with a
reason) or not_applicable; nothing is filled in when the check does not
answer.
Host adapters: envelope and error codes
@satohub/kit/ai-sdk (satoKitTools(kit, opts)), @satohub/kit/agentkit
(satoKitActionProvider(kit, opts)), @satohub/kit/claude-agent-sdk
(createSatoKitSdkServer(kit, opts) + requireApprovalHook()),
@satohub/kit/openai-agents (satoKitOpenAITools(kit, opts), OpenAI Agents
SDK function tools with needsApproval), @satohub/kit/langchain
(satoKitLangChainTools(kit, opts), LangChain JS DynamicStructuredTools
whose func returns the envelope as a JSON string) and @satohub/kit/eliza
(satoKitElizaPlugin(kit, opts)) are built from the same tool surface as the
local MCP server (sato-kit mcp). Options:
{ toolsets?, actions?, policy?, signerKind?, fetch?, statusTimeoutMs? }
(AgentKit, LangChain and elizaOS also take approve; none of these hosts has an approval step,
so execute is refused without it).
@satohub/kit/eliza is a thin compatibility adapter for existing elizaOS 1.x
agents, not a supported framework: no Sato template depends on elizaOS, and
the subpath is dropped rather than patched if an elizaOS release breaks it.
Its actions read arguments from options.parameters (then
message.content.parameters). Each adapter tool returns one envelope:
{ ok: true, tool, result }{ ok: false, tool, error: { code, message, refusals? }, intent? }
Error codes: unknown_tool, invalid_input, policy_refused,
approval_required, approval_denied, not_configured, error. A policy
refusal lists each { rule, limit, observed }. execute takes { intent_id }
and nothing else, and every host asks a person before it runs.
On the MCP server a refused prepare is a normal result whose
structuredContent.policy.refusals names each rule; a failed call sets
isError and carries its detail in _meta["ai.satohub/error"].
Consuming an existing AgentKit provider (@satohub/kit/agentkit)
fromAgentKitProvider(provider, { chain }) turns each action of an AgentKit ActionProvider into kit actions. Read actions (a get_/check_/list_… name, or the names you pass as reads) become reads. Every other action runs the provider's own invoke() against a capturing wallet that records the transaction instead of sending it; that one transaction becomes an ordinary intent — simulated, put through the policy pre-flight, and sent once by execute(intent_id) with your signer.
- An action that tries to send more than one transaction, or to sign a message, typed data or a raw transaction, is refused with the reason. Nothing was sent, so nothing is partly done.
- A schema that cannot be made portable is listed in
not_consumablewith the lint's reasons rather than turned into a tool. An amount-named string with no pattern is narrowed to a decimal pattern and listed inconsumed[].tightened. - The USD value of a consumed action is unknown, so a
max_usd_*cap refuses it underunknown_price;max_per_tradereads the ERC-20 amount or the native value off the captured transaction. - AgentKit's own
@CreateActiondecorator posts an invocation analytics event tocca-lite.coinbase.comon every invoke; the kit does not block or add to it. - Consumed actions appear under toolsets
"all"and throughactions_search/actions_describe; the default MCP profile is unchanged.
Consuming an existing GOAT plugin (@satohub/kit/goat)
await fromGoatPlugin(plugin, { chain }) works like fromAgentKitProvider: reads run as reads; a write runs the plugin's own tool against a capturing wallet that records the one transaction instead of sending it, and that transaction becomes an ordinary intent (simulate, pre-flight, execute(intent_id) once with your signer). Message or typed-data signing, a paymaster request, or more than one transaction is refused with the reason. GOAT has been quiet upstream; if your install holds two copies of @goat-sdk/core, GOAT's own wallet lookup can miss the wallet — keep one copy.
Safe proposals
safe.propose builds the SafeTx for the Safe's owners to sign; the policy pre-flight applies to the call inside it. When the intent has a Safe Transaction Service target, execute signs and submits it and the receipt carries safe_tx_hash; without one, the receipt carries the signature as typed_data_signature. For Safe's hosted gateway, pass safeTxService: { apiKey } to createKit (or opt in to reading SAFE_API_KEY); the key is sent as Authorization: Bearer … only to api.safe.global or an origin you configure, and is never logged or written to a receipt.
Solana
The Solana actions need a Solana RPC (solanaRpc in createKit). solanaLocalSigner is devnet-only and needs @solana/kit 8 or later installed next to the kit (npm i @solana/kit@^8); it is not declared as a peer so that installs holding an older @solana/kit (for example through AgentKit) still resolve.
Use with Base MCP (Coinbase Wallet MCP)
Base MCP, now served at https://wallet-mcp.coinbase.com, signs with your Base Account. The kit's
Base MCP plugin runs the policy pre-flight and the simulation in your shell first, then hands Base
MCP the unsigned call for you to approve in Base Account. It is a custom plugin: Base does not list,
maintain or endorse it.
In a harness with a shell (Claude Code shown; Base's install steps cover Codex and Cursor):
Then write your own policy.json (the plugin file has a starting point; without one the default
policy refuses every mainnet request), set SATO_RPC_URL_BASE, and ask for the plugin by name:
"Use the Sato Kit plugin to swap 5 USDC for WETH on Base." Base routes to a plugin only when you
name it. Chat-only surfaces (Claude.ai, ChatGPT) cannot run the kit, and the plugin says so and stops.
Not included: Stripe MPP
mpp.prepare is not built. Its client (mppx) is pre-1.0 with breaking changes in minor releases, and its payment methods do not map onto one unsigned transaction the kit's signer executes. Reasons and sources: docs/mpp-research.md.
Sato OS hand-off (@satohub/kit/sato-os)
In live mode an agent can send prepared intents to a self-hosted Sato OS for a person's approval and signing there, instead of signing locally. attachToSatoOs({ baseUrl, name, goal, walletAddresses, chains }) attaches the agent and stores its scoped token in .sato/sato-os.json (mode 0600, gitignored; never returned or printed). proposeIntent(prepared, { baseUrl, token }) files the intent (unsigned payload, summary, policy verdict, simulation, fee disclosure) through Sato OS's sato_os_create_action_proposal tool and returns { proposal_id, status }. A refused or expired intent is never sent. Nothing in this path signs or broadcasts.
来源:packages/kit/README.md,提交 f4f4778
工具
0版本历史
1- v0.1.0最新Sep 30, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分