https://mcp.molpha.io/mcp is the Molpha MCP server over HTTP. It is keyless: it holds no signer and accepts no private keys. Read tools work immediately, and anything that needs a signature comes back for your own wallet to sign.
Connect
submitter for describe_feed and get_latest_value, payer for get_x402_status.
What your wallet signs
autoSubmit, dryRun and encryptSecrets are not offered on the hosted server: the prepare steps are already previews, and private API secrets must not pass through a shared server. Use the local server for private sources.
Pay per request (x402)
No subscription and no sign-in: the payment is the authorization.1
Quote
get_x402_status({ signaturesRequired, payer }) returns the round price, the payee (the protocol treasury) and your USDC balance.2
Prepare
prepare_x402_round({ apiConfig, signaturesRequired, payer, chains, maxAge? }) returns an unsignedTransaction (a USDC transfer to the protocol treasury), a summary of the payment, and a challenge.3
Sign, don't send
Check the Pass
summary against your wallet’s view of the transaction, then sign it as payer. Do not broadcast it: the gateway’s facilitator co-signs, pays the network fee and submits it.In Node, with a devnet keypair and @solana/kit:signedTransaction to the next step. The same code signs the transaction from prepare_submit_attestation.4
Execute
execute_x402_round({ challenge, signedTransaction }) runs the round and returns the attestation, verifier arguments and a paymentReceipt.execute_x402_round answers payment_expired and you prepare again. One payment buys one round. Pricing and settlement are described in x402 pay-per-request.
Sign in with your wallet (SIWX)
Subscription rounds are authorized by a sign-in session. Your wallet signs one Sign-In-With-X text message (the x402sign-in-with-x extension in its Solana form), and the gateway returns a short-lived bearer token. The message is not a transaction and moves no funds.
1
Check access
describe_access({ address, owner? }) returns the wallet’s role (owner, delegate or none) and its limits. Run it first: a wallet with role none is refused only after it has signed.2
Begin a session
begin_session({ address, owner? }) returns the message to sign, an opaque challenge and expiresAt. A delegate passes its own address as address and the subscription owner as owner.3
Sign the message
Sign the exact UTF-8 bytes of
message with your wallet’s message-signing function (signMessage), not transaction signing. No prefix, no envelope, no trailing newline. Base58, base64 or hex signatures are accepted.4
Complete the session
complete_session({ challenge, signature }) returns a sessionToken, the role it carries and expiresAt.5
Run rounds
execute_subscription_round({ sessionToken, apiConfig, signaturesRequired, chains }) returns the attestation and verifier arguments. Each call uses one round of the subscription’s quota.@solana/kit:
solana sign-offchain-message does not work: it wraps the text in an envelope and is refused with invalid_signature. Never paste a private key into a chat to get a signature.
About the session token
- Short-lived. 30 minutes by default, never past the subscription term. There is no refresh: sign in again.
- One wallet, one gateway. The token is valid only at the gateway that issued it.
- Identity only. The gateway checks the subscription and delegate against chain state (cached for a few seconds) on every round, so removing a delegate or a lapsed subscription ends access within seconds, whatever tokens exist.
- A credential. Keep it out of logs. It passes through the hosted server on each call and is never stored there. To keep it off the server entirely, call the gateway’s session routes directly.
Publish to Solana
prepare_submit_attestation({ result, payer }) takes a round tool’s output unchanged and returns an unsigned submit_attestation transaction. payer pays the fee and becomes the feed’s submitter. Sign it, then broadcast it yourself or pass it to send_signed_transaction({ challenge, signedTransaction }).
Errors
The full list is in the tool reference.