Skip to main content
Glama
code-rabi

Interactive Brokers MCP Server

by code-rabi

place_order

Execute buy or sell orders for stocks through Interactive Brokers trading accounts using market, limit, or stop order types.

Instructions

Place a trading order. Examples:

  • Market buy: { "accountId":"abc","symbol":"AAPL","action":"BUY","orderType":"MKT","quantity":1 }

  • Limit sell: { "accountId":"abc","symbol":"AAPL","action":"SELL","orderType":"LMT","quantity":1,"price":185.5 }

  • Stop sell: { "accountId":"abc","symbol":"AAPL","action":"SELL","orderType":"STP","quantity":1,"stopPrice":180 }

  • Suppress confirmations: { "accountId":"abc","symbol":"AAPL","action":"BUY","orderType":"MKT","quantity":1,"suppressConfirmations":true }

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
accountIdYes
symbolYes
actionYes
orderTypeYes
quantityYes
priceNo
stopPriceNo
suppressConfirmationsNo

Implementation Reference

  • Main MCP tool handler for place_order. Ensures prerequisites (gateway, auth) and delegates order placement to IBClient, returning 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 for place_order input validation, including refinements to ensure required fields for order types (price for LMT, stopPrice for STP).
    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 registration of the 'place_order' tool, including description, input shape, and handler reference.
    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)
    );
  • Low-level IBClient method that performs symbol lookup, constructs the order payload, submits to IB Gateway API, and handles confirmations if suppressed.
    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");
      }
    }
  • Base Zod shape definition for place_order input parameters, used in tool registration and schema.
    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()
    };

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