Skip to main content
Glama
Habinar

MCP Paradex Server

by Habinar

paradex_vault_positions

Monitor active trading positions to track performance, manage risk, and assess liquidation prices and margin requirements for a vault.

Instructions

Monitor active trading positions to track performance and manage risk.

Use this tool when you need to:
- Get a complete view of all open positions for a vault
- Monitor unrealized P&L across all positions
- Check liquidation prices and margin requirements
- Assess position sizing and leverage across markets
- Track entry prices and position duration

Position monitoring is fundamental to risk management and provides
the necessary information for trade management decisions.

Example use cases:
- Checking the current status of all open trades
- Monitoring unrealized profit/loss across positions
- Assessing liquidation risk during market volatility
- Comparing performance across different markets
- Planning adjustments to position sizes or leverage

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
vault_addressYesThe address of the vault to get positions for.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The main handler function decorated with @server.tool(name="paradex_vault_positions"). It fetches vault positions from the Paradex API using get_paradex_client and api_call, validates with position_adapter, and returns the list of Position objects.
    @server.tool(name="paradex_vault_positions")
    async def get_vault_positions(
        vault_address: Annotated[
            str, Field(description="The address of the vault to get positions for.")
        ],
    ) -> list[Position]:
        """
        Monitor active trading positions to track performance and manage risk.
    
        Use this tool when you need to:
        - Get a complete view of all open positions for a vault
        - Monitor unrealized P&L across all positions
        - Check liquidation prices and margin requirements
        - Assess position sizing and leverage across markets
        - Track entry prices and position duration
    
        Position monitoring is fundamental to risk management and provides
        the necessary information for trade management decisions.
    
        Example use cases:
        - Checking the current status of all open trades
        - Monitoring unrealized profit/loss across positions
        - Assessing liquidation risk during market volatility
        - Comparing performance across different markets
        - Planning adjustments to position sizes or leverage
        """
        try:
            client = await get_paradex_client()
            response = await api_call(client, "vaults/positions", params={"address": vault_address})
            positions = position_adapter.validate_python(response["results"])
            return positions
        except Exception as e:
            logger.error(f"Error fetching positions for vault {vault_address}: {e!s}")
            raise e
  • Pydantic BaseModel defining the schema for individual Position objects returned by the tool. Used in position_adapter for list validation.
    class Position(BaseModel):
        """Position model representing a trading position on Paradex."""
    
        id: Annotated[str, Field(description="Unique string ID for the position")]
        account: Annotated[str, Field(description="Account ID of the position")]
        market: Annotated[str, Field(description="Market for position")]
        status: Annotated[
            str, Field(description="Status of Position : Open or Closed", enum=["OPEN", "CLOSED"])
        ]
        side: Annotated[str, Field(description="Position Side : Long or Short", enum=["SHORT", "LONG"])]
        size: Annotated[
            float,
            Field(description="Size of the position with sign (positive if long or negative if short)"),
        ]
        average_entry_price: Annotated[float, Field(description="Average entry price")]
        average_entry_price_usd: Annotated[float, Field(description="Average entry price in USD")]
        average_exit_price: Annotated[float, Field(description="Average exit price")]
        unrealized_pnl: Annotated[
            float, Field(description="Unrealized P&L of the position in the quote asset")
        ]
        unrealized_funding_pnl: Annotated[
            float, Field(description="Unrealized running funding P&L for the position")
        ]
        cost: Annotated[float, Field(description="Position cost")]
        cost_usd: Annotated[float, Field(description="Position cost in USD")]
        cached_funding_index: Annotated[float, Field(description="Position cached funding index")]
        last_updated_at: Annotated[int, Field(description="Position last update time")]
        last_fill_id: Annotated[
            str, Field(description="Last fill ID to which the position is referring")
        ]
        seq_no: Annotated[
            int,
            Field(
                description="Unique increasing number (non-sequential) that is assigned to this position update. Can be used to deduplicate multiple feeds"
            ),
        ]
        liquidation_price: Annotated[
            str, Field(default="", description="Liquidation price of the position")
        ]
        leverage: Annotated[float, Field(default=0, description="Leverage of the position")]
        realized_positional_pnl: Annotated[
            float,
            Field(
                default=0,
                description="Realized PnL including both positional PnL and funding payments. Reset to 0 when position is closed or flipped.",
            ),
        ]
        created_at: Annotated[int, Field(default=0, description="Position creation time")]
        closed_at: Annotated[int, Field(default=0, description="Position closed time")]
        realized_positional_funding_pnl: Annotated[
            str,
            Field(
                default="",
                description="Realized Funding PnL for the position. Reset to 0 when position is closed or flipped.",
            ),
        ]
  • The @server.tool decorator registers the get_vault_positions function as the MCP tool named 'paradex_vault_positions'.
    @server.tool(name="paradex_vault_positions")

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv1.0.0
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$defs": {
      +    "Position": {
      +      "description": "Position model representing a trading position on Paradex.",
      +      "properties": {
      +        "account": {
      +          "description": "Account ID of the position",
      +          "title": "Account",
      +          "type": "string"
      +        },
      +        "average_entry_price": {
      +          "description": "Average entry price",
      +          "title": "Average Entry Price",
      +          "type": "number"
      +        },
      +        "average_entry_price_usd": {
      +          "description": "Average entry price in USD",
      +          "title": "Average Entry Price Usd",
      +          "type": "number"
      +        },
      +        "average_exit_price": {
      +          "description": "Average exit price",
      +          "title": "Average Exit Price",
      +          "type": "number"
      +        },
      +        "cached_funding_index": {
      +          "description": "Position cached funding index",
      +          "title": "Cached Funding Index",
      +          "type": "number"
      +        },
      +        "closed_at": {
      +          "default": 0,
      +          "description": "Position closed time",
      +          "title": "Closed At",
      +          "type": "integer"
      +        },
      +        "cost": {
      +          "description": "Position cost",
      +          "title": "Cost",
      +          "type": "number"
      +        },
      +        "cost_usd": {
      +          "description": "Position cost in USD",
      +          "title": "Cost Usd",
      +          "type": "number"
      +        },
      +        "created_at": {
      +          "default": 0,
      +          "description": "Position creation time",
      +          "title": "Created At",
      +          "type": "integer"
      +        },
      +        "id": {
      +          "description": "Unique string ID for the position",
      +          "title": "Id",
      +          "type": "string"
      +        },
      +        "last_fill_id": {
      +          "description": "Last fill ID to which the position is referring",
      +          "title": "Last Fill Id",
      +          "type": "string"
      +        },
      +        "last_updated_at": {
      +          "description": "Position last update time",
      +          "title": "Last Updated At",
      +          "type": "integer"
      +        },
      +        "leverage": {
      +          "default": 0,
      +          "description": "Leverage of the position",
      +          "title": "Leverage",
      +          "type": "number"
      +        },
      +        "liquidation_price": {
      +          "default": "",
      +          "description": "Liquidation price of the position",
      +          "title": "Liquidation Price",
      +          "type": "string"
      +        },
      +        "market": {
      +          "description": "Market for position",
      +          "title": "Market",
      +          "type": "string"
      +        },
      +        "realized_positional_funding_pnl": {
      +          "default": "",
      +          "description": "Realized Funding PnL for the position. Reset to 0 when position is closed or flipped.",
      +          "title": "Realized Positional Funding Pnl",
      +          "type": "string"
      +        },
      +        "realized_positional_pnl": {
      +          "default": 0,
      +          "description": "Realized PnL including both positional PnL and funding payments. Reset to 0 when position is closed or flipped.",
      +          "title": "Realized Positional Pnl",
      +          "type": "number"
      +        },
      +        "seq_no": {
      +          "description": "Unique increasing number (non-sequential) that is assigned to this position update. Can be used to deduplicate multiple feeds",
      +          "title": "Seq No",
      +          "type": "integer"
      +        },
      +        "side": {
      +          "description": "Position Side : Long or Short",
      +          "enum": [
      +            "SHORT",
      +            "LONG"
      +          ],
      +          "title": "Side",
      +          "type": "string"
      +        },
      +        "size": {
      +          "description": "Size of the position with sign (positive if long or negative if short)",
      +          "title": "Size",
      +          "type": "number"
      +        },
      +        "status": {
      +          "description": "Status of Position : Open or Closed",
      +          "enum": [
      +            "OPEN",
      +            "CLOSED"
      +          ],
      +          "title": "Status",
      +          "type": "string"
      +        },
      +        "unrealized_funding_pnl": {
      +          "description": "Unrealized running funding P&L for the position",
      +          "title": "Unrealized Funding Pnl",
      +          "type": "number"
      +        },
      +        "unrealized_pnl": {
      +          "description": "Unrealized P&L of the position in the quote asset",
      +          "title": "Unrealized Pnl",
      +          "type": "number"
      +        }
      +      },
      +      "required": [
      +        "id",
      +        "account",
      +        "market",
      +        "status",
      +        "side",
      +        "size",
      +        "average_entry_price",
      +        "average_entry_price_usd",
      +        "average_exit_price",
      +        "unrealized_pnl",
      +        "unrealized_funding_pnl",
      +        "cost",
      +        "cost_usd",
      +        "cached_funding_index",
      +        "last_updated_at",
      +        "last_fill_id",
      +        "seq_no"
      +      ],
      +      "title": "Position",
      +      "type": "object"
      +    }
      +  },
      +  "properties": {
      +    "result": {
      +      "items": {
      +        "$ref": "#/$defs/Position"
      +      },
      +      "title": "Result",
      +      "type": "array"
      +    }
      +  },
      +  "required": [
      +    "result"
      +  ],
      +  "title": "get_vault_positionsOutput",
      +  "type": "object"
      +}
  2. First observed

