loading…
Search for a command to run...
loading…
A comprehensive MCP server that wraps the complete World of Warcraft retail API into 197 tools for Game Data and Profile information. It enables users to query
A comprehensive MCP server that wraps the complete World of Warcraft retail API into 197 tools for Game Data and Profile information. It enables users to query character statistics, achievements, collections, and game mechanics across all global regions and locales.
MCP server that wraps the complete World of Warcraft retail API (Game Data + Profile) as 197 MCP tools. Supports OAuth 2.1 authentication (authorization code + PKCE for ChatGPT, client credentials for CLI tools) and is fully region-agnostic — every tool accepts region and locale as optional parameters, so a single server instance can query any region.

cp .env.example .env
# Fill in BNET_CLIENT_ID and BNET_CLIENT_SECRET
npm install
npm run build
npm start # stdio transport
npm run dev # runs via tsx (no build step)
npm run inspect # opens MCP Inspector UI
npm run lint # type-check only
npm test # run auth integration tests
All 196 retail WoW endpoints are registered as individual MCP tools, plus one custom computed tool:
wow_character_achievementsTimeline builds a chronologically sorted timeline of completed achievements (computed, not a raw Blizzard endpoint).Every tool accepts two optional parameters:
region — "us" (default), "eu", "kr", or "tw"locale — "en_US" (default), or any locale supported by the target region (e.g. "es_MX", "de_DE", "fr_FR", "ko_KR")No region configuration is needed in the environment. The same Battle.net credentials work across all regions.
See .env.example. Only two are required:
BNET_CLIENT_ID — Battle.net OAuth client IDBNET_CLIENT_SECRET — Battle.net OAuth client secretOptional auth (OAuth 2.1 for the MCP HTTP endpoint):
MCP_AUTH_SECRET — passphrase that enables OAuth. Used as the login on the /authorize page (for ChatGPT / browser clients), as the client_secret for client_credentials grants, and directly as a static Bearer token for simple clients (Warp, curl, etc.).MCP_TOKEN_TTL_SECONDS — access token lifetime (default: 3600)DATABASE_URL — PostgreSQL connection string (e.g. postgresql://user:pass@host:5432/db). When set, OAuth tokens, clients, and auth codes are persisted in PostgreSQL so they survive restarts. When absent, in-memory stores are used. The docker-compose.yml sets this up automatically.When MCP_AUTH_SECRET is set, the server exposes a full OAuth 2.1 provider:
GET /.well-known/oauth-protected-resource — RFC 9728 metadataGET /.well-known/oauth-authorization-server — RFC 8414 metadata (includes code_challenge_methods_supported: ["S256"])POST /register — RFC 7591 dynamic client registrationGET|POST /authorize — authorization code + PKCE flow with passphrase loginPOST /token — supports authorization_code (with PKCE) and client_credentials grantsThe MCP_AUTH_SECRET value can also be passed directly as a Bearer token (e.g. Authorization: Bearer <your-secret>) — useful for clients like Warp that don't support OAuth flows.
If MCP_AUTH_SECRET is not set, the server runs without auth.
Optional tuning:
LOG_LEVEL — pino log level (default: info)HTTP_TIMEOUT_MS — request timeout (default: 15000)HTTP_RETRY_LIMIT — retry count (default: 2)CACHE_TTL_SECONDS — response cache TTL (default: 300)CACHE_SIZE — max cached entries (default: 500)npm test
Integration tests use Node's built-in test runner (node:test) via tsx — no extra test dependencies. The suite spins up the server on a random port with test credentials and verifies OAuth 2.1 auth end-to-end:
/.well-known/oauth-protected-resource metadata/.well-known/oauth-authorization-server metadata with S256POST /register/mcp without a token (401 with resource_metadata hint)client_credentials with wrong secret (401)client_credentials with correct secret (200)/mcp with MCP_AUTH_SECRET as a static bearer token (200)/mcp with a bogus token (401)docker compose build
docker compose up -d
Secrets are injected via .env on the host (not committed). The container runs as a non-root user with production dependencies only.
The compose stack includes a PostgreSQL instance for persistent OAuth token storage. PostgreSQL data is bind-mounted to ./data/postgres/ on the host (maps to /var/lib/postgresql/data inside the container), so it persists across container recreates, host reboots, and Docker engine upgrades. DATABASE_URL is pre-configured automatically.
NAS / self-hosting note: make sure the
data/postgres/directory is on a reliable filesystem. Back up this folder to preserve all OAuth state.
src/
index.ts # entry point — loads env, starts server
app.ts # HTTP server factory (all routes)
auth.ts # OAuth 2.1 provider (metadata, registration, authorize, token, bearer validation)
config/
env.ts # zod env parsing (credentials + tuning)
regions.ts # region enum, API hosts, OAuth URL
store/
types.ts # OAuthStore interface + record types
memory.ts # in-memory store (default)
postgres.ts # PostgreSQL store (when DATABASE_URL set)
index.ts # factory — picks store based on env
mcp/
tools.ts # auto-registers all endpoints + custom tools
schemas.ts # shared zod input schemas
blizzard/
tokenManager.ts # OAuth client-credentials + single-flight
client.ts # got wrapper: bearer injection, cache, 401 retry
endpoints/
types.ts # EndpointDef interface, buildPath(), schema helpers
gamedata.ts # 161 Game Data API endpoint definitions
profileEndpoints.ts # 35 Profile API endpoint definitions
schemas/
characterSchemas.ts # zod response schemas
achievementSchemas.ts
dto/
characterDto.ts # normalized character DTO
timeline.ts # achievement timeline builder
util/
http.ts # got defaults
cache.ts # TTL cache
logger.ts # pino (stderr)
test/
auth.test.ts # OAuth2 auth integration tests
Endpoints are defined declaratively in gamedata.ts and profileEndpoints.ts. Each entry specifies a tool name, path template, namespace type, and zod input schema. The tools.ts module iterates over the registry and auto-registers every entry as an MCP tool, injecting region and locale parameters automatically.
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"wow-mcp": {
"command": "npx",
"args": []
}
}
}