rivals-api 2.0.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.
- rivals_api-2.0.0/.github/workflows/publish-pypi.yml +22 -0
- rivals_api-2.0.0/.gitignore +8 -0
- rivals_api-2.0.0/CONTRIBUTING.md +103 -0
- rivals_api-2.0.0/LICENSE +21 -0
- rivals_api-2.0.0/PKG-INFO +325 -0
- rivals_api-2.0.0/README.md +289 -0
- rivals_api-2.0.0/docs/API.md +172 -0
- rivals_api-2.0.0/docs/CHANGELOG.md +78 -0
- rivals_api-2.0.0/docs/PROJECT_CONTEXT.md +87 -0
- rivals_api-2.0.0/docs/PROVIDER_FEATURE_GAPS.md +162 -0
- rivals_api-2.0.0/docs/PROVIDER_INTEGRATION.md +113 -0
- rivals_api-2.0.0/docs/RIVALSTRACKER_API.md +54 -0
- rivals_api-2.0.0/docs/RIVALSTRACKER_API_AUDIT.md +59 -0
- rivals_api-2.0.0/docs/SITE_COMPARISON_GS4.md +57 -0
- rivals_api-2.0.0/docs/SITE_COMPARISON_GS_MULTI_SEASON.md +127 -0
- rivals_api-2.0.0/docs/TRACKER_NETWORK_API.md +69 -0
- rivals_api-2.0.0/docs/provider-feature-gaps.json +654 -0
- rivals_api-2.0.0/pyproject.toml +48 -0
- rivals_api-2.0.0/src/rivals_api/__init__.py +165 -0
- rivals_api-2.0.0/src/rivals_api/client.py +437 -0
- rivals_api-2.0.0/src/rivals_api/exceptions.py +17 -0
- rivals_api-2.0.0/src/rivals_api/extensions.py +161 -0
- rivals_api-2.0.0/src/rivals_api/hero_catalog.json +10091 -0
- rivals_api-2.0.0/src/rivals_api/hero_ids.py +107 -0
- rivals_api-2.0.0/src/rivals_api/history.py +138 -0
- rivals_api-2.0.0/src/rivals_api/mcp_server.py +742 -0
- rivals_api-2.0.0/src/rivals_api/models.py +1034 -0
- rivals_api-2.0.0/src/rivals_api/normalize.py +342 -0
- rivals_api-2.0.0/src/rivals_api/providers.py +118 -0
- rivals_api-2.0.0/src/rivals_api/resources.py +641 -0
- rivals_api-2.0.0/src/rivals_api/selection.py +129 -0
- rivals_api-2.0.0/src/rivalsdata/__init__.py +2 -0
- rivals_api-2.0.0/src/rivalsdata/client.py +8 -0
- rivals_api-2.0.0/src/rivalsdata/exceptions.py +8 -0
- rivals_api-2.0.0/src/rivalsdata/extensions.py +8 -0
- rivals_api-2.0.0/src/rivalsdata/hero_ids.py +8 -0
- rivals_api-2.0.0/src/rivalsdata/history.py +8 -0
- rivals_api-2.0.0/src/rivalsdata/mcp_server.py +8 -0
- rivals_api-2.0.0/src/rivalsdata/models.py +8 -0
- rivals_api-2.0.0/src/rivalsdata/normalize.py +8 -0
- rivals_api-2.0.0/src/rivalsdata/providers.py +8 -0
- rivals_api-2.0.0/src/rivalsdata/resources.py +8 -0
- rivals_api-2.0.0/src/rivalsdata/selection.py +8 -0
- rivals_api-2.0.0/tests/fixtures/providers.json +6017 -0
- rivals_api-2.0.0/tests/test_class_stats.py +131 -0
- rivals_api-2.0.0/tests/test_hero_names.py +31 -0
- rivals_api-2.0.0/tests/test_providers.py +246 -0
- rivals_api-2.0.0/tests/test_selection.py +163 -0
- rivals_api-2.0.0/tests/test_typed_responses.py +90 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Publish rivals-api to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
environment:
|
|
11
|
+
name: pypi
|
|
12
|
+
url: https://pypi.org/p/rivals-api
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: '3.x'
|
|
18
|
+
- run: python -m pip install build
|
|
19
|
+
- run: python -m build
|
|
20
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
21
|
+
with:
|
|
22
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for helping improve rivals-api. It combines public data from RivalsData,
|
|
4
|
+
RivalsTracker, and Tracker.gg. Several routes are undocumented, so keep requests
|
|
5
|
+
conservative and record how behavior and field meanings were observed.
|
|
6
|
+
|
|
7
|
+
## Development setup
|
|
8
|
+
|
|
9
|
+
Use an isolated virtual environment:
|
|
10
|
+
|
|
11
|
+
```console
|
|
12
|
+
python -m venv .venv
|
|
13
|
+
# Windows PowerShell
|
|
14
|
+
.venv\Scripts\Activate.ps1
|
|
15
|
+
# macOS or Linux
|
|
16
|
+
source .venv/bin/activate
|
|
17
|
+
python -m pip install --upgrade pip
|
|
18
|
+
python -m pip install -e '.[dev]'
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Install the optional browser dependencies only when working on Camoufox:
|
|
22
|
+
|
|
23
|
+
```console
|
|
24
|
+
python -m pip install -e '.[browser,dev]'
|
|
25
|
+
python -m camoufox fetch
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The browser extra does not include GeoIP support because the project does not
|
|
29
|
+
need geographic spoofing. A virtual environment also prevents this package's
|
|
30
|
+
dependencies from changing unrelated applications installed in system Python.
|
|
31
|
+
|
|
32
|
+
## Project map
|
|
33
|
+
|
|
34
|
+
- `src/rivals_api/client.py`: HTTP client, username resolution, UID lookup,
|
|
35
|
+
source enrichment, shared request handling, and optional Camoufox retry.
|
|
36
|
+
- `src/rivals_api/providers.py`: per-provider transports, cache, and browser
|
|
37
|
+
context reuse.
|
|
38
|
+
- `src/rivals_api/normalize.py`, `selection.py`: adapters, evidence and
|
|
39
|
+
cross-provider value selection.
|
|
40
|
+
- `src/rivals_api/history.py`: federated history, cursor scoping and filtering.
|
|
41
|
+
- `src/rivals_api/extensions.py`: extended analytics and community reads.
|
|
42
|
+
- `src/rivals_api/models.py`: mapping-compatible response models and the typed
|
|
43
|
+
`Player` wrapper.
|
|
44
|
+
- `src/rivals_api/resources.py`: lazy player and site-wide endpoint resources.
|
|
45
|
+
- `src/rivals_api/exceptions.py`: public exception types.
|
|
46
|
+
- `src/rivals_api/__init__.py`: package exports and version.
|
|
47
|
+
- `pyproject.toml`: build backend, package metadata, runtime and optional
|
|
48
|
+
dependencies.
|
|
49
|
+
- `docs/API.md`: observed site sections, endpoint inventory, response samples,
|
|
50
|
+
and open questions.
|
|
51
|
+
- `docs/PROJECT_CONTEXT.md`: contributor and new-chat handoff notes.
|
|
52
|
+
- `docs/CHANGELOG.md`: package migration and release history.
|
|
53
|
+
|
|
54
|
+
## How the client currently works
|
|
55
|
+
|
|
56
|
+
The main client uses curl_cffi with browser TLS impersonation against
|
|
57
|
+
`https://api.rivalsdata.com`. Optional provider transports use their respective
|
|
58
|
+
public sites/APIs and maintain separate error, cache and privacy handling:
|
|
59
|
+
|
|
60
|
+
- `POST /players/search` with JSON `{"name": "..."}` returns search
|
|
61
|
+
suggestions. Search records include an `aid`, such as
|
|
62
|
+
`11001_1970288503`; the final numeric segment is the profile UID.
|
|
63
|
+
- `POST /player` with JSON `{"uid": 1970288503}` returns a typed `Player`
|
|
64
|
+
object. Profile keys work as both mapping values and attributes.
|
|
65
|
+
- Resource managers cover public leaderboard, hero, team-up, insight, faction,
|
|
66
|
+
match, and player-tab endpoints. See `docs/API.md` for the current inventory.
|
|
67
|
+
- If these requests are blocked and `use_browser_fallback=True`, the client
|
|
68
|
+
loads RivalsData in Camoufox and retries the POST from the page context.
|
|
69
|
+
- RivalsTracker and Tracker.gg enrich profile, match, history and analytics
|
|
70
|
+
methods where comparable public data is available. Their route details and
|
|
71
|
+
limitations are documented in `docs/RIVALSTRACKER_API_AUDIT.md` and
|
|
72
|
+
`docs/TRACKER_NETWORK_API.md`.
|
|
73
|
+
- Merge changes must retain scope, source evidence and all alternatives. Do not
|
|
74
|
+
compare different seasons, modes, count bases or units, and do not claim that
|
|
75
|
+
a public tracker supports live Custom-game discovery without direct evidence.
|
|
76
|
+
|
|
77
|
+
These are observed implementation details, not a supported RivalsData contract.
|
|
78
|
+
Do not assume that `aid` formats, filters, routes, or JSON fields are permanent.
|
|
79
|
+
|
|
80
|
+
## Contribution workflow
|
|
81
|
+
|
|
82
|
+
1. Check the existing public API and exception behavior before changing it.
|
|
83
|
+
2. Keep changes focused, typed, and documented. Avoid adding new runtime
|
|
84
|
+
dependencies unless the feature needs them.
|
|
85
|
+
3. For endpoint changes, note the page or action that exposed the route and
|
|
86
|
+
the request shape. Never commit cookies, tokens, or browser profile data.
|
|
87
|
+
4. Add or update automated tests for behavior changes. Keep network-dependent
|
|
88
|
+
checks opt-in; routine tests should use captured fixtures and mocked HTTP
|
|
89
|
+
responses.
|
|
90
|
+
5. Run the checks for the code you changed:
|
|
91
|
+
|
|
92
|
+
```console
|
|
93
|
+
python -m pytest
|
|
94
|
+
ruff check .
|
|
95
|
+
python -m build
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
6. Update the README and project context if user-facing methods, dependencies,
|
|
99
|
+
routes, or setup steps changed.
|
|
100
|
+
|
|
101
|
+
There is no live API compatibility guarantee. If RivalsData changes a route,
|
|
102
|
+
prefer a clear typed error over returning an empty profile or silently
|
|
103
|
+
mislabeling a search result.
|
rivals_api-2.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 rivalsdata-api contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: rivals-api
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Multi-source Python client and MCP server for Marvel Rivals player stats
|
|
5
|
+
Project-URL: Homepage, https://github.com/GS-Rionnag/rivals-api
|
|
6
|
+
Project-URL: Repository, https://github.com/GS-Rionnag/rivals-api
|
|
7
|
+
Project-URL: Issues, https://github.com/GS-Rionnag/rivals-api/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/GS-Rionnag/rivals-api/releases
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: game-stats,marvel-rivals,mcp,multi-source,tracker
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Games/Entertainment
|
|
22
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: curl-cffi>=0.7
|
|
25
|
+
Provides-Extra: browser
|
|
26
|
+
Requires-Dist: camoufox>=0.5.6; extra == 'browser'
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.11; extra == 'dev'
|
|
31
|
+
Provides-Extra: mcp
|
|
32
|
+
Requires-Dist: mcp-ui-server>=1.0.0; extra == 'mcp'
|
|
33
|
+
Requires-Dist: mcp<2,>=1.12; extra == 'mcp'
|
|
34
|
+
Requires-Dist: uvicorn>=0.30; extra == 'mcp'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# rivals-api
|
|
38
|
+
|
|
39
|
+
An unofficial, multi-source Python tracker for public Marvel Rivals data. It
|
|
40
|
+
combines RivalsData, RivalsTracker, and Tracker.gg, keeps source disagreements
|
|
41
|
+
visible, and preserves unfamiliar response fields as providers change. The
|
|
42
|
+
project also includes a read-only MCP server.
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
Python 3.10 or newer:
|
|
47
|
+
|
|
48
|
+
```console
|
|
49
|
+
python -m pip install rivals-api
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
For editable development, clone the repository and run
|
|
53
|
+
`python -m pip install -e '.[dev]'`. The optional Camoufox Cloudflare fallback
|
|
54
|
+
is installed with `python -m pip install 'rivals-api[browser]'`, followed
|
|
55
|
+
by `python -m camoufox fetch`.
|
|
56
|
+
|
|
57
|
+
## Quick start
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from rivals_api import RivalsClient, hero_id, hero_name
|
|
61
|
+
|
|
62
|
+
print(hero_name(1016)) # Loki
|
|
63
|
+
print(hero_id("Loki")) # 1016
|
|
64
|
+
|
|
65
|
+
with RivalsClient() as rd:
|
|
66
|
+
player = rd.get_player("GS-") # numeric UID works too
|
|
67
|
+
print(player.name, player.level, player.rank_game_season)
|
|
68
|
+
print(player.win_rate) # Current-season competitive win rate
|
|
69
|
+
|
|
70
|
+
# Player profile sections are lazy resource managers.
|
|
71
|
+
hero_season = player.heroes.fetch(season=20)
|
|
72
|
+
all_hero_seasons = player.heroes.fetch(season="all")
|
|
73
|
+
map_stats = player.stats.maps(season=20)
|
|
74
|
+
match_page = player.matches.fetch(season=20)
|
|
75
|
+
|
|
76
|
+
# Current match when its provider exposes it; Custom discovery is unsupported.
|
|
77
|
+
live_game = player.live_game.fetch()
|
|
78
|
+
if live_game is not None:
|
|
79
|
+
print(live_game.players, live_game.team_avg_rank)
|
|
80
|
+
|
|
81
|
+
# Site-wide resources are available from the client.
|
|
82
|
+
leaderboard = rd.leaderboards.fetch(limit=100, season=20, platform=1)
|
|
83
|
+
tier_list = rd.heroes.tier_list(platform=1, rank="grandmaster_plus")
|
|
84
|
+
team_ups = rd.team_ups.fetch(platform=1, rank="grandmaster_plus")
|
|
85
|
+
xp_page = rd.insights.xp()
|
|
86
|
+
|
|
87
|
+
print(hero_season[0].win_rate) # integer percent when wins/losses are present
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`RivalsDataClient` remains an alias for `RivalsClient`. The old `rivalsdata`
|
|
91
|
+
import path is also retained for existing projects. To migrate an existing
|
|
92
|
+
installation, uninstall `rivalsdata-api` first, then install `rivals-api`;
|
|
93
|
+
this avoids the two distributions sharing the compatibility-package files.
|
|
94
|
+
|
|
95
|
+
The player overview's overall win rate (`player.win_rate`) is the **current-season
|
|
96
|
+
competitive win rate**. It uses the latest available competitive season with
|
|
97
|
+
usable counts when a direct source rate is absent; it does not combine seasons.
|
|
98
|
+
Hero and class stats use the season selector supplied to their own methods.
|
|
99
|
+
|
|
100
|
+
Calculated player class statistics are available through
|
|
101
|
+
`player.stats.classes(season=20)` and the MCP `get_player_stats` tool with
|
|
102
|
+
`category="classes"`. Pass a numeric season ID for that season, or
|
|
103
|
+
`season="all"` for combined all-seasons data, matching `player.heroes.fetch`.
|
|
104
|
+
Omitting the season uses the endpoint default. `player.stats.heroes` also
|
|
105
|
+
accepts `season="all"`. Each row contains `player_class` (`tank`, `support`,
|
|
106
|
+
`dps`), the official role, hero IDs, and separate `competitive` and `quickplay`
|
|
107
|
+
totals for games, wins, losses, and available MVP/SVP counts.
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
with RivalsClient() as rd:
|
|
111
|
+
player = rd.get_player("GS-")
|
|
112
|
+
stats = player.stats.classes(season=20)
|
|
113
|
+
all_seasons = player.stats.classes(season="all")
|
|
114
|
+
for row in stats.classes:
|
|
115
|
+
print(row.player_class, row.competitive.win_rate)
|
|
116
|
+
print(stats.excluded) # Unknown roles or incomplete win/loss records
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
For MCP, use `get_player_stats(uid_or_name="GS-", category="classes", season=20)`
|
|
120
|
+
for one season, or `season="all"` for combined all-seasons stats. Both return
|
|
121
|
+
the same class response structure.
|
|
122
|
+
|
|
123
|
+
Detailed hero stats require a mode and match the website's selected tab:
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
competitive = player.stats.heroes(mode="competitive", season="all")
|
|
127
|
+
quickplay = player.stats.heroes(mode="quickplay", season=20)
|
|
128
|
+
print(competitive[0].competitive.games)
|
|
129
|
+
print(competitive[0].rank) # Hero leaderboard position, or None if unavailable
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Only heroes with data for the chosen mode are returned, with that mode's nested
|
|
133
|
+
stats and a `mode` label; the other mode is omitted. Rows are sorted by the
|
|
134
|
+
selected mode's games played descending, with ties retaining the JSON order.
|
|
135
|
+
The source returns both modes in one response; filtering and sorting happen
|
|
136
|
+
in this package, as they do on the website. Existing calls to
|
|
137
|
+
`player.stats.heroes()` must now supply `mode`. MCP also requires `mode` when
|
|
138
|
+
`get_player_stats` uses `category="heroes"`; other categories do not require it.
|
|
139
|
+
The separate summary method `player.heroes.fetch()` keeps its existing behavior.
|
|
140
|
+
|
|
141
|
+
Hero stats include the source's top-level `rank`, matching the **#N** displayed
|
|
142
|
+
in the left-hand hero card. It is preserved for either mode and all-seasons
|
|
143
|
+
requests when supplied by the source; it is not recalculated as a quickplay or
|
|
144
|
+
all-seasons leaderboard position. Missing ranks are returned as `None`.
|
|
145
|
+
|
|
146
|
+
Win rates are `total wins / (total wins + total losses)`, rounded to an integer
|
|
147
|
+
percent. They are weighted by hero records, rather than averaging hero win
|
|
148
|
+
rates. The response's `metadata` identifies the source, formula, and requested
|
|
149
|
+
season scope. Upstream hero-switch attribution is unknown; hero records may
|
|
150
|
+
overlap within a match, so these totals cannot establish distinct match counts
|
|
151
|
+
or the player's overall match win rate. All-seasons coverage is limited to
|
|
152
|
+
records returned by the source; complete lifetime coverage is unverified.
|
|
153
|
+
Excluded rows also produce a metadata warning. Empty modes
|
|
154
|
+
have a `None` win rate. Role mappings were observed on RivalsData on
|
|
155
|
+
2026-09-30, including Deadpool's separate role IDs; generic Deadpool and unknown
|
|
156
|
+
IDs are excluded rather than assigned a guessed class.
|
|
157
|
+
|
|
158
|
+
Character playtime was checked with Camoufox on 2026-09-30. Player hero stats
|
|
159
|
+
did not expose cumulative hours, including in All Seasons. Match details do
|
|
160
|
+
provide seconds in `match.teams[].players[].heroes[].play_time`; the site shows
|
|
161
|
+
these as minutes and seconds when hovering a hero portrait. Sum the relevant
|
|
162
|
+
player's entries across distinct retrieved matches and divide by 3600 to get
|
|
163
|
+
character hours for those matches. Incomplete history prevents treating this as
|
|
164
|
+
a lifetime total. See [the playtime investigation](docs/API.md#character-playtime-investigation-2026-09-30)
|
|
165
|
+
for the observed fields and example.
|
|
166
|
+
|
|
167
|
+
## MCP server (ChatGPT and Claude)
|
|
168
|
+
|
|
169
|
+
Install the MCP extra and the package:
|
|
170
|
+
|
|
171
|
+
```console
|
|
172
|
+
python -m pip install 'rivals-api[mcp]'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The server exposes read-only tools for player search and profiles, a player's
|
|
176
|
+
current live match (when they are in one), match history, player stats,
|
|
177
|
+
leaderboards, heroes, team-ups, public insights, matches, and factions. The
|
|
178
|
+
`show_player_dashboard` tool returns an MCP-UI player card with rank and
|
|
179
|
+
competitive record plus one optional data section per call: current match
|
|
180
|
+
roster, hero win-rate chart, or recent match form with K/D/A. This keeps each
|
|
181
|
+
dashboard pull to the profile plus one selected data section. Provider enrichment
|
|
182
|
+
can make additional requests to compare the reported values. It supports
|
|
183
|
+
local stdio for Claude Desktop
|
|
184
|
+
and Streamable HTTP for remote MCP clients such as ChatGPT. Data comes from
|
|
185
|
+
public provider endpoints and may be incomplete, private, or stale. Live
|
|
186
|
+
Custom-game discovery is not currently implemented.
|
|
187
|
+
|
|
188
|
+
Known `hero_id` and `top_hero_id` fields in MCP results include corresponding
|
|
189
|
+
`hero_name` and `top_hero_name` fields. The `resolve_hero` tool accepts either
|
|
190
|
+
a hero name or numeric ID. The pip package also exports `hero_name(id)` and
|
|
191
|
+
`hero_id(name)`; returned `DataModel` rows provide `.hero_name` and
|
|
192
|
+
`.top_hero_name` conveniences. Those resolved fields are included in mapping
|
|
193
|
+
iteration and `.to_dict()` output to simplify serialization; `.raw` remains the
|
|
194
|
+
untouched source payload.
|
|
195
|
+
|
|
196
|
+
### How the MCP UI works
|
|
197
|
+
|
|
198
|
+
`show_player_dashboard` fetches current data, then returns an HTML UI resource
|
|
199
|
+
alongside the tool result. It advertises the dashboard through
|
|
200
|
+
`_meta.ui.resourceUri`, uses the `text/html;profile=mcp-app` resource MIME type,
|
|
201
|
+
and registers that URI for `resources/read` so the host can actually load the
|
|
202
|
+
app frame. The tool result carries the rendered dashboard as structured content
|
|
203
|
+
for the app frame and an embedded HTML resource for older MCP-UI clients. It
|
|
204
|
+
also includes `openai/outputTemplate` as a ChatGPT compatibility alias. Hosts
|
|
205
|
+
without UI support still receive a text result and can use the regular MCP
|
|
206
|
+
tools. The dashboard is a snapshot from the time the tool runs; ask for it
|
|
207
|
+
again to refresh.
|
|
208
|
+
The `section` argument defaults to `live_match`; use `hero_form` or
|
|
209
|
+
`recent_matches` in separate calls when you need those views.
|
|
210
|
+
|
|
211
|
+
### Claude Desktop (local)
|
|
212
|
+
|
|
213
|
+
Add a server entry to Claude Desktop's `claude_desktop_config.json`, replacing
|
|
214
|
+
the path with the Python executable in the environment where the extra is
|
|
215
|
+
installed:
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"mcpServers": {
|
|
220
|
+
"rivals-api": {
|
|
221
|
+
"command": "C:\\path\\to\\venv\\Scripts\\python.exe",
|
|
222
|
+
"args": ["-m", "rivals_api.mcp_server"]
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
On macOS/Linux, use the environment's `bin/python` path. Restart Claude Desktop
|
|
229
|
+
after saving the configuration.
|
|
230
|
+
|
|
231
|
+
### ChatGPT or remote Claude connector
|
|
232
|
+
|
|
233
|
+
Run the server on a host reachable over HTTPS:
|
|
234
|
+
|
|
235
|
+
```console
|
|
236
|
+
uvicorn rivals_api.mcp_server:app --host 0.0.0.0 --port 8000
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The MCP endpoint is `/mcp` (for example, `https://your-host.example/mcp`). Add
|
|
240
|
+
that endpoint through the client's custom/remote MCP connector settings. The
|
|
241
|
+
server does not implement authentication; put it behind an authenticated
|
|
242
|
+
HTTPS gateway before exposing it publicly. For local development, bind to
|
|
243
|
+
`127.0.0.1` instead. The `app` is the MCP SDK's Streamable HTTP ASGI
|
|
244
|
+
application; Uvicorn manages its lifespan and session manager.
|
|
245
|
+
|
|
246
|
+
Every implemented response route now has named endpoint models and row models
|
|
247
|
+
with annotations for fields observed in the API inventory. This includes
|
|
248
|
+
`Player`, `Match`, `MatchHistory`, `MatchTeam`, `MatchPlayer`, `Character`,
|
|
249
|
+
`ProficiencyResponse`, `LeaderboardResponse`, `PunishmentsPage`, `XPPage`,
|
|
250
|
+
`Top500Response`, and typed teammate, crosshair, stats, faction, and insight
|
|
251
|
+
records. For example, `rd.matches.get(match_id)` returns a `Match`,
|
|
252
|
+
`player.matches.fetch()` returns a `MatchHistory`, and
|
|
253
|
+
`player.proficiency.fetch()` returns a `ProficiencyResponse`. Nested match
|
|
254
|
+
teams and participants are converted to `MatchTeam` and `MatchPlayer`; embedded
|
|
255
|
+
character records use `Character`. Models support mapping access
|
|
256
|
+
(`player["level"]`) and attribute access (`player.level`). Unknown upstream
|
|
257
|
+
fields are still preserved and available through `.raw`; endpoint schemas
|
|
258
|
+
that have not been observed completely are annotated only for known fields.
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
with RivalsClient() as rd:
|
|
262
|
+
player = rd.get_player(1970288503) # Player
|
|
263
|
+
proficiency = player.proficiency.fetch() # ProficiencyResponse
|
|
264
|
+
account = next(iter(proficiency.accounts.values())) # Proficiency
|
|
265
|
+
hero = account.hero_proficiency_infos["1011"] # HeroProficiency
|
|
266
|
+
print(hero.proficiency_level, hero.proficiency_point)
|
|
267
|
+
|
|
268
|
+
tier_list = rd.heroes.tier_list() # TierListResponse
|
|
269
|
+
print(tier_list.heroes[0].hero_id) # Character
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Public resources
|
|
273
|
+
|
|
274
|
+
- `rd.leaderboards.fetch(...)` — global player ranking.
|
|
275
|
+
- `rd.heroes.tier_list(...)`, `.get(hero_id)`, `.meta(hero_id, range=90)`,
|
|
276
|
+
`.leaderboard(hero_id, **filters)` — hero metrics and ranking.
|
|
277
|
+
- `rd.team_ups.fetch(...)` — team-up stats.
|
|
278
|
+
- `rd.insights.punishments(...)`, `.xp(...)`, `.top_500(...)`, `.commbans(...)`,
|
|
279
|
+
`.leavers(...)` — public insights and cursor metadata.
|
|
280
|
+
- `rd.factions.get(faction_id)`, `rd.matches.get(match_id)`,
|
|
281
|
+
`rd.profiles.get(username)`, and `rd.favorites.fetch(uids)` — detail/profile
|
|
282
|
+
lookups.
|
|
283
|
+
- `player.heroes.fetch(...)`, `.matches.fetch(...)`, `.live_game.fetch()`, `.teammates.fetch(...)`,
|
|
284
|
+
`.crosshairs.fetch()`, `.proficiency.fetch()`, `.punishments.fetch()`,
|
|
285
|
+
`.name_history.fetch()` — profile sections.
|
|
286
|
+
- `player.stats.heroes(...)`, `.maps(...)`, `.bans(...)` — detailed profile stats.
|
|
287
|
+
|
|
288
|
+
See [the observed API inventory](docs/API.md) for methods, parameters, observed
|
|
289
|
+
response shapes, and endpoints that require a RivalsData account. The API
|
|
290
|
+
inventory distinguishes observed behavior from inferred/unverified details.
|
|
291
|
+
|
|
292
|
+
## Cloudflare fallback
|
|
293
|
+
|
|
294
|
+
Requests use curl_cffi with a Chrome TLS profile by default. If blocked, enable
|
|
295
|
+
the optional browser fallback:
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
with RivalsClient(use_browser_fallback=True) as rd:
|
|
299
|
+
player = rd.get_player(1970288503)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Errors and contributions
|
|
303
|
+
|
|
304
|
+
All package exceptions inherit from `RivalsAPIError` (also exported under the
|
|
305
|
+
legacy `RivalsDataError` name). See
|
|
306
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) for setup, code layout, change workflow, and
|
|
307
|
+
notes for new contributors. [docs/PROJECT_CONTEXT.md](docs/PROJECT_CONTEXT.md)
|
|
308
|
+
is the handoff document for new coding sessions.
|
|
309
|
+
|
|
310
|
+
This project is not affiliated with RivalsData, RivalsTracker, Tracker.gg,
|
|
311
|
+
NetEase, or Marvel. Keep
|
|
312
|
+
request rates reasonable and respect the site's terms.
|
|
313
|
+
|
|
314
|
+
## Multi-provider data
|
|
315
|
+
|
|
316
|
+
Existing functions combine public RivalsData, RivalsTracker, and Tracker.gg data with evidence-based selection of comparable values. New functions expose rank timelines, cosmetics, encounters, advanced career stats, global analytics, and community listings. Live Custom-game detection is not currently supported by the investigated public sources. See [provider integration](docs/PROVIDER_INTEGRATION.md) for examples, source semantics, and browser setup. Use `RivalsClient(enrich=False)` for RivalsData-only behavior.
|
|
317
|
+
|
|
318
|
+
## Documentation
|
|
319
|
+
|
|
320
|
+
- [2.0.0 release notes and migration guide](docs/CHANGELOG.md)
|
|
321
|
+
- [Provider integration and data-selection rules](docs/PROVIDER_INTEGRATION.md)
|
|
322
|
+
- [Research findings and unsupported features](docs/PROVIDER_FEATURE_GAPS.md)
|
|
323
|
+
- [RivalsTracker API audit](docs/RIVALSTRACKER_API_AUDIT.md)
|
|
324
|
+
- [Tracker.gg API audit](docs/TRACKER_NETWORK_API.md)
|
|
325
|
+
- [Observed RivalsData endpoints](docs/API.md)
|