Skip to main content
Glama
VGFP

colyseus-docs-mcp

by VGFP
README.md
# colyseus-docs-mcp

An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that
exposes the [Colyseus](https://colyseus.io/) multiplayer-framework documentation
to AI agents such as [opencode](https://opencode.ai), Claude Code, Cursor, etc.

Published as an npm package. With this server wired up, an agent you're chatting
with can:

- enumerate every documentation page (`list_docs`)
- read any page rendered as clean Markdown (`read_doc`)
- run a relevance-ranked full-text search (`search_docs`)
- subscribe to per-page resources (`colyseus://docs/{slug}`)

The MDX scaffolding (frontmatter, imports, `<Tabs>`, `<Callout>`, icon
components, JSX comments, ...) is stripped ahead of time so the agent only ever
sees prose + working code blocks.

## Status

- Loads **114** doc pages from the bundled `docs/` snapshot.
- Speaks MCP over **stdio** (the standard local-server transport).
- Provides 3 tools, 1 resource template, and 1 ready-made prompt.
- Zero runtime deps beyond `@modelcontextprotocol/sdk` and `zod`.
- Lint + smoke-tested end-to-end.

## Install

```sh
# Run once (downloads & caches the package)
npx -y colyseus-docs-mcp

# Or install globally
npm install -g colyseus-docs-mcp
colyseus-docs-mcp
```

The server speaks JSON-RPC over stdio, so running the binary directly just waits
for MCP messages on stdin - point an MCP client at it (see below) rather than
running it by hand.

### From source

```sh
git clone https://github.com/VGFP/colyseus-docs-mcp.git
cd colyseus-docs-mcp
npm install
npm run build
node dist/index.js      # speaks JSON-RPC over stdio
```

You can sanity-check the server without an MCP-aware client:

```sh
npm run smoke       # node scripts/smoke-test.mjs - exercises every tool/resource
npm run lint        # node scripts/lint-preprocessed.mjs - validates MDX stripping
npm test            # build + lint + smoke
```

## Pointing an MCP client at it

### opencode

Add the following to your project's `.opencode/opencode.json` (or
`~/.config/opencode/opencode.json` for global use):

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "colyseus-docs-mcp": {
      "type": "local",
      "command": ["npx", "-y", "colyseus-docs-mcp"],
      "enabled": true
    }
  }
}
```

If you installed it globally, the command can be just `["colyseus-docs-mcp"]`.
For a local build, use the absolute path to `dist/index.js`:

```json
{
  "mcp": {
    "colyseus-docs-mcp": {
      "type": "local",
      "command": ["node", "/absolute/path/to/colyseus-docs-mcp/dist/index.js"],
      "enabled": true
    }
  }
}
```

Restart opencode after saving the file - MCP servers are loaded once at startup.

### Other MCP clients (Claude Code, Cursor, etc.)

The server speaks standard MCP over stdio, so any compliant client works. Use
`npx -y colyseus-docs-mcp` or `node /path/to/dist/index.js` as the launch
command.

## Tools

### `list_docs`

Returns the catalogue of every documentation page known to the server. Use this
first when you don't know which page covers a topic.

```jsonc
// Input
{}

// Output (truncated)
{
  "total": 114,
  "docs_root": "/abs/path/to/colyseus-docs-mcp/docs",
  "pages": [
    { "slug": "",                  "title": "Colyseus - Multiplayer Game Framework for Node.js", "category": "index", "description": "…" },
    { "slug": "state",             "title": "State Synchronization", "category": "state",  "description": null },
    { "slug": "room/messages",     "title": "Message Composability", "category": "room",   "description": null },
    …
  ]
}
```

### `read_doc`

Returns the preprocessed Markdown body of a single page.

```jsonc
// Input
{ "slug": "state" }     // "" or "index" returns the landing page

// Output
{
  "content": [
    { "type": "text", "text": "# State Synchronization\n\n…full Markdown…" }
  ]
}
```

The slug lookup is forgiving - `"state"`, `"/state"`, `"state/"`, and
`"index"` are all accepted.

### `search_docs`

Relevance-ranked full-text search. Title hits weighted highest, then headings,
then body. Each hit includes a ~250-character snippet around the first match.

```jsonc
// Input
{ "query": "schema @type decorator", "limit": 5 }

