MCP server
Your bundles, readable by any MCP-capable agent.
What it gives you
Until now, an agent needed a shell to read your bundles: the CLI for text, the graph server for a browser, the Ruby library for code. okf-mcp adds the fourth surface: any MCP-capable host, Claude Desktop, Claude Code, or anything else speaking the protocol, can discover, orient in, search, and read the bundles on your machine, with no shell access and no files pasted into context.
The payoff is the same one the agent skill delivers inside Claude Code, now available to hosts that cannot run a CLI: the agent retrieves the three concepts that answer a question instead of swallowing the bundle whole, and the answer it reads is always the file on disk right now, never a stale copy.
Install and connect
gem install okf-mcp
That is the whole installation. The gem registers an okf mcp verb with the CLI, so it shows up in okf help under installed extensions. Point your host at it; for hosts configured with a JSON block, the shape is:
{
"mcpServers": {
"okf": { "command": "okf", "args": ["mcp"] }
}
}
With no arguments, okf mcp serves every bundle in your registry, project-local registries included. Passing arguments closes the list instead: okf mcp <dir> @slug ... serves exactly those bundles and nothing else, and no tool call can widen the set afterwards. The identity is the registry's own: the bundle argument every tool takes is the same @slug you use at the CLI, minus the @.
It needs okf 1.13.0 or newer and Ruby 2.7 or newer. It is a separate gem rather than part of the baseline on purpose: the MCP SDK brings dependencies the three-dependency core refuses, so you only install the weight where a host will use it.
Ten tools, all read-only
The tools map onto the CLI's read verbs: list_bundles, dirs, index, search, read_concept, catalog, log, validate, lint, and graph. Every one is read-only and says so in its annotations; the first release ships no write surface at all.
Two properties matter more than the list:
- Every answer is bounded.
searchcaps at 20 rows,catalogpages at 200,logreturns the newest three date groups per file instead of the whole history, rollups cap with a named remainder, and every list carries a visibletotalthat counts the thing it bounds. A byte budget caps every answer and announces itself withtruncatedwhen it cuts. An agent asking "what changed recently" gets an answer sized to the question, not to the age of your project. - Nine of the ten declare a result schema and return structured content beside the text, so a host consumes fields instead of parsing a blob. The tenth,
read_concept, returns the concept body as Markdown, which is already its structure.
Failures are honest: a kernel refusal (an unknown bundle, a directory that does not exist) comes back as a tool error carrying the CLI's own sentence, and an empty directory is refused rather than answered with a zero that reads like a fact.
Resources and prompts
Tools are what the model calls; resources are what the host can attach without asking it. Every served bundle's root index.md is available as okf://<slug>, and every concept as okf://<slug>/<id>, with completions so the URIs are browsable rather than a shape you must already know. Pinning a bundle's map into context at the start of a session costs a few hundred tokens and saves the orientation round-trips.
The server also ships two prompts, the retrieval doctrine the skill teaches, rewritten in the tools' own vocabulary: orient with dirs, descend with index, search for pointed questions, read only the winners. They exist because a Desktop host never sees the skill; the prompts are the same playbook where the CLI is not available.
Fresh by construction
The server holds one parsed bundle per root and re-reads only when the files on disk actually change, so bodies are live without a per-request scan. The registry gets the same treatment: register, rename, or repoint a bundle while the server runs and the served set follows, no restart. A search index over a set of bundles is dropped the moment any member changes, because a held index outliving its bundle is a wrong answer, not a slow one.
Transports and exposure
The default transport is stdio: each host spawns its own process and there is nothing to reach over the network. okf mcp --http serves Streamable HTTP instead, for hosts that connect to a URL.
Over HTTP, the same posture as the graph server applies: the read surface follows the bind you choose, and there is no authentication behind it. --bind 0.0.0.0 publishes every served bundle to anything that can reach the port, and the boot line says so in those words. Keep it on loopback unless you mean to publish.
When to reach for it
Inside Claude Code with the plugin installed, you rarely need it: the skill drives the CLI directly and can also author, which the MCP surface deliberately cannot. Reach for okf-mcp when the host has no shell (Claude Desktop), when you want several tools sharing one served set, or when a teammate's agent should read your team's bundles without installing anything but a config block. The team CI guide covers the complementary path of publishing a bundle as a static page.