Skip to main content
Glama

place_order

Submit market or limit orders to Alpaca paper trading for buying or selling stocks using specified symbols, quantities, and order types.

Instructions

Submits a market or limit order to Alpaca paper trading.

Args:
    symbol: Ticker symbol.
    side: 'buy' or 'sell'.
    qty: Quantity to trade.
    order_type: 'market' or 'limit'.
    limit_price: Required if order_type is 'limit'.
    
Returns:
    Confirmation message or error

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
symbolYes
sideYes
qtyYes
order_typeNomarket
limit_priceNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • Core handler function for the 'place_order' tool. Implements order submission to Alpaca (market/limit), pre-trade risk validation via validate_trade, price fetching via yfinance, logging, and detailed success/error responses.
    def place_order(
        symbol: str, 
        side: Literal["buy", "sell"], 
        qty: float, 
        order_type: Literal["market", "limit"] = "market", 
        limit_price: Optional[float] = None
    ) -> str:
        """
        Submits a market or limit order to Alpaca paper trading.
        
        Args:
            symbol: Ticker symbol.
            side: 'buy' or 'sell'.
            qty: Quantity to trade.
            order_type: 'market' or 'limit'.
            limit_price: Required if order_type is 'limit'.
            
        Returns:
            Confirmation message or error
        """
        if broker is None:
            return "ERROR: Alpaca broker not initialized. Check your API credentials in .env file."
        
        # Import here to avoid circular dependency
        from tools.risk_engine import validate_trade
        
        try:
            # Get current price for risk validation
            ticker = yf.Ticker(symbol)
            try:
                current_price = ticker.fast_info.last_price
            except:
                return f"Failed to get price for {symbol}"
            
            if current_price is None:
                return f"Failed to get price for {symbol}"
            
            # Pre-Trade Risk Check
            risk_error = validate_trade(symbol, side, qty, current_price)
            if risk_error:
                logger.warning(f"Trade rejected by risk engine: {risk_error}")
                return risk_error
            
            # Submit order to Alpaca
            if order_type == "market":
                logger.info(f"Submitting MARKET order: {side.upper()} {qty} {symbol}")
                order_result = broker.submit_market_order(symbol, side, qty)
                logger.info(f"Order submitted successfully: ID={order_result['order_id']}")
                return (
                    f"✅ Market Order Submitted: {side.upper()} {qty} {symbol}\n"
                    f"Order ID: {order_result['order_id']}\n"
                    f"Status: {order_result['status']}\n"
                    f"Submitted at: {order_result['submitted_at']}"
                )
            
            elif order_type == "limit":
                if not limit_price:
                    return "ERROR: Limit price required for limit orders."
                
                # Validate limit price direction
                if side == "buy" and limit_price > current_price:
                    logger.warning(f"Buy limit {limit_price} is above market {current_price}")
                if side == "sell" and limit_price < current_price:
                    logger.warning(f"Sell limit {limit_price} is below market {current_price}")
                
                logger.info(f"Submitting LIMIT order: {side.upper()} {qty} {symbol} @ ${limit_price}")
                order_result = broker.submit_limit_order(symbol, side, qty, limit_price)
                logger.info(f"Order submitted successfully: ID={order_result['order_id']}")
                return (
                    f"✅ Limit Order Submitted: {side.upper()} {qty} {symbol} @ ${limit_price:.2f}\n"
                    f"Order ID: {order_result['order_id']}\n"
                    f"Status: {order_result['status']}\n"
                    f"Submitted at: {order_result['submitted_at']}"
                )
            else:
                logger.error(f"Unknown order type requested: {order_type}")
                return f"ERROR: Unknown order type: {order_type}"
                
        except Exception as e:
            logger.error(f"Order failed: {e}", exc_info=True)
            return f"ERROR: Order failed - {str(e)}"
  • server.py:375-378 (registration)
    Registers the place_order function as an MCP tool by including it in the execution tools list passed to register_tools, which applies the @mcp.tool() decorator.
    register_tools(
        [place_order, cancel_order, get_positions, flatten, get_order_history],
        "Execution"
    )
  • Helper function used to batch-register MCP tools, including place_order, by dynamically applying the @mcp.tool() decorator to each function in the list.
    def register_tools(tools: List[Callable], category: str):
        """Helper to register multiple tools with logging."""
        for tool in tools:
            try:
                mcp.tool()(tool)
                logger.info(f"Registered {category} tool: {tool.__name__}")
            except Exception as e:
                logger.error(f"Failed to register {tool.__name__}: {e}")
                raise
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions the tool submits orders but lacks details on execution behavior (e.g., immediate vs. pending), error handling, rate limits, authentication needs, or whether it's a simulation (paper trading) versus real trading. This is inadequate for a mutation tool with zero annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded with the core purpose in the first sentence, followed by structured parameter and return explanations. It avoids redundancy, though the return statement could be more specific.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of a trading tool with 5 parameters, no annotations, and an output schema (implied by 'Returns'), the description is partially complete. It covers parameter semantics well but lacks behavioral context (e.g., execution details, error cases) and relies on the output schema for return values, leaving gaps in operational guidance.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds significant meaning beyond the input schema, which has 0% schema description coverage. It explains each parameter's purpose (e.g., 'symbol: Ticker symbol', 'limit_price: Required if order_type is limit'), clarifying semantics that the schema alone does not provide, though it could elaborate on units or constraints for qty and limit_price.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Submits a market or limit order'), the target resource ('to Alpaca paper trading'), and distinguishes it from siblings like cancel_order or get_order_history by focusing on order creation rather than modification or retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for trading orders in a paper trading environment but does not explicitly state when to use this tool versus alternatives like cancel_order or get_order_history, nor does it mention prerequisites such as account setup or market hours.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other 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/N-lia/MonteWalk'

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