place_order
Submit trading orders on the Interactive Brokers MCP Server by specifying account ID, symbol, action, order type, and quantity. Supports market, limit, and stop orders for efficient trade execution.
Instructions
Place a trading order
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| accountId | Yes | Account ID | |
| action | Yes | Order action | |
| orderType | Yes | Order type | |
| price | No | Limit price (required for LMT orders) | |
| quantity | Yes | Number of shares | |
| stopPrice | No | Stop price (required for STP orders) | |
| symbol | Yes | Trading symbol |
Implementation Reference
- src/tool-handlers.ts:404-442 (handler)Main tool handler for place_order: validates input, ensures auth/gateway ready, calls IBClient.placeOrder, returns formatted result or errorasync placeOrder(input: PlaceOrderInput): Promise<ToolHandlerResult> { try { // Ensure Gateway is ready await this.ensureGatewayReady(); // Ensure authentication in headless mode if (this.context.config.IB_HEADLESS_MODE) { await this.ensureAuth(); } const result = await this.context.ibClient.placeOrder({ accountId: input.accountId, symbol: input.symbol, action: input.action, orderType: input.orderType, quantity: input.quantity, // Already converted by Zod schema price: input.price, stopPrice: input.stopPrice, suppressConfirmations: input.suppressConfirmations, }); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: this.formatError(error), }, ], }; } }
- src/tool-definitions.ts:29-134 (schema)Zod schema and TypeScript type for place_order input validation, including shape, refinement for order types, and input type inferenceexport const PlaceOrderZodShape = { accountId: z.string(), symbol: z.string(), action: z.enum(["BUY", "SELL"]), orderType: z.enum(["MKT", "LMT", "STP"]), quantity: IntegerOrStringIntegerZod, price: z.number().optional(), stopPrice: z.number().optional(), suppressConfirmations: z.boolean().optional() }; export const GetOrderStatusZodShape = { orderId: z.string() }; export const GetLiveOrdersZodShape = { accountId: z.string().optional() }; export const ConfirmOrderZodShape = { replyId: z.string(), messageIds: z.array(z.string()) }; export const GetAlertsZodShape = { accountId: z.string() }; export const CreateAlertZodShape = { accountId: z.string(), alertRequest: z.object({ orderId: z.number().optional(), alertName: z.string(), alertMessage: z.string().optional(), alertRepeatable: z.number().optional(), expireTime: z.string().optional(), outsideRth: z.number().optional(), iTWSOrdersOnly: z.number().optional(), showPopup: z.number().optional(), toolId: z.number().optional(), playAudio: z.string().optional(), emailNotification: z.string().optional(), sendMessage: z.number().optional(), tif: z.string().optional(), logicBind: z.string().optional(), conditions: z.array(z.object({ conidex: z.string(), type: z.string(), operator: z.string(), triggerMethod: z.string(), value: z.string(), logicBind: z.string().optional(), timeZone: z.string().optional() })) }) }; export const ActivateAlertZodShape = { accountId: z.string(), alertId: z.string() }; export const DeleteAlertZodShape = { accountId: z.string(), alertId: z.string() }; // Flex Query Zod Shapes export const GetFlexQueryZodShape = { queryId: z.string(), queryName: z.string().optional(), // Optional friendly name for auto-saving parseXml: z.boolean().optional().default(true) }; export const ListFlexQueriesZodShape = { confirm: z.literal(true) }; export const ForgetFlexQueryZodShape = { queryId: z.string() }; // Full Zod Schemas (for validation if needed) export const AuthenticateZodSchema = z.object(AuthenticateZodShape); export const GetAccountInfoZodSchema = z.object(GetAccountInfoZodShape); export const GetPositionsZodSchema = z.object(GetPositionsZodShape); export const GetMarketDataZodSchema = z.object(GetMarketDataZodShape); export const PlaceOrderZodSchema = z.object(PlaceOrderZodShape).refine( (data) => { if (data.orderType === "LMT" && data.price === undefined) { return false; } if (data.orderType === "STP" && data.stopPrice === undefined) { return false; } return true; }, { message: "LMT orders require price, STP orders require stopPrice", path: ["price", "stopPrice"] } );
- src/tools.ts:74-83 (registration)MCP server.tool registration for 'place_order', with description, Zod shape schema, and handler callbackserver.tool( "place_order", "Place a trading order. Examples:\n" + "- Market buy: `{ \"accountId\":\"abc\",\"symbol\":\"AAPL\",\"action\":\"BUY\",\"orderType\":\"MKT\",\"quantity\":1 }`\n" + "- Limit sell: `{ \"accountId\":\"abc\",\"symbol\":\"AAPL\",\"action\":\"SELL\",\"orderType\":\"LMT\",\"quantity\":1,\"price\":185.5 }`\n" + "- Stop sell: `{ \"accountId\":\"abc\",\"symbol\":\"AAPL\",\"action\":\"SELL\",\"orderType\":\"STP\",\"quantity\":1,\"stopPrice\":180 }`\n" + "- Suppress confirmations: `{ \"accountId\":\"abc\",\"symbol\":\"AAPL\",\"action\":\"BUY\",\"orderType\":\"MKT\",\"quantity\":1,\"suppressConfirmations\":true }`", PlaceOrderZodShape, async (args) => await handlers.placeOrder(args) );
- src/ib-client.ts:391-459 (helper)Underlying IBClient.placeOrder method: resolves symbol to conid, builds order payload, submits to IB Gateway API, handles confirmations if suppressed, manages auth errorsasync placeOrder(orderRequest: OrderRequest): Promise<any> { try { // First, get the contract ID for the symbol const searchResponse = await this.client.get( `/iserver/secdef/search?symbol=${orderRequest.symbol}` ); if (!searchResponse.data || searchResponse.data.length === 0) { throw new Error(`Symbol ${orderRequest.symbol} not found`); } const contract = searchResponse.data[0]; const conid = contract.conid; // Prepare order object const order = { conid: Number(conid), // Ensure conid is number orderType: orderRequest.orderType, side: orderRequest.action, quantity: Number(orderRequest.quantity), // Ensure quantity is number tif: "DAY", // Time in force }; // Add price for limit orders if (orderRequest.orderType === "LMT" && orderRequest.price !== undefined) { (order as any).price = Number(orderRequest.price); } // Add stop price for stop orders if (orderRequest.orderType === "STP" && orderRequest.stopPrice !== undefined) { (order as any).auxPrice = Number(orderRequest.stopPrice); } // Place the order const response = await this.client.post( `/iserver/account/${orderRequest.accountId}/orders`, { orders: [order], } ); // Check if we received confirmation messages that need to be handled if (response.data && Array.isArray(response.data) && response.data.length > 0) { const firstResponse = response.data[0]; // Check if this is a confirmation message response if (firstResponse.id && firstResponse.message && firstResponse.messageIds && orderRequest.suppressConfirmations) { Logger.log("Order confirmation received, automatically confirming...", firstResponse); // Automatically confirm all messages const confirmResponse = await this.confirmOrder(firstResponse.id, firstResponse.messageIds); return confirmResponse; } } return response.data; } catch (error) { Logger.error("Failed to place order:", error); // Check if this is likely an authentication error if (this.isAuthenticationError(error)) { const authError = new Error("Authentication required to place orders. Please authenticate with Interactive Brokers first."); (authError as any).isAuthError = true; throw authError; } throw new Error("Failed to place order"); } }