Skip to main content
Glama
slest1
by slest1
README.md
# mcp-osrs

An [MCP](https://modelcontextprotocol.io) server for Old School RuneScape. It answers whole player questions in one call: "can I do Dragon Slayer II?", "what do I bring on each trip?", "how do I get these items as an ironman?", "what's a whip worth?". It combines the OSRS Wiki's structured data, Quest Helper's quest definitions, real-time Grand Exchange prices and the player's own account.

Answers are compact JSON under 12 KB, carry their source URLs and the age of any live data, and continue long lists with a cursor.

## Install

Requires Node.js 20 or newer. The server speaks MCP over stdio and is started with `npx`.

### Claude Code

```sh
claude mcp add -s user osrs -- npx -y @slest1/mcp-osrs
```

### Claude Desktop, Cursor, Windsurf, Gemini CLI

Add this to the client's MCP configuration file:

```json
{
  "mcpServers": {
    "osrs": {
      "command": "npx",
      "args": ["-y", "@slest1/mcp-osrs"]
    }
  }
}
```

| Client | Configuration file |
|---|---|
| Claude Desktop | `claude_desktop_config.json` (Settings → Developer → Edit Config) |
| Cursor | `~/.cursor/mcp.json`, or `.cursor/mcp.json` in a project |
| Windsurf | `~/.codeium/windsurf/mcp_config.json` |
| Gemini CLI | `~/.gemini/settings.json` |

### VS Code

In `.vscode/mcp.json` (or the user-level MCP configuration):

```json
{
  "servers": {
    "osrs": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@slest1/mcp-osrs"]
    }
  }
}
```

### Codex CLI

```sh
codex mcp add osrs -- npx -y @slest1/mcp-osrs
```

or in `~/.codex/config.toml`:

```toml
[mcp_servers.osrs]
command = "npx"
args = ["-y", "@slest1/mcp-osrs"]
```

### Any other stdio client

Run `npx -y @slest1/mcp-osrs` as the server command. Settings go in environment variables (see [Configuration](#configuration)).

### From source

```sh
git clone https://github.com/slest1/mcp-osrs.git
cd mcp-osrs
npm ci
npm run build
node dist/index.js --version
```

Point your client at `node /path/to/mcp-osrs/dist/index.js`.

### Troubleshooting

- **`npx` not found, or the server never starts from a desktop app.** Desktop apps often don't inherit your shell's `PATH`. Use the absolute path to `npx` (from `which npx`, or `where npx` on Windows) as the command.
- **Updating.** `npx` caches packages. Use `@slest1/mcp-osrs@latest` in the arguments to always get the newest release, or clear the npx cache.
- **Checking the install.** `npx -y @slest1/mcp-osrs --version` prints the version. Logs go to stderr as JSON lines; set `LOG_LEVEL=debug` for more.

## Tools

| Group | Tool | What it answers |
|---|---|---|
| Account | `set_account` | Save the player's name and mode so later answers are checked against it |
| Account | `get_account` | Which account is saved and where it came from |
| Account | `lookup_player` | Hiscores: levels, XP, ranks, boss kills, clues and combat level |
| Account | `get_player_progress` | WikiSync quests, diaries, collection log and combat achievements |
| Wiki | `search_wiki` | Search the OSRS Wiki |
| Wiki | `get_page` | Read an article or one section as clean text |
| Wiki | `get_page_sections` | List an article's sections |
| Wiki | `query_wiki_data` | Query any wiki Bucket table directly |
| GE | `get_price` | Live prices, margin after GE tax, volumes, buy limits, batch totals |
| GE | `get_price_history` | Price history with low, high, average and % change |
| Items | `get_item` | Item facts, equipment bonuses, versions and live price |
| Items | `find_item_sources` | How to get items or a quest's items, with a practical recommendation for each |
| Items | `get_shop` | A shop's stock, prices and restock times |
| Items | `find_recipes` | Recipes that make or use an item, or train a skill |
| Monsters | `get_monster` | Stats, weaknesses, slayer info and map-linked locations |
| Monsters | `get_drops` | Drop table at live prices and expected gp per kill |
| Quests | `get_quest` | Can the player start it, prerequisites ✓/✗/?, rewards |
| Quests | `get_quest_guide` | Quest Helper's steps, one section at a time |
| Quests | `plan_quest_trips` | What to bring on each trip, fitted to 28 slots |
| Quests | `suggest_quests` | The next quests in the optimal order the player can start |
| Achievements | `get_diary` | Diary requirements, tasks, completion and rewards |
| Achievements | `get_slayer_tasks` | A slayer master's tasks, weights and chances |
| Achievements | `get_combat_achievements` | Combat achievement tasks, points and completion |
| Skills | `plan_skill` | XP to a goal, actions and materials, best methods and XP quests |
| Skills | `get_money_makers` | Money-making methods by gp/hr that the account can do |
| Clues | `solve_clue` | Solutions for anagrams, ciphers, cryptics and emote clues |

## Personalization

- **Save an account once.** Ask the assistant to save your name and mode (`set_account`). Modes are `main`, `ironman`, `hardcore_ironman`, `ultimate_ironman`, `deadman` and `seasonal`. The account is stored in a small JSON file (see `OSRS_STATE_FILE`). Without a saved account, answers are generic and the first personal question includes a one-time hint.
- **A `player` argument** overrides the saved account for one call.
- **Hiscores** give skill levels to every tool that checks requirements.
- **WikiSync** is opt-in: install the WikiSync plugin in RuneLite and log in. It unlocks quest, diary, collection log and combat achievement checks, quest points and finished-quest skipping in suggestions. Without it those checks show `?`. Deadman accounts have no WikiSync data.
- **Ironman modes** get Quest Helper's ironman quest data, the ironman quest order, procurement plans that never use the GE, and ironman notes on quests.

## Configuration

Every setting is optional and read from the environment. Invalid values stop the server at startup with a message naming the variable.

| Variable | Default | Meaning |
|---|---|---|
| `OSRS_ACCOUNT` | none | Default player name until one is saved with `set_account` |
| `OSRS_ACCOUNT_MODE` | `main` | Default account mode |
| `OSRS_STATE_FILE` | `$XDG_CONFIG_HOME/mcp-osrs/state.json`, else `~/.config/mcp-osrs/state.json` | Saved-account file; `off` disables saving |
| `OSRS_CACHE_DIR` | `$XDG_CACHE_HOME/mcp-osrs`, else `~/.cache/mcp-osrs` | Where the quest data release is cached |
| `OSRS_WIKI_URL` | `https://oldschool.runescape.wiki/api.php` | Wiki API |
| `OSRS_PRICES_URL` | `https://prices.runescape.wiki/api/v1/osrs` | Real-time prices API |
| `OSRS_HISCORES_URL` | `https://secure.runescape.com` | Official hiscores |
| `OSRS_WIKISYNC_URL` | `https://sync.runescape.wiki` | WikiSync |
| `OSRS_DATA_URL` | `https://github.com/slest1/osrs-data/releases/latest/download` | Quest data release |
| `OSRS_MAX_RESPONSE_BYTES` | `12288` | Response size cap |
| `OSRS_CACHE_MAX_ENTRIES` | `1000` | In-memory response cache size |
| `OSRS_MAX_CONCURRENCY` | `4` | Concurrent requests per host |
| `OSRS_REQUEST_TIMEOUT_MS` | `15000` | Timeout per request |
| `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, `error` or `silent` (logs go to stderr) |

For example, in an `mcpServers` entry:

```json
"env": { "OSRS_ACCOUNT": "Zezima", "OSRS_ACCOUNT_MODE": "ironman" }
```

## Data sources

| Source | Used for | Cached |
|---|---|---|
| [OSRS Wiki](https://oldschool.runescape.wiki) Action API and Bucket tables | Articles, items, monsters, drops, shops, recipes, quests, diaries, clues, money making | 1 hour; large catalogs 24 hours |
| [OSRS Wiki real-time prices](https://prices.runescape.wiki) | Item mapping, latest prices, averages, history | 1 minute to 24 hours |
| Official hiscores | Skills, bosses, clues | 5 minutes |
| [WikiSync](https://oldschool.runescape.wiki/w/RuneScape:WikiSync) | Quests, diaries, collection log, combat achievements | 5 minutes |
| [osrs-data](https://github.com/slest1/osrs-data) releases | Quest Helper quest data, verified by sha256 | On disk, checked daily; a bundled snapshot is the fallback |

Every request sends the User-Agent `mcp-osrs/<version> (+https://github.com/slest1/mcp-osrs)`, respects a per-host concurrency limit, and retries with backoff that honours `Retry-After`.

## Development

```sh
npm ci
npm run check        # typecheck, lint and tests
npm run build        # compile to dist/
npm run dev          # run from source with tsx
```

| Script | Does |
|---|---|
| `dev` | Run the server from source |
| `build` | Compile to `dist/` |
| `start` | Run the compiled server |
| `typecheck` | TypeScript, no emit |
| `lint` / `format` | Biome check, or check and fix |
| `test` / `test:watch` | Vitest |
| `check` | typecheck, lint and test |
| `fixtures:record` | Re-record the HTTP fixtures from the live APIs (optionally only named scenarios) |

Tests never touch the network: they replay recorded responses from `test/fixtures/<host>/`, and the integration tests drive the real server through an MCP client over an in-memory transport. To add or refresh fixtures, add a scenario to `test/support/scenarios.ts` and run `npm run fixtures:record -- <scenario>`.

A weekly CI job (the drift canary) re-records every scenario, runs the tests against the fresh recordings, compares `src/sources/wiki/tables.ts` with the live Bucket schemas (`scripts/check-drift.ts`) and checks the bundled quest data against the latest osrs-data release.

`docs/extending.md` has step-by-step recipes for adding tools, data sources, wiki tables and more.

## Licence and attribution

- The MIT licence (see `LICENSE`) covers this project's code only.
- Wiki content, both fetched at runtime and recorded in `test/fixtures/`, is from the Old School RuneScape Wiki under [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/), the licence the wiki declares; answers link the pages they draw on. `test/fixtures/NOTICE` lists the sources of every recorded response.
- The bundled quest data in `data/osrsdata/` comes from [Quest Helper](https://github.com/Zoinkwiz/quest-helper) by Zoinkwiz and contributors, under the BSD 2-Clause License, via the osrs-data releases; `data/osrsdata/NOTICE` has the licence text, and it ships in the npm package. Quest answers carry this attribution.
- Prices come from the OSRS Wiki real-time prices API.
- Hiscores are Jagex's public data. Old School RuneScape is a trademark of Jagex Ltd; this project is not affiliated with Jagex.

TDQS

A3.8/5.0

Scored across 26 tools

Disambiguation4/5

Most tools target clearly distinct resources and actions, with explicit guidance like 'no other tool covers' for wiki search and structured data. Some overlap exists among quest-related tools (get_quest, get_quest_guide, plan_quest_trips, suggest_quests) and player progress tools, but descriptions distinguish them well.

Naming Consistency5/5

All tool names use consistent snake_case with predictable verb_noun or verb constructions such as get_item, find_recipes, plan_quest_trips, and solve_clue. There are no mixed naming conventions or vague standalone verbs.

Tool Count2/5

26 tools exceeds the typical well-scoped range and the rubric marks 25+ as too many for the apparent scope. Although the OSRS domain is broad and most tools cover distinct areas, the surface is still heavy and could be consolidated or grouped.

Completeness5/5

The toolset covers account management, player stats and progress, wiki search/pages/structured data, prices and price history, items, shops, recipes, monsters, drops, quests and quest planning, diaries, slayer, combat achievements, clues, money makers, and skill planning. No major gaps are apparent for an OSRS companion server.