vlrdevapi 3.0.0__tar.gz → 3.1.0__tar.gz

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.
Files changed (240) hide show
  1. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.github/workflows/docs-check.yml +1 -1
  2. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.github/workflows/publish.yml +2 -2
  3. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.github/workflows/test.yml +6 -2
  4. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.gitignore +3 -1
  5. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/CHANGELOG.md +50 -0
  6. vlrdevapi-3.0.0/README.md → vlrdevapi-3.1.0/PKG-INFO +157 -7
  7. vlrdevapi-3.0.0/PKG-INFO → vlrdevapi-3.1.0/README.md +86 -56
  8. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/pyproject.toml +34 -2
  9. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/scripts/download_fixtures.py +10 -7
  10. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/__init__.py +1 -1
  11. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/info/models.py +23 -1
  12. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/list/models.py +32 -2
  13. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/matches/models.py +32 -1
  14. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/stages/models.py +17 -1
  15. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/standings/models.py +27 -1
  16. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/teams/models.py +43 -1
  17. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/completed/models.py +45 -1
  18. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/live/models.py +38 -1
  19. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/upcoming/models.py +42 -1
  20. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/article/models.py +24 -2
  21. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/list/models.py +25 -1
  22. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/namespace.py +10 -0
  23. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/_common_parsing.py +2 -2
  24. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/agents/models.py +47 -1
  25. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/info/models.py +25 -2
  26. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/matches/models.py +32 -1
  27. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/placements/models.py +23 -1
  28. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/profile/models.py +27 -2
  29. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/teams/models.py +31 -1
  30. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/economy/models.py +70 -3
  31. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/info/models.py +61 -2
  32. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/performance/models.py +64 -1
  33. vlrdevapi-3.1.0/src/vlrdevapi/_series/players/models.py +280 -0
  34. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/players/namespace.py +2 -0
  35. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/players/parser.py +63 -35
  36. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/replay/models.py +68 -1
  37. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/rounds/models.py +43 -1
  38. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/vods/models.py +37 -1
  39. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/completed_matches/models.py +35 -1
  40. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/info/models.py +24 -1
  41. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/info/namespace.py +0 -1
  42. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/placements/models.py +36 -1
  43. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/roster/models.py +25 -1
  44. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/stats/models.py +27 -2
  45. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/transactions/models.py +23 -1
  46. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/upcoming_matches/models.py +32 -1
  47. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/commons/__init__.py +2 -0
  48. vlrdevapi-3.1.0/src/vlrdevapi/commons/export.py +306 -0
  49. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/exceptions.py +5 -0
  50. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/fetcher.py +9 -1
  51. vlrdevapi-3.1.0/src/vlrdevapi/mcp/__init__.py +5 -0
  52. vlrdevapi-3.1.0/src/vlrdevapi/mcp/_common.py +69 -0
  53. vlrdevapi-3.1.0/src/vlrdevapi/mcp/server.py +33 -0
  54. vlrdevapi-3.1.0/src/vlrdevapi/mcp/tools/__init__.py +35 -0
  55. vlrdevapi-3.1.0/src/vlrdevapi/mcp/tools/composite.py +179 -0
  56. vlrdevapi-3.1.0/src/vlrdevapi/mcp/tools/events.py +88 -0
  57. vlrdevapi-3.1.0/src/vlrdevapi/mcp/tools/matches.py +40 -0
  58. vlrdevapi-3.1.0/src/vlrdevapi/mcp/tools/news.py +30 -0
  59. vlrdevapi-3.1.0/src/vlrdevapi/mcp/tools/players.py +74 -0
  60. vlrdevapi-3.1.0/src/vlrdevapi/mcp/tools/series.py +105 -0
  61. vlrdevapi-3.1.0/src/vlrdevapi/mcp/tools/teams.py +91 -0
  62. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/validators.py +2 -1
  63. vlrdevapi-3.1.0/uv.lock +2111 -0
  64. vlrdevapi-3.0.0/src/vlrdevapi/_series/players/models.py +0 -84
  65. vlrdevapi-3.0.0/uv.lock +0 -1165
  66. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.gitattributes +0 -0
  67. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  68. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  69. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.github/workflows/cleanup-caches.yml +0 -0
  70. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.nvmrc +0 -0
  71. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.python-version +0 -0
  72. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/.readthedocs.yaml +0 -0
  73. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/CODE_OF_CONDUCT.md +0 -0
  74. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/CONTRIBUTING.md +0 -0
  75. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/LICENCE +0 -0
  76. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/SECURITY.md +0 -0
  77. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/SUPPORT.md +0 -0
  78. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/scripts/check_mdx_examples.py +0 -0
  79. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/__init__.pyi +0 -0
  80. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_base.py +0 -0
  81. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_cache.py +0 -0
  82. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_client.py +0 -0
  83. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/__init__.py +0 -0
  84. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/_common.py +0 -0
  85. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/info/__init__.py +0 -0
  86. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/info/namespace.py +0 -0
  87. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/info/namespace.pyi +0 -0
  88. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/info/parser.py +0 -0
  89. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/list/__init__.py +0 -0
  90. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/list/namespace.py +0 -0
  91. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/list/namespace.pyi +0 -0
  92. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/list/parser.py +0 -0
  93. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/matches/__init__.py +0 -0
  94. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/matches/namespace.py +0 -0
  95. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/matches/namespace.pyi +0 -0
  96. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/matches/parser.py +0 -0
  97. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/namespace.py +0 -0
  98. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/namespace.pyi +0 -0
  99. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/stages/__init__.py +0 -0
  100. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/stages/namespace.py +0 -0
  101. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/stages/namespace.pyi +0 -0
  102. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/stages/parser.py +0 -0
  103. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/standings/__init__.py +0 -0
  104. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/standings/namespace.py +0 -0
  105. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/standings/namespace.pyi +0 -0
  106. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/standings/parser.py +0 -0
  107. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/teams/__init__.py +0 -0
  108. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/teams/namespace.py +0 -0
  109. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/teams/namespace.pyi +0 -0
  110. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_event/teams/parser.py +0 -0
  111. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/__init__.py +0 -0
  112. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/common.py +0 -0
  113. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/completed/__init__.py +0 -0
  114. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/completed/namespace.py +0 -0
  115. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/completed/namespace.pyi +0 -0
  116. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/completed/parser.py +0 -0
  117. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/live/__init__.py +0 -0
  118. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/live/namespace.py +0 -0
  119. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/live/namespace.pyi +0 -0
  120. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/live/parser.py +0 -0
  121. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/namespace.py +0 -0
  122. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/namespace.pyi +0 -0
  123. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/upcoming/__init__.py +0 -0
  124. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/upcoming/namespace.py +0 -0
  125. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/upcoming/namespace.pyi +0 -0
  126. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_matches/upcoming/parser.py +0 -0
  127. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/__init__.py +0 -0
  128. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/article/__init__.py +0 -0
  129. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/article/namespace.py +0 -0
  130. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/article/namespace.pyi +0 -0
  131. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/article/parser.py +0 -0
  132. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/common.py +0 -0
  133. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/list/__init__.py +0 -0
  134. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/list/namespace.py +0 -0
  135. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/list/namespace.pyi +0 -0
  136. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/list/parser.py +0 -0
  137. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_news/namespace.pyi +0 -0
  138. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/__init__.py +0 -0
  139. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/agents/__init__.py +0 -0
  140. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/agents/namespace.py +0 -0
  141. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/agents/namespace.pyi +0 -0
  142. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/agents/parser.py +0 -0
  143. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/info/__init__.py +0 -0
  144. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/info/namespace.py +0 -0
  145. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/info/namespace.pyi +0 -0
  146. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/info/parser.py +0 -0
  147. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/matches/__init__.py +0 -0
  148. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/matches/namespace.py +0 -0
  149. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/matches/namespace.pyi +0 -0
  150. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/matches/parser.py +0 -0
  151. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/namespace.py +0 -0
  152. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/namespace.pyi +0 -0
  153. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/placements/__init__.py +0 -0
  154. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/placements/namespace.py +0 -0
  155. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/placements/namespace.pyi +0 -0
  156. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/placements/parser.py +0 -0
  157. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/profile/__init__.py +0 -0
  158. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/profile/namespace.py +0 -0
  159. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/profile/namespace.pyi +0 -0
  160. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/profile/parser.py +0 -0
  161. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/teams/__init__.py +0 -0
  162. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/teams/namespace.py +0 -0
  163. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/teams/namespace.pyi +0 -0
  164. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_player/teams/parser.py +0 -0
  165. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/__init__.py +0 -0
  166. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/_utils.py +0 -0
  167. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/economy/__init__.py +0 -0
  168. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/economy/namespace.py +0 -0
  169. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/economy/namespace.pyi +0 -0
  170. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/economy/parser.py +0 -0
  171. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/info/__init__.py +0 -0
  172. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/info/namespace.py +0 -0
  173. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/info/namespace.pyi +0 -0
  174. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/info/parser.py +0 -0
  175. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/match_namespace.py +0 -0
  176. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/match_namespace.pyi +0 -0
  177. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/namespace.py +0 -0
  178. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/namespace.pyi +0 -0
  179. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/performance/__init__.py +0 -0
  180. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/performance/namespace.py +0 -0
  181. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/performance/namespace.pyi +0 -0
  182. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/performance/parser.py +0 -0
  183. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/players/__init__.py +0 -0
  184. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/players/namespace.pyi +0 -0
  185. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/replay/__init__.py +0 -0
  186. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/replay/namespace.py +0 -0
  187. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/replay/namespace.pyi +0 -0
  188. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/replay/parser.py +0 -0
  189. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/rounds/__init__.py +0 -0
  190. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/rounds/namespace.py +0 -0
  191. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/rounds/namespace.pyi +0 -0
  192. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/rounds/parser.py +0 -0
  193. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/vods/__init__.py +0 -0
  194. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/vods/namespace.py +0 -0
  195. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/vods/namespace.pyi +0 -0
  196. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_series/vods/parser.py +0 -0
  197. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/__init__.py +0 -0
  198. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/completed_matches/__init__.py +0 -0
  199. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/completed_matches/namespace.py +0 -0
  200. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/completed_matches/namespace.pyi +0 -0
  201. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/completed_matches/parser.py +0 -0
  202. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/info/__init__.py +0 -0
  203. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/info/namespace.pyi +0 -0
  204. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/info/parser.py +0 -0
  205. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/namespace.py +0 -0
  206. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/namespace.pyi +0 -0
  207. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/placements/__init__.py +0 -0
  208. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/placements/namespace.py +0 -0
  209. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/placements/namespace.pyi +0 -0
  210. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/placements/parser.py +0 -0
  211. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/roster/__init__.py +0 -0
  212. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/roster/namespace.py +0 -0
  213. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/roster/namespace.pyi +0 -0
  214. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/roster/parser.py +0 -0
  215. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/stats/__init__.py +0 -0
  216. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/stats/namespace.py +0 -0
  217. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/stats/namespace.pyi +0 -0
  218. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/stats/parser.py +0 -0
  219. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/transactions/__init__.py +0 -0
  220. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/transactions/namespace.py +0 -0
  221. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/transactions/namespace.pyi +0 -0
  222. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/transactions/parser.py +0 -0
  223. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/upcoming_matches/__init__.py +0 -0
  224. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/upcoming_matches/namespace.py +0 -0
  225. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/upcoming_matches/namespace.pyi +0 -0
  226. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_team/upcoming_matches/parser.py +0 -0
  227. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_utils/__init__.py +0 -0
  228. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_utils/pagination.py +0 -0
  229. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_utils/paths.py +0 -0
  230. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_utils/team_enrichment.py +0 -0
  231. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_utils/team_parsing.py +0 -0
  232. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/_utils/text.py +0 -0
  233. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/commons/countries.py +0 -0
  234. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/commons/datetime.py +0 -0
  235. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/commons/mappings.py +0 -0
  236. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/commons/prizes.py +0 -0
  237. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/commons/regions.py +0 -0
  238. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/commons/timezone.py +0 -0
  239. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/src/vlrdevapi/py.typed +0 -0
  240. {vlrdevapi-3.0.0 → vlrdevapi-3.1.0}/wrangler.jsonc +0 -0
