propline-mcp 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -105,6 +105,11 @@ var PropLineClient = class {
|
|
|
105
105
|
daysFrom: opts.daysFrom
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
|
+
getMlbGrandSalami(opts = {}) {
|
|
109
|
+
return this.request(`/v1/sports/baseball_mlb/grand-salami`, {
|
|
110
|
+
date: opts.date
|
|
111
|
+
});
|
|
112
|
+
}
|
|
108
113
|
getResolutionSummary(opts = {}) {
|
|
109
114
|
return this.request(`/v1/markets/resolution-summary`, {
|
|
110
115
|
days: opts.days
|
|
@@ -133,7 +138,7 @@ var PropLineClient = class {
|
|
|
133
138
|
};
|
|
134
139
|
|
|
135
140
|
// src/index.ts
|
|
136
|
-
var VERSION = "0.
|
|
141
|
+
var VERSION = "0.3.0";
|
|
137
142
|
var apiKey = process.env.PROPLINE_API_KEY;
|
|
138
143
|
var baseUrl = process.env.PROPLINE_BASE_URL;
|
|
139
144
|
var _client = null;
|
|
@@ -265,6 +270,24 @@ var tools = [
|
|
|
265
270
|
daysFrom: args.days_from
|
|
266
271
|
})
|
|
267
272
|
},
|
|
273
|
+
{
|
|
274
|
+
name: "propline_get_mlb_grand_salami",
|
|
275
|
+
description: "Free-tier endpoint. Returns the synthetic daily MLB Grand Salami for a given UTC date \u2014 total runs scored across every MLB game on the slate plus each book's implied Grand Salami line (median of per-game primary totals across our MLB books incl. Pinnacle, Polymarket, Matchbook, Smarkets). No retail sportsbook quotes this as a single market. Useful for: 'what's the total run line for tonight's full MLB slate', 'did the Grand Salami go over yesterday', 'historical Grand Salami results for backtesting'.",
|
|
276
|
+
inputSchema: {
|
|
277
|
+
type: "object",
|
|
278
|
+
properties: {
|
|
279
|
+
date: {
|
|
280
|
+
type: "string",
|
|
281
|
+
description: "YYYY-MM-DD UTC date. Defaults to today (UTC) when omitted."
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
required: [],
|
|
285
|
+
additionalProperties: false
|
|
286
|
+
},
|
|
287
|
+
handler: (args) => client().getMlbGrandSalami({
|
|
288
|
+
date: args.date
|
|
289
|
+
})
|
|
290
|
+
},
|
|
268
291
|
{
|
|
269
292
|
name: "propline_get_resolution_summary",
|
|
270
293
|
description: "Free-tier endpoint. Returns the factual volume of player props PropLine has graded against real box scores over the last N days (aggregated counts only): total graded/settled, games, sports covered, plus per-sport and top-market breakdowns. Useful for: 'how much graded prop data does PropLine have, what's the coverage'. A coverage proof, never a profitability claim.",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/client.ts"],"sourcesContent":["/**\n * PropLine MCP server.\n *\n * Exposes the PropLine REST API as Model Context Protocol tools so AI\n * clients (Claude Desktop, Claude Code, ChatGPT desktop with MCP, etc.)\n * can pull live odds, prop resolution, cross-book +EV, scores, and\n * box-score stats directly via tool calls.\n *\n * Run via: npx -y propline-mcp\n * Auth: PROPLINE_API_KEY env var (free key at https://prop-line.com)\n * Optional: PROPLINE_BASE_URL env var (override for self-hosted setups)\n */\n\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { PropLineClient, PropLineHTTPError } from \"./client.js\";\n\nexport const VERSION = \"0.2.3\";\n\nconst apiKey = process.env.PROPLINE_API_KEY;\nconst baseUrl = process.env.PROPLINE_BASE_URL;\n\n// The API key is intentionally NOT required at startup. MCP clients and\n// directory crawlers (Glama, the MCP Registry) must be able to introspect\n// the tool list before a key is configured — exiting here would make the\n// server undiscoverable and break the install-then-configure UX. The key\n// is enforced lazily on the first real tool call instead; tools/list never\n// touches the client.\nlet _client: PropLineClient | null = null;\nfunction client(): PropLineClient {\n if (!_client) {\n if (!apiKey) {\n throw new Error(\n \"PROPLINE_API_KEY is not set. Get a free key at \" +\n \"https://prop-line.com and add it to your MCP client config \" +\n \"(env var: PROPLINE_API_KEY).\",\n );\n }\n _client = new PropLineClient({ apiKey, baseUrl });\n }\n return _client;\n}\n\n// ---------------------------------------------------------------------\n// Tool definitions\n// ---------------------------------------------------------------------\n\ninterface ToolDef {\n name: string;\n description: string;\n inputSchema: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n };\n // Returns either JSON-serializable data (will be JSON.stringify'd in the\n // tool result) or a string (returned as-is).\n handler: (args: Record<string, unknown>) => Promise<unknown>;\n}\n\nconst tools: ToolDef[] = [\n {\n name: \"propline_list_sports\",\n description:\n \"List all sports PropLine currently polls. Returns sport keys \" +\n \"(e.g. baseball_mlb, basketball_nba, soccer_epl) along with human \" +\n \"titles and active status. Use this first to discover what \" +\n \"sport_key values are valid for the other tools.\",\n inputSchema: {\n type: \"object\",\n properties: {},\n additionalProperties: false,\n },\n handler: () => client().listSports(),\n },\n {\n name: \"propline_list_events\",\n description:\n \"List upcoming events for a sport. Returns each event's id, \" +\n \"home_team, away_team, commence_time. Use the returned event_id \" +\n \"to drill into per-event odds, props, +EV, or results.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: {\n type: \"string\",\n description:\n \"Sport key from propline_list_sports — e.g. baseball_mlb, basketball_nba\",\n },\n live: {\n type: \"boolean\",\n description:\n \"If true, only return in-progress (live) events. Defaults to false.\",\n },\n },\n required: [\"sport_key\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().listEvents(args.sport_key as string, {\n live: args.live as boolean | undefined,\n }),\n },\n {\n name: \"propline_list_event_markets\",\n description:\n \"List the market types available for a specific event (e.g. h2h, \" +\n \"spreads, totals, player_points, pitcher_strikeouts). Useful when \" +\n \"you don't know which prop markets a given event carries.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: { type: [\"string\", \"number\"] },\n },\n required: [\"sport_key\", \"event_id\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().listEventMarkets(\n args.sport_key as string,\n args.event_id as string | number,\n ),\n },\n {\n name: \"propline_get_odds\",\n description:\n \"Get live odds. If event_id is supplied, returns full per-event \" +\n \"props for that event; otherwise returns bulk game-line odds for \" +\n \"the whole sport. Pass markets as a comma-separated list (e.g. \" +\n \"'h2h,spreads,totals' or 'player_points,player_rebounds'). \" +\n \"Response includes a bookmakers[] array across every book that \" +\n \"carries the requested markets (currently up to 13: Bovada, \" +\n \"DraftKings, FanDuel, Pinnacle, BetMGM, BetRivers, Unibet, \" +\n \"Underdog, PrizePicks, Kalshi, Polymarket, Matchbook, Smarkets \" +\n \"— coverage varies by sport).\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: {\n type: [\"string\", \"number\"],\n description: \"Optional. If set, returns props for this event.\",\n },\n markets: {\n type: \"string\",\n description:\n \"Comma-separated market keys. Defaults to h2h on bulk; h2h,spreads,totals on event. Pass an explicit list to fetch player props (sport-specific — e.g. player_points,player_rebounds for NBA; pitcher_strikeouts,batter_home_runs for MLB).\",\n },\n bookmakers: {\n type: \"string\",\n description:\n \"Comma-separated subset of book keys (bovada, draftkings, fanduel, pinnacle, betmgm, betrivers, unibet, underdog, prizepicks, kalshi, polymarket, matchbook, smarkets). Default returns all available.\",\n },\n },\n required: [\"sport_key\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getOdds(args.sport_key as string, {\n eventId: args.event_id as string | number | undefined,\n markets: args.markets as string | undefined,\n bookmakers: args.bookmakers as string | undefined,\n }),\n },\n {\n name: \"propline_get_odds_history\",\n description:\n \"Pro-tier endpoint. Returns the historical line-movement snapshot \" +\n \"series for an event (every recorded price/point change per \" +\n \"outcome over the event's lifetime). Free tier returns market \" +\n \"structure with redacted snapshots and an upgrade pointer.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: { type: [\"string\", \"number\"] },\n markets: { type: \"string\" },\n },\n required: [\"sport_key\", \"event_id\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getOddsHistory(\n args.sport_key as string,\n args.event_id as string | number,\n { markets: args.markets as string | undefined },\n ),\n },\n {\n name: \"propline_get_scores\",\n description:\n \"Free-tier endpoint. Returns recent and live game scores plus \" +\n \"status (scheduled, live, final) for a sport. Useful for: 'is \" +\n \"this game over yet, what was the final score'.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n days_from: {\n type: \"number\",\n description:\n \"How many past days of completed games to include. Defaults to 1.\",\n },\n },\n required: [\"sport_key\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getScores(args.sport_key as string, {\n daysFrom: args.days_from as number | undefined,\n }),\n },\n {\n name: \"propline_get_resolution_summary\",\n description:\n \"Free-tier endpoint. Returns the factual volume of player props \" +\n \"PropLine has graded against real box scores over the last N days \" +\n \"(aggregated counts only): total graded/settled, games, sports \" +\n \"covered, plus per-sport and top-market breakdowns. Useful for: \" +\n \"'how much graded prop data does PropLine have, what's the \" +\n \"coverage'. A coverage proof, never a profitability claim.\",\n inputSchema: {\n type: \"object\",\n properties: {\n days: {\n type: \"number\",\n description: \"Look-back window, 1-90. Defaults to 30.\",\n },\n },\n required: [],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getResolutionSummary({ days: args.days as number | undefined }),\n },\n {\n name: \"propline_get_event_stats\",\n description:\n \"Book-agnostic raw box-score stats for a completed event. Returns \" +\n \"per-player stats (e.g. strikeouts, hits, points, rebounds, \" +\n \"shots-on-goal) decoupled from any sportsbook's lines. Free tier.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: { type: [\"string\", \"number\"] },\n },\n required: [\"sport_key\", \"event_id\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getEventStats(\n args.sport_key as string,\n args.event_id as string | number,\n ),\n },\n {\n name: \"propline_get_event_results\",\n description:\n \"Pro-tier endpoint. Returns graded prop outcomes for a completed \" +\n \"event — every Over/Under marked won, lost, push, or void with \" +\n \"the actual stat value next to the line. The single most \" +\n \"distinctive feature vs the-odds-api: they don't grade props at \" +\n \"any tier. Free tier returns the same structure with resolution \" +\n \"and actual_value redacted plus an upgrade pointer.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: { type: [\"string\", \"number\"] },\n },\n required: [\"sport_key\", \"event_id\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getEventResults(\n args.sport_key as string,\n args.event_id as string | number,\n ),\n },\n {\n name: \"propline_get_player_history\",\n description:\n \"Player prop history across recent games. Returns each prior prop \" +\n \"this player took with line, prices, resolution, and actual value. \" +\n \"Pro tier returns full data; free tier returns redacted \" +\n \"resolution/actual_value with an upgrade pointer.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n player_name: {\n type: \"string\",\n description:\n \"Player name as it appears in box scores — e.g. 'Aaron Judge', 'Nikola Jokic'\",\n },\n limit: {\n type: \"number\",\n description: \"Max number of past games (default 20, max 100)\",\n },\n markets: {\n type: \"string\",\n description:\n \"Comma-separated subset of markets (e.g. 'player_points,player_rebounds')\",\n },\n },\n required: [\"sport_key\", \"player_name\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getPlayerHistory(\n args.sport_key as string,\n args.player_name as string,\n {\n limit: args.limit as number | undefined,\n markets: args.markets as string | undefined,\n },\n ),\n },\n {\n name: \"propline_get_event_ev\",\n description:\n \"Pro-tier endpoint. Returns cross-book +EV per outcome for an \" +\n \"event. We anchor on Pinnacle's sharp line, remove vig, derive a \" +\n \"no-vig fair line, and compute EV% per book at the same line. \" +\n \"Outcomes are sorted with +EV plays floated to the top of each \" +\n \"line group. PrizePicks is excluded from EV math (DFS payouts \" +\n \"aren't comparable to per-book prices).\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: { type: [\"string\", \"number\"] },\n markets: { type: \"string\" },\n min_ev_pct: {\n type: \"number\",\n description: \"Filter to outcomes with EV ≥ this percent (e.g. 2.0).\",\n },\n },\n required: [\"sport_key\", \"event_id\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getEventEv(\n args.sport_key as string,\n args.event_id as string | number,\n {\n markets: args.markets as string | undefined,\n minEvPct: args.min_ev_pct as number | undefined,\n },\n ),\n },\n];\n\n// ---------------------------------------------------------------------\n// MCP server wiring\n// ---------------------------------------------------------------------\n\nconst server = new Server(\n { name: \"propline-mcp\", version: VERSION },\n { capabilities: { tools: {} } },\n);\n\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: tools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n}));\n\nserver.setRequestHandler(CallToolRequestSchema, async (req) => {\n const tool = tools.find((t) => t.name === req.params.name);\n if (!tool) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Unknown tool: ${req.params.name}`,\n },\n ],\n };\n }\n\n try {\n const data = await tool.handler(req.params.arguments ?? {});\n const text =\n typeof data === \"string\" ? data : JSON.stringify(data, null, 2);\n return {\n content: [{ type: \"text\", text }],\n };\n } catch (err) {\n const msg =\n err instanceof PropLineHTTPError\n ? `PropLine API error ${err.statusCode}: ${err.body.slice(0, 500)}`\n : err instanceof Error\n ? err.message\n : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: msg }],\n };\n }\n});\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n// stderr is fine in MCP — clients route it to logs without breaking the\n// JSON-RPC stream on stdout.\nconsole.error(`[propline-mcp ${VERSION}] connected via stdio`);\nif (!apiKey) {\n console.error(\n \"[propline-mcp] note: PROPLINE_API_KEY is not set. Tools are listed \" +\n \"for discovery, but any tool call will error until you configure it. \" +\n \"Free key: https://prop-line.com\",\n );\n}\n","/**\n * Thin REST client for the PropLine API. Mirrors the public surface of\n * the `propline` npm package but kept inline here so the MCP server has\n * zero non-MCP runtime dependencies (the official SDK is the right choice\n * for application code; MCP servers want the tightest possible install).\n */\n\nconst DEFAULT_BASE_URL = \"https://api.prop-line.com\";\n\nexport class PropLineHTTPError extends Error {\n constructor(public statusCode: number, public body: string) {\n super(`PropLine HTTP ${statusCode}: ${body.slice(0, 200)}`);\n this.name = \"PropLineHTTPError\";\n }\n}\n\nexport interface ClientOptions {\n apiKey: string;\n baseUrl?: string;\n timeoutMs?: number;\n}\n\nexport class PropLineClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n\n constructor(opts: ClientOptions) {\n if (!opts.apiKey) {\n throw new Error(\n \"PROPLINE_API_KEY is required. Get one at https://prop-line.com\",\n );\n }\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n this.timeoutMs = opts.timeoutMs ?? 20_000;\n }\n\n private async request<T = unknown>(\n path: string,\n query: Record<string, string | number | boolean | undefined> = {},\n ): Promise<T> {\n const url = new URL(this.baseUrl + path);\n for (const [k, v] of Object.entries(query)) {\n if (v !== undefined && v !== null && v !== \"\") {\n url.searchParams.set(k, String(v));\n }\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const r = await fetch(url, {\n headers: {\n \"X-API-Key\": this.apiKey,\n Accept: \"application/json\",\n \"User-Agent\": \"propline-mcp/0.1.0\",\n },\n signal: controller.signal,\n });\n const text = await r.text();\n if (!r.ok) {\n throw new PropLineHTTPError(r.status, text);\n }\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as unknown as T;\n }\n } finally {\n clearTimeout(timer);\n }\n }\n\n // ----- Discovery -----\n\n listSports(): Promise<unknown> {\n return this.request(\"/v1/sports\");\n }\n\n listEvents(sportKey: string, opts: { live?: boolean } = {}): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/events`, {\n live: opts.live ? \"true\" : undefined,\n });\n }\n\n listEventMarkets(sportKey: string, eventId: string | number): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/events/${eventId}/markets`);\n }\n\n // ----- Odds -----\n\n getOdds(\n sportKey: string,\n opts: {\n markets?: string;\n bookmakers?: string;\n eventId?: string | number;\n } = {},\n ): Promise<unknown> {\n if (opts.eventId) {\n return this.request(\n `/v1/sports/${sportKey}/events/${opts.eventId}/odds`,\n {\n markets: opts.markets,\n bookmakers: opts.bookmakers,\n },\n );\n }\n return this.request(`/v1/sports/${sportKey}/odds`, {\n markets: opts.markets,\n bookmakers: opts.bookmakers,\n });\n }\n\n getOddsHistory(\n sportKey: string,\n eventId: string | number,\n opts: { markets?: string } = {},\n ): Promise<unknown> {\n return this.request(\n `/v1/sports/${sportKey}/events/${eventId}/odds/history`,\n { markets: opts.markets },\n );\n }\n\n // ----- Scores + stats + resolution -----\n\n getScores(sportKey: string, opts: { daysFrom?: number } = {}): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/scores`, {\n daysFrom: opts.daysFrom,\n });\n }\n\n getResolutionSummary(opts: { days?: number } = {}): Promise<unknown> {\n return this.request(`/v1/markets/resolution-summary`, {\n days: opts.days,\n });\n }\n\n getEventStats(sportKey: string, eventId: string | number): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/events/${eventId}/stats`);\n }\n\n getEventResults(sportKey: string, eventId: string | number): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/events/${eventId}/results`);\n }\n\n // ----- Player history -----\n\n getPlayerHistory(\n sportKey: string,\n playerName: string,\n opts: { limit?: number; markets?: string } = {},\n ): Promise<unknown> {\n return this.request(\n `/v1/sports/${sportKey}/players/${encodeURIComponent(playerName)}/history`,\n { limit: opts.limit, markets: opts.markets },\n );\n }\n\n // ----- Cross-book +EV -----\n\n getEventEv(\n sportKey: string,\n eventId: string | number,\n opts: { markets?: string; minEvPct?: number } = {},\n ): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/events/${eventId}/ev`, {\n markets: opts.markets,\n min_ev_pct: opts.minEvPct,\n });\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client.ts"],"sourcesContent":["/**\n * PropLine MCP server.\n *\n * Exposes the PropLine REST API as Model Context Protocol tools so AI\n * clients (Claude Desktop, Claude Code, ChatGPT desktop with MCP, etc.)\n * can pull live odds, prop resolution, cross-book +EV, scores, and\n * box-score stats directly via tool calls.\n *\n * Run via: npx -y propline-mcp\n * Auth: PROPLINE_API_KEY env var (free key at https://prop-line.com)\n * Optional: PROPLINE_BASE_URL env var (override for self-hosted setups)\n */\n\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { PropLineClient, PropLineHTTPError } from \"./client.js\";\n\nexport const VERSION = \"0.3.0\";\n\nconst apiKey = process.env.PROPLINE_API_KEY;\nconst baseUrl = process.env.PROPLINE_BASE_URL;\n\n// The API key is intentionally NOT required at startup. MCP clients and\n// directory crawlers (Glama, the MCP Registry) must be able to introspect\n// the tool list before a key is configured — exiting here would make the\n// server undiscoverable and break the install-then-configure UX. The key\n// is enforced lazily on the first real tool call instead; tools/list never\n// touches the client.\nlet _client: PropLineClient | null = null;\nfunction client(): PropLineClient {\n if (!_client) {\n if (!apiKey) {\n throw new Error(\n \"PROPLINE_API_KEY is not set. Get a free key at \" +\n \"https://prop-line.com and add it to your MCP client config \" +\n \"(env var: PROPLINE_API_KEY).\",\n );\n }\n _client = new PropLineClient({ apiKey, baseUrl });\n }\n return _client;\n}\n\n// ---------------------------------------------------------------------\n// Tool definitions\n// ---------------------------------------------------------------------\n\ninterface ToolDef {\n name: string;\n description: string;\n inputSchema: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n };\n // Returns either JSON-serializable data (will be JSON.stringify'd in the\n // tool result) or a string (returned as-is).\n handler: (args: Record<string, unknown>) => Promise<unknown>;\n}\n\nconst tools: ToolDef[] = [\n {\n name: \"propline_list_sports\",\n description:\n \"List all sports PropLine currently polls. Returns sport keys \" +\n \"(e.g. baseball_mlb, basketball_nba, soccer_epl) along with human \" +\n \"titles and active status. Use this first to discover what \" +\n \"sport_key values are valid for the other tools.\",\n inputSchema: {\n type: \"object\",\n properties: {},\n additionalProperties: false,\n },\n handler: () => client().listSports(),\n },\n {\n name: \"propline_list_events\",\n description:\n \"List upcoming events for a sport. Returns each event's id, \" +\n \"home_team, away_team, commence_time. Use the returned event_id \" +\n \"to drill into per-event odds, props, +EV, or results.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: {\n type: \"string\",\n description:\n \"Sport key from propline_list_sports — e.g. baseball_mlb, basketball_nba\",\n },\n live: {\n type: \"boolean\",\n description:\n \"If true, only return in-progress (live) events. Defaults to false.\",\n },\n },\n required: [\"sport_key\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().listEvents(args.sport_key as string, {\n live: args.live as boolean | undefined,\n }),\n },\n {\n name: \"propline_list_event_markets\",\n description:\n \"List the market types available for a specific event (e.g. h2h, \" +\n \"spreads, totals, player_points, pitcher_strikeouts). Useful when \" +\n \"you don't know which prop markets a given event carries.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: { type: [\"string\", \"number\"] },\n },\n required: [\"sport_key\", \"event_id\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().listEventMarkets(\n args.sport_key as string,\n args.event_id as string | number,\n ),\n },\n {\n name: \"propline_get_odds\",\n description:\n \"Get live odds. If event_id is supplied, returns full per-event \" +\n \"props for that event; otherwise returns bulk game-line odds for \" +\n \"the whole sport. Pass markets as a comma-separated list (e.g. \" +\n \"'h2h,spreads,totals' or 'player_points,player_rebounds'). \" +\n \"Response includes a bookmakers[] array across every book that \" +\n \"carries the requested markets (currently up to 13: Bovada, \" +\n \"DraftKings, FanDuel, Pinnacle, BetMGM, BetRivers, Unibet, \" +\n \"Underdog, PrizePicks, Kalshi, Polymarket, Matchbook, Smarkets \" +\n \"— coverage varies by sport).\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: {\n type: [\"string\", \"number\"],\n description: \"Optional. If set, returns props for this event.\",\n },\n markets: {\n type: \"string\",\n description:\n \"Comma-separated market keys. Defaults to h2h on bulk; h2h,spreads,totals on event. Pass an explicit list to fetch player props (sport-specific — e.g. player_points,player_rebounds for NBA; pitcher_strikeouts,batter_home_runs for MLB).\",\n },\n bookmakers: {\n type: \"string\",\n description:\n \"Comma-separated subset of book keys (bovada, draftkings, fanduel, pinnacle, betmgm, betrivers, unibet, underdog, prizepicks, kalshi, polymarket, matchbook, smarkets). Default returns all available.\",\n },\n },\n required: [\"sport_key\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getOdds(args.sport_key as string, {\n eventId: args.event_id as string | number | undefined,\n markets: args.markets as string | undefined,\n bookmakers: args.bookmakers as string | undefined,\n }),\n },\n {\n name: \"propline_get_odds_history\",\n description:\n \"Pro-tier endpoint. Returns the historical line-movement snapshot \" +\n \"series for an event (every recorded price/point change per \" +\n \"outcome over the event's lifetime). Free tier returns market \" +\n \"structure with redacted snapshots and an upgrade pointer.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: { type: [\"string\", \"number\"] },\n markets: { type: \"string\" },\n },\n required: [\"sport_key\", \"event_id\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getOddsHistory(\n args.sport_key as string,\n args.event_id as string | number,\n { markets: args.markets as string | undefined },\n ),\n },\n {\n name: \"propline_get_scores\",\n description:\n \"Free-tier endpoint. Returns recent and live game scores plus \" +\n \"status (scheduled, live, final) for a sport. Useful for: 'is \" +\n \"this game over yet, what was the final score'.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n days_from: {\n type: \"number\",\n description:\n \"How many past days of completed games to include. Defaults to 1.\",\n },\n },\n required: [\"sport_key\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getScores(args.sport_key as string, {\n daysFrom: args.days_from as number | undefined,\n }),\n },\n {\n name: \"propline_get_mlb_grand_salami\",\n description:\n \"Free-tier endpoint. Returns the synthetic daily MLB Grand Salami \" +\n \"for a given UTC date — total runs scored across every MLB game \" +\n \"on the slate plus each book's implied Grand Salami line (median \" +\n \"of per-game primary totals across our MLB books incl. Pinnacle, \" +\n \"Polymarket, Matchbook, Smarkets). No retail sportsbook quotes \" +\n \"this as a single market. Useful for: 'what's the total run line \" +\n \"for tonight's full MLB slate', 'did the Grand Salami go over \" +\n \"yesterday', 'historical Grand Salami results for backtesting'.\",\n inputSchema: {\n type: \"object\",\n properties: {\n date: {\n type: \"string\",\n description:\n \"YYYY-MM-DD UTC date. Defaults to today (UTC) when omitted.\",\n },\n },\n required: [],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getMlbGrandSalami({\n date: args.date as string | undefined,\n }),\n },\n {\n name: \"propline_get_resolution_summary\",\n description:\n \"Free-tier endpoint. Returns the factual volume of player props \" +\n \"PropLine has graded against real box scores over the last N days \" +\n \"(aggregated counts only): total graded/settled, games, sports \" +\n \"covered, plus per-sport and top-market breakdowns. Useful for: \" +\n \"'how much graded prop data does PropLine have, what's the \" +\n \"coverage'. A coverage proof, never a profitability claim.\",\n inputSchema: {\n type: \"object\",\n properties: {\n days: {\n type: \"number\",\n description: \"Look-back window, 1-90. Defaults to 30.\",\n },\n },\n required: [],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getResolutionSummary({ days: args.days as number | undefined }),\n },\n {\n name: \"propline_get_event_stats\",\n description:\n \"Book-agnostic raw box-score stats for a completed event. Returns \" +\n \"per-player stats (e.g. strikeouts, hits, points, rebounds, \" +\n \"shots-on-goal) decoupled from any sportsbook's lines. Free tier.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: { type: [\"string\", \"number\"] },\n },\n required: [\"sport_key\", \"event_id\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getEventStats(\n args.sport_key as string,\n args.event_id as string | number,\n ),\n },\n {\n name: \"propline_get_event_results\",\n description:\n \"Pro-tier endpoint. Returns graded prop outcomes for a completed \" +\n \"event — every Over/Under marked won, lost, push, or void with \" +\n \"the actual stat value next to the line. The single most \" +\n \"distinctive feature vs the-odds-api: they don't grade props at \" +\n \"any tier. Free tier returns the same structure with resolution \" +\n \"and actual_value redacted plus an upgrade pointer.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: { type: [\"string\", \"number\"] },\n },\n required: [\"sport_key\", \"event_id\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getEventResults(\n args.sport_key as string,\n args.event_id as string | number,\n ),\n },\n {\n name: \"propline_get_player_history\",\n description:\n \"Player prop history across recent games. Returns each prior prop \" +\n \"this player took with line, prices, resolution, and actual value. \" +\n \"Pro tier returns full data; free tier returns redacted \" +\n \"resolution/actual_value with an upgrade pointer.\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n player_name: {\n type: \"string\",\n description:\n \"Player name as it appears in box scores — e.g. 'Aaron Judge', 'Nikola Jokic'\",\n },\n limit: {\n type: \"number\",\n description: \"Max number of past games (default 20, max 100)\",\n },\n markets: {\n type: \"string\",\n description:\n \"Comma-separated subset of markets (e.g. 'player_points,player_rebounds')\",\n },\n },\n required: [\"sport_key\", \"player_name\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getPlayerHistory(\n args.sport_key as string,\n args.player_name as string,\n {\n limit: args.limit as number | undefined,\n markets: args.markets as string | undefined,\n },\n ),\n },\n {\n name: \"propline_get_event_ev\",\n description:\n \"Pro-tier endpoint. Returns cross-book +EV per outcome for an \" +\n \"event. We anchor on Pinnacle's sharp line, remove vig, derive a \" +\n \"no-vig fair line, and compute EV% per book at the same line. \" +\n \"Outcomes are sorted with +EV plays floated to the top of each \" +\n \"line group. PrizePicks is excluded from EV math (DFS payouts \" +\n \"aren't comparable to per-book prices).\",\n inputSchema: {\n type: \"object\",\n properties: {\n sport_key: { type: \"string\" },\n event_id: { type: [\"string\", \"number\"] },\n markets: { type: \"string\" },\n min_ev_pct: {\n type: \"number\",\n description: \"Filter to outcomes with EV ≥ this percent (e.g. 2.0).\",\n },\n },\n required: [\"sport_key\", \"event_id\"],\n additionalProperties: false,\n },\n handler: (args) =>\n client().getEventEv(\n args.sport_key as string,\n args.event_id as string | number,\n {\n markets: args.markets as string | undefined,\n minEvPct: args.min_ev_pct as number | undefined,\n },\n ),\n },\n];\n\n// ---------------------------------------------------------------------\n// MCP server wiring\n// ---------------------------------------------------------------------\n\nconst server = new Server(\n { name: \"propline-mcp\", version: VERSION },\n { capabilities: { tools: {} } },\n);\n\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: tools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n}));\n\nserver.setRequestHandler(CallToolRequestSchema, async (req) => {\n const tool = tools.find((t) => t.name === req.params.name);\n if (!tool) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Unknown tool: ${req.params.name}`,\n },\n ],\n };\n }\n\n try {\n const data = await tool.handler(req.params.arguments ?? {});\n const text =\n typeof data === \"string\" ? data : JSON.stringify(data, null, 2);\n return {\n content: [{ type: \"text\", text }],\n };\n } catch (err) {\n const msg =\n err instanceof PropLineHTTPError\n ? `PropLine API error ${err.statusCode}: ${err.body.slice(0, 500)}`\n : err instanceof Error\n ? err.message\n : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: msg }],\n };\n }\n});\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n// stderr is fine in MCP — clients route it to logs without breaking the\n// JSON-RPC stream on stdout.\nconsole.error(`[propline-mcp ${VERSION}] connected via stdio`);\nif (!apiKey) {\n console.error(\n \"[propline-mcp] note: PROPLINE_API_KEY is not set. Tools are listed \" +\n \"for discovery, but any tool call will error until you configure it. \" +\n \"Free key: https://prop-line.com\",\n );\n}\n","/**\n * Thin REST client for the PropLine API. Mirrors the public surface of\n * the `propline` npm package but kept inline here so the MCP server has\n * zero non-MCP runtime dependencies (the official SDK is the right choice\n * for application code; MCP servers want the tightest possible install).\n */\n\nconst DEFAULT_BASE_URL = \"https://api.prop-line.com\";\n\nexport class PropLineHTTPError extends Error {\n constructor(public statusCode: number, public body: string) {\n super(`PropLine HTTP ${statusCode}: ${body.slice(0, 200)}`);\n this.name = \"PropLineHTTPError\";\n }\n}\n\nexport interface ClientOptions {\n apiKey: string;\n baseUrl?: string;\n timeoutMs?: number;\n}\n\nexport class PropLineClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n\n constructor(opts: ClientOptions) {\n if (!opts.apiKey) {\n throw new Error(\n \"PROPLINE_API_KEY is required. Get one at https://prop-line.com\",\n );\n }\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n this.timeoutMs = opts.timeoutMs ?? 20_000;\n }\n\n private async request<T = unknown>(\n path: string,\n query: Record<string, string | number | boolean | undefined> = {},\n ): Promise<T> {\n const url = new URL(this.baseUrl + path);\n for (const [k, v] of Object.entries(query)) {\n if (v !== undefined && v !== null && v !== \"\") {\n url.searchParams.set(k, String(v));\n }\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const r = await fetch(url, {\n headers: {\n \"X-API-Key\": this.apiKey,\n Accept: \"application/json\",\n \"User-Agent\": \"propline-mcp/0.1.0\",\n },\n signal: controller.signal,\n });\n const text = await r.text();\n if (!r.ok) {\n throw new PropLineHTTPError(r.status, text);\n }\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as unknown as T;\n }\n } finally {\n clearTimeout(timer);\n }\n }\n\n // ----- Discovery -----\n\n listSports(): Promise<unknown> {\n return this.request(\"/v1/sports\");\n }\n\n listEvents(sportKey: string, opts: { live?: boolean } = {}): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/events`, {\n live: opts.live ? \"true\" : undefined,\n });\n }\n\n listEventMarkets(sportKey: string, eventId: string | number): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/events/${eventId}/markets`);\n }\n\n // ----- Odds -----\n\n getOdds(\n sportKey: string,\n opts: {\n markets?: string;\n bookmakers?: string;\n eventId?: string | number;\n } = {},\n ): Promise<unknown> {\n if (opts.eventId) {\n return this.request(\n `/v1/sports/${sportKey}/events/${opts.eventId}/odds`,\n {\n markets: opts.markets,\n bookmakers: opts.bookmakers,\n },\n );\n }\n return this.request(`/v1/sports/${sportKey}/odds`, {\n markets: opts.markets,\n bookmakers: opts.bookmakers,\n });\n }\n\n getOddsHistory(\n sportKey: string,\n eventId: string | number,\n opts: { markets?: string } = {},\n ): Promise<unknown> {\n return this.request(\n `/v1/sports/${sportKey}/events/${eventId}/odds/history`,\n { markets: opts.markets },\n );\n }\n\n // ----- Scores + stats + resolution -----\n\n getScores(sportKey: string, opts: { daysFrom?: number } = {}): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/scores`, {\n daysFrom: opts.daysFrom,\n });\n }\n\n getMlbGrandSalami(opts: { date?: string } = {}): Promise<unknown> {\n return this.request(`/v1/sports/baseball_mlb/grand-salami`, {\n date: opts.date,\n });\n }\n\n getResolutionSummary(opts: { days?: number } = {}): Promise<unknown> {\n return this.request(`/v1/markets/resolution-summary`, {\n days: opts.days,\n });\n }\n\n getEventStats(sportKey: string, eventId: string | number): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/events/${eventId}/stats`);\n }\n\n getEventResults(sportKey: string, eventId: string | number): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/events/${eventId}/results`);\n }\n\n // ----- Player history -----\n\n getPlayerHistory(\n sportKey: string,\n playerName: string,\n opts: { limit?: number; markets?: string } = {},\n ): Promise<unknown> {\n return this.request(\n `/v1/sports/${sportKey}/players/${encodeURIComponent(playerName)}/history`,\n { limit: opts.limit, markets: opts.markets },\n );\n }\n\n // ----- Cross-book +EV -----\n\n getEventEv(\n sportKey: string,\n eventId: string | number,\n opts: { markets?: string; minEvPct?: number } = {},\n ): Promise<unknown> {\n return this.request(`/v1/sports/${sportKey}/events/${eventId}/ev`, {\n markets: opts.markets,\n min_ev_pct: opts.minEvPct,\n });\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "propline-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"mcpName": "io.github.proplineapi/propline-mcp",
|
|
5
5
|
"description": "Model Context Protocol server for the PropLine player props betting odds API. Exposes live odds, prop resolution, cross-book +EV, scores, and box-score stats as tool calls for Claude Desktop, Claude Code, and any MCP-compatible client.",
|
|
6
6
|
"keywords": [
|