get_oi_history
Retrieve hourly open interest snapshots for a Polymarket market to chart OI trends over time.
Instructions
Get hourly open interest snapshots for a specific Polymarket market. Use this to chart OI trends over time. The conditionId can be obtained from get_market_open_interest or the main subgraph.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| conditionId | Yes | The conditionId (hex string) of the market | |
| first | No | Number of hourly snapshots to return (default 168 = 1 week) | |
| orderDirection | No | Sort direction by timestamp | desc |
Implementation Reference
- src/index.ts:658-691 (registration)Registration of the 'get_oi_history' tool via server.registerTool with the name 'get_oi_history'. The input schema expects a conditionId (string), first (number, default 168), and orderDirection (enum 'asc' or 'desc', default 'desc').
server.registerTool( "get_oi_history", { description: "Get hourly open interest snapshots for a specific Polymarket market. Use this to chart OI trends over time. The conditionId can be obtained from get_market_open_interest or the main subgraph.", inputSchema: { conditionId: z.string().describe("The conditionId (hex string) of the market"), first: z.number().min(1).max(1000).default(168).describe("Number of hourly snapshots to return (default 168 = 1 week)"), orderDirection: z.enum(["asc", "desc"]).default("desc").describe("Sort direction by timestamp"), }, }, async ({ conditionId, first, orderDirection }) => { try { const query = `{ oisnapshots( first: ${first}, orderBy: timestamp, orderDirection: ${orderDirection}, where: { market: "${conditionId.toLowerCase()}" } ) { id amount amountRaw blockNumber timestamp } }`; const data = await querySubgraph(SUBGRAPHS.open_interest.ipfsHash, query); return textResult(data); } catch (error) { return errorResult(error); } } ); - src/index.ts:669-691 (handler)The handler function that executes the tool logic. It queries the 'open_interest' subgraph (ipfsHash from SUBGRAPHS.open_interest) for oisnapshots filtered by market (conditionId), ordered by timestamp. Returns hourly OI snapshots with id, amount, amountRaw, blockNumber, and timestamp fields.
async ({ conditionId, first, orderDirection }) => { try { const query = `{ oisnapshots( first: ${first}, orderBy: timestamp, orderDirection: ${orderDirection}, where: { market: "${conditionId.toLowerCase()}" } ) { id amount amountRaw blockNumber timestamp } }`; const data = await querySubgraph(SUBGRAPHS.open_interest.ipfsHash, query); return textResult(data); } catch (error) { return errorResult(error); } } ); - src/graphClient.ts:12-59 (helper)The querySubgraph helper is used by the handler to execute the GraphQL query against The Graph's decentralized network, using the open_interest subgraph's IPFS hash.
export async function querySubgraph( ipfsHash: string, query: string, variables?: Record<string, unknown> ): Promise<unknown> { const apiKey = process.env.GRAPH_API_KEY; if (!apiKey) { throw new GraphClientError( "GRAPH_API_KEY environment variable is required. " + "Get one at https://thegraph.com/studio/apikeys/" ); } const url = `https://gateway.thegraph.com/api/${apiKey}/deployments/id/${ipfsHash}`; const body: Record<string, unknown> = { query }; if (variables && Object.keys(variables).length > 0) { body.variables = variables; } const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); if (!response.ok) { throw new GraphClientError( `Graph API returned HTTP ${response.status}: ${response.statusText}`, response.status ); } const json = (await response.json()) as { data?: unknown; errors?: unknown[]; }; if (json.errors && json.errors.length > 0) { throw new GraphClientError( `GraphQL errors: ${JSON.stringify(json.errors)}`, undefined, json.errors ); } return json.data; } - src/index.ts:32-44 (helper)The textResult and errorResult helpers format the tool's response as JSON content for the MCP protocol.
function textResult(data: unknown) { return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }], }; } function errorResult(error: unknown) { const message = error instanceof Error ? error.message : String(error); return { content: [{ type: "text" as const, text: `Error: ${message}` }], isError: true, }; } - src/index.ts:663-667 (schema)The input schema for the tool defines conditionId (required string), first (optional number, default 168, max 1000), and orderDirection (optional enum asc/desc, default desc).
inputSchema: { conditionId: z.string().describe("The conditionId (hex string) of the market"), first: z.number().min(1).max(1000).default(168).describe("Number of hourly snapshots to return (default 168 = 1 week)"), orderDirection: z.enum(["asc", "desc"]).default("desc").describe("Sort direction by timestamp"), },