@@ -22,7 +22,7 @@ jobs:
22
22
  python-version: '3.12'
23
23
 
24
24
  - name: Install package
25
- run: uv sync --group dev
25
+ run: uv sync --group dev --all-extras
26
26
 
27
27
  # Restore fixture cache scoped to the current ref (branch or main) and version prefix (v3).
28
28
  # This ensures caches are never shared across unrelated branches or older versions.
@@ -13,7 +13,7 @@ jobs:
13
13
  runs-on: ubuntu-latest
14
14
  strategy:
15
15
  matrix:
16
- python-version: ['3.11', '3.12', '3.13', '3.14']
16
+ python-version: ['3.11', '3.12', '3.13', '3.14', '3.15']
17
17
 
18
18
  steps:
19
19
  - uses: actions/checkout@v7
@@ -23,7 +23,7 @@ jobs:
23
23
  python-version: ${{ matrix.python-version }}
24
24
 
25
25
  - name: Install dependencies
26
- run: uv sync --group dev
26
+ run: uv sync --group dev --all-extras
27
27
 
28
28
  - name: Download fixtures
29
29
  run: uv run python scripts/download_fixtures.py
@@ -5,6 +5,8 @@ on:
5
5
  paths:
6
6
  - 'src/**'
7
7
  - 'tests/**'