TDQS

A4.3/5.0
Behavior3/5

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

No annotations are provided, so the description carries full burden. It discloses the tool's purpose (monitoring/read-only) and what information it returns (positions, P&L, liquidation prices, etc.), but doesn't specify behavioral traits like rate limits, authentication requirements, error conditions, or pagination. It adequately describes the tool's function but lacks operational details.

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 well-structured with clear sections (purpose, usage scenarios, rationale, examples) and front-loaded key information. It's appropriately sized for the tool's complexity, though slightly verbose in listing multiple similar examples (e.g., 'monitoring unrealized profit/loss' appears twice). Every sentence adds value.

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

Completeness4/5

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

Given the tool's moderate complexity (single parameter, read-only monitoring function), the description is quite complete. It explains what the tool does, when to use it, and provides examples. With an output schema present (per context signals), the description doesn't need to detail return values. The main gap is lack of behavioral transparency details (auth, limits, errors).

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?

Schema description coverage is 100% (single parameter 'vault_address' is well-described in schema). The description doesn't add parameter-specific semantics beyond what the schema provides, but with only one parameter and high schema coverage, the baseline is strong. No additional parameter context is needed.

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 tool's purpose with specific verbs ('monitor', 'track', 'manage') and resources ('active trading positions', 'vault'), distinguishing it from siblings like paradex_account_positions (which appears to be for individual accounts rather than vaults). It explicitly lists what the tool provides: complete view of open positions, P&L monitoring, liquidation prices, margin requirements, etc.

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

Usage Guidelines5/5

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

The description provides explicit usage guidelines with a dedicated 'Use this tool when you need to:' section listing five specific scenarios, plus example use cases. It implicitly distinguishes from siblings by focusing on vault-level positions rather than account-level (e.g., vs. paradex_account_positions), though it doesn't name alternatives directly.

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