Skip to main content
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

The server has no wallet of its own, so name the wallet you mean on reads: 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 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:
Pass 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.
A prepared payment is valid for about a minute; after that 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 x402 sign-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.
Before returning a challenge, the server checks it against its own configuration: the gateway domain, the Solana cluster, the gateway PDA and program, and a short expiry. Read it anyway before you sign. It looks like this:
In Node, with a devnet keypair and @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.