Developer Guide
This guide is the shortest path for developers who want to use or extend
ibkr-agent-gateway.
Install and Run
From this checkout:
cargo run --bin ibkr-agent -- health --json
cargo run --bin ibkr-agent -- accounts list --json
Install the CLI locally:
cargo install --path .
ibkr-agent health --json
Embed the library from another local Rust project:
cargo add ibkr-agent-gateway --path /path/to/ibkr-agent-gateway
use ibkr_agent_gateway::prelude::*;
#[tokio::main]
async fn main() -> Result<(), GatewayError> {
let gateway = Gateway::new(GatewayConfig::fake_local())?;
let accounts = gateway.list_accounts().await?;
println!("visible_accounts={}", accounts.len());
Ok(())
}
Backend Modes
Use GatewayConfig::fake_local() while developing. It reads deterministic
fixtures from tests/fixtures/cpapi/ and needs no broker session.
Use GatewayConfig::client_portal(url) only when the Interactive Brokers
Client Portal Gateway is already running and manually authenticated outside this
project. TLS verification can be disabled only for localhost URLs.
For production-like deployments, read
production-readiness.md. The CLI runner defaults to
fake fixtures only when --config is omitted. A real broker CLI run should pass
an explicit YAML config, such as config/local.example.yaml, and supply the
configured audit HMAC secret through the environment.
CLI Surface
Read and session inspection:
ibkr-agent backend status --json
ibkr-agent session requirements --json
ibkr-agent account summary --account DU1234567 --json
ibkr-agent portfolio snapshot --account DU1234567 --json
ibkr-agent positions list --account DU1234567 --json
ibkr-agent market snapshot --contract-id 265598 --json
ibkr-agent executions list --account DU1234567 --json
Order preview is non-executable and must be explicitly enabled:
ibkr-agent orders preview \
--account DU1234567 \
--symbol AAPL \
--side buy \
--quantity 1 \
--limit-price 100 \
--currency USD \
--enable-preview \
--json
Paper submit/cancel commands require explicit paper enablement and an
idempotency key. Submit also requires the approval id returned by
approvals create:
ibkr-agent approvals create --account DU1234567 --preview-id <preview_id> --ttl-seconds 300 --json
ibkr-agent orders submit --account DU1234567 --approval-id <approval_id> --idempotency-key paper-submit-001 --enable-paper --json
ibkr-agent orders cancel --account DU1234567 --broker-order-id paper-order-local --idempotency-key paper-cancel-001 --enable-paper --json
CLI live submit and cancel run the full gate stack and then call a
LiveOrderWriter. The CLI defaults to LocalCandidateLiveWriter, so the
broker order id is a deterministic local-candidate-* value. Use
--live-broker client-portal with a Client Portal Gateway config to call
ClientPortalLiveWriter from the CLI; --live-broker refusing is available
for fail-closed checks. Production deployments can also inject their own
writer through the SDK boundary (see docs/production-readiness.md):
ibkr-agent orders live-submit \
--account DU1234567 \
--approval-id <approval_id> \
--idempotency-key live-submit-001 \
--enable-live \
--live-scope \
--open-kill-switch \
--acknowledge-paper-to-live \
--live-broker local-candidate \
--json
Audit review:
ibkr-agent audit tail --limit 20 --json
ibkr-agent audit export --limit 500 --json
ibkr-agent audit verify --json
MCP
Local stdio MCP:
ibkr-agent mcp serve --transport stdio --describe --json
ibkr-agent mcp serve --transport stdio --json
--describe exits after a smoke-check description. Without it, the command
runs the stdio JSON-RPC loop, advertises only tools enabled by local scopes, and
audits every tool call.
Remote HTTP MCP is disabled by default. Enabling it requires complete
remote MCP runtime config, an OAuth/OIDC issuer, RS256/RSA JWKS validation, a
token-id HMAC secret, accepted audiences, allowed scopes, and the independent
safety flag. In CLI YAML, that safety flag is safety.remote_mcp_enabled; the
SDK-facing GatewayConfiguration field is safety.remote_public_mcp_enabled.
ibkr-agent --config config/remote.example.yaml mcp serve --transport http --enable-remote-mcp --bind 127.0.0.1:8080
The HTTP listener serves protected-resource metadata and routes authorized
JSON-RPC requests on POST /mcp. See
remote-mcp-oauth.md.
Example client configs live under examples/mcp-clients/.
Validation
Run these before changing package behavior:
cargo fmt --check
cargo clippy --workspace --all-targets --features unstable-internal-test-support -- -D warnings
cargo test --workspace --features unstable-internal-test-support
cargo test --workspace --features unstable-internal-test-support secret
Run packaging checks before release work:
cargo package --allow-dirty --no-verify --list
cargo publish --dry-run --locked
Safety Rules for Contributors
- Do not return broker cookies, bearer tokens, credentials, raw headers, local paths, or raw session material from any CLI, MCP, log, fixture, or audit path.
- Keep broker logic provider-neutral; provider-specific behavior belongs in compatibility examples and tests.
- Keep write-capable flows fail-closed unless explicit config, scope, approval, idempotency, audit, and risk gates are satisfied.
- Preserve the public facade boundary in
src/public/*andsrc/lib.rs; keep implementation details undersrc/internal/*.