MCP tools & resources

25 tools in the tria_trade_* namespace plus 8 auto-context resources. Each tool's input schema is discoverable via the MCP tools/list request — the LLM sees the same shape you do.

Tools

CategoryTools
Orders (7)place_order, place_batch, cancel_order, cancel_all_orders, modify_order, order_status, open_orders
Positions (3)positions, close_position, attach_tpsl
Account (4)balances, margin_state, account, fills
Market data (5)markets, orderbook, candles, recent_trades, ticker
Risk (1)scheduled_cancel
Helpers (1)generate_client_order_id
Streams (4)start_stream, read_stream, stop_stream, list_streams

Each maps 1:1 onto a TriaClient method — see the SDK reference for argument shapes and venue behavior. place_order requires a clientOrderId (use generate_client_order_id for an HL-compatible 0x + 32-hex value); for market-style execution use tif: "ioc" with a crossing price.

Provisioning tools (gated)

ToolAuthorizationWhen registered
tria_trade_provision_inspectnone (read-only)always — survey setup state without master authority
tria_trade_provisionTRIA_TRADE_HL_MASTER_KEY at startuponly when the master key is present

The write tool is gated on purpose: a deployment where the operator hands a trading env to someone else never exposes master-wallet authority to the LLM. Most users skip both and use the npx tria-trade-provision CLI.

Resources (auto-context)

Read-only URIs that MCP clients auto-fetch into the LLM's context without spending a tool call:

URIReturns
tria://markets/{venue}MarketInfo[] — full market listing
tria://account/{venue}AccountSnapshot — balances + margin + leverage + builder + network
tria://positions/{venue}Position[] — open positions
tria://open-orders/{venue}OrderStatus[] — resting orders

{venue} is hl or decibel; the list is conditional on the venues you configured. No caching and no change-notifications in v1 — each read fetches live; for event-driven flow use streams.

Stream-handle protocol

MCP is request/response — there's no server-push channel for tools. The server keeps a per-handle event buffer the LLM drains at its own pace:

start_stream({ kind: "fills", venue: "hl" })
  → { handle_id: "stream_a1b2…", kind, venue, started_at }

read_stream({ handle_id, max_events: 50 })
  → { events: [...], more: true, last_seq: 123 }

stop_stream({ handle_id })
  → { stopped: true, events_seen: 123 }

Stream kind: fills, orders, account, positions. Defensive caps: 8 concurrent streams per process, a 1000-event ring buffer per handle (oldest dropped, surfaced as eventsDropped), and a 10-minute idle TTL that auto-stops a handle if read_stream isn't called. After a context compact, call list_streams() to re-discover open handles.

Common workflows

Real prompts that work end-to-end in Claude Desktop:

  • "What's BTC doing on HL right now?"ticker({venue:"hl", market:"BTC"}).
  • "Show my open positions across all venues" → reads the tria://positions/hl + tria://positions/decibel resources (no tool call).
  • "Place a $15 BTC long with TP +5% and SL −5%"tickermarkets (precision) → generate_client_order_idplace_order (crossing IOC) → attach_tpsl.
  • "Cancel all my orders on Decibel"cancel_all_orders({venue:"decibel"}).
  • "Watch for fills on HL for a minute"start_stream → wait → read_streamstop_stream → summarize.
  • "Close my BTC position and tell me the PnL"close_positionfills → agent computes PnL.

The agent's chain-of-thought is visible in the client UI — you can interrupt at any step.

Was this page helpful?