wiki-skills
MCP connector for the ok-wiki knowledge base, enabling search, read, create, edit, history, tags, and asset management via natural language.
README
ok-wiki-skills
A local MCP connector and Codex plugin that lets Claude and Codex search, read, create, and edit pages in the ok-wiki knowledge base.
It reaches the wiki over HTTP with an API key that never enters the model's context, and speaks MCP
two ways: over stdio as a child process of Claude Code or the self-contained Codex plugin, or
over Streamable HTTP for claude.ai, which connects from Anthropic's infrastructure and so needs
a public URL and OAuth (docs/adr/0006).
Start at
docs/architecture.md.
What it can do
- Search and read — full-text search, fetch a page by path or id, list pages by tag or recency
- Create and edit — create markdown pages at a path the connector derives (see below); patch an existing page's content, title, description, tags, or published state
- History — list a page's revisions, fetch a specific version, restore a page to an earlier one
- Tags — list and autocomplete the wiki's existing tag vocabulary
- Assets — upload a file and get back a ready-to-paste markdown reference; list assets and create folders
What it deliberately cannot do
No moving, renaming, or deleting pages. Those break inbound links or lose content, and a
mistyped path is exactly the error a model makes. Do them in the ok-wiki UI. The boundary is
enforced by the tool surface—move and delete tools do not exist—and the connector group withholds
delete:pages. The group still needs manage:pages because ok-wiki requires it for single-page
reads. Reasoning: docs/adr/0005.
Also out of scope: comments, navigation, users and groups, theming, and administrative operations.
Where new pages land
You don't choose the path—each creation tool derives it. There is no path input on either
creation tool. Claude's wiki_create_page takes three human names and slugifies each into one
segment:
project: "Moontower" chatTitle: "Release planning" artifactName: "Deployment checklist"
↓
claude/moontower/release-planning/deployment-checklist
Codex uses the separate wiki_create_codex_page contract:
workspace: "wiki-skills" threadTitle: "Add Codex support" artifactName: "Plugin guide.md"
↓
codex/wiki-skills/add-codex-support/plugin-guide
The claude/ and codex/ roots preserve host provenance. Slugification lowercases, turns spaces,
underscores and dots into hyphens, drops a trailing file extension, and discards anything outside
a-z, 0-9, and -.
Because there is no move tool, a wrong path is permanent—which is why placement is a schema rule
rather than advice. Pages that predate either convention stay where they are and remain editable by
path through wiki_update_page. Claude conventions live in SKILL.md; Codex policy
lives in plugins/ok-wiki/skills/wiki-authoring/SKILL.md.
Quickstart
1. Build
Install Node.js 22 or newer, then:
cd /path/to/wiki-skills
npm install
npm run build # MCP registration points at dist/index.js, not src/
2. Enable the ok-wiki API
In the wiki: Administration → API Access → enable. Without this, every request is rejected with "API is disabled. You must enable it from the Administration Area first."
3. Mint a scoped API key
Create a group for the connector granting exactly:
read:pages, read:source, write:pages, read:history, read:assets, write:assets,
manage:pages
Grant them in both the group's global permissions and its page rules — the wiki checks both
layers. manage:pages looks like more than a reader needs, but the wiki's single-page resolvers
require it: without it, page lookups fail with "You are not authorized to view this page" even
though listing works (docs/ok-wiki-api.md §4).
Then Administration → API Access → New API Key, bound to that group.
read:source is the one that fails quietly if you forget it — pages come back with a null body
instead of an error. Use a dedicated key so it can be revoked independently and so wiki history
distinguishes agent edits from human ones. Details:
docs/ok-wiki-api.md §2.
4. Register with Claude Code
claude mcp add wiki \
--env WIKI_BASE_URL=http://localhost:3000 \
--env WIKI_API_KEY=<your-api-key> \
-- node /path/to/wiki-skills/dist/index.js
Or, to share it with a project via .mcp.json:
{
"mcpServers": {
"wiki": {
"command": "node",
"args": ["/path/to/wiki-skills/dist/index.js"],
"env": {
"WIKI_BASE_URL": "http://localhost:3000",
"WIKI_API_KEY": "${WIKI_API_KEY}"
}
}
}
}
Prefer the ${VAR} form in any file you might commit — don't put the key in version control.
5. Verify
Run /mcp in Claude Code and confirm wiki is connected with its tools listed. Then ask for
something read-only, like "search the wiki for onboarding", to exercise wiki_search_pages.
Codex plugin installation
The repository marketplace packages ok-wiki version 1.0.0 from plugins/ok-wiki for Codex CLI
and ChatGPT desktop. Both surfaces consume the same plugin source, bundled ./mcp/server.mjs, and
ok-wiki MCP server definition, but they maintain separate installation records and may use
separate caches. Writable mode publishes 14 total tools; readonly mode publishes 8 read-only tools.
The plugin requires Node.js 22 or newer, matching package.json
(engines.node: ">=22").
From a clean clone, install dependencies and deterministically rebuild the checked-in bundle:
npm install
npm run build:plugin
The plugin reads required WIKI_BASE_URL and WIKI_API_KEY values from the local process
environment. It also forwards the seven optional variables WIKI_LOCALE, WIKI_TIMEOUT_MS,
WIKI_READONLY, WIKI_MAX_CONTENT_BYTES, WIKI_LOG_LEVEL, WIKI_MAX_UPLOAD, and
WIKI_UPLOAD_ALLOWLIST. Keep secret values only in local environment configuration; never add
them to the plugin, .mcp.json, .codex-plugin/plugin.json, or
.agents/plugins/marketplace.json.
Codex CLI
Register the repository marketplace, verify discovery, and install the plugin in this exact order:
codex plugin marketplace add <repo-root>
codex plugin list --marketplace wiki-skills --available --json
codex plugin add ok-wiki@wiki-skills
Start a fresh Codex CLI thread and confirm /mcp lists the ok-wiki server. After local source
changes, run npm run build:plugin, rerun codex plugin add ok-wiki@wiki-skills, and start a new
thread so the rebuilt artifact is loaded.
ChatGPT desktop
After registering the repository marketplace, restart ChatGPT desktop, install ok-wiki from the
wiki-skills source, and start a fresh desktop thread. After local updates, run
npm run build:plugin, then restart or reinstall the desktop plugin and start another fresh thread.
Desktop installation is independent of the CLI installation and cache.
Authoring modes
The bundled skill starts in ask mode: creating Markdown does not write to the wiki or trigger
an unsolicited save offer. An explicit request to save, post, or publish a new Markdown artifact
uses wiki_create_codex_page.
A clear instruction such as "use auto mode" enables conversation-local automatic saving until
the user disables it. Auto mode saves each completed .md file newly created by Codex during the
active task exactly once after finalization. It excludes edited pre-existing Markdown, scratch
files, files created by another process, and non-Markdown outputs. Auto mode is never persisted and
never converts a collision into an update; existing pages require an explicit
wiki_get_page → wiki_update_page workflow.
The product and safety contracts for this workflow are
docs/codex-plugin-architecture.md,
docs/codex-plugin-prd.md, and
docs/codex-plugin-tasks.md.
Connecting from claude.ai
claude.ai cannot spawn a local process — it reaches a public HTTPS URL from Anthropic's
infrastructure. Its Add custom connector form offers only OAuth Client ID and OAuth Client
Secret, with no field for a static token, so the connector runs its own OAuth 2.1 authorization
server (docs/adr/0006). Leave both OAuth
fields empty — client registration is automatic.
1. Run the HTTP entrypoint
WIKI_BASE_URL=http://localhost:3000 \
WIKI_API_KEY=<your-api-key> \
WIKI_MCP_BEARER=$(openssl rand -base64 32) \
WIKI_MCP_PUBLIC_URL=https://wiki.example.com \
WIKI_MCP_HOST=127.0.0.1 \
npm run http
npm run http runs the compiled dist/http.js, so step 1 above has to have happened.
WIKI_MCP_PUBLIC_URL is the OAuth issuer and must match the URL you give claude.ai, minus the
/mcp path. Setting it is what turns OAuth on; without it the entrypoint stays static-bearer only.
To run it as a service rather than a foreground process, see
deploy/README.md — a hardened systemd user unit, plus the two settings
whose obvious values are the wrong ones.
2. Put an HTTPS ingress in front
TLS and the public hostname belong to the ingress, not this process. With a Cloudflare Tunnel, point the public hostname at the origin, with no path:
ingress:
- hostname: wiki.example.com
service: http://127.0.0.1:8787
If cloudflared runs in a Docker container, 127.0.0.1 there is the container, not your host —
use the bridge gateway (typically http://172.17.0.1:8787) and set WIKI_MCP_HOST to match. Point
the tunnel's health check at /healthz, which is unauthenticated; /mcp answers 405 to GET.
3. Add the connector
In claude.ai, Settings → Connectors → Add custom connector, URL:
https://wiki.example.com/mcp
The /mcp suffix is required. Approve in the browser using WIKI_MCP_BEARER as the passphrase, and
tick Create and edit pages if you want write access — it is unchecked by default, and a
read-only grant publishes 8 tools instead of 14.
Rotating credentials
WIKI_MCP_BEARER guards two doors: it is the header credential and the consent passphrase.
Rotating it closes both but does not invalidate tokens already issued — for that, delete
WIKI_MCP_STATE_FILE, which is the revoke-everything gesture. That file holds the token signing
key, so it lives at mode 0600; the server refuses to start if that has slipped.
Configuration
| Variable | Required | Default | Purpose |
|---|---|---|---|
WIKI_BASE_URL |
yes | — | e.g. http://localhost:3000 — http://ok-wiki.local also serves the wiki |
WIKI_API_KEY |
yes | — | ok-wiki API key (JWT) |
WIKI_LOCALE |
no | en |
Default locale |
WIKI_TIMEOUT_MS |
no | 15000 |
Per-request timeout |
WIKI_READONLY |
no | 0 |
1 registers only read tools |
WIKI_MAX_CONTENT_BYTES |
no | 100000 |
Cap on page body returned into context |
WIKI_LOG_LEVEL |
no | info |
Diagnostics, always to stderr |
WIKI_MAX_UPLOAD |
no | 10485760 |
Max upload size in bytes for wiki_upload_asset (10 MB) |
WIKI_UPLOAD_ALLOWLIST |
no | unset | Colon-separated absolute path prefixes uploads may come from; unset = unrestricted |
WIKI_MCP_HOST |
no | 127.0.0.1 |
Bind address for the remote HTTP entrypoint |
WIKI_MCP_PORT |
no | 8787 |
Listen port for the remote HTTP entrypoint |
WIKI_MCP_BEARER |
no | unset | Static bearer token for header-auth clients; also the consent passphrase |
WIKI_MCP_PUBLIC_URL |
no | unset | Public https:// origin — the OAuth issuer. Unset disables OAuth |
WIKI_MCP_STATE_FILE |
no | $XDG_STATE_HOME/wiki-skills/oauth.json, else ~/.local/state/wiki-skills/oauth.json |
OAuth signing key and issued-token state |
WIKI_MCP_CLIENT_HOSTS |
no | claude.ai |
Hosts whose OAuth client metadata may be fetched |
Development
| Command | What it does |
|---|---|
npm run build |
Compile the shared stdio and HTTP entrypoints into dist/ |
npm run build:plugin |
Deterministically rebuild the checked-in self-contained Codex bundle |
npm run dev |
Watch-mode stdio server via tsx — no build step |
npm test |
Full vitest suite, including the doc-consistency tests that pin this README to src/config.ts |
npm run lint |
ESLint, which carries the rule that forbids writing to stdout |
npm run smoke |
End-to-end against a live wiki; needs WIKI_BASE_URL and WIKI_API_KEY. Creates one unpublished throwaway page and one small asset, and deletes nothing — clean up by hand |
Documentation
| Document | What's in it |
|---|---|
docs/architecture.md |
System context, module layout, invariants, request flows, error model, security, testing |
docs/codex-plugin-architecture.md |
Codex desktop/CLI plugin packaging, page namespace, authoring modes, and compatibility design |
docs/codex-plugin-prd.md |
Numbered Codex plugin requirements, milestones, acceptance criteria, risks, and rollout plan |
docs/codex-plugin-tasks.md |
Developer/QA task pairs, dependency graph, milestone gates, and completion criteria for the Codex plugin |
docs/codex-plugin-development-status.md |
Implementation ledger, completed QA evidence, and remaining manual release work |
docs/tool-surface.md |
Every tool's inputs, outputs, and behavior |
docs/ok-wiki-api.md |
Upstream endpoints, auth, permissions, and the gotchas that shape the design |
SKILL.md |
The wiki-authoring skill — placement, naming, and formatting conventions the model follows |
docs/conventions.md |
Survey of how the live wiki is actually written, which is where those conventions came from |
deploy/README.md |
Running the HTTP entrypoint as a systemd user unit |
docs/prd.md |
Numbered requirements, milestones, and acceptance criteria — the build plan, decomposed into tasks in docs/tasks.md |
docs/adr/ |
Why stdio, why GraphQL, why TypeScript, why read-modify-write, why no deletes, why our own OAuth server |
If you read only one thing before writing code, make it
docs/adr/0004: ok-wiki's pages.update is a full
replace, not a patch, and a naive implementation silently unpublishes pages and drops their tags.
Troubleshooting
| Symptom | Cause |
|---|---|
| Connector won't connect; no useful error | Something wrote to stdout. Under stdio, stdout is the protocol channel — all logging must go to stderr. |
| Tools missing after a source edit | You edited src/ but the server runs dist/. Re-run npm run build. |
| Codex still uses old plugin behavior | Re-run npm run build:plugin, reinstall or restart the plugin for that surface, and start a fresh thread. |
| "API is disabled" | Step 2 not done. |
| "API Key is invalid or was revoked" | Key revoked or expired; mint a new one. |
| Listing works but fetching a single page is "not authorized" | The key's group is missing manage:pages (required by the single-page resolvers), or lacks it in the group's page rules. |
Page reads succeed but content is null |
The key's group is missing read:source. |
| Edits rejected as conflicts | Someone edited the page after your read. Re-read and retry. |
| claude.ai fails at the authorize step | WIKI_MCP_PUBLIC_URL must be the connector URL minus /mcp, exactly. It is the OAuth issuer, and a mismatch fails discovery. |
| "cannot reach the wiki" | ok-wiki isn't up. It runs as a systemd unit — check systemctl status wiki.service, and journalctl -u wiki.service for why it stopped. |
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。