8
+ - 'pyproject.toml'
9
+ - 'uv.lock'
8
10
  - 'scripts/download_fixtures.py'
9
11
  - '.github/workflows/test.yml'
10
12
  push:
@@ -12,6 +14,8 @@ on:
12
14
  paths:
13
15
  - 'src/**'
14
16
  - 'tests/**'
17
+ - 'pyproject.toml'
18
+ - 'uv.lock'
15
19
  - 'scripts/download_fixtures.py'
16
20
  - '.github/workflows/test.yml'
17
21
 
@@ -20,7 +24,7 @@ jobs:
20
24
  runs-on: ubuntu-latest
21
25
  strategy:
22
26
  matrix:
23
- python-version: ['3.11', '3.12', '3.13', '3.14']
27
+ python-version: ['3.11', '3.12', '3.13', '3.14', '3.15']
24
28
 
25
29
  steps:
26
30
  - uses: actions/checkout@v7
@@ -30,7 +34,7 @@ jobs:
30
34
  python-version: ${{ matrix.python-version }}
31
35
 
32
36
  - name: Install dependencies
33
- run: uv sync --group dev
37
+ run: uv sync --group dev --all-extras
34
38
 
35
39
  - name: Download fixtures
36
40
  run: uv run python scripts/download_fixtures.py
@@ -30,4 +30,6 @@ main.py
30
30
  official-docs/node_modules/
31
31
 
32
32
  # Zensical cache
