Skip to main content

How to Connect LibreChat to NinjaTrader 8 with CrossTrade MCP

LibreChat is a self-hosted MIT-licensed ChatGPT-style frontend that supports multiple providers and MCP. Strongest multi-user MCP story: each user gets their own OAuth session per server, so trading accounts stay isolated. Native OAuth 2.1 + PKCE + Dynamic Client Registration.

OAuth scope: mcp:readMulti-model harness

Prerequisites

RequirementDetail
CrossTrade subscriptionElite
CrossTrade Add-Onv1.13.0 or higher
NinjaTrader 8Running, broker connected
AccountSim101 for first runs
OAuth scopemcp:read
Config filelibrechat.yaml (in your LibreChat deployment root)
CrossTrade MCP server
https://app.crosstrade.io/v1/api/mcp
Transport: streamable-http. Auth: OAuth 2.1 + PKCE. Request scope mcp:read. Read-only. Inspect accounts, orders, positions, journal, NinjaScript.

Step 1: Deploy LibreChat

git clone https://github.com/danny-avila/LibreChat
cd LibreChat
cp .env.example .env
docker compose up -d

Or follow www.librechat.ai/docs for k8s / standalone deploys.

Step 2: Add CrossTrade to librechat.yaml

mcpServers:
crosstrade:
type: streamable-http
url: https://app.crosstrade.io/v1/api/mcp
headers:
Authorization: "Bearer ${API_TOKEN}"
X-User-ID: "{{LIBRECHAT_USER_ID}}"
timeout: 30000
serverInstructions: true

Restart LibreChat. The MCP server appears in the model's tool list.

Per-user variables

LibreChat supports ${ENV_VAR} env interpolation AND {{LIBRECHAT_USER_ID}} / {{LIBRECHAT_USER_EMAIL}} user-context placeholders. This means each user's tool calls can carry their own identity to the upstream server.

You can also add MCP servers via the UI now (no restart required), but UI-added servers can only resolve customUserVars placeholders — env vars and OIDC tokens are restricted to the YAML path.

Step 3: OAuth (per-user)

On first chat, each LibreChat user is prompted to authenticate with CrossTrade via OAuth. Browser opens, sign in, return. Tokens are stored per user, per server.

The callback URL pattern is ${baseUrl}/api/mcp/${serverName}/oauth/callback — CrossTrade's OAuth flow supports Dynamic Client Registration, so no pre-registration needed.

Step 4: First chat

Sign in to your LibreChat. Pick a model. Send:

Confirm CrossTrade MCP. ListAccounts and summarize open positions. Read-only.

Multi-user note

This is the cleanest multi-user MCP story among self-hosted options:

FrontendMCP credential scope
LibreChatPer-user (each user has their own OAuth grant per server)
Open WebUIPer-connection at admin level (all users share)
AnythingLLMGlobal (all users share)

For team trading workflows where each trader should authenticate against their own CrossTrade account, LibreChat is the right choice.

FAQ

Free?

Yes, MIT-licensed.

Which transports?

streamable-http (recommended for production), sse (remote, legacy), stdio (local single-user only).

OAuth handshake

The first tool call surfaces an authorization URL. Open it in a browser, approve mcp:read, 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.
Read-only scope
You authorized mcp:read. The agent can inspect state but cannot place orders, deploy strategies, or write NinjaScript files.

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
YAML changes don't take effectlibrechat.yaml edits require a restartdocker compose restart api (or restart your LibreChat process)
SSE/streamable connections dropReverse-proxy timeouts (nginx/traefik default ~60s)Bump proxy timeouts to 300s+ for /api/mcp routes
startup hangs waiting on user credentialsOAuth flow needs each user to authenticate firstAdd startup: false on the server entry so LibreChat doesn't block waiting