markets.discover
Find Polymarket prediction markets filtered by resolution deadline and category. Returns market question, price, volume, and end date. Use ending='today' for fast-resolving markets or 'all' for full browse.
Instructions
Find active Polymarket prediction markets filtered by resolution deadline and category. Returns market question, price, volume, and end date. Use ending='today' for fast-resolving markets, or 'all' to browse everything.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ending | No | Filter by resolution deadline: today, this_week, or all active markets | today |
| category | No | Filter by category (e.g. politics, sports, crypto, pop-culture) | |
| min_volume | No | Minimum trading volume in USDC to include a market | |
| limit | No | Maximum number of markets to return |
Implementation Reference
- src/tools/discover-markets.ts:17-78 (handler)The handleDiscoverMarkets function executes the 'markets.discover' tool logic. It checks for a pro license, constructs a Polymarket Gamma API URL with optional ending/category filters, fetches markets, filters by min_volume, and returns a formatted markdown table of markets.
export async function handleDiscoverMarkets(input: DiscoverMarketsInput): Promise<string> { const isPro = await checkLicense(); if (!isPro) return requirePro("discover_markets"); const now = new Date(); let endBefore = ""; if (input.ending === "today") { const tomorrow = new Date(now); tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setHours(0, 0, 0, 0); endBefore = tomorrow.toISOString(); } else if (input.ending === "this_week") { const nextWeek = new Date(now); nextWeek.setDate(nextWeek.getDate() + 7); endBefore = nextWeek.toISOString(); } let url = `${GAMMA_API_BASE}/markets?closed=false&order=volume&ascending=false&limit=${input.limit}`; if (endBefore) { url += `&end_date_max=${endBefore}`; } if (input.category) { url += `&tag=${input.category}`; } log("info", `Discovering markets: ending=${input.ending}, category=${input.category ?? "all"}`); try { const res = await fetchWithRetry(url); if (!res.ok) throw new Error(`API error: ${res.status}`); const data = await res.json(); const markets = (data as any[]).filter((m: any) => { const vol = parseFloat(m.volume ?? "0"); return vol >= input.min_volume; }); if (markets.length === 0) { return "No markets found matching criteria. Try 'this_week' or 'all' for more results."; } let output = `## Markets (${markets.length}) — ending: ${input.ending}\n\n`; output += `| # | Market | Condition ID | End Date | Volume | Price |\n`; output += `|---|--------|--------------|----------|--------|-------|\n`; for (let i = 0; i < markets.length; i++) { const m = markets[i] as any; const q = (m.question ?? "").slice(0, 40); const end = (m.endDate ?? "").slice(0, 16).replace("T", " "); const vol = parseFloat(m.volume ?? "0"); const prices = m.outcomePrices ?? ""; // Exposing conditionId here lets the agent skip a second lookup via // search_markets/resolveMarketByConditionId before pre-trade gating. const cid = (m.conditionId ?? "").slice(0, 12) + "…"; output += `| ${i + 1} | ${q} | \`${cid}\` (${m.conditionId ?? ""}) | ${end} | $${vol.toFixed(0)} | ${prices} |\n`; } return output; } catch (err) { log("error", `Failed to discover markets: ${err}`); return "Could not reach the Polymarket API. This may be a temporary issue — try again in a moment."; } } - src/tools/discover-markets.ts:8-13 (schema)Zod schema defining input parameters: ending (today/this_week/all), category (optional string), min_volume (default 100), limit (1-50, default 20).
export const discoverMarketsSchema = z.object({ ending: z.enum(["today", "this_week", "all"]).optional().default("today").describe("Filter by resolution deadline: today, this_week, or all active markets"), category: z.string().optional().describe("Filter by category (e.g. politics, sports, crypto, pop-culture)"), min_volume: z.number().optional().default(100).describe("Minimum trading volume in USDC to include a market"), limit: z.number().int().min(1).max(50).optional().default(20).describe("Maximum number of markets to return"), }); - src/index.ts:246-251 (registration)Registration of 'markets.discover' as an MCP tool via server.tool() with its description, schema, and handler wrapper using safe().
server.tool( "markets.discover", "Find active Polymarket prediction markets filtered by resolution deadline and category. Returns market question, price, volume, and end date. Use ending='today' for fast-resolving markets, or 'all' to browse everything.", discoverMarketsSchema.shape, safe("markets.discover", async (input) => ({ content: [{ type: "text" as const, text: await handleDiscoverMarkets(discoverMarketsSchema.parse(input)) }] })) ); - src/index.ts:46-46 (registration)Import of discoverMarketsSchema and handleDiscoverMarkets from the handler module.
import { discoverMarketsSchema, handleDiscoverMarkets } from "./tools/discover-markets.js";