Pair and use an EVM and/or Solana wallet via WalletConnect v2. **No authentication required** — available to every user (including unauthenticated/anonymous). Non-custodial: the server never holds keys and the user approves every signature/transaction in their own wallet. **Pairing proposal** is controlled per request via optional `pairingTarget` on `action: "connect"`: `eth` (default, eip155 only), `solana`, or `both`. Many mobile wallets fail if eip155 and solana are proposed together; prefer `eth` or `solana` unless the user needs both in one session. **Every call must include `action`** (string).
**Connect QR (critical for assistants):** On `action: "connect"`, successful responses return **(1) a `resource_link`** to the pairing QR PNG when storage works, then **(2) text JSON** with `pairingQrResourceUri`, `presentation`, `nextSteps`, `url`, optional `mobileDeeplinks`, etc. **Desktop / scan UX:** surface the pairing QR **first**: call MCP `resources/read` on `pairingQrResourceUri` in the **same MCP session** as `connect`, then open the PNG per OS (`open` / `xdg-open` / `start`) or render it inline so the user can scan. **Mobile / no-camera:** follow `nextSteps`; when present, `mobileDeeplinks` lists HTTPS `url` (+ `nativeUrl`) per curated WalletConnect wallet so the user can open pairing without QR (`presentation.mobilePreferred === "deeplinks"`); links overlay WalletConnect Explorer data when Redis cache allows; otherwise curated fallbacks still work. Raw `wc:` (`url` / `walletConnectLinkForUser`) remains fallback if links fail to open in the host. **Avoid calling `connect` again while pairing is still in progress** unless the user must reset—duplicate calls used to invalidate the WalletConnect URI; the server now returns the same in-flight URI when Redis shows pairing pending *and* `pairingTarget` matches, but the wallet may still expire stale links if you wait too long.
**Flow:** (1) `connect` as above. (2) User approves in the wallet (EVM only, Solana only, or both). (3) `status` until `kind` is `session` — optional `evm` / `solana` blocks; `address`/`chains` remain legacy EVM when EVM is connected. (4) `sign` / `send_transaction` or swap `execute=true` (swap execute remains EVM unless extended elsewhere). `kind: "pending"` on `status` is success — keep polling.
**Actions (exact JSON shapes):**
- **connect** — `{ "action": "connect", "sessionTtlDays"?: number, "pairingTarget"?: "eth" | "solana" | "both" }`
- **status** — `{ "action": "status" }`
- **sign** — EVM: `personal_sign` / `eth_signTypedData_v4`. Solana: `solana_signMessage` / `solana_signTransaction` (see schema fields `params`, `chainId`, `solanaChainId`).
- **send_transaction** — EVM: `tx.to`, numeric `tx.chainId`. Solana: string `tx.chainId` (`solana:...`), `tx.serializedTransaction` (base64). Set `tx.namespace` when both WC namespaces are active and the payload is ambiguous.
- **disconnect** — `{ "action": "disconnect" }`
**Anonymous durable sessions:** for unauthenticated callers, `connect` returns a `walletSessionToken`. Store it and pass it back as `walletSessionToken` on later `status` / `sign` / `send_transaction` / `disconnect` so the wallet stays connected after the MCP session rotates; omit it and the session is scoped to the current MCP session only. Authenticated callers ignore the token (their WC session is scoped by org/app).
Non-custodial relay; no authentication required.
Connector