propline-mcp 0.39.0 → 0.41.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/README.md CHANGED
@@ -27,7 +27,7 @@ The model uses these tools transparently:
27
27
  | `propline_list_sports` | Discover what sports PropLine polls (54 today) |
28
28
  | `propline_list_events` | Upcoming events for a sport, with ids |
29
29
  | `propline_list_event_markets` | Available market types for an event |
30
- | `propline_get_odds` | Live odds — bulk by sport or full props per event. Accepts `period` (q1/h1/p1/f5/…) to scope to game-period markets. |
30
+ | `propline_get_odds` | Live odds — bulk by sport or full props per event. Accepts `period` (q1/h1/p1/f5/…) to scope to game-period markets; `include_depth` adds order-book depth per outcome. |
31
31
  | `propline_get_odds_history` | Hobby+: snapshot history per outcome; supports `period` (q1/h1/…) plus time-window filters (from/to, relative_from/relative_to, interval, changes_only) |
32
32
  | `propline_get_odds_closing` | Hobby+: opening **and** closing line per (book, market, outcome) — CLV helper. Accepts `period` to scope to a specific game period. |
33
33
  | `propline_grade_clv` | Hobby+: grade **placed** bets against their closing lines. Returns closing price, de-vigged closing fair (`fair_source` = sharpest book at close, not yours), `clv_pct` (price-vs-price, vig-blind) **and** `ev_vs_close_pct` (the honest number), plus the graded result once the game settles. Fail-closed matching; unstarted events come back `closing_is_final: false` and are excluded from the averages. `devig`: multiplicative or shin. |
@@ -41,7 +41,7 @@ The model uses these tools transparently:
41
41
  | `propline_get_resolution_summary` | Graded-prop volume + per-sport/market breakdown (free) |
42
42
  | `propline_get_event_stats` | Raw box-score stats (free, book-agnostic) |
43
43
  | `propline_get_event_context` | Game conditions a prop settles under — probable pitchers, lineup flag, home-plate umpire, first-pitch weather (free) |
44
- | `propline_get_event_movement` | Line movement + steam detection (sharp-money signal across all books) from the tick history (Hobby+) |
44
+ | `propline_get_event_movement` | Line movement + steam detection (sharp-money signal across all books) from the tick history (Hobby+). `since` (e.g. `-6h`) measures from a moment; `include_book_ids` adds book ids. |
45
45
  | `propline_get_event_results` | Pro: graded won/lost/push per prop |
46
46
  | `propline_get_player_history` | Player prop history with resolution |
47
47
  | `propline_get_player_games` | Player game log — recent games with every raw box-score stat per game, one call instead of one per event; `opponent` gives head-to-head (last N *meetings*). Raw-stat archive, so it includes games no book priced |
package/dist/http.js CHANGED
@@ -123,7 +123,8 @@ var PropLineClient = class {
123
123
  bookmakers: opts.bookmakers,
124
124
  period: opts.period,
125
125
  includeLinks: opts.includeLinks ? "true" : void 0,
126
- includeBookIds: opts.includeBookIds ? "true" : void 0
126
+ includeBookIds: opts.includeBookIds ? "true" : void 0,
127
+ includeDepth: opts.includeDepth ? "true" : void 0
127
128
  };
