Skip to main content
Glama
code-rabi

Interactive Brokers MCP Server

by code-rabi

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
NameRequiredDescriptionDefault
accountIdYesAccount ID
actionYesOrder action
orderTypeYesOrder type
priceNoLimit price (required for LMT orders)
quantityYesNumber of shares
stopPriceNoStop price (required for STP orders)
symbolYesTrading symbol

Implementation Reference

  • Main tool handler for place_order: validates input, ensures auth/gateway ready, calls IBClient.placeOrder, returns formatted result or error
    async 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), }, ], }; } }
  • Zod schema and TypeScript type for place_order input validation, including shape, refinement for order types, and input type inference
    export 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 callback
    server.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) );
  • Underlying IBClient.placeOrder method: resolves symbol to conid, builds order payload, submits to IB Gateway API, handles confirmations if suppressed, manages auth errors
    async 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"); } }

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/code-rabi/interactive-brokers-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server