MCP server

The canix402 MCP is a remote, walletless wrapper over the public Caddy gateway. Agents connect over Streamable HTTP, call typed tools for discovery, opportunity data, Haystack Launch, and unsigned quotes, and sign x402 payments on the client. An agent may use Algorand, Base, or both. Algorand tool arguments take an Algorand address alone. Omitting a Base address does not change rank, eligibility, price, or access.

Endpoint

The MCP never stores mnemonics or private keys. Paid tools return structured payment requirements on the first call; your agent signs USDC client-side and retries with paymentSignature.

Swaps

Pass the quote returned by canix_get_quote into the opt-in or swap tool. The MCP does not retain quotes, sign transactions, or submit them; gateway responses pass through to the caller.

// Free quote
canix_get_quote({
  address: "YOUR_ALGORAND_ADDRESS",
  fromAssetId: 0,
  toAssetId: 31566704,
  amount: "1000000",
  type: "fixed-input"
})

// Free opt-in (pass quote from previous step)
canix_optin({
  address: "YOUR_ALGORAND_ADDRESS",
  quote: { /* quote data */ }
})

// Paid swap — preflight, then retry with paymentSignature
canix_swap({
  address: "YOUR_ALGORAND_ADDRESS",
  quote: { /* fresh quote data */ },
  slippage: 0.005
})
canix_swap({
  address: "YOUR_ALGORAND_ADDRESS",
  quote: { /* fresh quote data */ },
  slippage: 0.005,
  paymentSignature: "<base64-json-payload>"
})

Positions and execution quotes (paid tools)

// Positions
canix_get_positions({ address: "YOUR_ALGORAND_ADDRESS" })
canix_get_positions({
  address: "YOUR_ALGORAND_ADDRESS",
  paymentSignature: "<base64-json-payload>"
})

// Claim desk
canix_list_claimable({ address: "YOUR_ALGORAND_ADDRESS" })
canix_list_claimable({
  address: "YOUR_ALGORAND_ADDRESS",
  paymentSignature: "<base64-json-payload>"
})

// Eligibility
canix_check_eligibility({
  address: "YOUR_ALGORAND_ADDRESS",  // pragma: allowlist secret
  opportunityIds: ["reti-staking-12"]
})
canix_check_eligibility({
  address: "YOUR_ALGORAND_ADDRESS",  // pragma: allowlist secret
  opportunityIds: ["reti-staking-12"],
  paymentSignature: "<base64-json-payload>"
})

// Intent compiler (consume this instead of forking a local compiler)
canix_get_plan({
  address: "YOUR_ALGORAND_ADDRESS",  // pragma: allowlist secret
  budget: { assetId: 0, amount: "1000000" },
  constraints: { noNewBorrows: true, executionReadyOnly: true },
  opportunityIds: ["reti-staking-12"]
})
canix_get_plan({
  address: "YOUR_ALGORAND_ADDRESS",  // pragma: allowlist secret
  budget: { assetId: 0, amount: "1000000" },
  constraints: { noNewBorrows: true, executionReadyOnly: true },
  opportunityIds: ["reti-staking-12"],
  paymentSignature: "<base64-json-payload>"
})

// Swap-aware enter compose (hold asset A, enter this opportunity)
canix_compose_enter({
  address: "YOUR_ALGORAND_ADDRESS",  // pragma: allowlist secret
  opportunityId: "reti-staking-12",
  fromAssetId: 0,
  amount: "1000000",
  slippage: 1
})
canix_compose_enter({
  address: "YOUR_ALGORAND_ADDRESS",  // pragma: allowlist secret
  opportunityId: "reti-staking-12",
  fromAssetId: 0,
  amount: "1000000",
  slippage: 1,
  paymentSignature: "<base64-json-payload>"
})

// Simulate compiled groups (no signing)
canix_simulate_execution({
  address: "YOUR_ALGORAND_ADDRESS",  // pragma: allowlist secret
  groups: [{ shapeKey: "mainnet:reti:v1:stake:algo", encodedTransactions: ["<base64-unsigned-txn>"] }]
})
canix_simulate_execution({
  address: "YOUR_ALGORAND_ADDRESS",  // pragma: allowlist secret
  groups: [{ shapeKey: "mainnet:reti:v1:stake:algo", encodedTransactions: ["<base64-unsigned-txn>"] }],
  paymentSignature: "<base64-json-payload>"
})

