GW2 MCP Server
The GW2 MCP Server is an agentic AI assistant that provides Guild Wars 2 answers using official wiki content and live game data. It exposes tools to:
Wiki: Search and fetch cleaned wiki pages.
Events: Get event timers for world bosses, meta events, and daily fractals.
Items & Trading Post: Search items, get static data, and live buy/sell prices.
Skills: Search and fetch skill details.
Waypoints: Find waypoints and POIs with in-game chat codes.
Crafting: Find recipes for items and get recipe details.
Meta: Current game build number.
Personal Account (with stored API key): View account overview, wallet, storage (bank, materials, shared slots), characters (overview, inventory, equipment, crafting), unlocks (recipes, dyes, skins, etc.), and progression (achievements, masteries, raid clears, Wizard's Vault).
API Key Management:
account_infoprovides a secure URL to manage keys without entering them in chat.
The server works with any MCP client (e.g., Claude, ChatGPT, Gemini) via stdio or HTTP, and also powers its own agent for REPL and Discord bot use.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@GW2 MCP ServerWhat are today's daily fractals?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
gw2mcp — GW2 Wiki Answers
An agentic AI assistant that answers Guild Wars 2 questions from authoritative
sources: the official wiki and the
official GW2 API, with citations back to the
wiki. Spec: specs/gw2-agentic-ai-spec.md.
Two components, one repo:
MCP tool server (
gw2mcp-server) — a FastMCP server exposing wiki search/fetch and GW2 API tools (items, skills, live trading-post prices, daily fractals, event timers, waypoint/POI chat codes) to any MCP client: Claude Desktop/Code, ChatGPT, Gemini, or our own agent.Agent core + adapters (
gw2mcp-repl,gw2mcp-discord) — the provider-pluggable tool-use loop (Anthropic, OpenAI, or OpenRouter) that turns "question in" into "grounded answer + citations out". Transport-agnostic: a terminal REPL and a Discord bot share the same core.
REPL / Discord bot any MCP client (Claude, ChatGPT, Gemini)
│ │
Agent core (Anthropic/OpenAI/OpenRouter) │
│ MCP: in-memory (default) or HTTP │ MCP: stdio or HTTP
└────────────────┬───────────────────────┘
FastMCP server (gw2mcp)
wiki_search · wiki_get_page · get_event_timer · search_items
get_item · get_item_prices · search_skills · get_skill
get_build_id · get_daily_fractals · search_waypoints
│
Supabase Postgres (TTL cache · name index · run traces)Setup
Prereqs: uv, Supabase CLI, Docker (for local Supabase).
supabase start # local Postgres on 127.0.0.1:54322
supabase migration up # create cache/name-index/run-trace tables
uv sync --all-groups
cp .env.example .env # then fill in ANTHROPIC_API_KEYEvery config variable the code reads is documented in
.env.example (optional tunables are listed commented-out with
their defaults). Secrets live only in .env (gitignored) — never commit them.
Related MCP server: OSRS MCP Server
Run
uv run gw2mcp-repl # terminal REPL (agent + in-process server)
uv run gw2mcp-server # MCP server over stdio (Claude Desktop/Code)
uv run gw2mcp-server --transport http # MCP server over streamable HTTP :8720To point an external MCP client at the server, use stdio config
(command: uv, args: [run, gw2mcp-server], cwd this repo) or the HTTP URL
http://127.0.0.1:8720/mcp.
To run the agent against a separately running server instead of in-process,
set MCP_SERVER_URL in .env.
Authentication (optional)
By default, the HTTP MCP server is unauthenticated — any client can call tools.
Setting MCP_AUTH_ENABLED=true requires all HTTP clients to authenticate via OAuth
(WorkOS AuthKit) before accessing tools.
Local transports are unaffected: stdio (Claude Desktop) and the in-memory transport
(REPL, tests) never see the HTTP auth layer. Pointing the REPL at a remote authed
server via MCP_SERVER_URL is not supported (it sends no bearer token).
Discord /link flow
Users can link their Discord account to a WorkOS identity (for higher rate limits):
/linkopens a temporary login URL to your AuthKit application.User completes sign-up or login at the AuthKit domain.
Authorization redirects back to the MCP server with an authorization code (which the server exchanges with WorkOS).
The bot stores the linked identity (person and tier); future
/gw2calls run at the linked tier with higher rate limits.Manage your GW2 API key from the /account page (link via
/setkeyoraccount_info): keys are validated against the GW2 API before storing and encrypted at rest; Discord never processes them./whoamishows the current link status;/unlinkdisconnects Discord only — your account, stored GW2 API key, and history remain (delete them any time from the /account page).
/account — GW2 API key for MCP clients
MCP users (Claude Desktop, etc.) manage their GW2 API key in the browser at
{PUBLIC_BASE_URL}/account — sign in with the same WorkOS account the MCP
OAuth uses, then save, replace, or clear the key. Keys are validated against the
GW2 API before storing and encrypted at rest; the key never appears in the
agent conversation. The account_info MCP tool returns this URL plus
non-secret status (key stored, tier, Discord linked).
The key is stored on the person, not the surface: /account is the only
place to set, replace, or clear it, and the same key is available to both
Discord and MCP clients — provided you sign into the same WorkOS account in
both places. Discord's /setkey command is a pointer to /account, not an
input path; it never sees the key. /link now asks for an explicit
confirmation in the browser before attaching a Discord account.
New env var: ACCOUNT_SESSION_TTL_S (optional, default 1800) — browser
session lifetime for /account.
Upgrade note: when /link (WorkOS) settings are configured, GW2_KEY_ENCRYPTION_KEY
is now REQUIRED at startup — a server with link settings but a missing or invalid
Fernet key refuses to boot.
WorkOS dashboard setup
To enable the /link flow and OAuth on the HTTP server:
Create an AuthKit application in your WorkOS organization; note the AuthKit domain, Client ID, and API key.
In AuthKit → Configuration → Dynamic Client Registration: enable it (required so Claude/ChatGPT can self-register with the MCP server).
In the Redirects tab, add both redirect URIs:
Add
<PUBLIC_BASE_URL>/link/callback(e.g.,https://your-host.example.com/link/callback).Add
<PUBLIC_BASE_URL>/account/callbackto the allowed Redirect URIs (exact byte match —127.0.0.1vslocalhostmatters).
Recommended: In OAuth → Resource Indicators (RFC 8707): enable it and register the MCP resource URL (e.g.,
https://your-host.example.com/mcp). This ensures tokens carry the correctaud(audience) claim.
Fill in the corresponding .env variables:
WORKOS_CLIENT_ID, WORKOS_API_KEY, AUTHKIT_DOMAIN, PUBLIC_BASE_URL.
Generate LINK_SIGNING_KEY and GW2_KEY_ENCRYPTION_KEY as random cryptographic
values (see comments in .env.example).
Smoke-testing account tools
The REPL has no person identity, so account tools answer with setup guidance there — that itself is the no-identity smoke test. Real-data smoke tests (do NOT commit keys):
Discord path:
/link, then store a real API key (all permissions) at/account, then/ask what's in my material storage?in Discord — expect real counts, ephemeral.Hosted OAuth path: connect Claude to the hosted server, store a key at /account, then ask the same question.
Ask with a key lacking
inventories— expect a message naming the missing permission, not an error.
Discord bot
The Discord adapter (spec §6.5–6.6) runs the same agent core behind two slash
commands: /gw2 question:<text> (defers ephemerally, then edits the answer
in, splitting across follow-ups past Discord's 2000-char limit) and /about.
Per-user (5/10 min) and per-guild (30/hour) rate limits plus a global monthly
budget kill-switch ($50 default, summed across all runs including REPL and
eval) are enforced as aggregate queries over run_traces — fail-closed: if
Postgres is unreachable, the bot declines to answer rather than run unmetered.
Discord application setup (once per environment)
Dev and prod are separate Discord applications so guild-scoped dev commands never collide with global prod ones.
Create an application at the Discord Developer Portal → Bot tab → Reset Token → put it in
.envasDISCORD_TOKEN. No privileged intents are needed (slash commands only — leave presence, server members, and message content off).For dev: enable Developer Mode in your Discord client, right-click your test server → Copy Server ID → set
DISCORD_DEV_GUILD_IDin.env. Commands sync instantly to that guild. For prod: leave it unset — commands register globally (first propagation can take up to an hour).Invite the bot with (replace
<APP_ID>from the portal's General Information page):https://discord.com/api/oauth2/authorize?client_id=<APP_ID>&scope=bot%20applications.commands&permissions=2048permissions=2048is just Send Messages; interaction replies work even without it, keeping the permission footprint minimal.
Run
uv run gw2mcp-discord # requires DISCORD_TOKEN in .env, local Supabase runningRate-limit and budget knobs (RATE_LIMIT_*, MONTHLY_BUDGET_USD) are
documented in .env.example.
Eval
uv run python eval/run_eval.py # full 25-question set, manual scoring
uv run python eval/run_eval.py --category live --limit 2The question set (eval/questions.yaml) is versioned; re-run it on every
significant prompt/tool change. Results land in eval/results/*.jsonl.
Baseline (2026-07-22, claude-sonnet-5, prompt v1): 21/25 pass (84%),
3 partial, 1 fail · median latency 12.0s (target ≤15s ✓) · avg cost
$0.0621/question (target ≤$0.06, marginal). The fail + 2 partials traced to a
wikitext-cleaner bug that stripped inline cost templates ({{gold|…}},
{{item icon|…}}); fixed after this run — re-run the eval to record a v2
baseline against the ≥90% target.
Model
LLM_PROVIDER env var picks the backend — anthropic (default), openai, or
openrouter — and MODEL_ID names the model in that provider's naming
(default claude-sonnet-5, $3/M input, $15/M output — the best
price/quality Sonnet-class model per the spec's cost target of
≤ $0.06/question; OpenRouter ids are vendor-prefixed, e.g.
anthropic/claude-sonnet-5). The agent loop is provider-agnostic
(src/gw2mcp/agent/providers/); pricing for cost accounting lives in
src/gw2mcp/agent/costs.py and is keyed by (provider, model) — a pair
without a pricing entry refuses to start (fail-closed, so nothing can spend
invisibly to the monthly budget cap).
Tests
uv run pytest # fully offline: respx-mocked HTTP, in-memory MCP, fake cacheObservability
Every run writes one JSON line to logs/runs.jsonl (every tool call, tokens,
cost, latency) and a queryable row to the run_traces table in Postgres —
the table the Discord adapter's rate limits count over. The monthly budget
kill-switch aggregates over budget_ledger instead, so admission reserves
capacity atomically rather than reading a stale sum
(src/gw2mcp/agent/gating.py).
Retention: a scheduled sweeper (src/gw2mcp/common/retention.py, every
6h by default) prunes run_traces/logs/runs.jsonl after 90 days,
mcp_tool_calls after 7 days, and budget_ledger rows older than the
previous calendar month; cache_entries expire per-row on their own TTL.
See docs/data-retention.md for the full policy,
including what's collected, the access boundary, and deletion behavior.
Production deployment
Running against a hosted/production Supabase or Postgres instance needs a
different database role than local dev (gw2mcp_app, not postgres), a
password set for that role, and a decision on the Supabase Data API. See
docs/deployment.md for credential separation, the
runtime role's exact privileges, Data API guidance, a residual service_role
risk, a portability caveat for hosted projects, reverse-proxy setup, and the
process model for scaling.
Security
docs/threat-model.md covers the trust boundaries
(Discord, browser, MCP client, Postgres, external APIs), the protected assets,
the attackers each control is aimed at, and — importantly — the accepted
residual risks, including what the /account delete flow does not reach.
docs/security-findings-2026-07-27.md
is the findings report from the 2026-07-27 hardening pass: one entry per
reviewed hypothesis with status, evidence, files changed, verification, and
residual risk — plus the two claims that turned out to be false, four
issues the original review missed, and the exact verification commands and
their real output.
No GDPR, CCPA, SOC 2, or HIPAA compliance is claimed. See
docs/data-retention.md for what is collected and
for how long.
Politeness & attribution
Wiki requests carry a descriptive User-Agent and are limited to ≤ 2 req/s.
Wiki content is cached (pages 24h, search 1h); GW2 API static data is cached keyed to the game build; prices for 5 minutes.
Wiki content is GFDL; this project is not affiliated with ArenaNet.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseBqualityCmaintenanceA MCP server that allows you to search and retrieve content on any wiki site using MediaWiki with LLMs 🤖. wikipedia.org, fandom.com, wiki.gg and more sites using Mediawiki are supported!Last updated226

OSRS MCP Serverofficial
AlicenseBquality-maintenanceMCP Server for interacting with Old School RuneScape Wiki API and game data files, providing tools to search the OSRS Wiki and access game data definitions through the Model Context Protocol.Last updated191171- Alicense-qualityBmaintenanceA research MCP server that enables AI agents to query the internet using multiple sources like SearXNG, GitHub, Reddit, and YouTube, and returns synthesized answers with citations.Last updatedMIT
- Alicense-qualityCmaintenanceMCP server that exposes structured World of Warcraft API data (functions, deprecated replacements, enums, events, widget methods) to AI agents, enabling querying and exploration of WoW API without wiki parsing.Last updated3311MIT
Related MCP Connectors
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
An MCP server that integrates with Discord to provide AI-powered features.
MCP server for skill documentation, generated by doc2mcp.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Guild-Wars-MCP/GW2_MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server