Skip to main content
Glama
verygoodplugins

Robinhood MCP

robinhood_get_position

Retrieve a current stock position for a single ticker symbol. Use this for quick lookup of holdings data.

Instructions

Get one current stock position with a faster single-symbol lookup.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
symbolYesStock ticker symbol (e.g., "HIMS", "AAPL")

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • MCP tool registration for 'robinhood_get_position' using @mcp.tool() decorator. Delegates to tools.get_position().
    @mcp.tool()
    def robinhood_get_position(symbol: str) -> dict:
        """Get one current stock position with a faster single-symbol lookup.
    
        Args:
            symbol: Stock ticker symbol (e.g., "HIMS", "AAPL")
    
        Returns a dict with held=False if absent, otherwise the position details
        for that symbol including quantity, price, average buy price, and P&L.
        """
        _ensure_logged_in()
        return get_position(symbol)
  • Core implementation of get_position(). Looks up cached positions first, otherwise validates the symbol instrument, fetches open stock positions, matches by instrument URL, and computes price/quantity/P&L fields.
    def get_position(symbol: str) -> dict[str, Any]:
        """Get a single position by symbol without rebuilding all holdings.
    
        Returns:
            Dict with held=False if absent, otherwise position details including
            price, quantity, average_buy_price, equity, percent_change, and equity_change.
        """
        symbol = _normalize_symbol(symbol)
        cached_positions = _get_positions_cached(time.monotonic())
        if cached_positions is not None:
            cached_position = cached_positions.get(symbol)
            if isinstance(cached_position, dict):
                return _position_payload(symbol, cached_position)
            _validate_symbol_instrument(symbol)
            return {"symbol": symbol, "held": False}
    
        instrument_url = _validate_symbol_instrument(symbol)
    
        positions = _safe_call(rh.account.get_open_stock_positions)
        if not isinstance(positions, list):
            raise RobinhoodError("Unexpected positions response type")
    
        match = next(
            (
                item
                for item in positions
                if isinstance(item, dict) and item.get("instrument") == instrument_url
            ),
            None,
        )
        if not match:
            return {"symbol": symbol, "held": False}
    
        quote = get_quote(symbol)
        price = quote.get("last_trade_price") or quote.get("mark_price")
        quantity = match.get("quantity")
        average_buy_price = match.get("average_buy_price")
        if price in (None, "") or quantity in (None, "") or average_buy_price in (None, ""):
            raise RobinhoodError(f"Incomplete position data for symbol: {symbol}")
    
        try:
            quantity_f = float(quantity)
            price_f = float(price)
            average_buy_price_f = float(average_buy_price)
        except (TypeError, ValueError) as e:
            raise RobinhoodError(f"Invalid numeric position data for symbol: {symbol}") from e
    
        equity = quantity_f * price_f
        equity_change = equity - (quantity_f * average_buy_price_f)
        percent_change = (
            0.0
            if average_buy_price_f == 0.0
            else ((price_f - average_buy_price_f) * 100 / average_buy_price_f)
        )
        return _position_payload(
            symbol,
            {
                "price": f"{price_f:.2f}",
                "quantity": quantity,
                "average_buy_price": average_buy_price,
                "equity": f"{equity:.2f}",
                "percent_change": f"{percent_change:.2f}",
                "equity_change": f"{equity_change:.2f}",
            },
        )
  • Helper function _position_payload() builds a stable position response dict with a fixed set of fields (price, quantity, average_buy_price, equity, percent_change, equity_change) and a 'held' boolean.
    def _position_payload(symbol: str, data: dict[str, Any]) -> dict[str, Any]:
        """Build a stable position response with a fixed set of fields."""
        fields = {k: data.get(k) for k in _POSITION_FIELDS}
        held = all(v not in (None, "") for v in fields.values())
        return {"symbol": symbol, "held": held, **fields}
  • Helper function _validate_symbol_instrument() resolves a ticker symbol to its instrument URL via the Robinhood API, raising RobinhoodError for unknown symbols.
    def _validate_symbol_instrument(symbol: str) -> str:
        """Resolve a symbol to its instrument URL, raising on unknown tickers."""
        instruments = _safe_call(rh.stocks.get_instruments_by_symbols, symbol)
        if (
            not isinstance(instruments, list)
            or not instruments
            or not isinstance(instruments[0], dict)
            or not instruments[0].get("url")
        ):
            raise RobinhoodError(f"No instrument found for symbol: {symbol}")
        return instruments[0]["url"]
  • Helper function _normalize_symbol() validates and normalizes a ticker symbol (uppercase, strip whitespace).
    def _normalize_symbol(symbol: str) -> str:
        """Normalize and validate ticker symbols."""
        if not symbol or not isinstance(symbol, str):
            raise RobinhoodError("Symbol must be a non-empty string")
        symbol = symbol.upper().strip()
        if not symbol:
            raise RobinhoodError("Symbol must be a non-empty string")
        return symbol
Behavior2/5

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

No annotations are provided, so description bears full burden. It describes a read operation but omits details like data freshness ('current'), authentication requirements, or rate limits. Minimal behavioral context beyond the tool name.

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

Conciseness5/5

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

Single sentence, front-loaded with key action and differentiator. No unnecessary words; every part earns its place.

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 a simple 1-parameter tool with output schema, description is minimally adequate but lacks context on what 'current' means (e.g., real-time vs delayed) and any prerequisites.

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

Parameters3/5

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

Schema covers 100% of parameters with description for 'symbol'. Description adds no additional meaning beyond schema, baseline score of 3 is appropriate.

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 it retrieves one current stock position, and 'faster single-symbol lookup' distinguishes it from the plural sibling tool 'robinhood_get_positions' which likely handles multiple symbols.

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

Usage Guidelines4/5

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

The description implies use for single-symbol lookups and suggests speed advantage, but does not explicitly exclude use cases or mention when to prefer the sibling tool for multiple symbols.

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/verygoodplugins/robinhood-mcp'

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