Skip to Content
MCP Server

MCP Server

@solidus-network/mcp is an MCP (Model Context Protocol) server that exposes Solidus as run-time tools an agent can call — resolve a did:solidus DID, verify a credential, and check, create, or authorize a scoped spend mandate. Point any MCP-compatible client (Claude Code, Cursor, Windsurf, or a custom agent loop) at it over stdio and those become ordinary tool calls.

This is the run-time half of agent-native distribution. The CLI is the install-time half — solidus init --with-mcp wires this server into a project’s .mcp.json in one step.

Install

You don’t install this globally — an MCP client launches it on demand with npx:

npx @solidus-network/mcp

Claude Code (.mcp.json)

{ "mcpServers": { "solidus": { "command": "npx", "args": ["-y", "@solidus-network/mcp"], "env": { "SOLIDUS_API_KEY": "<your operator key, only needed for create_mandate>" } } } }

Any other MCP client (Cursor, Windsurf, a custom StdioClientTransport) works the same way — it’s a standard stdio MCP server, command: npx, args: ["-y", "@solidus-network/mcp"].

Tools

5 tools, 3 read (no side effects, no auth) and 2 write (side effects; a human should confirm the terms before an agent calls them):

ToolTypeWhat it does
resolve_didreadResolve a did:solidus DID document from the Solidus chain.
verify_credentialreadVerify a Solidus verifiable credential by id against the chain.
check_mandatereadCheck whether a spend-mandate envelope authorizes a given amount/currency/rail. Pure — no auth, moves nothing. This is the counterparty refusal check.
create_mandatewriteIssue a scoped spend_mandate credential (bounded by maxAmount/currency/rail/expiresAt) for an agent, on behalf of a principal DID. Returns the checkable envelope — never the private key or credential bundle.
agent_paywriteAuthorize a payment under a mandate and return the envelope for the caller’s own rail. Settles nothing — a refusal short-circuits and does no further work.

check_mandate calls the same POST /v1/mandates/check route documented on the Agents API page — the mandate-check flow — and passes authorized/reason through verbatim.

Configuration

All optional except where noted; the server has working defaults for every read tool out of the box.

Env varDefaultUsed by
SOLIDUS_RPC_URLhttps://rpc.solidus.networkresolve_did, verify_credential (chain SDK)
SOLIDUS_AGENTS_URLhttps://agents.solidus.networkcheck_mandate, create_mandate, agent_pay (agents backend)
SOLIDUS_API_KEYcreate_mandate only — an operator bearer token. The other four tools need no auth.
SOLIDUS_SDK_MODEtestnetChain SDK mode: testnet (public chain, no key needed for reads), mainnet, or stub (local Postgres-backed simulation for development).

Quickstart: resolve, refuse, raise, authorize

A mandate bounds what an agent can spend; check_mandate is the refusal a counterparty runs before accepting a payment. This walks resolving a DID, hitting the refusal, then raising the mandate and authorizing:

// 1. Resolve the paying agent's DID resolve_did({ "did": "did:solidus:testnet:<addr>" }) // → { "did": "did:solidus:testnet:<addr>", "document": { ... }, "resolved": true } // 2. Issue a mandate capped at 500 TRY create_mandate({ "agentId": "<agent-id>", "principalDid": "did:solidus:testnet:<principal-addr>", "maxAmount": "500", "currency": "TRY", "rail": "moka", "expiresAt": "2026-08-01T00:00:00.000Z" }) // → { "mandateId": "...", "envelope": "<base64url envelope>", "expiresAt": "2026-08-01T00:00:00.000Z" } // 3. The counterparty checks a 750 TRY charge against it — over the cap, refused check_mandate({ "envelope": "<envelope from step 2>", "amount": 750, "currency": "TRY", "rail": "moka" }) // → { "authorized": false, "reason": "amount exceeds mandate limit" } // 4. Raise the mandate to 1000 TRY create_mandate({ /* same as step 2, "maxAmount": "1000" */ }) // → { "mandateId": "...", "envelope": "<new envelope>", "expiresAt": "..." } // 5. agent_pay authorizes the same 750 TRY charge under the raised mandate agent_pay({ "envelope": "<envelope from step 4>", "amount": 750, "currency": "TRY", "rail": "moka" }) // → { "authorized": true, "envelope": "<same envelope>", "header": "x-solidus-mandate" }

Step 5’s envelope and header are what the caller sends to their own payment rail — Solidus’s part ends at authorization. agent_pay settles nothing; no money moves through this package or through Solidus at any point.

Trust boundary

This package is a thin adapter over @solidus-network/sdk (chain reads) and @solidus-network/agent-identity (mandates, credentials). It holds no issuer keys and does no cryptography of its own — credential signing happens in the Solidus backend; trust in a credential is trust in the issuer key, not in this code.

Status

  • First release (0.1.0). New package, testnet-grade.
  • Solidus L1 is testnet-only — there is no mainnet. DIDs resolve as did:solidus:testnet:<addr>. Treat anything you create through these tools (DIDs, credentials, mandates) as sandbox data, not a durable production record.
  • Credential signing (BBS+) has no external security audit yet. Do not protect production-grade value with it.

Next steps

  • CLIsolidus init --with-mcp wires this server into .mcp.json for you
  • Agents API — the HTTP surface check_mandate, create_mandate, and agent_pay call underneath
  • SDK Reference — the packages this server wraps
Last updated on