Skip to main content
Glama
berlinbra

PolyMarket MCP Server

list-markets

Retrieve a list of prediction markets from PolyMarket, with filters for status, pagination, and result limit to access relevant market data efficiently.

Instructions

Get a list of prediction markets with optional filters

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoNumber of markets to return (default: 10)
offsetNoNumber of markets to skip (for pagination)
statusNoFilter by market status (e.g., open, closed, resolved)

Implementation Reference

  • The main handler logic for the 'list-markets' tool within the @server.call_tool() function. It fetches markets from ClobClient, parses and filters the response based on status, applies pagination using offset and limit, formats the data, and returns it as text content.
    elif name == "list-markets":
        status = arguments.get("status")
        
        # Get markets using CLOB client
        markets_data = client.get_markets()
    
        # Handle string response (if the response is a JSON string)
        if isinstance(markets_data, str):
            try:
                markets_data = json.loads(markets_data)
            except json.JSONDecodeError:
                return [types.TextContent(type="text", text="Error: Invalid response format from API")]
        
        # Ensure we have a list of markets
        if not isinstance(markets_data, list):
            if isinstance(markets_data, dict) and 'data' in markets_data:
                markets_data = markets_data['data']
            else:
                return [types.TextContent(type="text", text="Error: Unexpected response format from API")]
        
        # Filter by status if specified
        if status:
            markets_data = [
                market for market in markets_data 
                if isinstance(market, dict) and market.get('status', '').lower() == status.lower()
            ]
        
        # Apply pagination
        offset = arguments.get("offset", 0)
        limit = arguments.get("limit", 10)
        markets_data = markets_data[offset:offset + limit]
        
        formatted_list = format_market_list(markets_data)
        return [types.TextContent(type="text", text=formatted_list)]
  • Registration of the 'list-markets' tool in the @server.list_tools() handler, defining the tool name, description, and input schema for validation.
    types.Tool(
        name="list-markets",
        description="Get a list of prediction markets with optional filters",
        inputSchema={
            "type": "object",
            "properties": {
                "status": {
                    "type": "string",
                    "description": "Filter by market status (e.g., open, closed, resolved)",
                    "enum": ["active", "resolved"],
                },
                "limit": {
                    "type": "integer",
                    "description": "Number of markets to return (default: 10)",
                    "default": 10,
                    "minimum": 1,
                    "maximum": 100
                },
                "offset": {
                    "type": "integer",
                    "description": "Number of markets to skip (for pagination)",
                    "default": 0,
                    "minimum": 0
                }
            },
        },
    ),
  • Helper function to format the list of markets into a human-readable string, extracting various fields like condition ID, description, volume, etc., and handling formatting errors.
    def format_market_list(markets_data: list) -> str:
        """Format list of markets into a concise string."""
        try:
            if not markets_data:
                return "No markets available"
                
            formatted_markets = ["Available Markets:\n"]
            
            for market in markets_data:
                try:
                    volume = float(market.get('volume', 0))
                    volume_str = f"${volume:,.2f}"
                except (ValueError, TypeError):
                    volume_str = f"${market.get('volume', 0)}"
                    
                formatted_markets.append(
                    f"Condition ID: {market.get('condition_id', 'N/A')}\n"
                    f"Description: {market.get('description', 'N/A')}\n"
                    f"Category: {market.get('category', 'N/A')}\n"
                    f"Tokens: {market.get('question', 'N/A')}\n"
                    f"Question: {market.get('active', 'N/A')}\n"
                    f"Rewards: {market.get('rewards', 'N/A')}\n"
                    f"Active: {market.get('active', 'N/A')}\n"
                    f"Closed: {market.get('closed', 'N/A')}\n"
                    f"Slug: {market.get('market_slug', 'N/A')}\n"
                    f"Min Incentive size: {market.get('min_incentive_size', 'N/A')}\n"
                    f"Max Incentive size: {market.get('max_incentive_spread', 'N/A')}\n"
                    f"End date: {market.get('end_date_iso', 'N/A')}\n"
                    f"Start time: {market.get('game_start_time', 'N/A')}\n"
                    f"Min order size: {market.get('minimum_order_size', 'N/A')}\n"
                    f"Max tick size: {market.get('minimum_tick_size', 'N/A')}\n"
                    f"Volume: {volume_str}\n"
                    "---\n"
                )
            
            return "\n".join(formatted_markets)
        except Exception as e:
            return f"Error formatting markets list: {str(e)}"
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 'optional filters' but fails to describe key behaviors: whether this is a read-only operation, how pagination works with limit/offset, what the default sorting is, or what the response format looks like. For a listing tool with zero annotation coverage, this leaves significant gaps in understanding its operation.

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?

The description is a single, efficient sentence that front-loads the core purpose ('Get a list of prediction markets') and adds essential qualification ('with optional filters'). There is no wasted language, and every word serves to clarify the tool's function appropriately for its complexity.

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

Completeness2/5

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

Given the lack of annotations and output schema, the description is incomplete for a listing tool with 3 parameters. It doesn't explain the return format, pagination behavior, or any error conditions. While the schema covers parameters well, the overall context for agent usage remains underspecified, especially for behavioral aspects.

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 description coverage is 100%, with all parameters well-documented in the schema (limit, offset, status with enum values). The description adds minimal value beyond the schema by mentioning 'optional filters,' which aligns with the status parameter but doesn't provide additional context or examples. This meets the baseline for high schema coverage.

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

Purpose4/5

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

The description clearly states the verb ('Get') and resource ('list of prediction markets'), making the purpose immediately understandable. It distinguishes this tool from its siblings (get-market-history, get-market-info, get-market-prices) by focusing on listing with filters rather than retrieving specific market details. However, it doesn't explicitly contrast with siblings beyond the general 'list' vs 'get' distinction.

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 through 'with optional filters,' suggesting this tool is for filtered listing operations. However, it provides no explicit guidance on when to use this tool versus its siblings (e.g., use list-markets for overviews vs get-market-info for details) or any prerequisites. The context is clear but lacks specific alternatives or exclusions.

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

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/berlinbra/polymarket-mcp'

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