CodeDocs Vault

The MCP Tool Surface

OpenKnowledge exposes its knowledge base to agents as a stdio MCP server with 17 tools. The plugin you "install" is a thin manifest; the real surface is server-side.


1. The plugin is a manifest, the server is the substance

packages/plugin is almost empty — its public surface is a Claude Code plugin descriptor:

// packages/plugin/.claude-plugin/plugin.json
{ "name": "open-knowledge", "version": "0.1.0",
  "description": "CRDT knowledge base with real-time collaboration and AI agent tools" }

It exports no code. The actual tool implementations live in packages/server/src/mcp/tools/, registered by registerAllTools(server, opts) (packages/server/src/mcp/tools/index.ts:33), and the agent reaches them through the stdio server booted by packages/cli/src/mcp/server.ts:145-260. The split is deliberate: the plugin/skill tells the agent what exists; the server decides what it does, so the contract can change server-side without reinstalling anything.


2. The 17 tools

Confirmed against the registry test (packages/server/src/mcp/tools/registry.test.ts:11-29):

# Tool Purpose
1 exec run read-only shell (ls, cat, grep, bash) over the KB
2 search ranked full-text + semantic search (needs the collab server)
3 history version history + snapshot listing
4 links link-graph ops — orphans, hubs, dead links, suggestions
5 config read project config + workspace metadata
6 palette folder structure + template discovery
7 preview_url route-only preview URL for a doc
8 share_link shareable public link (needs the server)
9 write create/overwrite docs, folders, templates, assets — via the CRDT layer
10 edit patch a doc (find/replace, frontmatter merge)
11 delete remove docs/folders/assets
12 move rename/relocate
13 checkpoint save a version with a user-facing summary
14 restore_version revert to a prior checkpoint
15 conflicts list CRDT/sync merge conflicts
16 resolve_conflict resolve (merge/keep strategies)
17 workflow dispatcher for discover / ingest / research / consolidate (see 04)

Note what's not here: there is no "ask the LLM" tool. OK never calls a model on the agent's behalf — the agent is the model. OK's tools are all deterministic operations on the knowledge base. The one place an LLM is implied is search, which uses embeddings, but the agent calling search is a different model than the one producing the embeddings (09_agentic_search.md).


3. Schemas: Zod, with a structured-output workaround

Every tool declares its inputs as a Zod schema and is registered with server.registerTool(name, { description, inputSchema }, handler):

// pattern from packages/server/src/mcp/tools/*.ts
const InputSchema = {
  query: z.string().describe('Search query — title, path, or body terms.'),
  intent: z.enum(['omnibar', 'full_text']).optional(),
  limit: z.number().int().min(1).max(100).optional(),
} as const;

Results come back in one of two shapes (shared.ts:99-132):

A subtle detail: outputSchemaWithText() (shared.ts:113-120) folds a text field into the structured output, a workaround for Claude Desktop hiding structuredContent when present. Worth noting if you build MCP tools — clients disagree about how they render structured results, so OK ships the human-readable text both ways.


4. Per-call project routing

One MCP server, many possible workspaces. OK resolves which project a tool call targets in a three-step fallback (packages/cli/src/mcp/server.ts:219-225):

  1. an explicit cwd argument on the tool call, else
  2. a sticky project remembered from the previous call, else
  3. the MCP client's single advertised root (with an ambiguity warning if the client advertises several — e.g. a multi-worktree repo).

This lets an agent start calling tools without pre-selecting a workspace, and lets one server serve a session that roams across projects. The sticky-anchor pattern is a small, reusable idea: make context optional-with-memory rather than required-up-front.


5. The exec tool is the escape hatch

exec runs read-only shell over the KB. It is what makes OK usable even in a skill-only install (no MCP): the discovery skill tells the agent to reach the knowledge base with plain ls/cat/grep if the MCP tools aren't present (05_skills.md). So the tool surface degrades gracefully — full fidelity over MCP, basic fidelity over the shell the agent already has.


What's worth stealing

  1. Tools are deterministic operations; the agent brings the intelligence. A clean separation that makes the tool layer testable (registry.test.ts) and model-agnostic.
  2. Sticky per-call routing. Optional cwd + remembered anchor + client-root fallback is a tidy way to serve many workspaces from one server.
  3. Ship the text both ways. MCP clients render structured output inconsistently; folding human-readable text into the structured payload sidesteps it.
  4. A shell escape hatch. exec means your integration still works when the rich tools aren't loaded — valuable for a meta-harness that can't assume every worker mounted your server.
  5. Thin manifest, fat server. Keep the installed surface declarative so you can evolve behavior without asking users to reinstall.