okf-mcp-server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@okf-mcp-serverlist recent architectural decisions"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
okf-mcp-server
Reusable, read-only MCP server that exposes a repo's knowledge files (backlog docs, decisions, design notes) as MCP resources over stdio. Files decide their own fate via OKF-style frontmatter — no per-source config, no kind/glob registry. One package, one process per owner repo, automatic URI namespacing from the repo basename.
Status: 0.2.0 — frontmatter-driven OKF source format.
What is this
okf-mcp-server ships a configurable MCP server (Server from the mcp SDK) and a CLI/Python entry point that:
resolves
ownerfromgit rev-parse --show-toplevelbasename (fallback tocwdbasename with a stderr warning);resolves scan roots by precedence:
--roots <csv>flag →OKF_MCP_ROOTSenv (colon-separated, PATH-style) → built-in default[design/, backlog/docs/, backlog/decisions/];recursively walks every root, parses frontmatter, and registers a file as an MCP resource iff
export: trueandtypeis non-empty (strict opt-in);serves
list_resourcesandread_resourceover stdio for any MCP-aware client (Claude Code, Cursor, etc.).
It is read-only — no write_resource, no hot-reload, no search tool.
Related MCP server: data-olympus MCP server
Frontmatter contract
Every exported file declares itself in its own frontmatter:
---
type: "Architecture Decision" # required for export; free-form, OKF-semantic; slugified into URI
title: Knowledge Mesh foundation
export: true # required; opt-in — absent or false → file is invisible
description: ... # optional; falls back to first non-heading paragraph (≤ 500 chars)
id: decision-2 # optional; falls back to filename-derived id
---Fields are read as-is; no schema validation beyond the strict export gate.
URI scheme
Every resource URI follows knowledge://{owner}/{type-slug}/{id}.
owner— basename of the git toplevel (stable contract).type-slug— deterministic slug of frontmattertype: lowercase, non-alphanumeric runs collapsed to-, leading/trailing-trimmed ("Architecture Decision"→architecture-decision). Mutable — editingtypechanges the slug; consumers must not pin to it.id— frontmatteridif present; otherwise filename-derived: first whitespace-delimited token of the stem (doc-7 - Partner-...md→doc-7), or the full stem when no whitespace is present (c8-saas-...-brainstorm.md→c8-saas-...-brainstorm). Stable — this is the contract that consumers cite.
Per matched file, the resource carries: uri, name (frontmatter title or filename stem), description (frontmatter description or first non-heading paragraph, truncated to 500 chars), mimeType: text/markdown, and the full body (frontmatter stripped) as content.
Scan roots
Roots are resolved relative to the git toplevel, not cwd. A non-existent root is skipped with a stderr warning, not a fatal error. Files outside any configured root (e.g. presentations/, .git/) are invisible.
Precedence:
Source | Separator | Example |
|
|
|
|
|
|
built-in default | n/a |
|
The first non-empty source wins; lower precedence is ignored entirely (not merged).
In-repo adoption (PEP 723 shim)
When the owner repo lives in the same workspace as this package, the shim resolves okf-mcp-server from a local path — no publish step required. One file in the owner repo:
mcp/server.py:
# /// script
# requires-python = ">=3.10"
# dependencies = ["okf-mcp-server"]
#
# [tool.uv.sources]
# okf-mcp-server = { path = "../okf-mcp-server" }
# ///
from okf_mcp_server import run
if __name__ == "__main__":
run()Run it:
uv run mcp/server.pyuv resolves the path source and installs deps on first run. Wire it into Claude Code via a project-level .mcp.json entry pointing at uv run mcp/server.py.
Cross-repo adoption
When the owner repo lives in a different repo, install via git URL pinned to a release tag:
uv add 'okf-mcp-server @ git+https://example.invalid/okf-mcp-server.git@v0.2.0'The host above is a placeholder — replace it with the canonical remote once the repository is published. The package lives at the repository root (no
#subdirectory=is needed). Pin by tag (e.g.@v0.2.0) for reproducible federation across owner repos.
The shim then drops the [tool.uv.sources] block:
# /// script
# requires-python = ">=3.10"
# dependencies = ["okf-mcp-server"]
# ///
from okf_mcp_server import run
if __name__ == "__main__":
run()Gateway (Streamable HTTP, multi-owner)
Everything above runs the server per owner over stdio. The gateway is the other deployment mode: one supervised container that serves many owners over MCP Streamable HTTP, so a team points its clients at a single always-on endpoint instead of spawning a stdio process per repo.
Git-sourced, no mounts. The gateway shallow-clones each owner's repo into a container-private cache volume and reuses the exact stdio core (
load_docs+build_server) against the checkout. There are no source or consumer mounts.Path-routed allowlist. Each owner is reachable at
/{owner}/mcp; theservers.yamlregistry is the allowlist — an unregistered owner gets 404.Fresh enough. Each request pulls the owner if it is staler than its TTL (default 60s);
POST /{owner}/refreshforces an immediate pull.Auth. A single shared north bearer token guards every route except
GET /healthz; south per-host git tokens are injected into clone/fetch URLs only and never persisted to.git/config.
servers.yaml
The owner allowlist. It holds no secrets — credentials names the
environment variable (token_env) that carries each host's token. Mounted
read-only into the container. A committed sample lives at
servers.yaml:
defaults:
ref: main # branch/tag checked out when an owner omits its own
ttl: 60 # per-owner staleness bound (seconds) before the next pull
owners:
acme: # reachable at /acme/mcp
url: https://git.example.invalid/acme/knowledge.git
beta:
url: https://bitbucket.example.invalid/beta/knowledge.git
ref: release # optional per-owner override of defaults.ref
ttl: 120 # optional per-owner override of defaults.ttl
credentials: # per git host; consumed only for authenticated clones
bitbucket.example.invalid:
token_env: OKF_GIT_TOKEN_BITBUCKET # the .env var holding the token
token_user: x-token-auth # provider-fixed usernameEnvironment variables
Secrets live in .env (copy it from .env.example:
cp .env.example .env); .env is gitignored.
Variable | Required | Default | Purpose |
| yes | — | North bearer token; the gateway refuses to start without it. |
| as needed | — | South per-host git tokens, referenced by |
| no |
| Path to the registry. |
| no | XDG cache | Directory for per-owner checkouts. |
| no |
| Bind host. |
| no |
| Bind port. |
Run it with Docker
Docker is the cross-platform keep-alive (restart: unless-stopped) — no
launchd/systemd. Bring it up from the repo root:
cp .env.example .env # then set OKF_GATEWAY_TOKEN (and any OKF_GIT_TOKEN_*)
# edit servers.yaml to list your owners
docker compose up -ddocker compose up -d is idempotent — run it again and it is a no-op when the
service is already running, so it doubles as the redeploy command.
Manual verification, not an offline gate. The actual
docker build/docker compose up -d— and the idempotent no-op-when-already-running behavior — pull base images and clone owner repos over the network, so they are a manual step. What the automated (offline) gate covers isdocker compose configplus file/content checks (seetests/test_docker_packaging.py).
Health and lifecycle:
curl -fsS http://localhost:8080/healthz # -> ok (no auth)
curl -X POST http://localhost:8080/acme/refresh \
-H "Authorization: Bearer $OKF_GATEWAY_TOKEN" # force a pullPoint a consumer at it
From a devcontainer or host, reach the gateway at host.docker.internal and send
the north bearer token. A project-level .mcp.json entry (Claude Code):
{
"mcpServers": {
"acme-knowledge": {
"type": "http",
"url": "http://host.docker.internal:8080/acme/mcp",
"headers": {
"Authorization": "Bearer ${OKF_GATEWAY_TOKEN}"
}
}
}
}Swap acme for the owner you want and set OKF_GATEWAY_TOKEN in the consumer's
environment to the same shared token the gateway runs with.
Known limitations
Single-process per owner. One running process serves exactly one git repo. Multi-owner federation is achieved by running one shim per owner; there is no built-in aggregator.
No hot-reload. Roots are walked once at startup. Edits to source files require restarting the server.
OKF
index.md/log.mdare not special. If they carryexport: true+type, they become ordinary resources; otherwise invisible.type-slugis not contractual. Editingtypewill silently change the URI's middle segment. Cite resources byid.
Linter
A companion CLI, okf-mcp-lint, enforces three frontmatter invariants over the same roots the server scans, so misconfigured files fail loud locally and in CI instead of silently disappearing from the served set.
Check | Severity | Behaviour |
Duplicate | error | Non-zero exit; both file paths reported. |
| error | Non-zero exit; file path reported. |
Distinct | warning | Zero exit; both type strings + slug reported. |
id derivation and type-slug derivation are imported directly from the server module (extract_id, slugify_type) — the linter never reimplements them, so a verdict from the linter implies the same outcome at server load time.
Run it from the owner repo (the okf-mcp-lint console script is available once the package is installed):
okf-mcp-lint
# or, with overrides:
okf-mcp-lint --roots design/,backlog/docs--roots and OKF_MCP_ROOTS precedence matches the server CLI.
Tests
Tests live in tests/. Run them from the repository root:
uv run pytesttests/fixtures/sample-project/ is the worked example used by the smoke / contract / protocol tests; tests/conftest.py copies it into a fresh tmp dir and git inits it so the resolver behaves as in a real owner repo.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/dddpaul/okf-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server