// Output
{
  "query": "schema @type decorator",
  "total_hits": 3,
  "hits": [
    {
      "slug": "state/schema",
      "title": "Schema Definition",
      "category": "state",
      "score": 23,
      "snippet": "…the **@type** decorator marks each property…"
    },
    …
  ]
}
```

## Resources

A single URI template is registered so clients can also use `resources/read`
instead of `tools/call` if they prefer:

```
colyseus://docs/{slug}
```

Example:

```jsonc
{ "uri": "colyseus://docs/room" }
```

## Prompts

| Name                | Purpose                                                                 |
|---------------------|-------------------------------------------------------------------------|
| `colyseus_overview` | Returns a system-style primer describing Colyseus + the full doc index.|

## Configuration

| Env var                | Default                                | Purpose                          |
|------------------------|----------------------------------------|----------------------------------|
| `COLYSEUS_DOCS_PATH`   | `<package_root>/docs`                  | Override the docs directory.     |

Pointing `COLYSEUS_DOCS_PATH` at a fresh clone of
<https://github.com/colyseus/docs> is the easiest way to pull in upstream
changes - the server reads MDX at startup, so just restart it after a `git pull`.

## Updating the bundled docs

The `docs/` directory is a snapshot of Colyseus's MDX pages. To refresh it:

```sh
# From another directory of your choice:
git clone https://github.com/colyseus/docs.git upstream-docs

# Back in this package:
rm -rf docs && cp -r ../upstream-docs/pages ./docs
npm run lint && npm run smoke
```

## Releasing

The package version mirrors the Colyseus version whose docs are bundled, with an
`-mcp.N` suffix for successive MCP-only revisions against the same upstream
release (e.g. `0.17.10-mcp.1`, `0.17.10-mcp.2`, …). When you sync `docs/` from
upstream, bump the upstream segment and reset the MCP counter:

```sh
# After `npm run lint && npm run smoke` pass with the refreshed docs:

# New upstream release → reset mcp counter:
npm version 0.18.0-mcp.1

# Same upstream, new MCP-only change → bump mcp counter:
npm version prerelease --preid mcp   # 0.17.10-mcp.1 → 0.17.10-mcp.2

git push --follow-tags
```

Pushing a `v*` tag triggers `.github/workflows/release.yml`, which builds and
publishes to npm (with provenance). The `NPM_TOKEN` secret must be set in the
repository's Actions secrets.

> Pre-release upstream tags (e.g. `0.18.0-preview.1`) are mirrored as
> `0.18.0-preview.1-mcp.1`.

## Project layout

```
colyseus-docs-mcp/
├── .github/workflows/
│   ├── ci.yml             # build + lint + smoke on push/PR
│   └── release.yml        # npm publish on version tags
├── docs/                  # All MDX documentation pages (the data)
├── scripts/
│   ├── smoke-test.mjs     # End-to-end JSON-RPC exercise of every tool/resource
│   └── lint-preprocessed.mjs
├── src/
│   ├── index.ts           # MCP server registration + stdio transport
│   └── lib/
│       ├── docs.ts        # Doc discovery + MDX → Markdown preprocessor
│       └── search.ts      # Ranked full-text search
├── package.json
├── tsconfig.json
└── README.md
```

## License

MIT (inherited from the upstream Colyseus docs - see `LICENSE`).

TDQS

A4.5/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a completely distinct purpose: listing all pages, reading a specific page, and searching across pages. There is no ambiguity or overlap.

Naming Consistency5/5

All three tool names follow a consistent verb_noun pattern using snake_case (list_docs, read_doc, search_docs), making them predictable and easy to understand.

Tool Count4/5

Three tools is minimal but appropriate for a documentation server, covering the essential operations of discovering, reading, and searching content. It is slightly on the thin side but well-scoped.

Completeness4/5

The tool surface covers the core documentation tasks (listing, reading, searching). Minor gaps exist, such as no way to get a table of contents or hierarchical navigation, but list_docs already provides category information, so the gaps are not critical.

Maintenance

ActivityInactive
ResponsivenessNo issues