propline-mcp 0.39.0 → 0.40.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(
@@ -252,7 +253,13 @@ var PropLineClient = class {
252
253
  getEventMovement(sportKey, eventId, opts = {}) {
253
254
  return this.request(
254
255
  `/v1/sports/${sportKey}/events/${eventId}/movement`,
255
- { markets: opts.markets, bookmakers: opts.bookmakers, period: opts.period }
256
+ {
257
+ markets: opts.markets,
258
+ bookmakers: opts.bookmakers,
259
+ period: opts.period,
260
+ since: opts.since,
261
+ includeBookIds: opts.includeBookIds ? "true" : void 0
262
+ }
256
263
  );
257
264
  }
258
265
  // ----- Player history -----
@@ -321,7 +328,7 @@ var PropLineClient = class {
321
328
  };
322
329
 
323
330
  // src/server.ts
324
- var VERSION = "0.39.0";
331
+ var VERSION = "0.40.0";
325
332
  var DEMO_KEY = "be2b8487fcfacb1fbc292a8aa925a84c";
326
333
  var apiKey = process.env.PROPLINE_API_KEY;
327
334
  var baseUrl = process.env.PROPLINE_BASE_URL;
@@ -425,7 +432,7 @@ var tools = [
425
432
  {
426
433
  name: "propline_get_odds",
427
434
  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.",
435
+ 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
436
  inputSchema: {
430
437
  type: "object",
431
438
  properties: {
@@ -453,6 +460,10 @@ var tools = [
453
460
  include_book_ids: {
454
461
  type: "boolean",
455
462
  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."
463
+ },
464
+ include_depth: {
465
+ type: "boolean",
466
+ 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
467
  }
457
468
  },
458
469
  required: ["sport_key"],
@@ -464,7 +475,8 @@ var tools = [
464
475
  bookmakers: args.bookmakers,
465
476
  period: args.period,
466
477
  includeLinks: args.include_links,
467
- includeBookIds: args.include_book_ids
478
+ includeBookIds: args.include_book_ids,
479
+ includeDepth: args.include_depth
468
480
  })
469
481
  },
470
482
  {
@@ -883,7 +895,7 @@ var tools = [
883
895
  {
884
896
  name: "propline_get_event_movement",
885
897
  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.",
898
+ 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
899
  inputSchema: {
888
900
  type: "object",
889
901
  properties: {
@@ -900,6 +912,14 @@ var tools = [
900
912
  period: {
901
913
  type: "string",
902
914
  description: "Game-period filter (q1..q4, h1/h2, p1..p3, i1..i9, f3/f5/f7; comma-separated, or 'all'). Omit for full-game."
915
+ },
916
+ since: {
917
+ type: "string",
918
+ 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."
919
+ },
920
+ include_book_ids: {
921
+ type: "boolean",
922
+ description: "When true, each outcome also carries book_outcome_id \u2014 the book's own selection id."
903
923
  }
904
924
  },
905
925
  required: ["sport_key", "event_id"],
@@ -911,7 +931,9 @@ var tools = [
911
931
  {
912
932
  markets: args.markets,
913
933
  bookmakers: args.bookmakers,
914
- period: args.period
934
+ period: args.period,
935
+ since: args.since,
936
+ includeBookIds: args.include_book_ids
915
937
  }
916
938
  )
917
939
  },