Skip to main content
Glama
README.md
# openwiki-mcp

MCP server that exposes **OpenWiki** (OpenChamber) documentation generation as
Model Context Protocol tools, so an official, unmodified OpenCode (or any MCP
host) can generate and update repository wikis.

Fully independent of the opencode source tree — openwiki itself is resolved as
an external package (`npm` install or a staged offline bundle), and agent
credentials are relayed via environment variables, never stored.

## Tools

| Tool | Maps to agent | Notes |
|---|---|---|
| `openwiki_status` | — (local only) | Inspects `openwiki/` + `.last-update.json`. No agent, no model, works offline. |
| `openwiki_generate` | `init` | First-time wiki generation. Optional `userMessage` steers the agent. |
| `openwiki_update` | `update` | Diff-based refresh; only stale pages are regenerated. |

## Prerequisites

- Node.js >= 22 (the MCP server and the agent child process both run under `node`)
- An openwiki package install:

  ```bash
  npm install -g openwiki          # online machine, or
  ```

  ```bash
  # offline machine: copy a prepared bundle and point at it
  set OPENWIKI_PACKAGE_ROOT=D:\path\to\staged\bundle\node_modules\openwiki
  ```

  `OPENWIKI_PACKAGE_ROOT` may point either directly at the package root or at a
  layout that contains `node_modules/openwiki`. The staged bundle needs no
  junction or symlink tricks — Node resolves the agent's bare imports through
  the normal `node_modules` walk.

## Agent model configuration

The server relays (never stores) the following variables into the agent child
process:

| Env var (server side) | Meaning |
|---|---|
| `OPENWIKI_PROVIDER` | `openai` (default) or `openai-compatible` |
| `OPENWIKI_MODEL_ID` | Model id, e.g. `gpt-5` |
| `OPENAI_COMPATIBLE_BASE_URL` | Point at a local OpenAI-compatible gateway to keep real keys out of the agent env |
| `OPENAI_COMPATIBLE_API_KEY` | Key for the openai-compatible provider |
| `OPENAI_API_KEY` | Key for the `openai` provider |
| `OPENWIKI_PACKAGE_ROOT` | Optional; explicit path to the openwiki install |

Per-call `modelId`/`language`/`userMessage` tool arguments override the ambient
environment for that run.

## Registering with OpenCode

Add to your `opencode.json` / `opencode.jsonc`:

```jsonc
{
  "mcp": {
    "openwiki": {
      "type": "local",
      "command": ["node", "D:/path/to/openwiki-mcp/dist/index.js"],
      "environment": {
        "OPENWIKI_PACKAGE_ROOT": "D:/path/to/staged/bundle/node_modules/openwiki",
        "OPENWIKI_PROVIDER": "openai-compatible",
        "OPENWIKI_MODEL_ID": "gpt-5",
        "OPENAI_COMPATIBLE_BASE_URL": "http://127.0.0.1:4096/v1"
      }
    }
  }
}
```

The three tools then appear in every OpenCode conversation as ordinary tools.

## Development

```bash
npm install
npm run build        # tsc -> dist/
npm test             # node --test (status inspection unit tests)
npm run dev          # run the server via tsx (dev)
```

Smoke tests:

```bash
node scripts/smoke.mjs <dir> status        # local inspection only
node scripts/smoke.mjs <dir> init "note"   # full agent run (needs model env)
```

Manual MCP protocol check:

```powershell
@'
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":1,"method":"tools/list"}
'@ | node dist/index.js
```

## Design notes

- `src/openwiki/resolve.ts` — package resolution: `OPENWIKI_PACKAGE_ROOT`, then
  `require.resolve("openwiki/package.json")`.
- `src/openwiki/worker.mjs` — adapter worker: reads one job from stdin, imports
  the agent entry by absolute path, emits NDJSON progress on stdout. Ported
  from the opencode fork's `packages/openwiki` adapter and kept independent.
- `src/openwiki/run.ts` — spawns the worker as a child of the MCP server, so a
  hung agent can never take down the MCP host.
- `src/status.ts` — local status inspection (no model cost).
- v0.1 maps `generate` to the agent's `init` command, matching openwiki 0.3.x
  where `init` is the first-generation command and `update` the refresh one.