Safe-MPC
Integrates with OpenZeppelin Governor-style on-chain DAO governance, allowing the Safe to cast votes with a reason through Safe transactions after checking proposal status, prior votes, and snapshot voting power.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Safe-MPCWhich DAOs can this Safe vote in, and are any proposals open?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Safe-MPC
An MCP (Model Context Protocol) server that connects a Safe smart-account wallet to AI agents so they can read DAO proposals and vote as the Safe — off-chain on Snapshot, and on-chain through OpenZeppelin or Compound-style Governors.
Point Claude Code, Claude Desktop, Cursor, or your own agent at this server and the Safe becomes a voter your agent can operate.
It runs two ways. On demand, as an MCP server your agent calls when you ask
it to vote. Unattended, with the bundled safe-mpc-watch scheduler, which
polls for new proposals and asks an agent to decide as each deadline
approaches.
How voting works
Snapshot (off-chain, gasless). The Safe cannot sign an EIP-712 payload
itself, so the vote is signed as an EIP-1271 contract signature. Safe-MPC builds
the Snapshot Vote payload, registers it as a Safe message, waits for the Safe
Transaction Service to assemble a signature meeting the Safe's threshold, then
posts it to the Snapshot sequencer. Voting again on the same proposal replaces
the earlier vote.
Governor (on-chain). Safe-MPC encodes castVoteWithReason and sends it as a
Safe transaction. This costs gas and is final once mined. Every vote runs
pre-flight checks against the Governor first: the proposal must be Active, the
Safe must not have voted already, and it must have had voting power at the
proposal's snapshot.
Proposals are discovered by reading ProposalCreated logs from the Governor
contract, so no third-party indexer sits anywhere in the path, and no API key is
needed to find a proposal. Nothing here depends on a hosted governance API
staying up.
The EIP-712 vote types match @snapshot-labs/snapshot.js field for field,
including the three distinct shapes Snapshot uses (uint32 for single-choice
and basic, uint32[] for approval and ranked-choice, a JSON string for weighted
and quadratic). The hub re-derives the typed-data hash from the payload it
receives, so this has to agree exactly.
Related MCP server: Safe MCP Server
Where the Safe votes
You should not have to hand the agent a list of DAOs. Safe-MPC works out where the Safe can vote and asks it to vote there.
snapshot_spaces_with_voting_power assembles the candidates from four places —
the spaces the Safe follows on Snapshot, the spaces it has voted in
before, the spaces you configured, and the test space — then reads the Safe's
voting power in each and keeps the ones where it has any.
snapshot_open_proposals turns that into the Safe's actual ballot: every
proposal open for a vote across those spaces, soonest deadline first.
> Which DAOs can this Safe vote in, and is anything open?
snapshot_spaces_with_voting_power → 2 spaces
snapshot_open_proposals → 3 proposals, one closing in 4hThe scheduler uses the same discovery. With WATCH_SNAPSHOT_AUTO=true, which is
the default, safe-mpc-watch re-resolves the watched spaces on every pass,
so a Safe that is delegated voting power in a new space starts being asked to
vote there without anyone editing a config file. WATCH_SNAPSHOT_SPACES still
names spaces explicitly, and those are watched even at zero voting power,
because a space you named on purpose may be about to grant the Safe weight.
Voting power here is read at the current block, which answers "is this space worth watching". Whether a particular vote will count is a different question, asked again per proposal at that proposal's snapshot block before anything is signed.
SNAPSHOT_TEST_SPACE defaults to staging.daoplomats.eth: a space that is
always tested and always watched, so a fresh install has somewhere to exercise
the whole path end to end before being pointed at a DAO that matters. Set it
empty in .env to drop it.
If ALLOWED_SNAPSHOT_SPACES is set, it wins over all of this. Spaces outside
the allowlist are never tested, never watched, and never voted in.
Setup
1. Install
git clone https://github.com/Zoldenburg-me/Safe-MPC.git
cd Safe-MPC
npm install
npm run build2. Run setup
There is no web UI to pick a Safe in. Safe-MPC is a headless stdio process, so this command is the setup screen:
npm run setupIt generates the agent's EOA, shows you the address to add as a Safe owner,
asks for the Safe and chain, and writes .env with mode 600. Votes are live from
the start: setup writes DRY_RUN=false, and --dry-run is how you opt into a
rehearsal instead. For scripts and containers there is a non-interactive form:
node dist/setup.js --safe 0xYourSafe --chain 1 --rpc https://... --api-key ...
node dist/setup.js --safe 0xYourSafe --space mydao.eth --dry-run
node dist/setup.js --new-key # just print a fresh keypair, write nothing
npm run check # verify readiness against the live chainnpm run check is worth running before you wire up any agent. It reports the
chain, both addresses, the agent's ETH balance, whether the agent is an owner,
the threshold, every Snapshot space the Safe holds voting power in, and, if a
Safe API key is set, every Safe the agent owns on that chain. It exits non-zero
and names what is missing when the agent cannot vote — including a Safe with no
voting power anywhere, which is the failure that otherwise only shows up when a
vote is rejected.
The server and the watcher both read .env from the working directory and then
from the package root, so you do not have to repeat the config in your MCP
client. Real environment variables always win over the file.
3. Add the agent as a Safe owner
Setup prints the agent address. Add it at app.safe.global, under Settings, then Setup, then Add new owner. That is the only screen involved, and it is Safe's, not ours. The agent key never holds the treasury — it only signs.
The Safe's threshold decides how much the agent can do alone:
Threshold | What a vote tool does |
1 | Casts the vote outright. |
2 or more | Queues the vote and reports what is still needed. Other owners confirm in the Safe UI, then |
A 1-of-N Safe gives the agent full autonomy. Raise the threshold to put a human in the loop without changing anything here.
4. Configure the rest
Setup writes the essentials. .env.example documents every other setting, and
cp .env.example .env is the manual route if you would rather not use setup at
all.
You need a SAFE_API_KEY from
developer.safe.global. The key is free. The
Safe SDK builds its Transaction Service client before any request is made, and
that constructor refuses a missing key, so every tool that touches the Safe
needs one. That includes governor_vote from a threshold-1 Safe, which executes
straight over RPC and never calls the service. Read-only discovery works without
a key, but voting does not, so the server refuses to start without either
SAFE_API_KEY or a self-hosted SAFE_TX_SERVICE_URL.
Votes are live unless you ask otherwise. DRY_RUN is off by default and
setup writes DRY_RUN=false. Set it to true — or run setup with --dry-run —
and every vote tool returns the exact payload it would have submitted, signing
nothing. A dry run reports blocked votes too, payload included, so the path can
be demonstrated on a Safe that has no voting power yet.
A variable set in the process environment beats .env. An MCP client that
launches the server with "DRY_RUN": "true" in its own config keeps winning over
the file however many times you edit it, and a plain restart may not reload that
config — the server entry has to be updated. safe_info reports both the value
in force and where it came from, so this is visible rather than baffling.
5. Write a voting policy
Drop your operating values into knowledge/ as Markdown. Those files are served
as MCP resources and inlined into the voting prompts, so the agent votes to a
stated policy rather than improvising. See knowledge/README.md.
6. Connect an agent
Claude Code, which picks up the project's .env on its own:
claude mcp add safe-mpc -- node /absolute/path/to/Safe-MPC/dist/index.jsClaude Desktop or Cursor, in the MCP config file:
{
"mcpServers": {
"safe-mpc": {
"command": "node",
"args": ["/absolute/path/to/Safe-MPC/dist/index.js"],
"env": {
"SAFE_ADDRESS": "0x...",
"SAFE_AGENT_PRIVATE_KEY": "0x...",
"SAFE_CHAIN_ID": "1",
"SAFE_RPC_URL": "https://...",
"SAFE_API_KEY": "..."
}
}
}
}Then ask the agent to run safe_info. It reports whether the agent's signer is
an owner and whether it can vote alone.
To poke at the server directly:
npm run inspectStep-by-step guides for hosting the server beside a self-hosted agent:
docs/running-the-server.md — the combined quick path for both OpenClaw and Grok, with links into the detail below.
docs/openclaw.md — OpenClaw, over stdio on one box.
docs/grokbot.md — Grok Build over stdio, and why Grok Bot needs a hosted endpoint this repo does not ship yet.
Which account needs ETH
The Safe does not pay gas for its own votes. The account that calls
execTransaction pays, and that is the agent's EOA. Funding the Safe instead is
the common mistake and does nothing for voting.
Case | Needs ETH | Why |
Snapshot votes | No | Signing is off-chain and verification is an |
Governor votes | The agent EOA | It submits |
The Safe itself | No | Only the governance token, or a delegation, for voting power. |
So a Safe voting only on Snapshot needs no ETH anywhere. For on-chain voting, send a small amount of ETH to the agent EOA and top it up as it drains.
safe_info reports both balances and says plainly whether on-chain voting will
work. governor_vote refuses before signing if the agent has no ETH, naming the
cause rather than surfacing an opaque RPC rejection.
Safe supports refunding the executor out of the Safe's own balance, via the
gasPrice, gasToken and refundReceiver transaction fields. Safe-MPC leaves
those at zero, so no refund happens and the accounting stays simple.
Voting on Snapshot X
Snapshot X (snapshot.box) is Snapshot's fully on-chain protocol. Its gasless
path has the voter sign an EIP-712 message for a relayer, which a Safe cannot
do on its own; the path snapshot.box offers smart-contract wallets is a plain
transaction instead. snapshot_x_vote takes that path: the Safe calls the
space's EthTx authenticator, which checks the voter is the caller and
forwards Space.vote(safe, proposalId, choice, strategies, metadataURI).
> Vote for https://snapshot.box/#/eth:0x594E…/proposal/7 — it funds the audit.
snapshot_x_proposal → VotingPeriod, Safe power 12000 across strategy 0, not voted
snapshot_x_vote → executed 0xabc…, For with power 12000Before anything is signed, the tool:
reads the proposal and requires it to be open (
VotingPeriodorVotingPeriodAccepted) and not already voted on by the Safe;evaluates every strategy active on the proposal at its snapshot block, the same
getVotingPowercall the space makes, and submits only those that give the Safe power (a strategy that reverts would revert the whole vote);checks the space whitelists the authenticator (by default snapshot.box's EthTx deployment,
0xBA06…Aed1, on every standard network);simulates
authenticate(...)from the Safe's address, so the chain itself vets the vote.
Choices are for, against and abstain (sx-evm values 1, 0 and 2 — not the
Governor order). A reason is pinned to IPFS through pineapple.fyi, Snapshot's
pinning service, and attached as the vote's metadata URI, which is how
snapshot.box displays it; if pinning fails the vote still goes through and the
reason stays in the local vote log. Like a Governor vote, this costs gas, and
Snapshot X votes are final: there is no revote.
Vanilla, Comp and OZ Votes strategies need no input. A merkle-whitelist or
ApeGas strategy needs a per-voter proof; pass it as strategyParams
([{ index, params }]), and the tool reports any strategy it had to leave out.
At threshold 1 the vote executes immediately; above that it queues on the Safe
like the cancel below, with the to / data / value co-signers should check.
Vetoing a Snapshot X proposal
Snapshot X (snapshot.box) is Snapshot's fully on-chain protocol: a space is a
contract, and cancelling a proposal means the space's controller — usually
the DAO's Safe — calling cancel(proposalId) on it. Done by hand, that is the
worst flow in DAO operations: someone opens app.safe.global, bridges
snapshot.box into the Safe over WalletConnect, double-checks they are acting as
the Safe and not their own wallet, clicks Cancel proposal, signs, and then
posts the calldata in the group chat so every co-signer can verify the bytes
before confirming.
snapshot_x_cancel_proposal collapses the first half of that into one call.
Given a snapshot.box proposal URL — or the space and proposal number — it
verifies the Safe is the space controller, simulates the cancel from the Safe's
address so the chain itself vets the call, then proposes the transaction to the
Safe:
> Cancel https://snapshot.box/#/eth:0x594E…/proposal/3 — it duplicates #2.
snapshot_x_proposal → status VotingPeriod, this Safe controls the space
snapshot_x_cancel_proposal → queued as 0xf00…, needs 4 more of 5 signaturesAt threshold 1 the cancel executes immediately. Above that, the tool reports
the queued safeTxHash, a link to the Safe's queue, and the exact
to / data / value the transaction must show — the same checklist
co-signers used to assemble by hand, now generated from the transaction that
was actually proposed. The other owners just open the queue, compare, and
confirm; the final signature executes the cancel. snapshot_x_proposal read
afterwards confirms the proposal is Cancelled.
Every attempt is recorded in the vote log with platform snapshot-x, and
DRY_RUN behaves as everywhere else: the tool returns the transaction it would
have proposed, blockers included, without signing anything.
Tools
Tool | Reads or writes | What it does |
| read | Chain, owners, threshold, nonce, balance, and whether the agent can vote alone. Needs the API key. |
| read | Transactions queued on the Safe. Needs the API key. |
| write | Adds the agent's signature to a queued transaction, executing it if that meets the threshold. Needs the API key. |
| read | Every Snapshot space this Safe can vote in, found without being told where to look. |
| read | Everything open for a vote across those spaces, soonest deadline first. |
| read | Proposals in a space, open ones by default. |
| read | Full body, indexed choices, scores, the Safe's voting power, and any vote it already cast. |
| read | The Safe's voting power on one proposal, by strategy. |
| read | Any GraphQL query against the Snapshot hub, for everything the fixed reads don't cover. Query operations only; responses over 1 MB are refused. |
| write | Casts an off-chain Snapshot vote as the Safe. Needs the API key. |
| write | Submits a vote whose Safe message needed more signatures. Needs the API key. |
| read | A Snapshot X proposal's live status and tally, the Safe's voting power and whether it voted, read from the space contract, and whether this Safe controls the space. No API key. |
| write | Casts an on-chain Snapshot X vote as the Safe through the space's EthTx authenticator. Needs the API key. |
| write | Vetoes a Snapshot X proposal by proposing |
| read | On-chain proposals, read from |
| read | Legacy: proposals via a hosted indexer API. Needs a key. |
| read | Legacy: title, description and vote counts via the same API. |
| read | Live Governor state, read straight from the contract. No API key needed. |
| write | Casts |
| read | Every vote this Safe has cast, with the choice and reason, so decisions stay consistent with precedent. |
| read | Proposals the scheduler has queued, and which are due now. |
Tools marked "Needs the API key" build a Safe client and fail without
SAFE_API_KEY or SAFE_TX_SERVICE_URL. The rest are plain RPC or Snapshot
hub reads and work with neither.
Four prompts wrap the tools into a reviewed workflow:
vote_on_snapshot_proposal, vote_on_governor_proposal,
vote_on_every_open_proposal, which works through the Safe's whole ballot, and
review_open_proposals, which recommends votes without casting any.
Choice format
Snapshot choices are 1-indexed, matching the UI, and their shape follows the proposal's voting system:
Voting system |
|
|
|
|
|
|
|
Governor votes take "for", "against" or "abstain" instead of the raw
support integers.
Vote log
Every vote attempt is appended to data/votes.jsonl: the proposal, the choice,
the reason given, the voting power, and the resulting vote id or transaction
hash. Failed and queued attempts are recorded too, so a vote that never landed
is visible rather than lost in a chat transcript.
It is a plain JSONL file, not a database. The authoritative record of a vote is
on Snapshot or on-chain; this exists so that you can audit what the agent did,
and so the agent can read its own precedent through vote_log before deciding.
The scheduler also uses it to guarantee it never votes twice on one proposal,
even across restarts.
jq -r '[.at, .venue, .choice, .outcome] | @tsv' data/votes.jsonl | column -tUnattended voting
safe-mpc-watch is the unattended path. It polls every Snapshot space the Safe
can vote in — plus any space or Governor you name — queues each open proposal,
and when a proposal is within VOTE_BEFORE_CLOSE of its deadline it runs your
agent command to decide and vote. Voting late rather than on discovery means the
decision reflects how sentiment developed, and leaves room to retry before the
deadline.
# In .env. Snapshot spaces are discovered automatically; everything here is
# optional except the agent command.
WATCH_SNAPSHOT_AUTO=true # watch wherever the Safe has voting power
WATCH_SNAPSHOT_SPACES=ens.eth,aavedao.eth # watched as well, power or not
WATCH_GOVERNORS=0x408ED6354d4973f66138C91495F2f2FCbd8724C3
VOTE_BEFORE_CLOSE=6h
POLL_INTERVAL=1h
AGENT_COMMAND=claude -p "{prompt}" --mcp-config .mcp.json --allowedTools mcp__safe-mpc__*npm run watch:plan # show what is queued and due, dispatch nothing
npm run watch # poll continuously
node dist/watch.js --once # a single pass, for system cron--once is usually the better choice in production: let cron own the schedule
and the restarts.
*/30 * * * * cd /srv/safe-mpc && node dist/watch.js --once >> watch.log 2>&1The queue lives in data/schedule.json and survives restarts. A proposal keeps
its status across passes, so a vote already cast is never repeated, and one that
failed stays pending and is retried on the next pass until its deadline. Run
--plan first, and set DRY_RUN=true for the first live pass if you want to
read the agent's reasoning before any vote is real.
The agent command
AGENT_COMMAND is parsed into an argument list and run without a shell, so
nothing in it is interpreted by sh. These placeholders are substituted:
{prompt}, {platform}, {proposalId}, {venue}, {endsAt}.
The same values plus the proposal title are also passed in the environment as
SAFE_MPC_PROMPT, SAFE_MPC_PLATFORM, SAFE_MPC_PROPOSAL_ID,
SAFE_MPC_VENUE, SAFE_MPC_PROPOSAL_TITLE and SAFE_MPC_ENDS_AT, which is how
you drive an agent that takes its input from the environment.
Proposal titles are written by whoever submitted the proposal, so they are never placed on the command line, only in the environment. Proposal ids and venues are checked against a strict character allowlist before substitution, and a dispatch is refused outright if either could alter how the command parses.
On-chain discovery and its limits
governor_find_proposals and the scheduler's Governor path both scan
ProposalCreated logs, then filter by the contract's live state().
The scan window comes from the Governor, not from a guess. A proposal can
only be open if it was created within votingDelay + votingPeriod of now, so
that is exactly how far back the scan reaches, plus
GOVERNOR_LOOKBACK_MARGIN. A DAO with a one-day delay and a three-day voting
period is scanned six days back, not a fixed month. Every result reports the
window it used and where that came from. GOVERNOR_LOOKBACK is only the
fallback for a Governor fork that does not expose those two methods, and the
lookback argument overrides both.
This does mean a proposal created before that window is invisible, which
matters only if the DAO shortened its voting period very recently. Widen
GOVERNOR_LOOKBACK_MARGIN or pass an explicit lookback if so.
Deadlines are estimated on a Governor that counts in blocks. OpenZeppelin
Governor v5 and later can report time in seconds via ERC-6372, and those
deadlines are exact. Older Governors and Compound Bravo count in block numbers,
so the deadline is derived from the chain's recent average block time, measured
by sampling two blocks rather than from a hardcoded table. Results flag this
with endsAtIsEstimate, and the estimate drifts as block times change. Leave
enough room in VOTE_BEFORE_CLOSE to absorb that drift.
Scans are chunked because most RPC providers cap the block span of a single
eth_getLogs call. Deriving the window from the contract keeps that cost
proportionate: on a chain producing a block every quarter second, a three-day
voting period is a far smaller scan than a blanket month would be. A scan
needing more than GOVERNOR_MAX_LOG_CHUNKS calls is still refused, reporting
the measured block time and where the window came from, rather than quietly
hammering your provider.
One known gap: a Governor fork that changed the ProposalCreated parameter
types would need its own event definition. Renaming parameters is fine, which
is why one definition covers both OpenZeppelin and Compound Bravo.
Guardrails
An agent with a Safe owner key is a real capability, so the server constrains it in five ways:
ALLOWED_SNAPSHOT_SPACESandALLOWED_GOVERNORSconfine voting to named spaces and contracts. Anything else is refused before a signature is made. This is the single most effective control here; set it.DRY_RUNsigns and submits nothing while still exercising every read and every validation. It is off by default — votes are real unless you turn it on.Pre-flight checks refuse votes that would be rejected or reverted anyway: closed proposals, zero voting power, a Governor proposal already voted on. Under
DRY_RUNthese become reported blockers rather than refusals, and the payload comes back anyway, so a rehearsal still shows you what it would sign.The Safe's own threshold stays authoritative. Nothing here can execute past it.
The vote log makes every attempt reviewable after the fact, including the ones that failed.
Beyond that, the agent key is an owner like any other: remove it in the Safe UI to revoke access immediately.
Unattended voting deserves more care than on-demand voting, because nobody is
reading the agent's reasoning as it happens. Set the allowlists, keep
VOTE_BEFORE_CLOSE long enough that you can still intervene, and read the vote
log for the first few proposals.
Development
npm run dev # watch mode
npm run typecheck
npm run build
npm test # offline, no network or keys neededThe tests cover the parts that fail silently rather than loudly. The most important one checks that the EIP-712 hash viem derives (what the Safe SDK signs) matches the hash ethers derives (what the Snapshot hub recomputes before verifying the Safe's EIP-1271 signature), across all six Snapshot voting systems. If those two ever diverge, votes are rejected at the hub with no obvious cause.
The rest cover the scheduler's timing and its double-vote guard, and the command dispatch path, including that a hostile proposal title cannot reach the command line.
src/
index.ts MCP server entry, stdio transport
config.ts Environment validation and the allowlist guards
chains.ts Chain registry and RPC resolution
safe.ts Safe client construction and owner checks
setup.ts safe-mpc-setup CLI: key generation, .env, readiness check
dotenv.ts Minimal .env loader, so config is not duplicated per client
policy.ts Reads the voting-policy documents
prompts.ts Prompts and policy resources
voteLog.ts Append-only JSONL record of every vote attempt
schedule.ts The scheduler's queue and its timing rules
watcher.ts Proposal discovery and agent dispatch
watch.ts safe-mpc-watch CLI
duration.ts Duration parsing for the config
platforms/
snapshot.ts Hub queries, EIP-712 vote types, sequencer submission
snapshotX.ts Snapshot X space ABI, vote and cancel calldata, on-chain reads
governor.ts Governor ABI, calldata encoding, on-chain state reads
governorIndexer.ts On-chain discovery from ProposalCreated logs
tally.ts Legacy hosted-indexer client, superseded by governorIndexer
tools/
safeTools.ts safe_*
snapshotTools.ts snapshot_*
snapshotXTools.ts snapshot_x_*
governorTools.ts governor_*
logTools.ts vote_log, vote_schedule
shared.ts Tool result helpers and the in-band error guardTroubleshooting
"SAFE_API_KEY is not set" at startup — the Safe SDK needs a Transaction
Service key to construct its client, even for paths that never call the service.
Get one free at developer.safe.global, or set
SAFE_TX_SERVICE_URL if you run your own service.
"is not an owner of Safe" — the address in SAFE_AGENT_PRIVATE_KEY has not
been added as a Safe owner. safe_info prints the current owner list.
"holds no ETH" — the agent EOA, not the Safe, pays gas for on-chain votes.
Send ETH to the address safe_info reports as agentSigner. Snapshot voting is
unaffected and needs no ETH at all.
"no voting power" — the Safe did not hold or was not delegated the
governance token at the proposal's snapshot block. Delegation set up after that
block does not apply retroactively. snapshot_spaces_with_voting_power with
includeZero: true shows every space that was tested and what each returned,
which is the quickest way to tell "wrong space" from "no tokens". Under
DRY_RUN the vote tool returns the payload anyway, flagged as blocked, so the
path can still be demonstrated.
dryRun: true when .env says otherwise — a variable in the process
environment beats the file, and MCP clients pass their own env block to the
server. Editing .env cannot fix that, and neither can a restart if the client
re-reads its cached config: remove DRY_RUN from the client's server entry, or
set it there to "false". safe_info reports dryRunSource, which says which
of the two is in force.
"signed by 1 of 2 required owners" — expected on a multi-owner Safe. The
message hash is in the result; once the other owners sign it in the Safe UI, call
snapshot_submit_pending_vote with it.
Snapshot sequencer rejects the vote — usually the space's validation, not the signature: a minimum-balance requirement, or voting closed between the read and the submission. The sequencer's own message is passed through verbatim.
The watcher queues nothing — --plan prints the spaces it resolved, the
Safe's voting power in each, and what every space and governor returned. An empty
result usually means the Safe has no voting power anywhere and no space was named
explicitly, or the space id or governor address is wrong, or nothing is open
right now. For on-chain proposals, the log line
reports the scan window that was used; check that it reaches back past the
proposal's creation, and that the governor is on SAFE_CHAIN_ID.
"needs N eth_getLogs calls" — the window is too wide for this chain's block
time. The error names where the window came from. If it was derived from the
Governor, the DAO genuinely has a long voting period, so raise
GOVERNOR_LOG_CHUNK_BLOCKS if your provider allows wider ranges. If it fell
back to GOVERNOR_LOOKBACK, shorten that instead.
The watcher dispatches but no vote appears — the entry stays pending with
lastError set in data/schedule.json, and the agent's output tail is on
stderr. The usual cause is an agent command that cannot reach the MCP server, so
check that --mcp-config points at a file naming this server.
License
MIT
Available Tools
21 toolsgovernor_find_proposalsFind on-chain Governor proposals (no API key)ARead-only
Discovers proposals by reading ProposalCreated logs straight from a Governor contract, then filtering by the contract's live state. Returns the full proposal description, so no third-party indexer is involved. This is the supported way to find on-chain proposals: Tally shut down in March 2026. Works with OpenZeppelin Governor and Compound Bravo.
| Name | Required | Description | Default |
|---|---|---|---|
| states | No | Which proposal states to return | |
| governor | Yes | Governor contract address | |
| lookback | No | Override how far back to scan, e.g. "7d". By default the window is derived from the Governor's own votingDelay and votingPeriod, which is the shortest span that can still contain an open proposal. Only set this if the Governor's parameters changed recently. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/openWorld annotations, the description discloses the data source (on-chain logs, no third-party indexer), that results are filtered against live contract state, and that full proposal descriptions are returned. It's missing any note on cost, rate limits, or scan size, which matters for an unbounded log scan.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the mechanism, then the no-indexer guarantee, then applicability. Mostly earns its space, though the Tally-shutdown justification is closer to marketing rationale than invocation information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully states the return shape (full proposal description) and the compatibility surface (OpenZeppelin Governor, Compound Bravo). For a three-parameter read tool this is largely sufficient; result size or pagination behavior is the remaining gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so governor, states, and lookback are already documented, including the default state set and the lookback derivation rationale. The description's mention of 'filtering by the contract's live state' loosely ties to the states parameter but adds no syntax or behavior beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('discovers proposals by reading ProposalCreated logs straight from a Governor contract') and explains the filtering mechanism. It doesn't differentiate itself from the near-identically named sibling governor_list_proposals, which an agent would also consider.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'supported way ... Tally shut down in March 2026' line implies when to prefer this tool, and the compatibility note scopes its applicability. But it never explicitly contrasts with governor_list_proposals or governor_get_proposal, so the agent must infer which sibling to pick.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
governor_get_proposalRead a Governor proposal via a hosted indexer (legacy)ARead-only
Legacy path: fetches a proposal's title, description and tallies from the Tally-compatible hosted API, which shut down in March 2026. Prefer governor_find_proposals for the description and governor_proposal_state for live on-chain state; neither needs an API key.
| Name | Required | Description | Default |
|---|---|---|---|
| tallyId | No | Tally's internal proposal id | |
| onchainId | No | The Governor contract's proposal id | |
| governorId | No | Required alongside onchainId |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnly and open-world; the description adds the decisive fact that the upstream service is gone, plus an implicit hint that this path may need an API key while the alternatives do not. It doesn't say what a call actually returns now (error, timeout, stale cache), which is the remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero waste, with the depreciation warning front-loaded before the redirect. Every clause carries operational value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a dead legacy endpoint the agent needs the deprecation notice and the exit path, both of which are present. What's missing is the failure mode on invocation and whether historical tallies are recoverable elsewhere.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already documents tallyId, onchainId and the governorId-alongside-onchainId constraint. The description adds no parameter guidance, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (fetches a proposal's title, description and tallies) and pins the source (Tally-compatible hosted API). Explicitly separates it from governor_find_proposals and governor_proposal_state, so an agent can route without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-not (the backing API shut down in March 2026) and names two concrete alternatives with the axis to choose between them (description vs. live on-chain state). The 'prefer X for Y' mapping leaves nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
governor_list_proposalsList Governor proposals via a hosted indexer (legacy)ARead-only
Legacy path: lists proposals through the Tally-compatible hosted API. Tally shut down in March 2026 and is now Cactus, so this may fail even with a key. Prefer governor_find_proposals, which reads the Governor contract directly and needs no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| governorId | No | Tally governor id, e.g. "eip155:1:0x408E..." | |
| organizationId | No | ||
| organizationSlug | No | Tally slug from the DAO's tally.xyz URL, e.g. "uniswap" |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnly and openWorld; the description adds the crucial facts that this hits an external hosted service that may be dead and that an API key may be required — context not available in structured fields. It stops short of describing response shape or pagination, but for a deprecated read-only list tool that is a minor gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the legacy status and ending with the actionable alternative. No filler, though the deprecation notice is nearly repeated via 'Tally shut down' and 'Legacy path'.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
It covers the important migration/deprecation and auth context, but with four parameters, only half documented, and no output schema, the description leaves the agent without guidance on what the proposals response looks like or how limit/organizationId interact. Adequate for steering away, incomplete for actually calling it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50% and the description mentions no parameters at all. The two undocumented parameters (limit, organizationId) and the Tally id format get no compensating explanation, so an agent must infer usage from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names the specific verb+resource (lists proposals) and the specific backend (Tally-compatible hosted API), and immediately labels it legacy, which separates it cleanly from governor_find_proposals.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states to prefer governor_find_proposals because it reads the contract directly and needs no API key, plus the condition under which this path fails (Tally shut down, now Cactus). When-to-use and when-not-to-use are both present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
governor_proposal_stateRead live Governor state for a proposalARead-only
Reads the Governor contract directly: the proposal's state, whether the Safe has already voted, the Safe's voting power at the proposal's snapshot, the quorum and the running tally. Needs no API key. Call this before voting.
| Name | Required | Description | Default |
|---|---|---|---|
| decimals | No | Governance token decimals, for readable vote weights | |
| governor | Yes | Governor contract address | |
| proposalId | Yes | On-chain proposal id (decimal or 0x hex) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint and openWorldHint already declared, the description adds real value by revealing the read source (reads the Governor contract directly) and that no API key is needed, which is important auth/routing context. It doesn't cover failure modes or rate limits, but that's minor against the annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the operation and its returned fields, then the usage cue and auth note. Every clause earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, but the description compensates by enumerating the returned values (state, voted status, voting power, quorum, tally). Combined with the schema-documented inputs and annotations, an agent has everything needed to call and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so governor, proposalId, and decimals are already documented in the schema. The description adds no parameter-level detail beyond what structured data provides, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (reads) and resource (the Governor contract for a proposal) and enumerates exactly what is returned: state, Safe's voted status, voting power at snapshot, quorum, and running tally. This distinguishes it functionally from siblings like governor_get_proposal or governor_list_proposals, though it does not name them explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear timing guidance with 'Call this before voting,' which tells the agent when to invoke it. It does not name an alternative tool or state when not to use it, so it falls short of the explicit alternatives-based 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
governor_voteCast an on-chain Governor vote from the SafeA
Votes on an OpenZeppelin or Compound-style Governor by executing castVoteWithReason from the Safe. This is a real on-chain transaction that costs gas and cannot be undone or changed. Check governor_proposal_state first to confirm the proposal is Active and the Safe has voting power.
| Name | Required | Description | Default |
|---|---|---|---|
| reason | No | Public rationale stored on-chain with the vote. Costs extra gas but is strongly recommended for an agent vote. | |
| support | Yes | How to vote. Maps to Governor support values 1, 0 and 2. | |
| governor | Yes | Governor contract address | |
| proposalId | Yes | On-chain proposal id (decimal or 0x hex) | |
| skipChecks | No | Bypass the pre-flight state and voting-power checks. Only for unusual Governor forks that do not implement the standard view methods. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as a non-read-only, non-idempotent, open-world operation. The description adds material context beyond that: it is a real on-chain transaction, costs gas, and is irreversible. It does not mention the return/confirmation format, but there is no output schema to defer to.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with zero waste. The irreversible-transaction warning is front-loaded and the prerequisite follows, making the key facts easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a gas-costing, irreversible mutation with no output schema, the description covers the essentials: mechanism, cost/irreversibility, and preconditions. Minor gaps remain (e.g., what skipChecks does behaviorally, expected confirmation behavior), but the schema handles the parameter-level caveats.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so each parameter (including reason's gas cost note and skipChecks' fork caveat) is already documented in the schema. The description only alludes to castVoteWithReason, adding no detail beyond the structured fields, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (votes) and resource (Governor) and names the exact mechanism (castVoteWithReason from the Safe). This clearly distinguishes it from the snapshot_vote siblings, which operate off-chain.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to governor_proposal_state first and states the preconditions (proposal Active, Safe has voting power). A clear prerequisite plus the named check tool leaves little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
safe_confirm_transactionConfirm a queued Safe transactionA
Adds the agent's signature to a queued Safe transaction. When this signature meets the threshold, the transaction is executed on-chain. Use this to help along a vote that was proposed but not yet executed.
| Name | Required | Description | Default |
|---|---|---|---|
| safeTxHash | Yes | The safeTxHash from safe_pending_transactions |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and destructiveHint=false, so the mutating nature is already known; the description adds real value by disclosing the threshold mechanic and that execution can occur on-chain as a result. It omits permission/ownership requirements and expected failure modes, which for an on-chain-signing tool would be worth stating.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and its consequence; no redundant restatement of the name or title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description conveys the meaningful outcome (threshold reached → executed) well. It does not describe what is returned or how a below-threshold signature is reported, leaving a modest gap for a single-parameter mutation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter, with 100% schema coverage that already describes the hash format and points to safe_pending_transactions as its source. The description adds no further parameter detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("adds the agent's signature to a queued Safe transaction") and immediately explains the consequence (threshold execution on-chain). This distinguishes it from the listing sibling safe_pending_transactions, which the schema names as the source of the hash.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use this to help along a vote that was proposed but not yet executed" gives a clear usage condition. It does not explicitly state exclusions (e.g., don't call when already executed or when the agent isn't an owner), so it falls short of a full when/when-not/alternatives treatment.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
safe_infoSafe wallet infoARead-only
Reports the configured Safe and the agent's readiness to vote: chain, owners, threshold, nonce, both ETH balances, and whether the agent's signer key is an owner that can execute alone. The agent's own balance is what pays gas for on-chain votes; Snapshot votes are gasless and need none. Call this first.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the description's job is to add operational meaning — and it does: the agent's own ETH balance is the gas source for on-chain votes, while Snapshot votes are gasless. It also surfaces the execution-authority fact (sole owner vs. needing confirmations), which materially affects downstream tool choice.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, each carrying distinct information: return fields, gas semantics, invocation priority. Slightly suboptimal that the most actionable instruction ('Call this first') is buried at the end rather than front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no parameters, the description must carry the return-value burden itself, and it does by enumerating every reported field. It also supplies the interpretive context (what the balances mean for voting) that an agent needs to act on the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes no parameters, so there is nothing for the description to disambiguate; baseline for zero params is 4. Nothing in the description misleads about inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb ('Reports') and a precisely enumerated resource: chain, owners, threshold, nonce, both ETH balances, and whether the signer key is a sole-executing owner. The scope is clearly a read-only configuration/readiness check, which separates it from siblings like safe_pending_transactions and safe_confirm_transaction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Call this first' gives an explicit ordering instruction that tells the agent when to reach for it relative to the rest of the Safe/Snapshot workflow. It also explains the gas distinction that determines whether on-chain voting is even viable. It stops short of naming a concrete alternative or a when-not-to-use condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
safe_pending_transactionsList queued Safe transactionsARead-only
Lists transactions queued on the Safe Transaction Service that are waiting for confirmations or execution.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety and external-service profile is covered. The description adds that the source is the Safe Transaction Service, which is useful, but says nothing about authentication requirements, pagination, result limits, or how the endpoint is scoped (which Safe or network).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. The resource and qualifying state both appear before any subordinate clause, so the key information survives a truncated read.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters and no output schema, the description carries the full descriptive burden, yet it never says which Safe or network the results belong to, nor what a returned entry contains or how many come back. For a zero-argument list tool scoped to an external service, that scope ambiguity is a real gap an agent may trip over.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. There is nothing for the description to disambiguate, and it doesn't waste words on parameter detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (Lists) plus a well-defined resource (transactions queued on the Safe Transaction Service) with a state qualifier: waiting for confirmations or execution. That state qualifier distinguishes it from a generic transaction history or from safe_confirm_transaction. It stops short of naming a sibling, so it is a 4 rather than a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The word 'queued' plus 'waiting for confirmations or execution' implies the use case (finding transactions that still need action), but no explicit when-to-use, when-not, or alternative is stated. An agent could reasonably infer it should call this before safe_confirm_transaction, but that inference is left unstated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_get_proposalRead a Snapshot proposalARead-only
Fetches a Snapshot proposal in full, including the body text, the voting system, every choice with its index, current scores, and how much voting power the Safe holds. Read this before voting.
| Name | Required | Description | Default |
|---|---|---|---|
| proposalId | Yes | Snapshot proposal id (0x… hash) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so safety is covered. The description adds real value by disclosing the returned contents — body text, voting system, indexed choices, current scores, and the Safe's voting power — which matters since there is no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the action and payload, ending with the actionable usage cue. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-value burden and does so well by listing the fields an agent will get back. It omits edge behavior (invalid/unknown proposalId, missing proposal), which keeps it just short of complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single proposalId parameter is documented as a 0x… hash in the schema. The description adds nothing about the parameter, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Fetches a Snapshot proposal in full') and enumerates the payload fields, so an agent knows exactly what it retrieves. The 'in full' framing implicitly separates it from siblings like snapshot_list_proposals, but no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Read this before voting' gives a concrete usage condition tied to the voting workflow. It stops short of naming alternatives (e.g., snapshot_list_proposals for discovery), so selection between siblings still requires inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_list_proposalsList Snapshot proposalsARead-only
Lists proposals in a Snapshot space, newest first. Defaults to proposals that are currently open for voting.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| space | Yes | Snapshot space id, e.g. "ens.eth" or "aavedao.eth" | |
| state | No | Which proposals to return | active |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds two useful behavioral facts (sort order and default state filter) but says nothing about result volume, pagination behavior, or what a proposal record contains.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, no filler, with the resource and ordering front-loaded ahead of the default-behavior note. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A simple three-parameter read tool with no output schema, so the bar is modest. Still, an agent gets no signal about whether 'limit' caps the page or total results, and no sense of the returned shape, which the description could cheaply have supplied.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67% — the space id and state enum are documented in the schema, and the description usefully restates that the default state means 'open for voting'. The limit parameter (default 10, max 50) is not explained in either place, so the description only marginally improves on the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Lists proposals in a Snapshot space') plus ordering ('newest first'), so the core action is unambiguous. However, it never distinguishes itself from close siblings like snapshot_open_proposals or snapshot_query, which an agent must choose between.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Defaults to proposals that are currently open for voting' implies the default filter behavior but gives no explicit when-to-use or when-not-to-use guidance. With snapshot_open_proposals and snapshot_query in the sibling set, a routing sentence is conspicuously absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_open_proposalsEvery open proposal this Safe can vote onARead-only
Lists the proposals currently open for voting across every Snapshot space the Safe holds voting power in, soonest deadline first, with the Safe's voting power on each. This is the whole of the Safe's Snapshot ballot: use it to decide what needs a vote, then snapshot_get_proposal to read one.
| Name | Required | Description | Default |
|---|---|---|---|
| spaces | No | Restrict to these space ids instead of every space with voting power | |
| limitPerSpace | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered; the description adds real value beyond them by disclosing sort order (soonest deadline first), the per-proposal inclusion of the Safe's voting power, and the implicit 'all spaces with voting power' default. It does not explain truncation/pagination behavior, which is a gap given a per-space limit exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with the scope and ordering front-loaded, followed by the routing hint. No filler, and every clause carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With readOnly/openWorld annotations but no output schema, the description does the right work by describing what is returned (open proposals with the Safe's voting power, deadline-ordered). The remaining omission is pagination/cap semantics for limitPerSpace, which matters for a zero-required-param list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50%: `spaces` is documented in the schema but `limitPerSpace` (default 20, max 50) has no description anywhere. The description's 'across every Snapshot space the Safe holds voting power in' hints at the default filtering behavior of `spaces`, but it never mentions restricting spaces or the per-space cap, so it does not compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Lists), resource (open proposals for voting), and precise scope (every Snapshot space the Safe holds voting power in), plus ordering (soonest deadline first) and payload (the Safe's voting power). This clearly separates it from generic siblings like snapshot_list_proposals and snapshot_query.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly frames the tool as 'the whole of the Safe's Snapshot ballot' and prescribes the next step: use it to decide what needs a vote, then snapshot_get_proposal to read one. It lacks an explicit when-not statement (e.g., versus snapshot_list_proposals or snapshot_query), which keeps it short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_queryRun a GraphQL query against the Snapshot hubARead-only
Runs any GraphQL query against the Snapshot hub API — spaces, proposals, votes, follows, users, strategies, anything the schema exposes — for questions the fixed read tools do not cover (a space's full vote history, who follows it, strategy parameters, cross-space voter lookups). The tool only sends query operations — mutations and subscriptions are rejected. Use first/skip and select only the fields you need: responses over 1 MB are refused, and results over 50k characters are truncated. Schema reference: https://docs.snapshot.box.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | GraphQL query, e.g. "query { space(id: \"ens.eth\") { name followersCount } }" | |
| variables | No | Values for the query's $variables, if it declares any |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond annotations: only query operations are allowed, responses over 1 MB are refused, and results over 50k characters are truncated. Annotations already declare readOnly/openWorld, but the response-size and operation-type constraints are valuable context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then constraints and schema reference in a compact paragraph. Every sentence earns its place by clarifying scope, limits, or safe usage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for an open-ended GraphQL query tool with no output schema: it explains allowed operations, size limits, truncation behavior, pagination guidance, and points to the external schema reference. Nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the query and variables parameters are already documented. The description adds meaningful usage semantics beyond the schema: use first/skip, select only needed fields, and keep responses within size limits.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — runs GraphQL queries against the Snapshot hub API — and enumerates the domains it can query. It explicitly positions itself as the fallback for questions the fixed read tools do not cover, distinguishing it from sibling read tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use guidance: for questions the fixed read tools do not cover, with concrete examples. It also gives when-not guidance by stating that mutations and subscriptions are rejected, and recommends pagination/field selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_spaces_with_voting_powerSnapshot spaces this Safe can vote inARead-only
Finds every Snapshot space where the Safe holds voting power, without needing a list up front: it tests the configured spaces, the spaces the Safe follows, and the spaces it has voted in before. Start here when you do not know where this Safe votes.
| Name | Required | Description | Default |
|---|---|---|---|
| spaces | No | Extra space ids to test, on top of the ones discovered automatically | |
| includeZero | No | Also return spaces where the Safe has no voting power |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the description is not obligated to restate safety, yet it usefully discloses the three discovery sources (configured spaces, followed spaces, prior votes), which explains why the tool is open-world and potentially slow. Return shape and cost/latency are left unstated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with the outcome and followed by the call-to-action condition; no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-required-parameter, read-only discovery tool with no output schema, the description conveys enough to invoke it correctly, though it never sketches what the result set looks like (space ids, names, voting power values).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are fully documented in the schema and the baseline of 3 applies. The description only hints at the 'spaces' parameter via 'on top of the ones discovered automatically' and never mentions includeZero.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Finds') and a precisely scoped resource ('every Snapshot space where the Safe holds voting power'), and the phrase 'without needing a list up front' separates it from sibling tools like snapshot_voting_power that require a known space id.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Start here when you do not know where this Safe votes' gives an explicit entry-point condition, but there is no complementary when-not guidance (e.g. use snapshot_voting_power when the space is already known) beyond the implied contrast.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_submit_pending_voteSubmit an already-signed Snapshot voteA
Finishes a vote whose Safe message was created earlier but not submitted, usually because the Safe needed more owner signatures. Pass the safeMessageHash reported by snapshot_vote.
| Name | Required | Description | Default |
|---|---|---|---|
| safeMessageHash | Yes | The safeMessageHash from an earlier snapshot_vote call |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare write (readOnlyHint=false), non-destructive, open-world. The description adds real context beyond them: this operates on a pre-existing Safe message rather than creating one, and the typical reason it is needed is a signature shortfall. It stops short of saying what happens if the message was already submitted or whether the call is safely repeatable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler, and the state that makes the tool necessary is front-loaded before the parameter instruction. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter submission tool with no output schema, the description covers the precondition and input origin well. It leaves minor gaps: what a successful call returns and how it behaves on a message that was already submitted, which an agent might want before retrying.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter and schema coverage is 100%, so the schema already documents the format and origin of safeMessageHash. The description restates that the hash comes from snapshot_vote without adding syntax, validation, or lifecycle detail, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (finishes/submits) and resource (a vote whose Safe message already exists), and scopes it to the incomplete-signature case. This cleanly separates it from snapshot_vote, which is where the message is originally created.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains the trigger condition clearly: the Safe message was created earlier but not submitted, usually due to missing owner signatures. It implies snapshot_vote is the originating call and that this is the recovery path, though it never explicitly says 'do not use this to start a new vote.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_voteCast a Snapshot vote from the SafeA
Casts an off-chain, gasless Snapshot vote on behalf of the Safe. Signs an EIP-712 vote as a Safe message, waits for the Safe's EIP-1271 signature, then submits it to the Snapshot sequencer. Read the proposal with snapshot_get_proposal first so the choice index and voting system match. Voting again on the same proposal replaces the earlier vote.
| Name | Required | Description | Default |
|---|---|---|---|
| choice | Yes | 1-indexed choice. A single number for single-choice/basic proposals, an array for approval or ranked-choice, or an object of option->weight for weighted or quadratic (e.g. {"1": 70, "2": 30}). | |
| reason | No | Public rationale recorded with the vote. Strongly recommended. | |
| proposalId | Yes | Snapshot proposal id (0x… hash) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare this is a non-read-only but non-destructive, open-world operation; the description adds real context beyond that: it is gasless, requires a Safe EIP-1271 signature round-trip, goes to the Snapshot sequencer, and a repeat call silently replaces the prior vote. Failure modes and timing of the signature wait are not described, keeping it below a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, front-loaded with the action and its mechanism, then the prerequisite, then the replacement caveat. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no output schema, the description covers the signing flow, prerequisite lookup and re-vote semantics, which is enough to call it correctly. What an agent gets back on success/failure, and how long the signature wait may take, are unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description adds genuine meaning by tying the meaning of 'choice' to the proposal's voting system and directing the agent to inspect the proposal before choosing an index. It does not restate the choice shapes, but the schema already does.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb, resource and mechanism: casts an off-chain gasless Snapshot vote on behalf of the Safe via EIP-712/EIP-1271. An agent can distinguish this from sibling vote tools like snapshot_x_vote or snapshot_submit_pending_vote because the signing path is spelled out.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit prerequisite: read the proposal with snapshot_get_proposal first so the choice index and voting system match. It also clarifies the re-vote case (voting again replaces the earlier vote). It stops short of routing the agent away from the other sibling vote-submission tools, so no explicit when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_voting_powerSafe voting power on a Snapshot proposalARead-only
Reports how much voting power the Safe has on a specific proposal, broken down by the space's strategies. Zero means the vote would carry no weight.
| Name | Required | Description | Default |
|---|---|---|---|
| space | Yes | ||
| proposalId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds useful behavior context by explaining that results are broken down by strategies and that zero means the vote carries no weight, but it does not discuss data freshness, required auth, or failure behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core purpose and followed by a decision-relevant caveat. There is no redundant or wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only query, the description gives enough to understand the high-level output: voting power broken down by strategies. However, with no output schema and no parameter documentation, it leaves out return-value shape, parameter formats, and any error or edge-case behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for both required parameters, so the description must compensate. It barely does: it implies that 'space' refers to the space whose strategies are used and that 'proposalId' identifies the proposal, but it gives no format, naming, or lookup guidance for either parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it reports the Safe's voting power on a specific Snapshot proposal, broken down by strategies. This clearly distinguishes it from siblings like snapshot_vote (casting a vote) and snapshot_spaces_with_voting_power (listing spaces).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the zero-power note, which helps an agent decide whether a vote would matter, but the description never explicitly says when to use this tool rather than snapshot_vote or snapshot_get_proposal. No alternatives or exclusions are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_x_cancel_proposalCancel a Snapshot X proposal from the SafeADestructive
Cancels (vetoes) an on-chain Snapshot X proposal by proposing Space.cancel(proposalId) from the Safe — the streamlined replacement for wiring snapshot.box to the Safe over WalletConnect by hand. Only works when the Safe is the space controller. At threshold 1 the transaction executes immediately; above that it lands in the Safe queue with the exact to/data/value for the other owners to verify and sign, and the final signer's confirmation executes it.
| Name | Required | Description | Default |
|---|---|---|---|
| space | Yes | The Snapshot X space: a space contract address, a prefixed id like "eth:0x594E…", or a full snapshot.box proposal URL (in which case proposalId can be omitted). | |
| reason | No | Why the proposal is being cancelled. Recorded in the local log only. | |
| proposalId | No | The proposal number, e.g. 3. Not needed when the space is a proposal URL. | |
| skipChecks | No | Bypass the pre-flight controller/state checks and simulation. Only for sx-evm forks that break the standard view methods. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag this as destructive, non-idempotent and open-world, but the description adds real context beyond them: execution behavior varies by Safe threshold (immediate at 1, queued with to/data/value above that) and the final signer's confirmation executes it. It doesn't cover failure modes or whether a cancel can be undone on-chain.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core action and mechanism. The WalletConnect aside and the threshold explanation are dense but each earns its place; the final sentence carries several clauses that could be split.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description covers the outcome (immediate execution vs. queued Safe transaction) and the key precondition, which is everything an agent needs to know before invoking a destructive on-chain tool. Schema covers the parameters fully.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents space, proposalId, reason and skipChecks, including the URL-omits-proposalId rule. The description adds no parameter-level detail beyond what the schema provides, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Cancels (vetoes) an on-chain Snapshot X proposal') plus the exact on-chain call it makes (Space.cancel(proposalId) from the Safe). This clearly separates it from siblings like snapshot_x_vote, snapshot_x_proposal, and safe_confirm_transaction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a hard precondition ('Only works when the Safe is the space controller') and positions itself against the manual WalletConnect alternative. It stops short of naming sibling tools (e.g. safe_pending_transactions for queue follow-up, snapshot_open_proposals to find the id), so it is clear but not fully routed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_x_proposalRead an on-chain Snapshot X proposalARead-only
Reads a Snapshot X (snapshot.box) proposal straight from its space contract: live status, the running For/Against/Abstain tally, the Safe's voting power at the proposal's snapshot block, whether the Safe already voted, and whether this Safe is the space controller that could cancel it. Use it before snapshot_x_vote or snapshot_x_cancel_proposal, and again afterwards to confirm the vote landed or the proposal shows Cancelled.
| Name | Required | Description | Default |
|---|---|---|---|
| space | Yes | The Snapshot X space: a space contract address, a prefixed id like "eth:0x594E…", or a full snapshot.box proposal URL (in which case proposalId can be omitted). | |
| proposalId | No | The proposal number, e.g. 3. Not needed when the space is a proposal URL. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so safety is covered; the description adds meaningful behavior beyond that, namely that data is read on-chain from the space contract, that voting power is evaluated at the proposal's snapshot block, and that Safe-specific state (already voted, is space controller) is included. It says nothing about RPC failures or staleness of 'live status', which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the verb and source, then the returned data, then the workflow. Every clause carries information an agent would otherwise have to infer.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by listing the returned fields (status, tally, snapshot-block voting power, voted flag, controller flag). Combined with the schema's parameter documentation and the read-only annotations, an agent has everything needed to call and interpret this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are documented in the schema, including the address / prefixed-id / URL forms of `space` and the URL-implies-no-proposalId rule. The description only echoes 'from its space contract' and adds no syntax or format detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Reads a Snapshot X (snapshot.box) proposal straight from its space contract') and enumerates exactly what information comes back, so the agent knows the payload without opening a schema. It distinguishes itself functionally from the write siblings it names, but never explicitly contrasts with the confusable read siblings snapshot_get_proposal / snapshot_query.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete call sequence: use before snapshot_x_vote or snapshot_x_cancel_proposal, and again afterwards to confirm the vote landed or the proposal shows Cancelled. That is real when-to-use guidance, though there are no exclusions and no routing advice against the other proposal-reading tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_x_voteCast an on-chain Snapshot X vote from the SafeA
Votes For, Against or Abstain on a Snapshot X (snapshot.box) proposal as the Safe. The Safe calls the space's EthTx authenticator, which forwards Space.vote with the Safe as voter — the path snapshot.box itself uses for smart-contract wallets, since a Safe cannot produce the gasless EIP-712 signature. This is an on-chain transaction: it costs gas and is final, Snapshot X does not allow changing a vote. The Safe's voting strategies are resolved automatically and the vote is simulated from the Safe before anything is signed. Read the proposal with snapshot_x_proposal first.
| Name | Required | Description | Default |
|---|---|---|---|
| space | Yes | The Snapshot X space: a space contract address, a prefixed id like "eth:0x594E…", or a full snapshot.box proposal URL (in which case proposalId can be omitted). | |
| choice | Yes | How to vote. Maps to the sx-evm Choice values 1, 0 and 2. | |
| reason | No | Public rationale. Pinned to IPFS and attached to the vote as its metadata URI, which is how snapshot.box shows a reason. | |
| proposalId | No | The proposal number, e.g. 3. Not needed when the space is a proposal URL. | |
| skipChecks | No | Bypass the pre-flight checks and simulation, and submit every active strategy. Only for sx-evm forks that break the standard view methods. | |
| metadataUri | No | Use this metadata URI (e.g. ipfs://…) instead of pinning the reason. Pass an empty string to vote with no metadata. | |
| authenticator | No | The space's EthTx authenticator. Defaults to the snapshot.box deployment 0xBA06E6cCb877C332181A6867c05c8b746A21Aed1; only needed for custom spaces. | |
| strategyParams | No | Per-strategy user params, for strategies that need them (a merkle whitelist proof, for instance). Other active strategies use 0x00. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond the annotations: on-chain, costs gas, final, Snapshot X forbids changing a vote, strategies resolved automatically, and the vote is simulated from the Safe before signing. This tells the agent the irreversibility and pre-flight behavior that the hint flags alone (non-idempotent, non-destructive) cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five tight sentences with no filler; the action, mechanism, and irreversibility warning are front-loaded and the read-first prerequisite closes it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers mechanism, cost, finality, and simulation for an 8-parameter mutation with no output schema. The remaining gap is what happens after submission — whether this executes immediately or becomes a pending Safe transaction needing co-owner confirmation, which the sibling safe_pending_transactions/safe_confirm_transaction tools suggest is relevant.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter is already documented, and the description adds only the note that strategies are resolved automatically (relevant to strategyParams) and that skipChecks exists for broken forks. Baseline 3 applies since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Votes For, Against or Abstain on a Snapshot X proposal as the Safe') and immediately explains the mechanism (EthTx authenticator → Space.vote with the Safe as voter). The gasless EIP-712 contrast distinguishes it from the off-chain sibling snapshot_vote.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to read the proposal with snapshot_x_proposal first, and explains that this is the path for smart-contract wallets because a Safe cannot produce a gasless signature — which implicitly tells the agent when to prefer it over the gasless vote path. It does not name snapshot_vote as the excluded alternative outright.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vote_logRead this Safe's voting recordARead-only
Returns votes this Safe has already cast through Safe-MPC, newest first, with the choice and the reason given. Read it before deciding so the Safe votes consistently with its own precedent, and to check whether a proposal has already been handled.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| venue | No | Snapshot space id, Snapshot X space contract, or Governor contract address | |
| outcome | No | ||
| platform | No | ||
| proposalId | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds useful behavior beyond that: results are newest-first and include the vote choice and reason. It does not discuss pagination or auth requirements, keeping it below a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly written sentences with no wasted words. The purpose and ordering are front-loaded, followed by the usage rationale.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with annotations and no output schema, the description covers purpose, return content, and when to use it. However, with five optional filter parameters and low schema coverage, the description leaves too much unexplained about how to target a specific proposal, platform, outcome, or result limit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20%, with just the 'venue' parameter documented, so the description needs to compensate. Instead it provides no guidance on limit, outcome, platform, or proposalId, leaving most filter semantics undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it returns votes this Safe has already cast through Safe-MPC. It also specifies ordering ('newest first') and returned content ('choice and the reason'), which distinguishes it from mutation siblings like snapshot_x_vote or governor_vote.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear usage context: read it before deciding so the Safe votes consistently with precedent, and to check whether a proposal has already been handled. It does not explicitly name alternatives or exclusion conditions, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vote_scheduleRead the scheduled vote queueARead-only
Shows proposals the watcher has queued for a decision, when each is due, and which are due now. Populated by safe-mpc-watch; empty if the watcher is not running.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | pending |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint=true, openWorldHint=false), so the description is free to add real value — and it does, by disclosing the external dependency on safe-mpc-watch and the critical gotcha that an empty result may mean the watcher isn't running rather than no pending items. Return shape is not described, but with a simple list output that is a minor omission.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no waste, and the core purpose is front-loaded ahead of the operational caveat. Nothing could be cut without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Purpose and the empty-result caveat are covered, but for a tool whose only knob is a six-value status enum, leaving that filter entirely unexplained is a real gap. No output schema exists, so a brief note on what a queued entry looks like would also have helped.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the single status parameter (pending/dispatched/voted/failed/expired/all) is never mentioned in the description. The phrase 'which are due now' hints at the default pending view, but the agent gets no explanation of what each enum value filters, which is the one thing the description needed to compensate for.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — a read of the watcher's queued vote schedule — plus what each entry contains (due time, due-now flag). It is distinguishable from vote_log by being a forward-looking queue rather than a historical record, though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implied usage is clear (inspect the pending queue before a decision), and the note about safe-mpc-watch gives useful context. But there is no explicit when-to-use vs vote_log or snapshot_pending_vote siblings, and no guidance on when to prefer each.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
21 tool updates
v0.1.0- First observed
governor_find_proposals - First observed
governor_get_proposal - First observed
governor_list_proposals - First observed
governor_proposal_state - First observed
governor_vote - First observed
safe_confirm_transaction - First observed
safe_info - First observed
safe_pending_transactions - First observed
snapshot_get_proposal - First observed
snapshot_list_proposals - First observed
snapshot_open_proposals - First observed
snapshot_query - First observed
snapshot_spaces_with_voting_power - First observed
snapshot_submit_pending_vote - First observed
snapshot_vote - First observed
snapshot_voting_power - First observed
snapshot_x_cancel_proposal - First observed
snapshot_x_proposal - First observed
snapshot_x_vote - First observed
vote_log - First observed
vote_schedule
TDQS
Scored across 21 tools
Most tools target a clearly distinct resource and voting path (Safe queue, Snapshot off-chain, Snapshot X on-chain, Governor). There is some potential overlap among Snapshot read tools and among the several vote-casting tools, plus legacy Governor read tools, but descriptions usually make the intended path clear.
All names use snake_case and most are grouped by domain prefix (safe_, snapshot_, governor_). However, several are noun phrases rather than verb_noun, and vote_log/vote_schedule lack the domain prefix used elsewhere, so the pattern is not fully uniform.
At 21 tools the surface is heavy, though some size is justified by supporting three different voting systems. Legacy Governor read tools and the generic snapshot_query add breadth that could likely be consolidated.
The voting lifecycle is well covered: discover spaces/proposals, inspect state and voting power, cast votes, confirm Safe transactions, and review past votes. Minor gaps remain around generic Safe transaction proposal/execution and Governor queue/execute operations, but core Safe voting workflows are supported.
Maintenance
Related MCP Connectors
Crypto wallet for AI agents: balances, payments, swaps and trading with owner controls.
AI agent infrastructure for discovery, authorization, execution, identity, and signed receipts.
AI Agent Utility Layer for agent safety, web monitoring, crypto research and tool discovery.
DeFi safety layer for AI agents: wallet safety, token risk, tx decode/simulate. 20 tools.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to check balances and send transactions across multiple blockchains with automatic spending limit protection and policy enforcement.3MIT
- AlicenseNot gradedqualityDmaintenanceEnable AI agents to manage Safe multisig wallets across multiple blockchains.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to analyze Ethereum wallets, simulate transactions, and draft transfers with deterministic policy and risk scoring, requiring human approval before on-chain execution.6 npmISC
- AlicenseNot gradedqualityBmaintenanceEnables autonomous agents to create and operate an Ethereum Safe wallet, send ETH or call contracts with their own signatures, and check transaction status without human approval or custody.01Apache 2.0