Cursor is an AI code editor with an MCP client built in: you describe servers in a small JSON file, and the agent in the editor discovers their tools (Cursor MCP docs, retrieved 2026-07-10). That changes what connecting it to NinjaTrader 8 means. You are not wiring a chat window to a trading platform. You are giving the agent that already sits inside your trading project typed tools against the platform, while you build that project. The safe way to do it is the same as for any agent runtime: a local bridge that speaks MCP on one side and NinjaTrader on the other, with a deterministic guardrail engine in between. This is the Cursor-specific registration, and the dev loop it opens.
What sits between Cursor and NinjaTrader 8
Three things make the connection, and only the middle one is Cursor-specific. NinjaTrader 8 runs as usual, with its own accounts and data. The PitBridge daemon runs locally and is the one process that both speaks MCP to Cursor and carries orders into NinjaTrader through a small C# AddOn. Between them sits a guardrail engine that checks every order. The daemon, the AddOn, the guardrail engine, and why the whole order path stays on your machine are the shared subject of how to connect an AI agent to NinjaTrader 8. This piece assumes that background and stays on the Cursor wiring and the workflow; if the agent you trade with lives in Claude or Hermes instead, the registration is the only part that changes.
Example decisions: ALLOW buy 2 MES, all rules pass. BLOCK buy 10 MES, size 10 exceeds max_contracts_per_order 2.
The order route: the agent proposes, the guardrail engine adjudicates, and only an allowed order reaches NinjaTrader 8. The block is shown as plainly as the allow.
Register the bridge in .cursor/mcp.json
Cursor reads MCP servers from mcp.json under an mcpServers key, in two places: .cursor/mcp.json in a project for project-specific servers, and ~/.cursor/mcp.json in your home directory for servers available everywhere (Cursor MCP docs, retrieved 2026-07-10). For a trading project the project file is the interesting one. The bridge registration lives in the repo next to the code that uses it, so checking out the project brings its tools along. A stdio entry gives Cursor a command to launch as a subprocess, spoken to over standard input and output.
{
"mcpServers": {
"pitbridge": {
"type": "stdio",
"command": "uvx",
"args": ["pitbridge", "mcp"]
}
}
}The stdio server in a project-scoped .cursor/mcp.json. The mcpServers key, the type field, and both file locations are from the Cursor MCP docs, retrieved 2026-07-10. For a custom daemon config, extend args with --config and the path to your config.toml.
Cursor can also install and manage servers from its Customize page in the editor (Cursor MCP docs, retrieved 2026-07-10); the JSON file is the form that goes into version control, so it is the one this guide uses.
Or point Cursor at the running daemon over HTTP
If you would rather run the daemon once and share it across editor windows, terminal sessions, and your own scripts, start it and register the local endpoint as a remote server. Cursor supports remote MCP servers over SSE and streamable HTTP, configured with a url and optional headers (Cursor MCP docs, retrieved 2026-07-10).
$ uvx pitbridge run # daemon up on 127.0.0.1:8873 # REST at /v1/*, WebSocket at /v1/ws, MCP over HTTP at /mcp
{
"mcpServers": {
"pitbridge": {
"url": "http://127.0.0.1:8873/mcp"
}
}
}The same bridge as a remote server. Streamable HTTP MCP has been served next to stdio since 0.2.0. On a localhost bind the agent token is optional; to require auth, set agent_token in the daemon config and send it from this entry’s headers field, which Cursor supports for remote servers. Source: Cursor MCP docs, retrieved 2026-07-10.
Both forms reach the same nine tools, the same guardrail pipeline, and the same audit log, so the choice is operational, not functional. Pick stdio when the editor should own the process; pick HTTP when a standing daemon is more convenient.
The dev loop this opens
This is where Cursor differs from a chat runtime. You are in an IDE because you are building something: a strategy script against the REST route, a backtest harness, your own agent. The bridge gives the in-editor agent a way to exercise all of it against paper while you write it.
It starts with zero setup. With no config at all, uvx pitbridge mcp boots a safe paper demo sandbox: a fake account, every guardrail on, live locked. Ask the agent to call get_accounts and get_guardrail_status and you have a working loop before you have configured anything.
$ uvx pitbridge mcp # no config found: booting a safe paper DEMO sandbox. # fake account, all 12 guardrails on, live locked. # your agent can now call get_accounts and get_guardrail_status.
The demo needs no NinjaTrader install and cannot place a real order. It exists so the agent in your editor can see the tools and the guardrail engine before setup.
Then the loop gets specific. Ask the agent to place a paper order and read the structured result. Have it break a limit on purpose and explain the reason code that comes back: a block returns as a typed result rather than an exception, so guardrail behavior is something you develop against instead of a crash you debug. If your project drives the daemon from Python, the same daemon serves REST at /v1/*, so your script and the agent helping you write it hit the same pipeline and the same limits. The loop also survives leaving the editor: the Cursor CLI reads the same MCP configuration as the editor (Cursor CLI MCP docs, retrieved 2026-07-10).
The nine tools the agent gets
Once registered, the agent sees exactly nine tools: five that read state and four that act. The reads never change anything. The four actions place, cancel, close, and flatten, and every place_order still passes the guardrail engine. What each tool returns, and the place_order fields (account, instrument, side, qty), are laid out in what a trading MCP server does.
reads5
get_accountsget_positionsget_ordersget_account_stateget_guardrail_status
Return state. They never change anything.
writes4
place_ordercancel_orderclose_positionflatten_account
Request a change. Every place_order still passes the guardrail engine.
There is deliberately no tool to release the kill switch, arm live trading, or change a threshold. Those live on an operator-only CLI the model never touches. The kill switch in particular carries the whole design on its back, and it has its own deep dive: what an AI trading kill switch must actually guarantee.
Your repo is untrusted input
An IDE agent does not only read your prompts. It reads the files you open, the files it searches, README text, comments, sample data, whatever a dependency shipped. Untrusted text is not an edge case in an editor, it is the working medium, and prompt injection through repository content is a known class of attack against coding agents. You cannot patch that with instructions, because instructions are exactly what injected text competes with.
So the design assumes the session can be steered. Every order the Cursor agent proposes, over stdio or HTTP, lands in a deterministic guardrail engine in a separate process, checked against limits from a config file the agent has no tool to edit. The same order and the same config always produce the same decision. Why a prompt is advice and an out-of-process check is a control is the whole subject of risk controls an LLM cannot override, and the guardrails page lists exactly what the engine refuses.
See a block, on purpose
The moment that proves the setup is a refused order. With a per-order cap configured, ask the agent to read the account, buy two contracts, then buy ten. The first fills in paper; the second breaks the cap, and the engine refuses it before NinjaTrader sees anything.
get_account_state -> link_up: true, day_pnl: 0.0 place_order account=sim instrument="MES 09-26" side=BUY qty=2 -> SUBMITTED, then FILLED filled_qty=2 place_order account=sim instrument="MES 09-26" side=BUY qty=10 -> BLOCKED reason_code=MAX_CONTRACTS_PER_ORDER
Example Cursor tool calls against the local daemon. Real tool names and reason code. Fills are synthetic simulation fills, not live results. The block returns as a structured result the agent can read and explain.
A refused order is the system doing its job, not an error to hide. The whole decision, allow or block, is written to an append-only, hash-chained audit log, so pitbridge audit why <order_id> explains any single order after the fact and pitbridge audit verify proves the log has not been edited.
Honest status: paper by default, live gated
Everything above runs against a paper or simulation account. In the open core mode = "live" is intentionally out of reach: arm-live refuses, because live execution ships separately as a paid, closed component, and there is no MCP tool or REST route to change that. Live execution has been in production on a funded futures account since 30 July 2026, behind an operator-run arm step. For a developer that is the point: you can build the whole workflow in Cursor, exercise every reason code, on a Mac with a fake AddOn, before any real money is in scope.
Connecting Cursor to NinjaTrader 8 the safe way is not about trusting a well-behaved model. It is about making it impossible for the model to leave the limits you set. The NinjaTrader 8 MCP bridge is the front door, the quickstart has the per-runtime setup, and the guardrails page lists exactly what the engine refuses. If a local, guardrailed bridge from Cursor to NinjaTrader is what you want, tell us your platform on the waitlist. PitBridge is trading infrastructure, not financial advice: it enforces the limits you configure and does not promise any trading outcome. Futures trading carries a substantial risk of loss.