Skip to main content

How to Connect Crush to NinjaTrader 8 with CrossTrade MCP

Crush is Charm's open-source coding agent with a clean TUI. JSON config, type: 'http' for remote MCP. No native OAuth, use a bearer token in headers.

OAuth scope: mcp:tradeMulti-model harness

Prerequisites

RequirementDetail
CrossTrade subscriptionElite
CrossTrade Add-Onv1.13.0 or higher
NinjaTrader 8Running, broker connected
AccountSim101 for first runs
OAuth scopemcp:trade
Install commandbrew install charmbracelet/tap/crush
Config file~/.config/crush/crush.json (global) or .crush.json / crush.json (project root)
CrossTrade MCP server
https://app.crosstrade.io/v1/api/mcp
Transport: streamable-http. Auth: OAuth 2.1 + PKCE. Request scope mcp:trade. Read plus write. Place/cancel orders, deploy strategies, compile NinjaScript.

Step 1: Install Crush

# Homebrew
brew install charmbracelet/tap/crush

# npm
npm install -g @charmland/crush

# Go
go install github.com/charmbracelet/crush@latest

# Windows (Winget)
winget install charmbracelet.crush

On first launch Crush prompts for an LLM provider API key, or you can pre-set env vars (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.).

Step 2: Add CrossTrade MCP

Edit ~/.config/crush/crush.json (or .crush.json / crush.json in your project root — checked in priority order):

{
"mcp": {
"crosstrade": {
"type": "http",
"url": "https://app.crosstrade.io/v1/api/mcp",
"timeout": 120,
"disabled": false,
"headers": {
"Authorization": "Bearer $CROSSTRADE_API_KEY"
}
}
}
}
Crush uses type: "http"

Crush's transport values are "stdio", "http", or "sse". Not "remote" (OpenCode) or "streamable_http" (Goose). Schema fields: type (required), url, headers, timeout, disabled, disabled_tools, enabled_tools, env.

Env var expansion: $VARNAME syntax in header values is supported.

Step 3: Get a bearer token

Crush doesn't have a native browser OAuth flow. To get a token:

  1. Authorize CrossTrade via Claude Code, Cursor, OpenCode, or any OAuth-capable client.
  2. Copy the issued token from your AI Clients page.
  3. export CROSSTRADE_API_KEY=... in your shell rc.

Step 4: First prompt

Confirm CrossTrade MCP. ListAccounts, GetConnections. One-line status per account.

FAQ

Why no OAuth?

Crush's MCP client is bearer-only as of this writing. Watch github.com/charmbracelet/crush for updates.

Schema autocomplete?

Crush doesn't auto-generate $schema references. Add "$schema": "https://charm.land/crush/schema.json" to the top of crush.json for IDE completion.

OAuth handshake

The first tool call surfaces an authorization URL. Open it in a browser, approve mcp:trade, and return to the harness. The access token is stored by the harness (keychain, config file, or memory depending on the client).

See CrossTrade MCP OAuth for the full flow, and 403/408 troubleshooting if the handshake fails.

Verify the connection

Smoke-test before doing anything stateful:

Call GetMcpCapabilities and McpSelfTest. Then ListAccounts and GetConnections.
Report add-on version, NT8 version, and which accounts are linked.

If you authorized mcp:trade, also confirm Sim101 is the default account before any order placement.

Funded-account safety
The mcp:trade scope grants order placement. The scope does not protect a funded account; your prompt and account selection do. Default to Sim101 during setup. For funded accounts, verify the firm's automation policy first.

Troubleshooting

SymptomLikely causeFix
403 insufficient_scopeToken authorized at mcp:read but tool requires mcp:tradeReauthorize the connection and select mcp:trade
OAuth callback failsSystem browser blocked the redirect or popupCopy the auth URL manually, complete it, paste the code back
Tools list is empty after connectServer registered but session did not refreshRestart the harness or trigger a tool list refresh
Add-on offline errorNT8 not running, or add-on not loadedConfirm NT8 is open and the CrossTrade add-on (v1.13.0+) is installed
type: "remote" rejectedCrush uses type: "http" (not "remote" like OpenCode, not "streamable_http" like Goose)Use type: "http"; valid values are "stdio", "http", "sse"
No OAuth flow startsCrush docs do not describe a native browser OAuth flowObtain a CrossTrade token via another client's OAuth flow and paste it in headers as a Bearer token