Metadata-Version: 2.4
Name: gw2-mcp
Version: 0.1.2
Summary: Local MCP server for Guild Wars 2 account analysis.
Project-URL: Homepage, https://github.com/KamilGucik/gw2-mcp
Project-URL: Repository, https://github.com/KamilGucik/gw2-mcp
Project-URL: Issues, https://github.com/KamilGucik/gw2-mcp/issues
Author: Kamil Gucik
License-Expression: MIT
License-File: LICENSE
Keywords: claude,codex,fastmcp,gemini,guild-wars-2,gw2,mcp
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Games/Entertainment
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: fastmcp>=3.4.0
Requires-Dist: httpx>=0.28.0
Description-Content-Type: text/markdown

# gw2-mcp

[![CI](https://github.com/KamilGucik/gw2-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/KamilGucik/gw2-mcp/actions/workflows/ci.yml)
[![Release](https://github.com/KamilGucik/gw2-mcp/actions/workflows/release.yml/badge.svg)](https://github.com/KamilGucik/gw2-mcp/actions/workflows/release.yml)
[![Latest release](https://badgen.net/github/release/KamilGucik/gw2-mcp)](https://github.com/KamilGucik/gw2-mcp/releases)
[![PyPI](https://img.shields.io/badge/PyPI-pending-yellow.svg)](docs/releasing.md#pypi-publishing)
[![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue.svg)](pyproject.toml)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

<!-- mcp-name: io.github.kamilgucik/gw2-mcp -->

Local [Model Context Protocol](https://modelcontextprotocol.io/) server for
Guild Wars 2 account analysis.

`gw2-mcp` lets Claude, Codex, Gemini CLI, and other MCP clients inspect your
Guild Wars 2 account through the official ArenaNet API without sending your API
key through chat. The server runs locally and reads the key from an environment
variable or a local `.env` file.

## What it can do

- Summarize account and token permissions.
- Read mastery point totals and trained mastery tracks.
- Find incomplete achievements that reward mastery points.
- Rank likely fast mastery point targets with transparent local heuristics.
- Read wallet currencies.
- Search bank, material storage, shared inventory, and character inventory.
- List compact character metadata.
- Read Wizard's Vault daily, weekly, special, and listing state.
- Optionally expose raw GW2 API GET access through an explicit `raw` toolset.

## Status

This project is usable, tested, and intentionally conservative about secrets.
The mastery point ranking is heuristic: the official API tells us which
achievements are missing and what they reward, but it does not know how fast
they are for your build, mounts, unlocks, skill level, or willingness to do
group content.

Distribution status:

- Latest GitHub Release: `v0.1.1`.
- Current no-clone install:
  `uvx --from git+https://github.com/KamilGucik/gw2-mcp@v0.1.1 gw2-mcp`.
- PyPI publishing is prepared through Trusted Publishing, but the PyPI project
  is not live yet. Until it is published, `uvx gw2-mcp` will not work.
- MCP Registry metadata is prepared in [`server.json`](server.json). The
  official registry can publish it after the PyPI package is live.

## Requirements

- Python 3.11+
- [uv](https://docs.astral.sh/uv/) recommended
- Guild Wars 2 API key from
  [account.arena.net/applications](https://account.arena.net/applications)

Recommended GW2 API key permissions:

- `account`
- `progression`
- `wallet`
- `inventories`
- `characters`
- `unlocks`

You can use a full key if you want broad account analysis, but a smaller key is
safer.

## Quick start

### Run without cloning

```bash
GW2_API_KEY=your-gw2-api-key \
  uvx --from git+https://github.com/KamilGucik/gw2-mcp@v0.1.1 gw2-mcp-smoke
```

MCP client command:

```json
{
  "command": "uvx",
  "args": [
    "--from",
    "git+https://github.com/KamilGucik/gw2-mcp@v0.1.1",
    "gw2-mcp"
  ]
}
```

Use the same command without `@v0.1.1` if you intentionally want the latest
`main` branch instead of the latest release.

### Run from PyPI

PyPI publishing is ready in CI, but it is not enabled until the PyPI pending
publisher is configured and `PUBLISH_PYPI=true` is set in this repository.
After that first PyPI publish, the shorter command will work:

```bash
GW2_API_KEY=your-gw2-api-key uvx gw2-mcp-smoke
GW2_API_KEY=your-gw2-api-key uvx gw2-mcp
```

MCP client command:

```json
{
  "command": "uvx",
  "args": ["gw2-mcp"]
}
```

### Run from GitHub main

```bash
uvx --from git+https://github.com/KamilGucik/gw2-mcp gw2-mcp
```

HTTP command:

```bash
uvx --from git+https://github.com/KamilGucik/gw2-mcp gw2-mcp \
  --transport http --host 127.0.0.1 --port 8000
```

### Run from a clone

```bash
git clone https://github.com/KamilGucik/gw2-mcp.git
cd gw2-mcp
uv sync
cp .env.example .env
chmod 600 .env
```

Edit `.env`:

```bash
GW2_API_KEY=your-gw2-api-key
GW2_API_LANG=en
GW2_MCP_TOOLSETS=default
```

Smoke test:

```bash
uv run gw2-mcp-smoke
```

Run as an MCP stdio server:

```bash
uv run gw2-mcp
```

Run as a local Streamable HTTP server for ChatGPT tunnel testing:

```bash
uv run gw2-mcp --transport http --host 127.0.0.1 --port 8000
```

Shortcut:

```bash
uv run gw2-mcp-http
```

The HTTP MCP endpoint is `/mcp`.

## AI agent install prompt

If you want another coding agent to install this MCP server for you, paste the
prompt below into Claude Code, Codex, Gemini CLI, Cursor, Windsurf, or another
agent that can read GitHub and edit local MCP client configuration.

```text
Install the Guild Wars 2 MCP server from this repository for me:
https://github.com/KamilGucik/gw2-mcp

Use the repository README as the source of truth. First read:
- https://raw.githubusercontent.com/KamilGucik/gw2-mcp/main/README.md
- https://raw.githubusercontent.com/KamilGucik/gw2-mcp/main/docs/clients.md
- https://raw.githubusercontent.com/KamilGucik/gw2-mcp/main/SECURITY.md

Important security rules:
- Do not ask me to paste my GW2 API key into chat.
- Do not print, log, commit, or store the key in the project repository.
- Prefer a local environment variable or an existing private MCP client config.
- If `GW2_API_KEY` is not already available locally, ask me to set it outside
  chat and stop before running live account checks.
- Use `GW2_MCP_TOOLSETS=default` unless I explicitly ask for raw API access.
- Do not enable the `raw` toolset unless I confirm that I want broad endpoint access.

Install strategy:
1. Detect which MCP client I am using: Claude Desktop, Claude Code, Codex,
   Gemini CLI, ChatGPT custom app/connector, Cursor, Windsurf, or another
   MCP-compatible client.
2. Prefer stdio with the current GitHub release:
   `uvx --from git+https://github.com/KamilGucik/gw2-mcp@v0.1.1 gw2-mcp`
3. Use `uvx gw2-mcp` only after confirming that
   https://pypi.org/project/gw2-mcp/ exists.
4. Configure the server name as `gw2`.
5. Configure environment variables:
   - `GW2_API_KEY` from my local shell, password manager, or private client config.
   - `GW2_MCP_TOOLSETS=default`.
6. For ChatGPT, use the README's local HTTP mode and register a private custom
   app/connector endpoint at `/mcp`; do not expose this server publicly without
   auth.
7. Run a smoke test only if `GW2_API_KEY` is already set locally. Do not echo
   the key. Use
   `uvx --from git+https://github.com/KamilGucik/gw2-mcp@v0.1.1 gw2-mcp-smoke`,
   or `uvx gw2-mcp-smoke` after PyPI is live.
8. Verify the MCP connection by asking the client to call `get_token_info` or
   `get_mastery_points`; summarize only permissions/results, never the key.

After setup, tell me:
- which client config you changed,
- the exact command and args configured,
- whether the smoke test passed,
- which MCP tools are available,
- any manual restart step I still need to do.
```

For direct manual setup, use the client-specific examples below.

## Client configuration

The examples below show clone-based setup. If you prefer no-clone setup today,
replace the command/args with the current GitHub release:

```json
{
  "command": "uvx",
  "args": [
    "--from",
    "git+https://github.com/KamilGucik/gw2-mcp@v0.1.1",
    "gw2-mcp"
  ]
}
```

After PyPI is live, you can shorten that to:

```json
{
  "command": "uvx",
  "args": ["gw2-mcp"]
}
```

### Claude Desktop

Open:

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

Add:

```json
{
  "mcpServers": {
    "gw2": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/gw2-mcp",
        "run",
        "gw2-mcp"
      ],
      "env": {
        "GW2_API_KEY": "your-gw2-api-key",
        "GW2_MCP_TOOLSETS": "default"
      }
    }
  }
}
```

Restart Claude Desktop after editing the file.

### ChatGPT

ChatGPT does not connect directly to local stdio MCP servers. To use `gw2-mcp`
from ChatGPT, run it as a private MCP server and connect through one of the
ChatGPT-supported remote paths:

- Secure MCP Tunnel, recommended for local/private account data.
- Public HTTPS endpoint, acceptable only if you add a real authentication layer
  and understand the account-data exposure risk.

Local HTTP server:

```bash
GW2_MCP_ENV_FILE=/secure/path/to/.env \
  uvx --from git+https://github.com/KamilGucik/gw2-mcp@v0.1.1 gw2-mcp \
  --transport http --host 127.0.0.1 --port 8000
```

Secure MCP Tunnel setup follows OpenAI's tunnel-client flow. Point the tunnel at:

```text
http://127.0.0.1:8000/mcp
```

Then create a ChatGPT custom app/connector and choose the tunnel connection.

See [docs/chatgpt.md](docs/chatgpt.md) for the full runbook.

### Claude Code

```bash
claude mcp add gw2 \
  --env GW2_API_KEY=your-gw2-api-key \
  --env GW2_MCP_TOOLSETS=default \
  -- uv --directory /absolute/path/to/gw2-mcp run gw2-mcp
```

No-clone variant:

```bash
claude mcp add gw2 \
  --env GW2_API_KEY=your-gw2-api-key \
  --env GW2_MCP_TOOLSETS=default \
  -- uvx --from git+https://github.com/KamilGucik/gw2-mcp@v0.1.1 gw2-mcp
```

Then run `/mcp` inside Claude Code and check that `gw2` is connected.

User-scoped JSON variant:

```bash
claude mcp add-json gw2 --scope user '{
  "type": "stdio",
  "command": "uvx",
  "args": [
    "--from",
    "git+https://github.com/KamilGucik/gw2-mcp@v0.1.1",
    "gw2-mcp"
  ],
  "env": {
    "GW2_API_KEY": "${GW2_API_KEY}",
    "GW2_MCP_TOOLSETS": "default"
  }
}'
```

Project-scoped `.mcp.json` variant:

```json
{
  "mcpServers": {
    "gw2": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/KamilGucik/gw2-mcp@v0.1.1",
        "gw2-mcp"
      ],
      "env": {
        "GW2_API_KEY": "${GW2_API_KEY}",
        "GW2_MCP_TOOLSETS": "default"
      }
    }
  }
}
```

### Codex

CLI form:

```bash
codex mcp add gw2 \
  --env GW2_API_KEY=your-gw2-api-key \
  --env GW2_MCP_TOOLSETS=default \
  -- uv --directory /absolute/path/to/gw2-mcp run gw2-mcp
```

No-clone variant:

```bash
codex mcp add gw2 \
  --env GW2_API_KEY=your-gw2-api-key \
  --env GW2_MCP_TOOLSETS=default \
  -- uvx --from git+https://github.com/KamilGucik/gw2-mcp@v0.1.1 gw2-mcp
```

Or edit `~/.codex/config.toml`:

```toml
[mcp_servers.gw2]
command = "uv"
args = ["--directory", "/absolute/path/to/gw2-mcp", "run", "gw2-mcp"]
env = { GW2_API_KEY = "your-gw2-api-key", GW2_MCP_TOOLSETS = "default" }
```

### Gemini CLI

Edit `~/.gemini/settings.json`:

```json
{
  "mcpServers": {
    "gw2": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/gw2-mcp",
        "run",
        "gw2-mcp"
      ],
      "env": {
        "GW2_API_KEY": "$GW2_API_KEY",
        "GW2_MCP_TOOLSETS": "default"
      },
      "timeout": 30000,
      "trust": false
    }
  }
}
```

Then export the key in your shell before starting Gemini CLI:

```bash
export GW2_API_KEY=your-gw2-api-key
gemini
```

## Toolsets

Toolsets reduce tool count and avoid exposing broad raw access by default.

Default:

```bash
GW2_MCP_TOOLSETS=default
```

Equivalent to:

```bash
GW2_MCP_TOOLSETS=account,progression,inventory
```

Enable raw API access:

```bash
GW2_MCP_TOOLSETS=default,raw
```

Enable everything:

```bash
GW2_MCP_TOOLSETS=all
```

Available toolsets:

| Toolset | Tools |
| --- | --- |
| `account` | `get_token_info`, `get_account_summary`, `get_wallet`, `get_characters` |
| `progression` | `get_mastery_points`, `get_missing_mastery_point_achievements`, `rank_fastest_mastery_points`, `get_wizards_vault` |
| `inventory` | `get_bank_items`, `get_materials`, `search_inventory` |
| `raw` | `gw2_raw_get` |

`gw2_raw_get` blocks `/v2/createsubtoken` even when enabled.

## Example prompts

```text
Use gw2 to show my mastery point totals by region.
```

```text
Which 8 Central Tyria mastery points look fastest for me right now?
Explain why and separate solo-friendly from group-content options.
```

```text
Search my account for Mystic Clovers and summarize where they are stored.
```

```text
Check my Wizard's Vault state and suggest what to finish today.
```

```text
Find missing Heart of Thorns mastery-point achievements and rank them by likely effort.
```

## Tools

### `get_token_info`

Returns token metadata and permissions. It never returns the API key.

### `get_account_summary`

Returns account metadata plus token permission names.

### `get_mastery_points`

Returns earned/spent mastery point totals and trained mastery tracks.

### `get_missing_mastery_point_achievements`

Arguments:

- `region`: optional ArenaNet mastery region, for example `Tyria`,
  `Maguuma`, `Desert`, `Tundra`, `Jade`, `Sky`, `Wild`.
- `limit`: default `50`.

Returns incomplete achievements that reward mastery points.

### `rank_fastest_mastery_points`

Arguments:

- `region`: optional region filter.
- `limit`: default `25`.

Returns missing mastery-point achievements sorted by a local effort score.
Lower score means likely faster. Reasons are included in each row.

### `get_wallet`

Returns wallet balances enriched with public currency metadata.

### `get_bank_items`

Arguments:

- `query`: optional item name substring or item id.
- `limit`: default `100`.

### `get_materials`

Arguments:

- `query`: optional item name substring or item id.
- `limit`: default `100`.

### `search_inventory`

Arguments:

- `query`: item name substring or item id.
- `include_characters`: default `true`.
- `limit`: default `100`.

Searches bank, material storage, shared inventory, and optionally character
bags.

### `get_characters`

Returns compact character metadata without equipment/build details.

### `get_wizards_vault`

Returns account Wizard's Vault daily, weekly, special, and listings state.

### `gw2_raw_get`

Disabled by default. Enable with `GW2_MCP_TOOLSETS=default,raw` or `all`.

Arguments:

- `path`: GW2 API path such as `/v2/account/titles`.
- `params`: optional query params object.
- `auth`: default `true`.

## Configuration

| Variable | Default | Description |
| --- | --- | --- |
| `GW2_API_KEY` | none | Guild Wars 2 API key. Required for account tools. |
| `GW2_API_LANG` | `en` | API language. Supported by public localized endpoints. |
| `GW2_API_BASE_URL` | `https://api.guildwars2.com` | API base URL. |
| `GW2_MCP_TOOLSETS` | `default` | Comma-separated toolsets or `all`. |
| `GW2_MCP_TIMEOUT_SECONDS` | `30` | HTTP timeout. |
| `GW2_MCP_MAX_CONCURRENCY` | `8` | Max concurrent API requests. |
| `GW2_MCP_PRIVATE_TTL_SECONDS` | `300` | In-memory cache TTL for account endpoints. |
| `GW2_MCP_PUBLIC_TTL_SECONDS` | `21600` | In-memory cache TTL for public definitions. |
| `GW2_MCP_ENV_FILE` | auto | Optional explicit `.env` path. |

## Development

```bash
uv sync --all-groups
uv run ruff check .
uv run pytest
uv run python scripts/benchmark.py --iterations 100000
uv build
uv run twine check dist/*
```

Live smoke test:

```bash
GW2_API_KEY=your-gw2-api-key uv run gw2-mcp-smoke
```

Live benchmark:

```bash
GW2_API_KEY=your-gw2-api-key uv run python scripts/benchmark.py --live --samples 3
```

## Security model

- `.env` is ignored by git.
- The API key is read from local environment/config only.
- API errors redact the configured key before raising.
- Public endpoints are called without an Authorization header.
- Raw API access is opt-in.
- `/v2/createsubtoken` is blocked.

See [SECURITY.md](SECURITY.md).
Repository contribution and branch-safety rules are documented in
[CONTRIBUTING.md](CONTRIBUTING.md) and
[docs/repository-policy.md](docs/repository-policy.md).

## License and funding

`gw2-mcp` is released under the [MIT License](LICENSE). Direct runtime
dependencies are permissively licensed, primarily MIT, BSD-3-Clause, and
Apache-2.0. See [docs/legal.md](docs/legal.md) for the dependency and
Guild Wars 2 API notes.

Funding links are intentionally not enabled until a maintainer-owned donation
URL or platform handle is selected. See [docs/funding.md](docs/funding.md) for
the low-friction options and the ready-to-fill GitHub Sponsors button template.

## CI/CD and releases

- CI runs lint, tests, offline benchmark, package build, and wheel entrypoint
  checks on GitHub Actions.
- CI uses the self-hosted runner selected by `CI_RUNNER_LABELS`, currently
  `["self-hosted","private-kamil-16","gw2-mcp"]`. Temporary hosted fallback is
  a repo-variable change to `["ubuntu-latest"]`.
- Release automation uses Release Please and Conventional Commits.
- Releases are trunk-based from `main` through generated release pull requests.
- GitHub Releases, tags, version bumps, `CHANGELOG.md` updates, and release
  assets are automated.
- PyPI publishing is supported through Trusted Publishing. It is enabled by
  setting `PUBLISH_PYPI=true` after configuring the pending publisher on PyPI.
- Existing GitHub release tags can be published to PyPI with the manual
  `Publish to PyPI` workflow.
- Publishing to the official MCP Registry is metadata-only and should happen
  after PyPI contains the matching version.

See [docs/releasing.md](docs/releasing.md).

## References

- [Guild Wars 2 API v2](https://api.guildwars2.com/v2)
- [Guild Wars 2 API wiki](https://wiki.guildwars2.com/wiki/API:Main)
- [Model Context Protocol](https://modelcontextprotocol.io/)
- [FastMCP](https://gofastmcp.com/)
