Bitcoin/Lightning DCA and cross-chain settlement MCP server with policy-checked proposals, execution, and multi-rail routing
SatRails defines 15 tools with consistent verb_noun naming (satrails_propose, satrails_execute, satrails_status, etc.). All tools have descriptions (10 - 200 chars, within baseline 34 - 392 range). Input schemas are present and typed with JSON Schema. However, parameter descriptions are sparse or missing context; many lack guidance on format, constraints, or dependencies. Output schemas are not documented. Error handling is minimal, no recovery guidance or actionable error messages visible. Tool composition is sound (single responsibility, idempotent operations via executionKey), but descriptions do not explain prerequisites, when to call each tool, or what fields downstream tools need.
Flex pocket UTXO balance (gap-limit 5) and next cold index.
Live Boltz submarine fee quote (read-only). Does not create a swap.
Create a DCA plan. Cron fires propose→execute with no model in the loop.
List DCA plans.
Pause (kill-switch) a DCA plan.
Resume a paused DCA plan.
Execute a previously returned proposal_id. execution_key makes retries safe (same key = same result).
Output schemas not documented. LLMs cannot infer what fields to expect from tool responses (e.g., what does satrails_status return? what fields does a receipt contain?). This forces agents to guess downstream field names and risks broken tool chains.
Parameter descriptions lack format guidance and constraints. E.g., 'spendUsd' says 'decimal USD' but does not specify precision, range, or whether it accepts '50' vs '50.00'. 'cron' in satrails_dca_create lacks examples or validation rules. LLMs cannot reliably format inputs without explicit constraints.
No error handling guidance. Tools lack descriptions of failure modes, recovery steps, or actionable error messages. E.g., satrails_execute does not explain what happens if proposalId is invalid or expired (30s window mentioned in satrails_propose but not linked). Agents cannot self-correct.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 53 | 2026-07-28+ | v2 |
Dev/test: grant one-time cosign for a proposal_id (skips Telegram).
Lightning channel balance when LND is configured; otherwise reports disabled.
Unlock PasskeySigner with HMAC proof (dev) or WebAuthn assertion (prod). Required before signing.
Return the active policy document.
Update policy limits (signed & persisted).
Get a policy-checked, priced proposal. Returns proposal_id valid ~30s. Never moves funds.
Signed JSON receipt bundle for third-party audit (txids, block refs, preimages).
Recent receipts and verification status.
Tool dependencies not documented. satrails_execute requires a proposalId from satrails_propose, but this prerequisite is not stated in satrails_execute's description. satrails_passkey_unlock must be called before signing, but no tool description mentions this. Agents cannot plan multi-step sequences.
Empty input schemas for read-only tools. satrails_balances, satrails_policy_get, satrails_dca_list, and satrails_ln_info accept no parameters ({}), but descriptions do not explain what data they return or when to call them. Minimal descriptions (60 - 70 chars) lack context for LLM selection.