OpenDota MCP
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
OpenDota MCP
A dependency-free OpenDota API client for MCP-compatible assistants and the terminal. It runs locally over stdio, uses Node.js 20 or later, and needs no API key for public endpoints.
Four MCP tools: endpoint discovery, endpoint details, API calls, and Steam ID conversion.
CLI commands for matches, players, heroes, and generic GET requests.
A bundled endpoint catalog for offline discovery.
Request pacing, timeouts, bounded GET retries, and API-key redaction in errors.
Explicit POST operations for replay parsing and player refresh.
This is an independent community client. It is not an official OpenDota or Valve product.
Install from GitHub
Clone the repository:
git clone https://github.com/HFUBlackRabbit/opendota-mcp.git
cd opendota-mcp
node server.mjs --help
node server.mjs --versionThere are no runtime or development npm dependencies to install. npm start launches the MCP server; npm test runs the local test suite. The package is marked private to prevent accidental npm registry publication; GitHub cloning and local use work normally.
Related MCP server: opendota-mcp-server
Connect an MCP client
Use an absolute path to the cloned server.mjs. If a desktop client cannot find node, use an absolute path to your Node.js executable as command.
For clients using JSON configuration, see examples/mcp.json:
{
"mcpServers": {
"opendota": {
"command": "node",
"args": ["/absolute/path/to/opendota-mcp/server.mjs"]
}
}
}For Codex, merge the following section into your user configuration. Do not replace unrelated settings. See examples/codex.toml.
[mcp_servers.opendota]
command = "node"
args = ["/absolute/path/to/opendota-mcp/server.mjs"]Use Windows paths in the form supported by your client, such as C:/tools/opendota-mcp/server.mjs. The server does not bind an HTTP port. Without CLI arguments it waits for newline-delimited JSON-RPC messages on stdin and writes protocol messages to stdout.
Tools
Tool | Purpose |
| Search the bundled catalog with |
| Read an endpoint's description and parameters using |
| Make a GET or an allowed POST using |
| Convert a Steam32 or SteamID64 value to OpenDota |
Start by finding an endpoint, then inspect its parameters. A compact API call looks like this:
{
"path": "/players/1/matches",
"params": {
"limit": 5,
"project": ["kills", "deaths"]
},
"fields": ["match_id", "kills", "deaths"],
"max_chars": 40000
}fields selects top-level properties of an object or of every element in an array after the API response arrives. It does not project fields inside players. Use upstream project/limit when the endpoint supports them.
MCP output defaults to 40,000 characters, with a configurable limit of 1,000–200,000. Larger results become a JSON object with truncated, total_chars, hint, and preview; that preview is not a complete match. The CLI emits the full JSON response, which is useful for replay analysis that requires all ten players.
Use the CLI
Commands that contact the API require network access. IDs below illustrate the syntax; choose a player or match whose public data is available.
node server.mjs heroes
node server.mjs heroes stats
node server.mjs player 1
node server.mjs player 1 recentMatches
node server.mjs player 1 heroes -p having=10
node server.mjs match 271145478
node server.mjs search Dendi
node server.mjs endpoints "players matches"
node server.mjs info "/players/{account_id}/matches"
node server.mjs account-id "76561197960265729"Generic GET requests accept paths relative to the API base: /heroes, not a full URL, /api prefix, or query string. Repeat a parameter for arrays:
node server.mjs get /players/1/matches -p limit=5 -p project=kills -p project=deaths --compactproject=kills,deaths is not equivalent to two project parameters. SteamID64 values must be passed as strings in JSON to preserve their precision. The player, refresh, and account-id commands accept Steam32 or SteamID64.
CLI API results are JSON on stdout; failures are written to stderr with a nonzero exit code. --help and --version return plain text. The package exposes both opendota and opendota-mcp executable aliases when installed as a local package.
Operations that change upstream state
These commands send POST requests and are never automatically retried:
# Request replay parsing. This creates an upstream job.
node server.mjs parse 271145478
# Use job.jobId from the previous response, not the match ID.
node server.mjs job 12345
# Request an upstream player-data refresh.
node server.mjs refresh 1Only POST /request/{match_id} and /players/{account_id}/refresh are allowed. A parse request counts as 10 calls toward OpenDota rate limits, but one call for billing. Check OpenDota's current limits and terms before large workloads.
GET /request/{jobId} may return a job or null. A disappeared job does not prove successful parsing: fetch the match again and inspect its parsed fields. Replay availability and public player history are controlled upstream.
Configuration and credentials
Environment variable | Default | Purpose |
| unset | Optional OpenDota key |
|
| Trusted API base; CLI override: |
|
| Per-attempt timeout; |
|
| Interval per rate-limit budget unit in one process; |
|
| Additional GET attempts; |
Supply credentials using your process environment or MCP client's secret configuration. .env files are not loaded automatically. The key is sent as OpenDota's api_key query parameter; passing it through CLI arguments or tool params is rejected.
Set OPENDOTA_BASE_URL only to a trusted server: the configured API key is sent to that base URL. Error output redacts the configured key, but that does not make arbitrary upstream content or HTTP logs safe to publish. Remove credentials and private data before attaching reports.
The queue is local to one process. Each GET or player refresh uses one interval; a replay-parse POST reserves ten intervals before the next request. Multiple CLI processes or MCP instances do not share a rate-limit budget. GET retries cover HTTP 429/502/503/504 and network timeouts/errors. Retry-After is respected; requests are not retried early when the requested delay exceeds the retry budget. POST is not retried.
Data limitations and catalog provenance
Player IDs, match IDs, and parse-job IDs are different identifiers.
recentMatchesreturns a limited recent sample; usematcheswith filters and pagination for history.Player aggregates usually apply
significant=1. Usesignificant=0when appropriate for nonstandard modes, and separate Turbo from ranked or tournament data.Amateur league team summaries can be empty even when direct match IDs are available. Consult
/leagues/{league_id}/matchIdsfor the league's catalog; a missing parse or absent field is not a zero statistic./healthis an API endpoint; OpenDota's service/statusis outside the API base and is not a relative CLI API route.
endpoints.json is a local OpenAPI-derived snapshot, retrieved 2026-10-19, API version 31.1.0. Endpoint discovery works offline and does not guarantee every route or field remains available on the live service. Sources: API specification, player parameters, and OpenDota documentation. See THIRD_PARTY_NOTICES.md for attribution.
Development and verification
npm test
npm run pack:checkThe Node test suite uses local HTTP fixtures and child processes. It checks CLI behavior, MCP initialization/tool calls, filtering, output truncation, retries, and credential redaction without calling the public API. The GitHub Actions workflow is configured to run it on Node.js 22 and 24 on Linux and Windows.
The repository also contains a small Postman simulation. It is optional and is not a runtime dependency. Fixtures are synthetic contract examples, not recorded player data. To exercise the real HTTP client against it, install Postman CLI 1.75.0 or later and run:
postman simulation run postman/simulations/opendota.sim.yaml --port 4900 --no-history --output ndjsonAfter its listening event, run the checker in a separate terminal. It accepts only a loopback base URL and replaces any inherited API key with empty or synthetic test values:
node scripts/verify-simulation.mjs --base-url http://127.0.0.1:4900/opendota/apiStop the simulation with Ctrl+C after checking. See docs/verification.md for the expected request counts and recorded evidence. Mocked checks establish behavior against those fixtures, not live OpenDota availability or completeness. No GitHub Actions step submits replay-parse or player-refresh requests to the public service.
License
MIT. See LICENSE. OpenDota's source material is attributed separately in THIRD_PARTY_NOTICES.md.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Discover, inspect and run 63,000+ agent tools from one balance. Pay per call, no subscriptions.
660+ data tools for agents: TikTok, Douyin, Instagram, YouTube, X, weather, GitHub. Pay per call.
Read-only search of 2,189 AI agent tools (MCP servers, x402 APIs) with daily automated trust scores.
Turn any task into the right API calls: discover, evaluate, and integrate public APIs.
Related MCP Servers
- AlicenseBqualityDmaintenanceModel Context Protocol server that enables LLMs and AI assistants to retrieve real-time Dota 2 statistics, match data, player information, and game metrics through a standardized interface.179MIT
- FlicenseAqualityDmaintenanceEnables querying Dota 2 player statistics, match data, and hero information through the OpenDota API using natural language.185-
- AlicenseNot gradedqualityCmaintenanceEnables querying Dota 2 data (hero stats, player matches, player heroes) via the STRATZ API, with support for arbitrary GraphQL queries.311 npmMIT
- AlicenseBqualityBmaintenanceEnables LLMs and agents to query Dota 2 matches, players, heroes, teams, and pro scene data through the OpenDota API, with numeric IDs resolved to localized names and readable labels.4258 npmMIT