128
129
  if (opts.eventId) {
129
130
  return this.request(
@@ -243,8 +244,11 @@ var PropLineClient = class {
243
244
  getEventStats(sportKey, eventId) {
244
245
  return this.request(`/v1/sports/${sportKey}/events/${eventId}/stats`);
245
246
  }
246
- getEventResults(sportKey, eventId) {
247
- return this.request(`/v1/sports/${sportKey}/events/${eventId}/results`);
247
+ getEventResults(sportKey, eventId, opts = {}) {
248
+ return this.request(`/v1/sports/${sportKey}/events/${eventId}/results`, {
249
+ markets: opts.markets,
250
+ bookmakers: opts.bookmakers
251
+ });
248
252
  }
249
253
  getEventContext(sportKey, eventId) {
250
254
  return this.request(`/v1/sports/${sportKey}/events/${eventId}/context`);
@@ -252,7 +256,13 @@ var PropLineClient = class {
252
256
  getEventMovement(sportKey, eventId, opts = {}) {
253
257
  return this.request(
254
258
  `/v1/sports/${sportKey}/events/${eventId}/movement`,
255
- { markets: opts.markets, bookmakers: opts.bookmakers, period: opts.period }
259
+ {
260
+ markets: opts.markets,
261
+ bookmakers: opts.bookmakers,
262
+ period: opts.period,
263
+ since: opts.since,
264
+ includeBookIds: opts.includeBookIds ? "true" : void 0
265
+ }
256
266
  );
257
267
  }
258
268
  // ----- Player history -----
@@ -321,7 +331,7 @@ var PropLineClient = class {
321
331
  };
322
332
 
323
333
  // src/server.ts
324
- var VERSION = "0.39.0";
334
+ var VERSION = "0.41.0";
325
335
  var DEMO_KEY = "be2b8487fcfacb1fbc292a8aa925a84c";
326
336
  var apiKey = process.env.PROPLINE_API_KEY;
327
337
  var baseUrl = process.env.PROPLINE_BASE_URL;
@@ -425,7 +435,7 @@ var tools = [
425
435
  {
426
436
  name: "propline_get_odds",
427
437
  title: "Get odds",
428
- description: "Get live odds. If event_id is supplied, returns full per-event props for that event; otherwise returns bulk game-line odds for the whole sport. Pass markets as a comma-separated list (e.g. 'h2h,spreads,totals' or 'player_points,player_rebounds'). Response includes a bookmakers[] array across every book that carries the requested markets (currently up to 27: Bovada, DraftKings, FanDuel, Pinnacle, BetMGM, BetRivers, Unibet, BetUS, BetOnline.ag, LowVig.ag, MyBookie.ag, Fanatics, Marathon Bet, 1xBet, TAB, Underdog Fantasy, PrizePicks, Sleeper, Dabble, Betr Picks, ReBet, Kalshi, Polymarket, Matchbook, Smarkets, Novig, ProphetX \u2014 coverage varies by sport). Underdog Fantasy outcomes carry a payout_multiplier on EVERY outcome (1.0 = standard pick, e.g. 1.5 = boost, 0.75 = discount; null means the book is not Underdog) \u2014 keep only payout_multiplier == 1.0 when comparing DFS lines to sportsbook consensus, since filtering on non-null would drop every Underdog line. Each market carries suspended_at: null while on the board, set when that book pulled the market pregame (late scratch, dropped market type) \u2014 its outcomes are then the last quoted legs, not a live price. Treat a suspended market as unbettable and, if several books show it for one player, as a probable scratch. Each BOOKMAKER carries pregame_only: true when the event is live and that book does not price it in play, so its prices are the last pregame quote and will never move again this game. suspended_at cannot show this \u2014 a book with no in-play feed is never polled once the game starts, so nothing goes missing to flag. Exclude pregame_only books when reasoning about a live game; they are still returned because on DFS books that frozen line is what the bet settles against. Each market also carries team: the canonical event team name when the market is scoped to ONE team (a TEAM total), and null for the game total. Both ride the totals key, so NEVER compare totals on (market key, point) alone \u2014 a team total at 0.5 is not a game total at 0.5. Filter team == null for the game total; team matches home_team/away_team exactly. Always null outside totals.",
438
+ description: "Get live odds. If event_id is supplied, returns full per-event props for that event; otherwise returns bulk game-line odds for the whole sport. Pass markets as a comma-separated list (e.g. 'h2h,spreads,totals' or 'player_points,player_rebounds'). Response includes a bookmakers[] array across every book that carries the requested markets (currently up to 27: Bovada, DraftKings, FanDuel, Pinnacle, BetMGM, BetRivers, Unibet, BetUS, BetOnline.ag, LowVig.ag, MyBookie.ag, Fanatics, Marathon Bet, 1xBet, TAB, Underdog Fantasy, PrizePicks, Sleeper, Dabble, Betr Picks, ReBet, Kalshi, Polymarket, Matchbook, Smarkets, Novig, ProphetX \u2014 coverage varies by sport). Underdog Fantasy outcomes carry a payout_multiplier on EVERY outcome (1.0 = standard pick, e.g. 1.5 = boost, 0.75 = discount; null means the book is not Underdog) \u2014 keep only payout_multiplier == 1.0 when comparing DFS lines to sportsbook consensus, since filtering on non-null would drop every Underdog line. Each market carries suspended_at: null while on the board, set when that book pulled the market pregame (late scratch, dropped market type) \u2014 its outcomes are then the last quoted legs, not a live price. Treat a suspended market as unbettable and, if several books show it for one player, as a probable scratch. Each BOOKMAKER carries pregame_only: true when the event is live and that book does not price it in play, so its prices are the last pregame quote and will never move again this game. suspended_at cannot show this \u2014 a book with no in-play feed is never polled once the game starts, so nothing goes missing to flag. Exclude pregame_only books when reasoning about a live game; they are still returned because on DFS books that frozen line is what the bet settles against. Each market also carries team: the canonical event team name when the market is scoped to ONE team (a TEAM total), and null for the game total. Both ride the totals key, so NEVER compare totals on (market key, point) alone \u2014 a team total at 0.5 is not a game total at 0.5. Filter team == null for the game total; team matches home_team/away_team exactly. Always null outside totals. Each outcome carries side ('home'/'away'/'draw', null for Over/Under/Yes/No/player legs) so you can pair legs without matching team spellings. Each event carries is_outright (true for a tournament listing with no away side) and, on tennis, tournament + tour (ATP/WTA/Challenger/ITF/\u2026).",
429
439
  inputSchema: {
430
440
  type: "object",
431
441
  properties: {
@@ -453,6 +463,10 @@ var tools = [
453
463
  include_book_ids: {
454
464
  type: "boolean",
455
465
  description: "When true, each bookmaker block carries book_event_id and each outcome carries book_outcome_id \u2014 that book's OWN ids for the event and the priced selection, for joining onto a book's native feed by id instead of matching team/player names and lines. Kalshi ships both (event ticker + per-contract market ticker, e.g. KXMLBGAME-26AUG08NYYBOS-NYY); most other books ship an event id; books without a stable id return null. NB a two-sided market can share ONE book_outcome_id across both legs \u2014 a Kalshi contract is binary, so Over/Under are its YES/NO sides; the outcome's name says which side."
466
+ },
467
+ include_depth: {
468
+ type: "boolean",
469
+ description: "When true, every outcome carries depth: up to three order-book levels beyond the served price, each {price (American), size (dollars)}. [] for books whose depth PropLine does not read (sportsbooks)."
456
470
  }
457
471
  },
458
472
  required: ["sport_key"],
@@ -464,7 +478,8 @@ var tools = [
464
478
  bookmakers: args.bookmakers,
465
479
  period: args.period,
466
480
  includeLinks: args.include_links,
467
- includeBookIds: args.include_book_ids
481
+ includeBookIds: args.include_book_ids,
482
+ includeDepth: args.include_depth
468
483
  })
469
484
  },
470
485
  {
@@ -852,14 +867,26 @@ var tools = [
852
867
  type: "object",
853
868
  properties: {
854
869
  sport_key: { type: "string" },
855
- event_id: { type: ["string", "number"] }
870
+ event_id: { type: ["string", "number"] },
871
+ markets: {
872
+ type: "string",
873
+ description: "Comma-separated market keys to restrict to (e.g. pitcher_strikeouts,batter_hits)."
874
+ },
875
+ bookmakers: {
876
+ type: "string",
877
+ description: "Comma-separated book keys to restrict to (e.g. bovada). Default returns all books; an unfiltered MLB game can run several MB, so pass one book when that is enough."
878
+ }
856
879
  },
857
880
  required: ["sport_key", "event_id"],
858
881
  additionalProperties: false
859
882
  },
860
883
  handler: (args) => client().getEventResults(
861
884
  args.sport_key,
862
- args.event_id
885
+ args.event_id,
886
+ {
887
+ markets: args.markets,
888
+ bookmakers: args.bookmakers
889
+ }
863
890
  )
864
891
  },
865
892
  {
@@ -883,7 +910,7 @@ var tools = [
883
910
  {
884
911
  name: "propline_get_event_movement",
885
912
  title: "Get line movement & steam",
886
- description: "Line movement + steam detection from the snapshot tick history. Per (book, market, outcome): opening line, latest line, signed implied-probability shift, point shift, direction. The steam[] array flags outcomes that multiple books moved the same direction \u2014 the classic sharp-money signal, computed across all 27 books PropLine polls. When a book moves the line itself, that outcome's prob_shift is null and direction is 'line_moved' (excluded from the steam signal). No pull-only odds API can produce this. Hobby+ full; free tier redacted.",
913
+ description: "Line movement + steam detection from the snapshot tick history. Per (book, market, outcome): opening line, latest line, signed implied-probability shift, point shift, direction. The steam[] array flags outcomes that multiple books moved the same direction \u2014 the classic sharp-money signal, computed across all 27 books PropLine polls. When a book moves the line itself, that outcome's prob_shift is null and direction is 'line_moved' (excluded from the steam signal). No pull-only odds API can produce this. Each outcome carries outcome_id (the id /odds and webhooks use); steam rows carry team (team totals) plus open_point/latest_point. Hobby+ full; free tier redacted.",
887
914
  inputSchema: {
888
915
  type: "object",
889
916
  properties: {
@@ -900,6 +927,14 @@ var tools = [
900
927
  period: {
901
928
  type: "string",
902
929
  description: "Game-period filter (q1..q4, h1/h2, p1..p3, i1..i9, f3/f5/f7; comma-separated, or 'all'). Omit for full-game."
930
+ },
931
+ since: {
932
+ type: "string",
933
+ description: "Measure movement from this moment instead of each line's first quote: ISO-8601 timestamp or a negative offset from now ('-6h', '-30m', '-2d'). Steam then covers only moves inside the window."
934
+ },
935
+ include_book_ids: {
936
+ type: "boolean",
937
+ description: "When true, each outcome also carries book_outcome_id \u2014 the book's own selection id."
903
938
  }
904
939
  },
905
940
  required: ["sport_key", "event_id"],
@@ -911,7 +946,9 @@ var tools = [
911
946
  {
912
947
  markets: args.markets,
913
948
  bookmakers: args.bookmakers,
914
- period: args.period
949
+ period: args.period,
950
+ since: args.since,
951
+ includeBookIds: args.include_book_ids
915
952
  }
916
953
  )
917
954
  },