33
- docs-py/.cache/
33
+ docs-py/.cache/
34
+
35
+ temp/
@@ -5,6 +5,55 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [3.1.0] - 2026-10-25
9
+
10
+ ### Added
11
+
12
+ - **Multi-Format Tabular Export Layer** — All Pydantic models now inherit from `ExportableModel`, enabling seamless tabular serialization into popular data science formats:
13
+ - `.to_records()` — extracts clean, unnested lists of Python dictionaries with semantic flattening across every namespace.
14
+ - `.to_df()` — converts records directly into a `pandas.DataFrame`.
15
+ - `.to_polars()` — converts records directly into a native `polars.DataFrame` with typed nested arrays (`pl.List(pl.String)`).
16
+ - `.to_csv(path=None)` — exports to standard CSV format with semicolon-delimited lists (`"Player;IGL"`) and in-memory string output when `path` is omitted.
17
+ - `.to_parquet(path, index=False)` — writes Apache Parquet files via pandas and pyarrow.
18
+ - `.to_excel(path, sheet_name="Sheet1", index=False)` — exports Excel `.xlsx` spreadsheets via pandas and openpyxl.
19
+ - `.to_json(path=None, indent=2)` — exports clean serialized JSON to string or disk with comprehensive recursive datetime and list handling.
20
+ - `.to_markdown(columns=None)` — generates GitHub-flavored markdown tables with proper column alignments, pipe escaping, and zero dependencies.
21
+ - **Granular Optional Dependency Extras** — Data export dependencies are strictly optional and modular:
22
+ - `vlrdevapi[pandas]`: installs `pandas>=2.0.0`
23
+ - `vlrdevapi[polars]`: installs `polars>=1.0.0`
24
+ - `vlrdevapi[excel]`: installs `openpyxl>=3.1.0` and `pandas>=2.0.0`
25
+ - `vlrdevapi[parquet]`: installs `pyarrow>=14.0.0` and `pandas>=2.0.0`
26
+ - `vlrdevapi[mcp]`: installs `mcp>=1.2.0`
27
+ - `vlrdevapi[all]`: installs all optional tabular, file, and MCP dependencies.
28
+ - Missing dependencies provide actionable, friendly install prompts with exact pip commands instead of generic import errors.
29
+ - **First-Class Model Context Protocol (MCP) Server** — Built-in MCP server for AI agents and LLMs (Claude Desktop, Cursor, Zed, Antigravity):
30
+ - CLI executable `vlrdevapi-mcp` (or `python -m vlrdevapi.mcp.server`, `uvx vlrdevapi-mcp`).
31
+ - Standard `stdio` transport with structured, formatted tool definitions.
32
+ - 40 tools covering all endpoints across Matches, Series, Teams, Players, Events, and News.
33
+ - High-level composite tools for complex agent tasks:
34
+ - `get_match_full_context(series_id)` — aggregates overview, player statistics, and streams/VODs into a single response.
35
+ - `get_team_overview(team_id)` — combines team info, roster, upcoming schedule, and tournament placements.
36
+ - `compare_teams(team_id_1, team_id_2, last_days=60)` — side-by-side comparison of two teams with rosters and recent map statistics/forms.
37
+ - `get_player_career_summary(player_id)` — consolidated dossier with profile, current teams, agent pool ratings, and tournament placements.
38
+ - `get_h2h_matchup(team_id_1, team_id_2)` — head-to-head match history between two organizations.
39
+ - `get_tournament_dossier(event_id)` — tournament overview with participating teams, stages, and standings.
40
+ - `get_live_and_upcoming_schedule(limit)` — live ticker combined with upcoming match schedule.
41
+ - `get_news_digest(limit, include_top_article_body)` — latest esports headlines with optional top article body.
42
+ - `series_map_summary(series_id, game_id)` — targeted map-level overview combining economy, replay timeline, and player stats.
43
+ - **Python 3.15 Ready** — Added Python 3.15 to the CI/CD test and publish workflows, verified across uv python matrix.
44
+ - **Production/Stable Status** — Package status promoted to `Development Status :: 5 - Production/Stable` in package metadata.
45
+
46
+ ### Improved
47
+
48
+ - **Semantic Model Flattening** — Tabular export extractors (`.to_records()`) now generate clean, non-redundant rows:
49
+ - Upcoming/completed matches omit static status columns and resolve unannounced teams as `"TBD"`.
50
+ - Player agent statistics provide unnested, clean numeric columns (`acs`, `kd`, `adr`, `kast`, `kpr`, `apr`).
51
+ - Series player stats properly segregate map rows, labeling the aggregate map view as `"All Maps"`.
52
+ - Team rosters separate `primary_role` and multi-role lists.
53
+ - **Unified Serialization in MCP Tools** — MCP server tools now leverage `ExportableModel.to_dict()` and `ExportableModel.to_json()`, eliminating redundant ad-hoc JSON conversion and drastically speeding up tool invocations.
54
+ - **CSV Multi-Value List Formatting** — Agent lists and team roles are formatted with standard semicolon delimiters (`"neon;raze;jett"`) instead of Python `repr()` strings, ensuring full compatibility with spreadsheet applications and analytical parsers.
55
+ - **Parser Corrections** — Fixed swapped KAST and ADR columns in `player.agents()` table extraction to match VLR.gg's actual table headers.
56
+
8
57
  ## [3.0.0] - 2026-10-23
9
58
 
10
59
  ### Breaking
@@ -436,6 +485,7 @@ The API surface, module structure, and type system are all new.
436
485
  - `aiohttp` and `asyncio` dependencies.
437
486
  - v1.x match/event/team parsing modules.
438
487
 
488
+ [3.1.0]: https://github.com/Vanshbordia/vlrdevapi/compare/v3.0.0...v3.1.0
439
489
  [3.0.0]: https://github.com/Vanshbordia/vlrdevapi/compare/v2.4.1...v3.0.0
440
490
  [2.4.1]: https://github.com/Vanshbordia/vlrdevapi/compare/v2.4.0...v2.4.1
441
491
  [2.4.0]: https://github.com/Vanshbordia/vlrdevapi/compare/v2.3.0...v2.4.0
@@ -1,3 +1,74 @@
1
+ Metadata-Version: 2.5
2
+ Name: vlrdevapi
3
+ Version: 3.1.0
4
+ Summary: A Python library to scrape data from vlr.gg
5
+ Project-URL: Homepage, https://vlrdevapi.pages.dev/
6
+ Project-URL: Repository, https://github.com/Vanshbordia/vlrdevapi
7
+ Project-URL: Documentation, https://vlrdevapi.pages.dev/docs/
8
+ License: MIT License
9
+
10
+ Copyright (c) 2026 Vansh Bordia
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ License-File: LICENCE
30
+ Keywords: api,esports,python,scraper,sdk,valorant,valorant esports,vct,vlr.gg,vlrgg
31
+ Classifier: Development Status :: 5 - Production/Stable
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Programming Language :: Python :: 3.11
35
+ Classifier: Programming Language :: Python :: 3.12
36
+ Classifier: Programming Language :: Python :: 3.13
37
+ Classifier: Programming Language :: Python :: 3.14
38
+ Classifier: Programming Language :: Python :: 3.15
39
+ Classifier: Topic :: Games/Entertainment
40
+ Classifier: Topic :: Internet :: WWW/HTTP
41
+ Requires-Python: >=3.11
42
+ Requires-Dist: httpx>=0.28.1
43
+ Requires-Dist: pydantic>=2.14.1
44
+ Requires-Dist: selectolax>=1.0.0
45
+ Provides-Extra: all
46
+ Requires-Dist: mcp>=1.2.0; extra == 'all'
47
+ Requires-Dist: openpyxl>=3.1.0; extra == 'all'
48
+ Requires-Dist: pandas>=2.0.0; extra == 'all'
49
+ Requires-Dist: polars>=1.0.0; extra == 'all'
50
+ Requires-Dist: pyarrow>=14.0.0; extra == 'all'
51
+ Provides-Extra: arrow
52
+ Requires-Dist: pandas>=2.0.0; extra == 'arrow'
53
+ Requires-Dist: pyarrow>=14.0.0; extra == 'arrow'
54
+ Provides-Extra: excel
55
+ Requires-Dist: openpyxl>=3.1.0; extra == 'excel'
56
+ Requires-Dist: pandas>=2.0.0; extra == 'excel'
57
+ Provides-Extra: mcp
58
+ Requires-Dist: mcp>=1.2.0; extra == 'mcp'
59
+ Provides-Extra: pandas
60
+ Requires-Dist: pandas>=2.0.0; extra == 'pandas'
61
+ Provides-Extra: parquet
62
+ Requires-Dist: pandas>=2.0.0; extra == 'parquet'
63
+ Requires-Dist: pyarrow>=14.0.0; extra == 'parquet'
64
+ Provides-Extra: polars
65
+ Requires-Dist: polars>=1.0.0; extra == 'polars'
66
+ Provides-Extra: test
67
+ Requires-Dist: pytest-cov>=7.1.0; extra == 'test'
68
+ Requires-Dist: pytest>=9.1.1; extra == 'test'
69
+ Requires-Dist: respx>=0.23.1; extra == 'test'
70
+ Description-Content-Type: text/markdown
71
+
1
72
  <div align="center">