// Policy-as-a-service (plan or quotes[] + operator policy)
canix_validate_policy({
  policy: {
    schemaVersion: "1.0.0",
    maxProtocolWeightBps: 4000,
    minAlgoReserveMicroAlgos: "1000000",
    minTvlUsd: 25000,
    maxSourceAgeSeconds: 86400,
    noNewBorrows: true,
    executionReadyOnly: true
  },
  quotes: [{
    shapeKey: "mainnet:reti:v1:stake:algo",
    protocol: "reti",
    opportunityId: "reti-staking-12",
    weightBps: 4000,
    allocatedAmount: "1000000",
    allocatedAssetId: 0,
    tvlUsd: 1000000,
    sourceTimestamp: "2026-08-28T11:00:00.000Z",
    executionReady: true
  }],
  walletAlgoMicroAlgos: "5000000"
})
canix_validate_policy({
  policy: { schemaVersion: "1.0.0", noNewBorrows: true, executionReadyOnly: true },
  quotes: [{ shapeKey: "mainnet:reti:v1:stake:algo", protocol: "reti", executionReady: true }],
  paymentSignature: "<base64-json-payload>"
})

// Execution quotes (batch)
canix_get_execution_quote({
  quotes: [{
    shapeKey: "mainnet:tinyman:v2:addLiquidity:flexible",
    input: {
      userAddress: "YOUR_ALGORAND_ADDRESS",
      assetAId: 0,
      assetAAmount: "1000000",
      assetBId: 31566704,
      assetBAmount: "1000000",
      maxSlippageBps: 50
    }
  }]
})
canix_get_execution_quote({
  quotes: [/* same body */],
  paymentSignature: "<base64-json-payload>"
})

Haystack Launch

canix_list_haystack_launches({
  q: "len",
  minProgress: 10,
  maxProgress: 90,
  order: "desc",
  limit: 25
})

canix_get_haystack_launch({ tokenNum: 175 })
canix_get_haystack_launch({
  assetId: 3729195158,
  address: "YOUR_ALGORAND_ADDRESS"
})

canix_get_execution_quote({
  quotes: [{
    shapeKey: "mainnet:haystack:v1:launch:token",
    input: {
      userAddress: "YOUR_ALGORAND_ADDRESS",
      symbol: "LENIN",
      name: "Lenin",
      assetUrl: "ipfs://bafkreiexample",
      bondingTokenId: 0
    }
  }]
})

canix_get_execution_quote({
  quotes: [{
    shapeKey: "mainnet:haystack:v1:buy:bonding",
    input: {
      userAddress: "YOUR_ALGORAND_ADDRESS",
      tokenNum: 175,
      fromAssetId: 0,
      amount: "1000000",
      slippageBps: 50
    }
  }]
})

Verify the deployment

curl -s https://canix402-mcp.compx.io/health | jq

curl -s https://canix402-mcp.compx.io/.well-known/mcp | jq

/.well-known/mcp should return transport: "streamable-http" and url pointing at https://canix402-mcp.compx.io/mcp.

Client setup

Point your MCP client at the remote endpoint. No local npm package or stdio process is required for production use.

Cursor / Claude Desktop (URL transport)

{
  "mcpServers": {
    "canix402": {
      "url": "https://canix402-mcp.compx.io/mcp"
    }
  }
}

See also the x402 page for payment context when using paid tools.

Paid tool flow

  1. Call a paid tool (e.g. canix_list_opportunities) without paymentSignature.
  2. The tool returns PAYMENT_REQUIRED metadata with gateway payment requirements (same x402 policy as direct HTTP). Select an accept by network. Algorand is first. Base is optional and the same price.
  3. Your agent builds a PAYMENT-SIGNATURE payload for that accept and retries the same tool with paymentSignature set. Algorand uses a signed ASA paymentGroup. Base uses an EIP-3009 authorization. A Base address is required only when you pay the Base accept or request a Morpho quote.
  4. On success, the tool returns the gateway response.

This mirrors the direct HTTP flow documented on x402 payment flow and Get started.

Available tools

Tool names match discovery mcpServer.tools.

A browser subset of these tools is also registered in-page on /webmcp via the WebMCP imperative API. Haystack Launch list and status stay on the remote MCP. The execution-quote tool on /webmcp can still compile the launch and bonding-buy shapes.

Free tools include health, metadata, discovery, OpenAPI, execution shapes, Haystack Launch status, swap quotes, and opt-ins. Paid tools include opportunities, positions, claimable rewards, the Haystack bonding list, execution quotes, and swap transactions.

MCP vs direct HTTP

Both paths hit the same public Caddy gateway for paid data. The MCP Worker is a thin pass-through and does not call a private upstream API.