Skip to main content
Glama
cbhl

stardew-mcp

by cbhl
README.md
# stardew-mcp

An [MCP](https://modelcontextprotocol.io) server that exposes the
[Stardew Valley Wiki](https://stardewvalleywiki.com) as queryable tools.

It parses a MediaWiki XML dump of the wiki (shipped as
`stardewvalleywiki-dump-20260628.zip`) into structured JSON at build time, then
serves it through a small set of MCP tools: keyword search, optional semantic
search, typed listings, and per-page/per-section retrieval.

## What it gives an LLM

- **`search_pages(query, limit?, type?)`** — BM25 keyword search over page
  titles, intros, infobox fields, and section headings.
- **`vector_search(query, limit?, type?)`** — semantic search over sentence
  embeddings (all-MiniLM-L6-v2). Falls back to keyword search if embeddings
  aren't built.
- **`get_page(title, include_raw?)`** — full structured page: entity type,
  parsed infobox fields (rendered to text), intro, all sections, categories.
- **`get_page_section(title, section)`** — a single section by heading.
- **`list_types()`** — entity types (from infoboxes) with counts.
- **`list_by_type(type, limit?)`** — all page titles of one type.
- **`search_by_type(type, query, limit?)`** — keyword search scoped to one type.

Entity types are derived from the wiki's infobox templates and include:
`villager`, `fish`, `item` (plain `{{Infobox}}`, e.g. crops/forage),
`seed`, `weapon`, `clothing`, `furniture`, `mousehat`, `mineral`, `monster`,
`location`, `artifact`, `building`, `tool`, `animal`, `tree`.

## Prerequisites

- Node.js 22+
- The `unzip` binary on `PATH` (used to extract the dump zip)
- The dump zip at the repo root:
  `stardewvalleywiki-dump-20260628.zip`

## Build

```bash
npm install
npm run build          # parse XML -> data/*.json, then compile TS
```

This produces:

- `data/pages.json` — every page, parsed (infobox fields, sections, categories, excerpt).
- `data/index.json` — title + type indices for fast lookup.
- `dist/` — compiled server.

### (Optional) Build embeddings for vector search

```bash
npm run build:embed     # downloads ~23MB model once, embeds 2005 pages
```

This adds `data/embeddings.json`. `vector_search` works without it (it falls
back to keyword search), but the tool is more useful with embeddings. Requires
the optional dependency `@huggingface/transformers`, which is installed by
default via `optionalDependencies`.

## Run

```bash
npm start               # node dist/server/index.js  (stdio transport)
npm run dev             # tsx src/server/index.ts    (no build step needed)
```

### Configure an MCP client

Add the server to your MCP client config (e.g. `.opencode/opencode.json` or
Claude Desktop's `claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "stardew": {
      "command": "node",
      "args": ["/absolute/path/to/stardew-mcp/dist/server/index.js"]
    }
  }
}
```

The server loads `data/pages.json` at startup; build before first run.

## How the data is parsed

`src/build/wikitext.ts` is a focused MediaWiki parser (not a full one):

- Finds the first top-level `{{Infobox ...}}` template with balanced-brace
  scanning, and parses its `key = value` fields.
- Renders fields to plaintext: `{{Price|N}}` → "N gold", `{{Name|X}}` → "X",
  `{{NPC|name|role}}` → "name (role)", `{{Season|Spring|13}}` → "Spring 13",
  links `[[A|b]]` → "b", and strips refs/tables/file links.
- Splits sections on `=`-headings and strips the infobox from the intro.
- Extracts `[[Category:...]]`.

Search (`src/search/search.ts`) is BM25 over tokenized excerpts with title
boosting, plus optional cosine search over L2-normalized embeddings.

## Scripts

| script | description |
| --- | --- |
| `npm run build:parse` | parse the XML dump → `data/pages.json` + `data/index.json` |
| `npm run build:embed` | compute sentence embeddings → `data/embeddings.json` |
| `npm run build:server` | `tsc` → `dist/` |
| `npm run build` | parse + compile |
| `npm run dev` | run server via tsx (no compile) |
| `npm start` | run compiled server |
| `npm test` | vitest (parser unit tests + end-to-end server tests) |
| `npm run typecheck` | `tsc --noEmit` |

## Layout

```
src/
  build/
    wikitext.ts     # MediaWiki parser (infobox, sections, render)
    build.ts        # XML dump -> data/pages.json + data/index.json
    embed.ts        # pages -> data/embeddings.json (transformers.js)
  search/
    search.ts       # BM25 + optional vector search, data loader
  server/
    index.ts        # MCP server + tool handlers
tests/
  parse.test.ts     # parser unit tests
  e2e.test.ts       # end-to-end server tests via MCP client SDK
data/               # generated (gitignored)
```