2
73
 
3
74
  <img src="official-docs/public/logo.png" width="120" alt="vlrdevapi logo">
@@ -6,8 +77,10 @@
6
77
 
7
78
  **The modern, type-safe Python library for VLR.gg Valorant esports data**
8
79
 
9
- [![PyPI version](https://img.shields.io/pypi/v/vlrdevapi.svg?color=fd4556)](https://pypi.org/project/vlrdevapi/)
10
- [![Python Version](https://img.shields.io/pypi/pyversions/vlrdevapi.svg)](https://pypi.org/project/vlrdevapi/)
80
+ [![PyPI version](https://img.shields.io/pypi/v/vlrdevapi.svg)](https://pypi.org/project/vlrdevapi/)
81
+ [![Python Version](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13%20%7C%203.14%20%7C%203.15-blue.svg)](https://pypi.org/project/vlrdevapi/)
82
+ [![Status: Stable](https://img.shields.io/badge/status-stable-brightgreen.svg)](https://pypi.org/project/vlrdevapi/)
83
+ [![MCP Server](https://img.shields.io/badge/MCP-40%20tools-red.svg)](https://vlrdevapi.pages.dev/docs/mcp/)
11
84
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
12
85
  [![Documentation](https://img.shields.io/badge/docs-vlrdevapi.pages.dev-blue.svg)](https://vlrdevapi.pages.dev/docs/)
13
86
 
@@ -25,6 +98,8 @@ Whether you need live match tickers, tournament brackets, historical player rati
25
98
 
26
99
  ## Highlights
27
100
 
101
+ - **Universal Tabular Data Exports** — Seamlessly export any response into `pandas.DataFrame` (`.to_df()`), native `polars.DataFrame` (`.to_polars()`), `CSV` (`.to_csv()`), `Apache Parquet` (`.to_parquet()`), `Excel` (`.to_excel()`), formatted `JSON` (`.to_json()`), and `Markdown` (`.to_markdown()`).
102
+ - **Model Context Protocol (MCP) Server** — Connect Claude Desktop, Cursor, Zed, and AI agents directly to live Valorant data via the built-in `vlrdevapi-mcp` stdio server with 40 tools.
28
103
  - **Complete Valorant Esports Coverage** — Tournaments, match schedules, live scoreboards, player careers, team rosters, roster transactions, and esports news.
29
104
  - **2D Kill-Feed Replay Timelines** — Spatial `(x, y)` kill coordinates, viewing angles, kill distances, plant/defuse events, spike detonations (`boom`), resurrections, alive player snapshots, and buy-phase **player loadouts** (weapons, shields, spent credits, remaining bank).
30
105
  - **Round-by-Round Economy** — Full team buy matrices (`loadout_value`, `spent`, `bank`, buy classifications like `Eco`, `Anti-eco`, `Semi-buy`, `Semi-rifle`, and `Full buy`).
@@ -41,14 +116,23 @@ Whether you need live match tickers, tournament brackets, historical player rati
41
116
  Install `vlrdevapi` using [uv](https://docs.astral.sh/uv/) (recommended) or `pip`:
42
117
 
43
118
  ```bash
44
- # Using uv (recommended)
119
+ # Basic installation
120
+ pip install vlrdevapi
121
+ # or with uv
45
122
  uv add vlrdevapi
46
123
 
47
- # Using pip
48
- pip install vlrdevapi
124
+ # With optional extras
125
+ pip install "vlrdevapi[pandas]" # pandas.DataFrame (.to_df())
126
+ pip install "vlrdevapi[polars]" # polars.DataFrame (.to_polars())
127
+ pip install "vlrdevapi[excel]" # Excel .xlsx (.to_excel())
128
+ pip install "vlrdevapi[parquet]" # Apache Parquet (.to_parquet())
129
+ pip install "vlrdevapi[mcp]" # MCP server (vlrdevapi-mcp)
130
+
131
+ # Install with all optional extras
132
+ pip install "vlrdevapi[all]"
49
133
  ```
50
134
 
51
- > **Requirements:** Python 3.11 or higher.
135
+ > **Requirements:** Python 3.11, 3.12, 3.13, 3.14, or 3.15.
52
136
 
53
137
  ---
54
138
 
@@ -252,11 +336,77 @@ Learn more in the [News Reference Documentation](https://vlrdevapi.pages.dev/doc
252
336
 
253
337
  ---
254
338
 
339
+ ## Tabular Data Exports (Data Science & Analytics)
340
+
341
+ Every response model inherits from `ExportableModel`, enabling instant conversion to dataframes, spreadsheets, and serialized files:
342
+
343
+ ```python
344
+ import vlrdevapi
345
+
346
+ # 1. Fetch player statistics for a grand final
347
+ players = vlrdevapi.series(754737).players()
348
+
349
+ # 2. Convert to pandas DataFrame
350
+ df = players.to_df()
351
+ print(df[["name", "team_name", "rating", "acs", "kills", "deaths"]].head())
352
+
353
+ # 3. Convert to Polars DataFrame (preserving typed list columns)
354
+ polars_df = players.to_polars()
355
+
356
+ # 4. Export to CSV (semicolon-delimited lists, e.g. "neon;raze;jett")
357
+ players.to_csv("grand_final_players.csv")
358
+
359
+ # 5. Export to Apache Parquet
360
+ players.to_parquet("grand_final_players.parquet")
361
+
362
+ # 6. Export to Excel (.xlsx)
363
+ players.to_excel("grand_final_players.xlsx", sheet_name="PlayerStats")
364
+
365
+ # 7. Export to JSON (in-memory string or written to disk)
366
+ json_payload = players.to_json(indent=2)
367
+
368
+ # 8. Print GitHub-flavored Markdown table
369
+ print(players.to_markdown())
370
+ ```
371
+
372
+ ---
373
+
374
+ ## Model Context Protocol (MCP) Server
375
+
376
+ VLRdevAPI includes a native MCP server for AI assistants and autonomous coding agents:
377
+
378
+ ```bash
379
+ # Run server over stdio
380
+ vlrdevapi-mcp
381
+
382
+ # Or zero-install with uvx
383
+ uvx --from "vlrdevapi[mcp]" vlrdevapi-mcp
384
+ ```
385
+
386
+ ### Claude Desktop & Cursor Integration
387
+
388
+ Add to your `claude_desktop_config.json` or `.cursor/mcp.json`:
389
+
390
+ ```json
391
+ {
392
+ "mcpServers": {
393
+ "vlrdevapi": {
394
+ "command": "uvx",
395
+ "args": ["--from", "vlrdevapi[mcp]", "vlrdevapi-mcp"]
396
+ }
397
+ }
398
+ }
399
+ ```
400
+
401
+ The MCP server provides **40 tools** covering matches, series, teams, players, tournaments, and editorial news, plus high-level composite tools (`get_match_full_context`, `get_team_overview`, `compare_teams`, `get_player_career_summary`, `get_h2h_matchup`, `get_tournament_dossier`, `get_live_and_upcoming_schedule`, `get_news_digest`, `series_map_summary`).
402
+
403
+ ---
404
+
255
405
  ## Configuration & Error Handling
256
406
 
257
407
  ### Rate Limiting & Concurrency
258
408
 
259
- `vlrdevapi` includes sensible defaults (`4.0` requests per second) to respect VLR.gg servers. When using `VLRClient`, you can customize client settings:
409
+ `vlrdevapi` includes sensible defaults (`3.0` requests per second) to respect VLR.gg servers. When using `VLRClient`, you can customize client settings:
260
410
 
261
411
  ```python
262
412
  from zoneinfo import ZoneInfo
@@ -1,52 +1,3 @@
1
- Metadata-Version: 2.5
2
- Name: vlrdevapi
3
- Version: 3.0.0
4
- Summary: A Python library to scrape data from vlr.gg
5
- Project-URL: Homepage, https://vlrdevapi.pages.dev/
6
- Project-URL: Repository, https://github.com/Vanshbordia/vlrdevapi
7
- Project-URL: Documentation, https://vlrdevapi.pages.dev/docs/
8
- License: MIT License
9
-
10
- Copyright (c) 2026 Vansh Bordia
11
-
12
- Permission is hereby granted, free of charge, to any person obtaining a copy
13
- of this software and associated documentation files (the "Software"), to deal
14
- in the Software without restriction, including without limitation the rights
15
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
- copies of the Software, and to permit persons to whom the Software is
17
- furnished to do so, subject to the following conditions:
18
-
19
- The above copyright notice and this permission notice shall be included in all
20
- copies or substantial portions of the Software.
21
-
22
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
- SOFTWARE.
29
- License-File: LICENCE
30
- Keywords: api,esports,python,scraper,sdk,valorant,valorant esports,vct,vlr.gg,vlrgg
31
- Classifier: Development Status :: 3 - Alpha
32
- Classifier: Intended Audience :: Developers
33
- Classifier: License :: OSI Approved :: MIT License
34
- Classifier: Programming Language :: Python :: 3.11
35
- Classifier: Programming Language :: Python :: 3.12
36
- Classifier: Programming Language :: Python :: 3.13
37
- Classifier: Programming Language :: Python :: 3.14
38
- Classifier: Topic :: Games/Entertainment
39
- Classifier: Topic :: Internet :: WWW/HTTP
40
- Requires-Python: >=3.11
41
- Requires-Dist: httpx>=0.28.1
42
- Requires-Dist: pydantic>=2.14.1
43
- Requires-Dist: selectolax>=1.0.0
44
- Provides-Extra: test
45
- Requires-Dist: pytest-cov>=7.1.0; extra == 'test'
46
- Requires-Dist: pytest>=9.1.1; extra == 'test'
47
- Requires-Dist: respx>=0.23.1; extra == 'test'
48
- Description-Content-Type: text/markdown
49
-
50
1
  <div align="center">
51
2
 
52
3
  <img src="official-docs/public/logo.png" width="120" alt="vlrdevapi logo">
@@ -55,8 +6,10 @@ Description-Content-Type: text/markdown
55
6
 
56
7
  **The modern, type-safe Python library for VLR.gg Valorant esports data**
57
8
 
58
- [![PyPI version](https://img.shields.io/pypi/v/vlrdevapi.svg?color=fd4556)](https://pypi.org/project/vlrdevapi/)
59
- [![Python Version](https://img.shields.io/pypi/pyversions/vlrdevapi.svg)](https://pypi.org/project/vlrdevapi/)
9
+ [![PyPI version](https://img.shields.io/pypi/v/vlrdevapi.svg)](https://pypi.org/project/vlrdevapi/)
10
+ [![Python Version](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13%20%7C%203.14%20%7C%203.15-blue.svg)](https://pypi.org/project/vlrdevapi/)
11
+ [![Status: Stable](https://img.shields.io/badge/status-stable-brightgreen.svg)](https://pypi.org/project/vlrdevapi/)
12
+ [![MCP Server](https://img.shields.io/badge/MCP-40%20tools-red.svg)](https://vlrdevapi.pages.dev/docs/mcp/)
60
13
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
61
14
  [![Documentation](https://img.shields.io/badge/docs-vlrdevapi.pages.dev-blue.svg)](https://vlrdevapi.pages.dev/docs/)
62
15
 
@@ -74,6 +27,8 @@ Whether you need live match tickers, tournament brackets, historical player rati
74
27
 
75
28
  ## Highlights
76
29
 
30
+ - **Universal Tabular Data Exports** — Seamlessly export any response into `pandas.DataFrame` (`.to_df()`), native `polars.DataFrame` (`.to_polars()`), `CSV` (`.to_csv()`), `Apache Parquet` (`.to_parquet()`), `Excel` (`.to_excel()`), formatted `JSON` (`.to_json()`), and `Markdown` (`.to_markdown()`).
31
+ - **Model Context Protocol (MCP) Server** — Connect Claude Desktop, Cursor, Zed, and AI agents directly to live Valorant data via the built-in `vlrdevapi-mcp` stdio server with 40 tools.
77
32
  - **Complete Valorant Esports Coverage** — Tournaments, match schedules, live scoreboards, player careers, team rosters, roster transactions, and esports news.
78
33
  - **2D Kill-Feed Replay Timelines** — Spatial `(x, y)` kill coordinates, viewing angles, kill distances, plant/defuse events, spike detonations (`boom`), resurrections, alive player snapshots, and buy-phase **player loadouts** (weapons, shields, spent credits, remaining bank).
79
34
  - **Round-by-Round Economy** — Full team buy matrices (`loadout_value`, `spent`, `bank`, buy classifications like `Eco`, `Anti-eco`, `Semi-buy`, `Semi-rifle`, and `Full buy`).
@@ -90,14 +45,23 @@ Whether you need live match tickers, tournament brackets, historical player rati
90
45
  Install `vlrdevapi` using [uv](https://docs.astral.sh/uv/) (recommended) or `pip`:
91
46
 
92
47
  ```bash
93
- # Using uv (recommended)
48
+ # Basic installation
49
+ pip install vlrdevapi
50
+ # or with uv
94
51
  uv add vlrdevapi
95
52
 
96
- # Using pip
97
- pip install vlrdevapi
53
+ # With optional extras
54
+ pip install "vlrdevapi[pandas]" # pandas.DataFrame (.to_df())
55
+ pip install "vlrdevapi[polars]" # polars.DataFrame (.to_polars())
56
+ pip install "vlrdevapi[excel]" # Excel .xlsx (.to_excel())
57
+ pip install "vlrdevapi[parquet]" # Apache Parquet (.to_parquet())
58
+ pip install "vlrdevapi[mcp]" # MCP server (vlrdevapi-mcp)
59
+
60
+ # Install with all optional extras
61
+ pip install "vlrdevapi[all]"
98
62
  ```
99
63
 
100
- > **Requirements:** Python 3.11 or higher.
64
+ > **Requirements:** Python 3.11, 3.12, 3.13, 3.14, or 3.15.
101
65
 
102
66
  ---
103
67
 
@@ -301,11 +265,77 @@ Learn more in the [News Reference Documentation](https://vlrdevapi.pages.dev/doc
301
265
 
302
266
  ---
303
267
 
268
+ ## Tabular Data Exports (Data Science & Analytics)
269
+
270
+ Every response model inherits from `ExportableModel`, enabling instant conversion to dataframes, spreadsheets, and serialized files:
271
+
272
+ ```python
273
+ import vlrdevapi
274
+
275
+ # 1. Fetch player statistics for a grand final
276
+ players = vlrdevapi.series(754737).players()
277
+
278
+ # 2. Convert to pandas DataFrame
279
+ df = players.to_df()
280
+ print(df[["name", "team_name", "rating", "acs", "kills", "deaths"]].head())
281
+
282
+ # 3. Convert to Polars DataFrame (preserving typed list columns)
283
+ polars_df = players.to_polars()
284
+
285
+ # 4. Export to CSV (semicolon-delimited lists, e.g. "neon;raze;jett")
286
+ players.to_csv("grand_final_players.csv")
287
+
288
+ # 5. Export to Apache Parquet
289
+ players.to_parquet("grand_final_players.parquet")
290
+
291
+ # 6. Export to Excel (.xlsx)
292
+ players.to_excel("grand_final_players.xlsx", sheet_name="PlayerStats")
293
+
294
+ # 7. Export to JSON (in-memory string or written to disk)
295
+ json_payload = players.to_json(indent=2)
296
+
297
+ # 8. Print GitHub-flavored Markdown table
298
+ print(players.to_markdown())
299
+ ```
300
+
301
+ ---
302
+
303
+ ## Model Context Protocol (MCP) Server
304
+
305
+ VLRdevAPI includes a native MCP server for AI assistants and autonomous coding agents:
306
+
307
+ ```bash
308
+ # Run server over stdio
309
+ vlrdevapi-mcp
310
+
311
+ # Or zero-install with uvx
312
+ uvx --from "vlrdevapi[mcp]" vlrdevapi-mcp
313
+ ```
314
+
315
+ ### Claude Desktop & Cursor Integration
316
+
317
+ Add to your `claude_desktop_config.json` or `.cursor/mcp.json`:
318
+
319
+ ```json
320
+ {
321
+ "mcpServers": {
322
+ "vlrdevapi": {
323
+ "command": "uvx",
324
+ "args": ["--from", "vlrdevapi[mcp]", "vlrdevapi-mcp"]
325
+ }
326
+ }
327
+ }
328
+ ```
329
+
330
+ The MCP server provides **40 tools** covering matches, series, teams, players, tournaments, and editorial news, plus high-level composite tools (`get_match_full_context`, `get_team_overview`, `compare_teams`, `get_player_career_summary`, `get_h2h_matchup`, `get_tournament_dossier`, `get_live_and_upcoming_schedule`, `get_news_digest`, `series_map_summary`).
331
+
332
+ ---
333
+
304
334
  ## Configuration & Error Handling
305
335
 
306
336
  ### Rate Limiting & Concurrency
307
337
 
308
- `vlrdevapi` includes sensible defaults (`4.0` requests per second) to respect VLR.gg servers. When using `VLRClient`, you can customize client settings:
338
+ `vlrdevapi` includes sensible defaults (`3.0` requests per second) to respect VLR.gg servers. When using `VLRClient`, you can customize client settings:
309
339
 
310
340
  ```python
311
341
  from zoneinfo import ZoneInfo
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "vlrdevapi"
7
- version = "3.0.0"
7
+ version = "3.1.0"
8
8
  description = "A Python library to scrape data from vlr.gg"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -22,13 +22,14 @@ keywords = [
22
22
  ]
23
23
  license = {file = "LICENCE"}
24
24
  classifiers = [
25
- "Development Status :: 3 - Alpha",
25
+ "Development Status :: 5 - Production/Stable",
26
26
  "Intended Audience :: Developers",
27
27
  "License :: OSI Approved :: MIT License",
28
28
  "Programming Language :: Python :: 3.11",
29
29
  "Programming Language :: Python :: 3.12",
30
30
  "Programming Language :: Python :: 3.13",
31
31
  "Programming Language :: Python :: 3.14",
32
+ "Programming Language :: Python :: 3.15",
32
33
  "Topic :: Games/Entertainment",
33
34
  "Topic :: Internet :: WWW/HTTP",
34
35
  ]
@@ -49,6 +50,37 @@ test = [
49
50
  "respx>=0.23.1",
50
51
  "pytest-cov>=7.1.0",
51
52
  ]
53
+ mcp = [
54
+ "mcp>=1.2.0",
55
+ ]
56
+ pandas = [
57
+ "pandas>=2.0.0",
58
+ ]
59
+ polars = [
60
+ "polars>=1.0.0",
61
+ ]
62
+ excel = [
63
+ "openpyxl>=3.1.0",
64
+ "pandas>=2.0.0",
65
+ ]
66
+ parquet = [
67
+ "pyarrow>=14.0.0",
68
+ "pandas>=2.0.0",
69
+ ]
70
+ arrow = [
71
+ "pyarrow>=14.0.0",
72
+ "pandas>=2.0.0",
73
+ ]
74
+ all = [
75
+ "mcp>=1.2.0",
76
+ "pandas>=2.0.0",
77
+ "polars>=1.0.0",
78
+ "openpyxl>=3.1.0",
79
+ "pyarrow>=14.0.0",
80
+ ]
81
+
82
+ [project.scripts]
83
+ vlrdevapi-mcp = "vlrdevapi.mcp.server:main"
52
84
 
53
85
  [dependency-groups]
54
86
  dev = [
@@ -1,6 +1,5 @@
1
1
  import asyncio
2
2
  from pathlib import Path
3
- from typing import Dict
4
3
 
5
4
  import httpx
6
5
 
@@ -19,7 +18,7 @@ HEADERS = {
19
18
  }
20
19
 
21
20
 
22
- ROUTES: list[tuple[str, str, Dict[str, str]]] = []
21
+ ROUTES: list[tuple[str, str, dict[str, str]]] = []
23
22
 
24
23
  # ── Matches ────────────────────────────────────────────────────
25
24
  ROUTES += [
@@ -275,6 +274,11 @@ ROUTES += [
275
274
  "team/14137/overview_light.html",
276
275
  {},
277
276
  ),
277
+ (
278
+ "/team/8050/mibr-gc",
279
+ "team/8050/overview_light.html",
280
+ {},
281
+ ),
278
282
  (
279
283
  "/team/matches/120/?core_id=all&group=completed&page=2",
280
284
  "team/120/completed_matches_page2.html",
@@ -487,8 +491,8 @@ for _gid in GAMES_BO5_2026:
487
491
  ]
488
492
 
489
493
  # ── Upcoming series (best_of + TBD map tabs) ─────────────────
490
- SERIES_ID_UPCOMING = 777946
491
- SERIES_SLUG_UPCOMING = "titan-esports-club-vs-unsettled-resentment-vct-china-2026-threshold-week-1-qf"
494
+ SERIES_ID_UPCOMING = 773433
495
+ SERIES_SLUG_UPCOMING = "mibr-gc-vs-gentle-mates-gc-game-changers-2026-championship-s-o-paulo-ubsf"
492
496
 
493
497
  ROUTES.append(
494
498
  (
@@ -529,7 +533,7 @@ for _sid, _sslug, _gid in SERIES_LOG_SAMPLES:
529
533
  # Unplayed map (Abyss, game 4 of the 2026 GF): graceful empty replay data.
530
534
  ROUTES.append(
531
535
  (
532
- f"/754737/loud-vs-team-vitality-valorant-champions-2026-gf/?game=283290&tab=logs",
536
+ "/754737/loud-vs-team-vitality-valorant-champions-2026-gf/?game=283290&tab=logs",
533
537
  "series/754737_loud-vs-team-vitality-valorant-champions-2026-gf/game_283290_logs.html",
534
538
  {},
535
539
  ),
@@ -560,8 +564,7 @@ def _parse_last_page(html: str) -> int | None:
560
564
  for el in pagination.css("a.btn.mod-page, span.btn.mod-page"):
561
565
  try:
562
566
  num = int(el.text(strip=True))
563
- if num > max_page:
564
- max_page = num
567
+ max_page = max(max_page, num)
565
568
  except ValueError:
566
569
  continue
567
570
  return max_page if max_page > 0 else None
@@ -54,7 +54,7 @@ if TYPE_CHECKING:
54
54
  news: NewsNamespace
55
55
  client: type[VLRClient]
56
56
 
57
- __version__ = "3.0.0"
57
+ __version__ = "3.1.0"
58
58
 
59
59
  _default_client: "VLRClient | None" = None
60
60