colyseus-docs-mcp
# 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
Scored across 3 tools
Each tool has a completely distinct purpose: listing all pages, reading a specific page, and searching across pages. There is no ambiguity or overlap.
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.
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.
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.