Hashpower MCP - agent instruction manual
How an agent harness (Cursor, Claude, a custom runtime, a cron bot) connects to Hashpower, scans the market, respects the guardrails, and trades. This server is not a trading API. The exchange is the contracts on Base plus the public subgraphs.
This copy is served from https://dev.hashpower.io and describes this environment (testnet / Base Sepolia, chain 84532). Client key: dev-hashpower. MCP URL: https://mcp.dev.hashpower.io/mcp.
HTML: /build/mcp/. Canonical git source: hashpower-mcp/docs/agent-manual.md.
1. What the MCP is for
Hashpower is a permissionless marketplace for Bitcoin hashprice risk: dated futures and a perpetual CLOB, priced by an on-chain hashprice oracle, collateralized in USDC, on Base.
Three layers an agent uses:
| Layer | Role | Holds keys? |
|---|---|---|
MCP (dev-hashpower / hashpower) |
Teach rules, scan the same surfaces as the trading UI, simulate fills and margin | No |
@hashpower/*-abi npm packages |
Encode deposit / withdraw / createOrder / cancelOrder calldata |
No |
| Operator wallet | Sign and broadcast. This is the only write path | Yes - on the operator's machine, never on ours |
The intended loop:
- Scan - MCP reads (or the agent reads subgraphs /
eth_callitself). - Decide - operator goals + market rules + live book/tape/oracle.
- Simulate -
simulate_orderandcheck_can_place_order(on-chain views). - Execute elsewhere - a local executor you run, with the private key only in that process: fund the EOA,
approve+depositintoCollateralVault, thencreateOrder/cancelOrder/ flatten /withdraw.
A production bot does not have to stay on MCP at runtime. Once the strategy is written, it can talk to chain and subgraphs directly. MCP is the research terminal and the on-ramp for a new harness.
2. Guardrails (hard rules)
Copy these into the harness system prompt. They are also the MCP server's own instructions.
- Never send a private key to the MCP server. It has no signing tools and must not gain any.
- Never ask the MCP to broadcast a transaction.
build_*_txreturns unsigned calldata only, and is a prototype - production code encodes via npm ABIs. - Wallet addresses are tool parameters, not login state. The hosted server is stateless (no MCP session, no sticky load balancer).
- Testnet vs mainnet are different venues. This site is
testnet: client keydev-hashpower->https://mcp.dev.hashpower.io/mcp. The other venue ishashpower->https://mcp.hashpower.io/mcp.initialize.serverInfo.namematches the venue you connected to. - Fund the wallet before trading: Base ETH for gas and USDC for collateral. Deposit USDC to
CollateralVaultfirst. One vault backs both futures and perps. - Call
PortfolioMarginEngine.canPlaceOrderbefore every order. MCP exposes this ascheck_can_place_order. Additional IM is USDC native units (6 decimals), integer string. - Subgraphs can lag the chain. Every market read reports
chainHeadvssubgraphHead(lagBlocks). Treat chain as source of truth for the live CLOB; treat the subgraph as the UI's tape, books'orderCount, and history. - Integer strings, no decimals, in tool arguments. Prices, quantities, amounts, and
expirationAtare decimal-integer strings (e.g."37680000"), never"37.68". - Signed quantity: positive = buy / long, negative = sell / short. Futures
createOrderalso needsexpirationAt(unix seconds). - Do not treat
build_*_txas a production order router. If you execute, you (or your local bot) import@hashpower/perps-abi,@hashpower/futures-abi,@hashpower/collateral-abiand sign yourself.
There is no API key, no staking gate on the MCP, and no hosted order router. Anyone who can sign a Base transaction can trade, with or without our MCP.
3. Names and URLs
This environment (what you should connect to from this site): dev-hashpower -> https://mcp.dev.hashpower.io/mcp (HASHPOWER_ENV=testnet, Base Sepolia 84532).
| Testnet | Mainnet | |
|---|---|---|
| MCP client key | dev-hashpower |
hashpower |
| Hosted URL | https://mcp.dev.hashpower.io/mcp |
https://mcp.hashpower.io/mcp |
Docs / llms.txt |
https://dev.hashpower.io |
https://hashpower.io |
| Chain | Base Sepolia (84532) |
Base (8453) |
HASHPOWER_ENV |
testnet |
mainnet |
| Health | https://mcp.dev.hashpower.io/health |
https://mcp.hashpower.io/health |
npm package for local stdio: @hashpower/mcp. Same image; env flips the deployments it loads.
4. Set up any agent harness
4.1 Hosted Streamable HTTP (usual path)
The hosted server speaks MCP Streamable HTTP, JSON responses, no session. Point the client at this site's MCP URL.
Cursor (~/.cursor/mcp.json or a project .cursor/mcp.json):
{
"mcpServers": {
"dev-hashpower": {
"url": "https://mcp.dev.hashpower.io/mcp"
}
}
}
Reload MCP tools after connecting. You should see get_market_snapshot, get_orderbook, simulate_order, and the rest - not a 12-tool subset from an older image.
Any other harness that supports Streamable HTTP: same URL. Typical JSON-RPC:
curl -sS -X POST https://mcp.dev.hashpower.io/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-harness","version":"0.0.0"}}}'
Then tools/list and tools/call with { "name": "<tool>", "arguments": { ... } }. No Mcp-Session-Id required.
Sanity check: GET https://mcp.dev.hashpower.io/health returns "ok": true and "name": "dev-hashpower".
4.2 Local stdio (your RPC, still no keys in the server)
{
"mcpServers": {
"dev-hashpower": {
"command": "npx",
"args": ["-y", "@hashpower/mcp"],
"env": {
"HASHPOWER_ENV": "testnet"
}
}
}
}
Optional env: HASHPOWER_RPC_URL (defaults to https://sepolia.base.org), HASHPOWER_DOCS_URL (defaults to https://dev.hashpower.io).
Stdio is for the MCP process. It still does not sign. Put keys only in a separate executor you run.
4.3 There is no "connect wallet" on MCP
Hashpower does not have accounts, API keys, or an MCP login. The EOA that signs is the account.
| What people call "connect" | What it actually is |
|---|---|
| Pointing Cursor at MCP | Research terminal only. No wallet, no session. |
| WalletConnect on the trading UI | Human blotter. Same address as the bot, so you can watch fills. Not required for trading. |
| Local executor with a private key | The write path. Load the key from env / KMS / hardware on that host. Sign approve, deposit, createOrder, cancelOrder, withdraw. |
Do not paste a private key into chat, MCP tool arguments, or hosted config. Give it only to the process you run.
4.4 Fund the EOA and deposit liquidity
A bot that "does everything" still cannot mint ETH or USDC. The operator funds the EOA first; the executor then moves USDC into the vault.
- Put Base ETH (gas) and USDC (6 decimals) on the EOA for
Base Sepolia. There is no Hashpower faucet. - Resolve addresses once (
get_deploymentsordeployments.json):CollateralToken(USDC),CollateralVault,HashPowerPerpsDEX,HashPowerFutures/Futures,PortfolioMarginEngine. - Approve the vault to spend USDC, then deposit:
USDC.approve(CollateralVault, amount)thenCollateralVault.deposit(amount)(two txs), orCollateralVault.depositForPermit(...)if the token supports EIP-2612 (one tx).
- Amounts are USDC 6-decimal integer strings (
"1000000"= $1).depositcredits a receipt balance that both futures and perps share. You do not deposit per venue. - Confirm with MCP
get_margin_status(wallet)(balance,initialMargin,maintenanceMargin,excessOverIM,isHealthy) orCollateralVault.balanceOf(wallet)on chain.
Until step 3 lands, check_can_place_order will fail for a funded-but-not-deposited wallet (USDC in the EOA is not margin until it is in the vault).
Full semantics: collateral-and-accounts or MCP get_market_rules with slug collateral-and-accounts.
5. Operating loop
Give the model goals in the user prompt (risk, venue, size cap, "recommend only" vs "you may send from my local signer"). Then the agent should:
get_deploymentsonce if it needs addresses / ABI package versions (optional if it will only scan).get_market_snapshot- one-shot UI scan: hashprice, perps book+tape+funding, futures expiries+nearest book, stats, 24h candles.- Pull semantics as needed:
get_market_rules(omit slug for the catalog),get_units_and_scaling,get_margin_model. - If a wallet is in play:
get_margin_statusandget_positions. Ifbalanceis"0"and the EOA holds USDC, the executor still needs the approve+deposit in section 4.4. - Form a concrete order: venue, price, signed quantity, TIF (
GTC/IOC/FOK),expirationAtfor futures. simulate_order- would it fill, at what average, remainder? Does not place.check_can_place_orderwith a conservativeadditionalImin USDC 6-decimal integer units.- Recommend the calldata and intent to the operator, or (only in a local executor that already has a key) encode and send. Stop if the operator said not to trade.
Starter prompts:
- Scan the Hashpower market like the trading UI and summarize hashprice, perps book, tape, funding, and the nearest futures expiry - do not trade.
- Using my goals (hedge 1 PH/s-day of hashprice for the front month, max 50 bps from mid, GTC), propose a futures order. Simulate it. Do not send.
- Wallet 0x... is the bot. Check margin and open orders. If the vault is empty, list the approve+deposit txs. Recommend whether we can add a small perps bid at best bid. Do not send.
- I run a local executor with the key in env (never send the key here). From wallet 0x..., deposit if needed, then trade perps and the front-month future within my limits, and flatten + withdraw free collateral if the book moves against the plan.
6. Tool catalog
Knowledge (docs, not chain)
| Tool | Use when |
|---|---|
get_deployments |
Addresses, subgraph URLs, chain ID, @hashpower/*-abi versions |
get_market_rules |
Optional slug (e.g. perps-trading, futures-margin). Omit to list the catalog from /semantics |
get_margin_model |
IM / MM / liquidation prose for both venues |
get_units_and_scaling |
Oracle decimals, ticks, QUANTITY_DECIMALS |
Read (UI-equivalent market data)
| Tool | Use when |
|---|---|
get_market_snapshot |
First look at the market. Optional maxLevels, trades, expirationAt |
get_hashprice |
pair: usd (trading index) or btc |
get_orderbook |
Depth with price + size + orderCount. venue perps or futures; futures requires expirationAt |
get_trades |
Public tape. Optional wallet filter. Each match appears twice (one row per side) |
get_funding |
Perps funding strip. Optional wallet adds on-chain getPendingFunding |
get_expirations |
Futures market selector + settlement overlay |
get_market_stats |
Fees, ticks, volume, getMarketPrice |
get_oracle_history |
Chart data: hashpriceUsd, hashpriceBtc, btcUsd, networkHashrate1d, networkHashrate7d; tick, hour, or day |
get_positions |
Open orders + sessions for a wallet. Order id is the on-chain bytes32 for cancelOrder |
get_margin_status |
Vault balance, portfolio IM/MM, excessOverIM, isHealthy |
Simulate
| Tool | Use when |
|---|---|
simulate_order |
venue, price, signed quantity; expirationAt required for futures |
check_can_place_order |
wallet, additionalIm (USDC 6-dec integer string) |
Scaffold (prototype only)
| Tool | Use when |
|---|---|
build_deposit_tx |
Learning the approve+deposit sequence. Do not treat as a production deposit API |
build_order_tx |
Learning createOrder encoding. Production bots encode via npm |
There is no build_withdraw_tx / build_cancel_tx on MCP. Encode those locally (section 8).
7. Units (so the agent does not invent decimals)
Always pass integer strings into tools. Scale for display yourself.
| Quantity | Scale | Example |
|---|---|---|
| CLOB price (both venues) | USDC 6 decimals; minimumPriceIncrement is typically 10000 ($0.01) |
"37680000" = $37.68 |
| Perps size | 6 decimals (QUANTITY_DECIMALS) |
"4024333" = 4.024333 |
| Futures size | Whole contracts (QUANTITY_DECIMALS = 0) |
"16" = 16 contracts |
| HashpriceUSD oracle | 8 decimals (latestRoundData().answer) |
"3766413350" = $37.66413350 |
| HashpriceBTC oracle | 16 decimals | see get_hashprice pair=btc |
Vault / additionalIm |
USDC 6 decimals | "1000000" = $1 |
Futures expirationAt |
Unix seconds | from get_expirations |
| Oracle subgraph timestamps | Goldsky microseconds (tools also return timestampUnix) |
n/a |
Perps fundingRate |
1e18-scaled; UI percent is about (rate / 1e18) * 100 |
may be 0 if funding is idle |
get_orderbook already returns bestBid / bestAsk / spread / mid / depths plus per-level quantity and orderCount.
8. Local execution bot (outside this server)
Split the work:
- Research - hosted MCP (or your own RPC + subgraphs). No keys.
- Execute - a process only you run. Private key in env, KMS, or hardware on that host.
That executor can cover the full life cycle: deposit liquidity, trade perps and futures, cancel, flatten when the market moves, withdraw free collateral. Hosted MCP never sees the key and never sends the txs.
Write-path (viem + the npm packages; this environment is testnet):
import { createWalletClient, createPublicClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { baseSepolia } from "viem/chains";
import { HashPowerPerpsDEXAbi } from "@hashpower/perps-abi";
import { CollateralVaultAbi } from "@hashpower/collateral-abi";
import { ERC20Abi, HashPowerFuturesAbi } from "@hashpower/futures-abi";
// account = privateKeyToAccount(process.env.EXECUTOR_PRIVATE_KEY) // local only
// addresses: @hashpower/*/deployments.json -> environments.testnet.contracts
// TIF: 0 = GTC, 1 = IOC, 2 = FOK
// Fund (operator, once): native ETH + USDC on the EOA
// USDC.approve(vault, amount)
// vault.deposit(amount) // or vault.depositForPermit(...)
// perps.createOrder(price, quantity, tif)
// futures.createOrder(price, expirationAt, quantity, tif)
// perps.cancelOrder(orderId) / futures.cancelOrder(orderId) // bytes32 from get_positions
// flatten: createOrder with the opposite signed quantity (and expirationAt on futures)
// vault.withdraw(amount) // reverts if it would breach portfolio MM
Exit when markets change:
get_positions(wallet)- cancel each resting order (cancelOrderwith thatid).- For each open session,
simulate_orderan opposite signed quantity, thencreateOrderto flatten (IOC/FOK if you must not rest). get_margin_status-excessOverIMis a hint;withdrawis still gated on chain. You cannot pull collateral that backs remaining exposure.- Optional: disconnect nothing. There is no session to close. Stop the executor.
Rules for that process:
- Private key stays in env / KMS / hardware on that host. Never in MCP tool arguments, never in chat logs you do not control.
- Re-run
simulateOrderandcanPlaceOrderimmediately before send; the book moves. - Match
HASHPOWER_ENV=testnetandenvironments.testnetindeployments.json. Do not point atestnetbot atmainnetaddresses. - Same wallet in the UI is your live blotter.
Addresses and subgraph URLs: MCP get_deployments, or https://dev.hashpower.io/deployments.json, or each package's deployments.json.
Market-rule prose (units, margin, settlement): https://dev.hashpower.io/semantics/index.json or MCP get_market_rules.
9. What this is not
- Not a wallet manager, custody service, or keystore
- Not a hosted order router or matching engine
- Not an API-key product
- Not in the runtime path of a production bot (optional at research time only)
- Not a substitute for reading
/semanticsbefore sizing risk
If a harness cannot speak MCP, skip the server: read llms.txt, import the npm ABIs, query subgraphs, eth_call the same view functions the MCP wraps. The exchange does not require our MCP.