okf-hub
Ce serveur MCP donne à des sessions Claude un accès en lecture à des bases de connaissance Markdown et un canal de propositions sans modification directe du corpus. Actuellement, aucune base n'est enregistrée.
kb_list: lister les bases disponibles, leur objet, nombre de documents et propositions en attente, et éventuellement les concerns.kb_search: recherche plein texte dans une base, en mode keyword ou regex, avec extraits pertinents.kb_read: lire un document complet ou une section précise, avec troncature au-delà du seuil et optionforce.kb_governance: consulter les règles de gouvernance et le schéma de frontmatter d'une base.kb_propose: déposer une proposition (observation, correction, addition, question) en attente de revue par le gestionnaire; aucine intgration automatique.kb_hub_rescan: relancer la découverte des bases après import d'un bundle, pour la session qui l'appelle.Aucun outil ne modifie le corpus : les propositions sont séparées dans
proposals/pending/et traitées par le rôle gestionnaire.
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-hubSearch the knowledge base for 'bundle spec' and summarize the key points."
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 Bundle Hub
Serveur MCP donnant à des sessions Claude multiples et isolées un accès en lecture à des bases de connaissance markdown, et un moyen de les alimenter sans jamais les modifier directement.
Implémente la spécification « OKF Bundle Hub v0 » (identifiant de version dans
les manifestes : bundle-spec: "0.1").
Documentation
Document | Contenu |
La spécification. Elle fait autorité ; tous les renvois « § x.y » du code y renvoient. | |
Conception : choix d'implémentation, mécanismes de correction, écarts assumés, traçabilité test ↔ exigence. | |
Contrat des sept outils | |
La spec OKF externe et ses trois divergences avec celle du hub. | |
Orientation pour une session ouvrant ce dépôt. | |
Déroulé de revue du rôle gestionnaire. |
Related MCP server: 50 First Tapes MCP Server
Principes
Git est canonique. Tout l'état vit dans les dépôts git des bases. Aucune base de données. Tout index ou cache est dérivé et régénérable.
Frontière de confiance à l'écriture. Les sessions consommatrices ne modifient jamais le corpus : elles déposent des propositions. Seul le rôle gestionnaire intègre.
Une base sans le hub reste utilisable. Un bundle est un dépôt markdown lisible par un humain ou n'importe quel outil.
Optimisation = économie de tokens. Les outils retournent le minimum pertinent ; toute sortie volumineuse est plafonnée (~4 000 tokens) avec troncature signalée.
Démarrage
Tout en une commande
Une fois les dépendances installées (uv sync, déjà fait par le
post-create du devcontainer), okf-hub setup enchaîne les quatre étapes
détaillées plus bas — sans en remplacer aucune : c'est le même résultat,
automatisé pour les cas qu'il peut détecter sans deviner un identifiant ou un
secret externe.
uv run okf-hub setupIdentité git — configurée si elle manque encore (interactif ;
--yespour sauter la saisie plutôt qu'attendre une réponse).Clé(s) SSH — dans un devcontainer, délègue à
.devcontainer/deploy-keys.sh(idempotent : relancerokf-hub setupaprès avoir enregistré une clé sur GitHub la valide).Client MCP — enregistre
okf-hubauprès de Claude Code (claude mcp add) si la commandeclaudeest dans le PATH, et met à jour la config de Claude Desktop si elle est détectée sur la machine.Bases livrées — installe ce qui manque dans
bases/(déjà fait automatiquement au premier démarrage du serveur ; utile ici pour une confirmation immédiate, sans attendre une connexion cliente).
Chaque étape sans objet dans l'environnement courant (pas de devcontainer,
aucun client MCP détecté, Claude Desktop absent, bootstrap-bundles: false)
est signalée comme telle dans le rapport final — jamais silencieuse — et
renvoie vers la procédure manuelle correspondante ci-dessous : hub hors
devcontainer, client MCP configuré à la main, hub derrière docker exec.
Dans le devcontainer (recommandé)
Ouvrir le dépôt dans VS Code → Reopen in Container. Le post-create installe
ripgrep, uv et les dépendances, pose l'identité git, prépare les deploy keys,
puis lance les tests.
Identité git
Un commit poussé sous une adresse qui n'existe pas n'est rattaché à aucun compte
GitHub : ni auteur identifiable dans l'historique, ni contribution comptée. Le
conteneur lit donc .devcontainer/git-identity.env, non versionné — chaque
mainteneur a la sienne :
cat > .devcontainer/git-identity.env <<'EOF'
OKF_GIT_NAME="Prénom NOM"
OKF_GIT_EMAIL="<id>+<login>@users.noreply.github.com"
EOFL'adresse noreply de GitHub (Settings > Emails) garantit le rattachement au
compte sans publier d'adresse personnelle. Sans ce fichier, post-create.sh
retombe sur une identité locale et le signale bruyamment : c'est un défaut
de repli, pas un réglage.
Pousser depuis le devcontainer
Un remote en git@github.com: n'a dans un conteneur ni clé ni agent —
git push échoue en « Permission denied (publickey) », et le commit reste sur
place sans que rien ne le signale. Les remotes en https:// semblent marcher
sans rien faire, mais par le helper de credentials de VS Code : ils tombent dès
qu'un processus git tourne hors de cette session — bootstrap.py au démarrage
du serveur, un docker exec.
.devcontainer/deploy-keys.sh règle les deux cas avec une deploy key par
dépôt, dans un volume nommé monté sur ~/.ssh (elles survivent aux rebuilds).
Il inventorie les dépôts — origin du hub, amonts de bundles/upstreams.yaml,
remotes des bases clonées —, génère la clé manquante de chacun, écrit le
~/.ssh/config associant dépôt et clé, et affiche les clés publiques restant à
enregistrer avec l'URL exacte où le faire (Settings > Deploy keys > Add deploy
key, cocher Allow write access pour pouvoir pousser). Il est idempotent :
relancez-le après chaque enregistrement.
Jamais de clé de compte (Settings > SSH and GPG keys) : elle ouvrirait tous les dépôts du compte, en écriture, depuis un conteneur où tournent des sessions Claude. Une deploy key ne vaut que son dépôt et se révoque seule.
Les URL versionnées ne sont pas touchées : bundles/upstreams.yaml doit rester
clonable depuis n'importe quelle machine. L'aiguillage vers la bonne clé passe
par des url.<alias>.insteadOf dans la config git globale du conteneur,
posés uniquement pour les deploy keys déjà acceptées par GitHub — tant qu'une
clé n'est pas enregistrée, l'accès existant continue de fonctionner. La
migration se fait donc dépôt par dépôt, sans coupure.
Sans aucun matériel de clé dans le conteneur : faire tourner un ssh-agent
sur l'hôte avant d'attacher VS Code, qui en transmet la socket. Le montage
devient alors inutile et peut être retiré — mais le hub ne peut plus rien
pousser quand VS Code est détaché.
Ce montage est un écart assumé à la lettre du § 4.3 de la spec (« montage : le
répertoire du hub uniquement ») : motif, mesure de ce qu'il ouvre et manière de
l'annuler sont dans docs/ARCHITECTURE.md § 5.3. C'est
un volume, jamais un bind sur un répertoire de l'hôte — la distinction est
gardée par un test.
Enregistrement automatique de la clé (GitHub App, optionnel)
L'enregistrement d'une deploy key reste, par défaut, la procédure manuelle ci-dessus : coller la clé publique affichée dans Settings > Deploy keys. Pour l'automatiser — utile dès qu'on ajoute plusieurs bases — installer une GitHub App dédiée, une fois, hors du conteneur :
Créer la GitHub App (github.com → Settings > Developer settings > GitHub Apps > New GitHub App), avec la permission de dépôt Administration : Read & write, et aucune autre. C'est la permission GitHub App la plus étroite qui couvre la gestion des deploy keys par API — GitHub n'expose pas de permission plus fine dédiée aux seules deploy keys ;
Administrationpermet aussi des actions plus larges sur le dépôt concerné (renommer, gérer la protection de branches, etc.). Aucun webhook n'est nécessaire.Installer l'App sur le ou les dépôts concernés (le hub, et/ou les bases dont on gère aussi le dépôt) — ce choix borne exactement les dépôts couverts, comme pour une deploy key classique.
Sur votre machine, jamais dans le conteneur, fabriquer un jeton d'installation de courte durée (~1h, révocable en désinstallant l'App) à partir de la clé privée de l'App téléchargée à l'étape 1 :
APP_ID=<identifiant de la GitHub App> INSTALLATION_ID=<identifiant de l'installation — visible dans l'URL après l'installation> PEM=<chemin vers la clé privée .pem de l'App> now=$(date +%s) b64url() { openssl base64 -A | tr '+/' '-_' | tr -d '='; } jwt_header=$(printf '{"alg":"RS256","typ":"JWT"}' | b64url) jwt_payload=$(printf '{"iat":%d,"exp":%d,"iss":"%s"}' "$((now-60))" "$((now+300))" "$APP_ID" | b64url) jwt_sig=$(printf '%s.%s' "$jwt_header" "$jwt_payload" | openssl dgst -sha256 -sign "$PEM" | b64url) jwt="$jwt_header.$jwt_payload.$jwt_sig" curl -sS -X POST -H "Authorization: Bearer $jwt" \ -H "Accept: application/vnd.github+json" \ "https://api.github.com/app/installations/$INSTALLATION_ID/access_tokens" \ | python3 -c 'import json,sys; print(json.load(sys.stdin)["token"])'Dans le conteneur, exporter ce jeton pour la durée d'une seule invocation, puis relancer l'enregistrement :
export OKF_HUB_GH_APP_TOKEN=<jeton collé depuis l'étape 3> .devcontainer/deploy-keys.shLe jeton n'est jamais écrit sur disque ni journalisé — il ne vit que dans cette variable, le temps de l'appel API, et expire de lui-même. Sans lui (cas par défaut), le script se comporte exactement comme avant : rien n'est cassé si vous ignorez cette section.
Ce que ce choix n'est pas : jamais un jeton de compte GitHub, jamais un
scope repo global, et surtout — la clé privée de la GitHub App elle-même
n'entre jamais dans ce conteneur, où tournent des sessions Claude qui
exécutent du code ; seul un jeton d'installation déjà limité et expirant y
transite, une fois, à l'initiative de l'opérateur. Détail du raisonnement et
de ce que la permission Administration ouvre au-delà des deploy keys :
docs/ARCHITECTURE.md § 5.3 bis.
Sur une machine, sans conteneur
Prérequis : Python ≥ 3.11, git, ripgrep.
curl -LsSf https://astral.sh/uv/install.sh | sh # si uv n'est pas installé
uv sync
uv run pytest -qOutils MCP
Outil | Rôle |
| Bases disponibles, avec titre, objet, nombre de documents et de propositions en attente. |
| Recherche plein texte dans une base. Mode |
| Lecture d'un document, ou d'une seule section. Au-delà du seuil, retourne la table des headings — |
| Golden rules et schéma de frontmatter d'une base. Signale par un bandeau une gouvernance en |
| Dépose une proposition dans |
| État et résolution des propositions : intégrée (avec les documents modifiés) ou rejetée (avec le motif). Lecture pure. |
| Rapport de découverte : bundles rejetés avec motif, collisions de |
Le paramètre base est toujours le champ name du manifeste, jamais le nom du
répertoire dans bases/ — les deux diffèrent dès qu'un clone est renommé.
Le schema.yaml d'une base décrit le frontmatter de son corpus, pas celui des
propositions. Une proposition n'a pas à s'y conformer : soumettez
l'information, sa mise en forme conforme au schéma relève du gestionnaire à
l'intégration. Les champs de kb_propose sont le seul format requis.
Connecter un client Claude
Le transport est stdio : chaque client connecté lance sa propre instance du serveur.
Claude Code
claude mcp add okf-hub -- /chemin/vers/okf-hub/.venv/bin/python -m okf_hub \
--hub-root /chemin/vers/okf-hubOu dans .mcp.json à la racine d'un projet :
{
"mcpServers": {
"okf-hub": {
"command": "/chemin/vers/okf-hub/.venv/bin/python",
"args": ["-m", "okf_hub", "--hub-root", "/chemin/vers/okf-hub"],
"env": { "PYTHONPATH": "/chemin/vers/okf-hub/src" }
}
}
}Claude Desktop
Dans claude_desktop_config.json : mêmes command et args.
Depuis Windows, hub dans WSL
La commande doit traverser la frontière WSL. wsl.exe prend le relais :
{
"mcpServers": {
"okf-hub": {
"command": "wsl.exe",
"args": [
"-d", "Ubuntu", "--cd", "/home/<utilisateur>/okf-hub", "--",
"/home/<utilisateur>/okf-hub/.venv/bin/python", "-m", "okf_hub"
]
}
}
}Points de vigilance : utiliser des chemins Linux après --, et vérifier le
nom de la distribution avec wsl.exe -l -q.
Hub dans un devcontainer
Le client doit lancer le serveur à l'intérieur du conteneur :
{
"mcpServers": {
"okf-hub": {
"command": "docker",
"args": [
"exec", "-i", "<nom-ou-id-du-conteneur>",
"/workspaces/okf-hub/.venv/bin/python", "-m", "okf_hub"
]
}
}
}-i est indispensable : sans lui, stdin est fermé et la poignée de main MCP
échoue sans message.
Vérifier
.venv/bin/python -m okf_hub --hub-root . --verboseLe serveur attend sur stdin ; le journal part sur stderr. Ctrl-D pour sortir.
Si rien n'apparaît, hub.log porte la trace du démarrage.
Importer une base
git clone <url> bases/<nom>Puis kb_hub_rescan depuis une session connectée. Il n'y a pas d'autre
étape — c'est un invariant du produit.
Pour créer une base : partir du template
okf-bundle-template et dérouler son
INSTANTIATE.md.
Choisir dans un catalogue plutôt que taper une URL
bundles/upstreams.yaml peut porter, en plus de l'URL, un titre, une
description et des tags par base connue :
uv run okf-hub catalog list # ce qui est connu, déployé ou non
uv run okf-hub catalog list --tag rh # filtré par tag
uv run okf-hub catalog show <nom> # détail d'une entrée
uv run okf-hub catalog add <nom> <url> --title "…" --description "…" --tag rh
uv run okf-hub catalog import <nom> # git clone <url> bases/<nom> — rien d'autrecatalog import exécute exactement la commande ci-dessus : c'est le même
invariant, seulement l'URL exacte à ne plus connaître ou taper. catalog add/remove ne font qu'éditer bundles/upstreams.yaml ; une entrée sans
titre ni description ni tag reste une simple URL, comme avant ce catalogue
(compatibilité intégrale avec le format historique).
⚠ Avant d'importer un bundle tiers
Importer un bundle en v0 est sans risque d'exécution — tools/ et
skills/ ne sont pas chargés — mais pas sans risque d'influence. Trois
vecteurs d'injection de prompt existent :
titleetdescriptiondu manifeste, injectés dans les descriptions d'outils MCP, donc dans le contexte de toutes les sessions connectées, sans même que quiconque ouvre le bundle ;GOVERNANCE.md, injecté dans le contexte du gestionnaire ;CLAUDE.md, dans celui de toute session ouvrant le dépôt.
La validation du manifeste limite la surface (pas de retour à la ligne dans
title, description normalisée et plafonnée à 500 caractères) sans
l'éliminer.
Consigne v0 : n'importer que des bundles de confiance, et relire le
manifeste, GOVERNANCE.md et CLAUDE.md avant le premier usage de tout
bundle tiers.
Retirer une base
Avant ce cycle, retirer une base n'était qu'une suppression manuelle de
répertoire, documentée en prose (okf-hub-guide, cycle de vie § 5), jamais
outillée :
uv run okf-hub catalog retire <nom> # garde-fous, puis suppression
uv run okf-hub catalog retire <nom> --forget # + oublie l'entrée du catalogueDeux garde-fous, jamais bloquants avec --force : aucune proposition ne doit
dormir dans proposals/pending/ de la base, et — si elle a un remote — sa
branche amont suivie ne doit pas être en retard sur HEAD (vérification
locale uniquement, sans nouvel accès réseau ; un dépôt purement local n'est
jamais concerné). La suppression elle-même reste ce qu'elle a toujours été : le
répertoire du bundle sous bases/, jamais l'entrée du catalogue (séparée,
--forget pour l'oublier aussi) ni le dépôt distant. Rien n'est perdu tant que
le dépôt existe ailleurs — un bundle est un dépôt git autonome. Le retrait est
visible dès le prochain kb_list ou kb_hub_rescan.
Modèle multi-instances — à lire avant d'exploiter
Le transport stdio implique qu'une instance du serveur tourne par client connecté. Plusieurs processus opèrent donc simultanément sur les mêmes dépôts git. Conséquences pratiques :
Chaque instance découvre les bases pour elle-même
Il n'y a ni état partagé ni démon : la vérité est sur le disque, chaque instance la relit. Deux déclencheurs automatiques, chacun sous un cooldown de 5 s par instance, font qu'une base importée après le démarrage d'une session lui devient visible sans intervention :
tout
kb_listdéclenche la découverte avant de répondre ;une erreur
UNKNOWN_BASEdéclenche un re-scan silencieux, puis retente l'appel.
Les deux comptent leur cooldown séparément : lister puis appeler dans la foulée une base importée entre-temps fonctionne, le premier appel ne consomme pas le re-scan du second.
kb_hub_rescan reste utile pour voir le rapport d'un import — bundles rejetés
avec leur motif, collisions de name — pas pour rafraîchir.
Un rescan « partagé au niveau du hub » a été demandé et refusé : il supposerait précisément l'état partagé que ce modèle exclut.
Certains clients ignorent tools/list_changed
Le serveur émet la notification MCP tools/list_changed quand la liste des
bases change. Claude Desktop l'a historiquement ignorée. L'implémentation ne
compte pas dessus : ce sont les re-scans ci-dessus qui garantissent le
fonctionnement.
Conséquence visible, et purement cosmétique : la description de kb_list,
qui énumère les bases connues, peut rester périmée dans le contexte d'une
session. Le contenu que l'outil retourne, lui, est à jour.
Les écritures sont sérialisées, les lectures ne le sont pas
Toute écriture git prend un verrou flock() exclusif sur
bases/<nom>/.okf-hub.lock — libéré automatiquement à la mort du processus, et
partagé entre le serveur et le script okf-lock. Au-delà de 15 s d'attente, une
erreur BASE_BUSY invite à réessayer.
Les lectures (kb_search, kb_read) ne prennent aucun verrou. Une lecture
pendant une intégration peut donc voir un état intermédiaire du worktree.
Accepté en v0.
Le rôle gestionnaire
Le gestionnaire n'est pas un démon : c'est une session Claude invoquée à la
demande, outillée par la skill kb-review.
Installer la skill pour Claude Code :
mkdir -p ~/.claude/skills
ln -s "$PWD/skills/kb-review" ~/.claude/skills/kb-reviewPuis, dans une session : « passe en revue les propositions de la base <name> ».
Le moteur sous-jacent est utilisable seul :
bin/okf-review reconcile <base> # étape 0, rattrapage
bin/okf-review reconcile <base> --apply
bin/okf-review context <base> # golden rules + schéma + corpus
bin/okf-review inventory <base> --full # propositions en attente
bin/okf-review resolve <base> --plan plan.json --dry-run
bin/okf-review resolve <base> --plan plan.jsonresolve et reconcile --apply prennent eux-mêmes le verrou, à la granularité
imposée : une résolution complète = une acquisition. Ne pas les envelopper
dans okf-lock.
Pour toute autre séquence git sur une base, passer par le wrapper :
root=$(bin/okf-base-path ma-base root)
bin/okf-lock ma-base -- sh -c "git -C '$root' … && git -C '$root' commit -m '…'"Le verrou doit couvrir la séquence complète, jamais commande par commande.
Limitations v0 assumées
Le corps d'une proposition résolue n'est pas relisible via MCP
kb_proposal_status rend l'état, la résolution, integrated-into et le motif de
rejet — c'est la boucle complète du contributeur, sans accès git. Ce qu'il ne
rend pas, délibérément, c'est le corps de la proposition : il peut peser
16 Ko, et une fois intégrée, ce qui compte est le corpus, lisible par kb_read
en suivant integrated-into.
Pour relire le texte exact d'une proposition rejetée :
git -C bases/<nom> log --grep "Proposal: prop-2026-08-30-a3f2"
cat bases/<nom>/proposals/rejected/prop-2026-08-30-a3f2.mdLa recherche est mono-base
kb_search interroge une base à la fois. L'extension multi-bases est reportée en
v1 optionnelle : un seul retour d'usage l'a demandée, on attend la récurrence
avant d'élargir la surface d'outils.
submitted_by n'est pas authentifié
C'est un champ déclaratif. Il ne doit peser dans aucune décision d'intégration.
Aucune synchronisation avec un remote
Le clone présent dans bases/ est la copie canonique. Aucun push ni pull
automatique n'est effectué, même si le bundle a un remote. Toute
synchronisation est manuelle et hors garanties : un pull qui écrase des
propositions locales non poussées est de la responsabilité de l'opérateur.
Pratique recommandée : pousser après chaque session de revue.
git -C bases/<nom> pushBases par défaut
Deux bases documentent le hub lui-même. Ce sont des bundles ordinaires —
aucun traitement de faveur dans le code, et le hub tourne sans elles — mais elles
comblent une lacune structurelle : une session connectée en MCP ne voit ni ce
README, ni docs/API.md, ni CLAUDE.md. Elle ne dispose que des outils et de
leurs descriptions.
Le serveur les annonce dans son champ instructions, le seul texte qu'une
session reçoit sans dépenser d'appel — et seulement si elles sont déployées.
okf-hub-guide — mode d'emploi pour une session
Séquences d'appels, stratégie de recherche et de lecture, rôles et frontière de confiance à l'écriture, ce qu'est une proposition recevable, et le cycle de vie complet d'une base : créer, déployer, alimenter, réviser, retirer — avec à chaque étape le rôle qui l'exécute et le moyen employé.
Elle ne contient aucun schéma d'outil, par golden rule. La référence vit dans
les descriptions d'outils et dans docs/API.md ; une troisième copie serait la
seule qu'aucun test ne garde, et une base se met à jour par le circuit de
propositions quand une référence d'API doit bouger en verrou avec le code.
Cette exclusion n'est pas qu'une intention : tests/test_bases_meta.py lit les
SCHEMA du code et échoue si un corpus meta cite un outil inexistant, attribue à
un outil un paramètre absent de son schéma, ou introduit un tableau de référence.
okf-hub-feedback — retours sur l'outillage
Le hub est son propre premier cas d'usage : les retours sur les outils — pas sur le contenu métier des autres bases — arrivent par le circuit standard.
kb_governance base=okf-hub-feedback → ce qu'un retour recevable contient
kb_propose base=okf-hub-feedback … → le dépôt
kb_proposal_status base=okf-hub-feedback id=… → le verdict, plus tardDeux golden rules décident de la recevabilité : citer l'outil concerné et décrire le comportement observé (entrées, base, sortie obtenue, sortie attendue) avant toute demande d'évolution. Son corpus porte la roadmap des évolutions — décidées, reportées, refusées, avec le motif de chaque arbitrage — et les limitations connues.
Elles s'installent au premier lancement
Leur source est versionnée dans bundles/. Au démarrage, le
serveur installe dans bases/ celles qui manquent : un git clone du hub suffit
donc à disposer du guide, sans second dépôt à cloner.
bin/okf-bootstrap --list # ce qui est livré, et ce qui est déployé
bin/okf-bootstrap # installe ce qui manque, sans rien écraserPour maîtriser entièrement le contenu de bases/, mettre
bootstrap-bundles: false dans hub-config.yaml.
Elles se synchronisent avec leur remote au démarrage
Une base clonée depuis un dépôt canonique (bundles/upstreams.yaml, ou
importée manuellement avec son propre remote) est mise à jour en
fast-forward-only à chaque démarrage d'une instance de serveur, avant sa
première découverte. Jamais de push : le § 4.5 de la spec confie toute
synchronisation à l'opérateur, ce mécanisme ne fait qu'automatiser le pull
quand il est sûr.
Une divergence — des propositions locales commitées par kb_propose mais
jamais poussées, pendant que le dépôt canonique a lui aussi avancé — n'est
jamais écrasée : elle est signalée dans hub.log, et la synchronisation de
cette base attend une résolution manuelle. Un remote absent, injoignable, ou
une base occupée par une écriture en cours ne bloque jamais le démarrage.
Désactivable par sync-on-start: false dans hub-config.yaml, pour un
opérateur qui gère ses pulls lui-même.
Pourquoi deux emplacements. Une base doit être son propre dépôt git. Si
elle n'était qu'un sous-répertoire du dépôt du hub, gitops.commit_paths
exécuterait git -C dans le dépôt englobant, et un kb_propose de n'importe
quelle session commiterait sur la branche main du hub — sans erreur. Le
détail est dans bundles/README.md.
La source de vérité diffère ensuite selon la base.
okf-hub-guide est rédigée par les mainteneurs, en verrou avec le code :
bundles/ fait foi, elle est semée de là, et un test vérifie que la copie
déployée n'en diverge pas.
okf-hub-feedback est alimentée par les sessions : son dépôt publié est
l'original, et elle est donc clonée, pas semée.
https://github.com/Movida/okf-hub-feedback
Semer une base qui a un dépôt canonique produirait sur chaque machine une
histoire git sans rapport avec la sienne, et les propositions qu'on y déposerait
seraient irrécupérables. Les dépôts canoniques sont déclarés dans
bundles/upstreams.yaml ; si le clone échoue, la base
n'est pas installée et le journal dit comment rattraper — absente vaut mieux
qu'orpheline.
Configuration
Le hub lit hub-config.yaml à sa racine (§ 4.1 de la spec). Cinq paramètres
configurables : bases-dir (emplacement des bundles), read-toc-threshold
(seuil pour retourner la table des matières au lieu du contenu complet),
log-file (journal partagé par toutes les instances), bootstrap-bundles et
sync-on-start (mentionnés plus haut).
Profils de configuration
Plutôt que de configurer chaque paramètre individuellement, on peut choisir un
profil prédéfini via le champ profile de hub-config.yaml :
profile: devProfils disponibles :
solo(par défaut) : comportement actuel — bases dans./bases, seuil 8 Ko, journal activé, bootstrap et sync automatiques au démarrage.dev: développement local —bootstrap-bundles: false,sync-on-start: false; reste identique àsolo.ci: CI/tests — seuil 16 Ko,log-filedésactivé ; reste identique àsolo.
Chaque paramètre explicite dans hub-config.yaml surcharge la valeur du profil.
Un opérateur qui ne configure rien (fichier absent ou vide) bénéficie du profil
solo, garantissant le comportement actuel.
Exemple combinant profil et surcharge :
profile: dev
read-toc-threshold: 4096 # surcharge du profil devInvariants d'audit
Toute proposition apparaît dans exactement deux commits : un de soumission, un de résolution (éventuellement partagé avec d'autres propositions du même sujet).
git -C bases/<nom> log --grep "Proposal: <id>" # histoire d'une proposition
git -C bases/<nom> log --grep "Submitted-By: <qui>" # contributions d'un auteurCes invariants reposent sur le rejet des retours à la ligne dans concerns,
submitted_by et sources : sans cette validation, un contributeur pourrait
forger de faux trailers.
Architecture
src/okf_hub/
├── __main__.py point d'entrée stdio
├── server.py câblage MCP, re-scan (kb_list et UNKNOWN_BASE), notifications
├── config.py hub-config.yaml
├── registry.py découverte, corpus, exclusions, confinement des chemins
├── manifest.py validation de okf-bundle.yaml
├── locking.py flock() — fd neuf par acquisition
├── gitops.py index git temporaire initialisé depuis HEAD, identité explicite
├── search.py ripgrep, ET strict puis repli OU
├── bootstrap.py installation des bases livrées (bundles/ → bases/)
├── remote_sync.py synchronisation fast-forward-only avec le remote, au démarrage
├── governance.py statut draft/stable d'un GOVERNANCE.md
├── mdutil.py frontmatter, headings, sections
├── textutil.py plafonnement des sorties
├── review.py moteur du rôle gestionnaire
└── tools/ un module par outil kb_*Langage, SDK, bibliothèque YAML, accès git, forme du wrapper de verrouillage :
ces choix étaient laissés ouverts par la spec (§ 10.1). Le raisonnement derrière
chacun, la carte détaillée des modules et les parcours d'appel sont dans
docs/ARCHITECTURE.md.
Écarts assumés par rapport à la spec
Deux, tous deux mesurés, documentés et réversibles :
Déclassement de
index.mdetlog.mddanskb_search— sur un corpus réel de 856 documents, 28 % des résultats étaient des sommaires générés ; 2 % après déclassement.Synchronisation de l'index git partagé après commit — sans elle,
git statusaffiche toutes les propositions commitées comme supprimées, et l'étape de réconciliation les re-commite, cassant l'invariant d'audit.
Motif complet, mesure et manière de les annuler :
docs/ARCHITECTURE.md, section « Écarts assumés ».
Tests
uv run pytest -q # tout, dont la boucle de stress
uv run pytest -q -m "not slow" # sans le test deux instances × 25 itérationsCouvre notamment : validation de manifeste et collisions de name, confinement
des chemins et symlinks sortants, repli ET→OU, headings dupliqués et formatés,
plafonnement des sorties, non-destruction du tree, worktree sale, dépôt sans
HEAD, collision d'identifiant, tentatives d'injection de trailers, exclusion
mutuelle entre okf-lock et le serveur, et deux instances proposant en
parallèle.
tests/test_boucle_contribution.py déroule le critère d'acceptation de la
rév. 4.1 : dépôt d'une proposition par un vrai client MCP en stdio, résolution
par okf-review, puis relecture du verdict — intégration ou motif de rejet —
toujours en MCP seul. Il tourne sur une copie du bundle okf-hub-feedback
réellement déployé quand il est présent.
Hors périmètre v0
Extensions tools/skills ; review: agent|auto ; validation automatique de
schéma ; authentification des contributeurs ; politique d'incrément de version ;
index de recherche dérivé ; revue d'import outillée ; synchronisation remote ;
multi-hub. Reporté en v1 optionnelle : kb_search multi-bases.
Licence
Apache 2.0. Voir NOTICE.
La spécification transcrite dans docs/ est de David Morvan et suit la même
licence. Le format OKF auquel le hub se réfère est publié séparément par
Google Cloud Platform, également sous Apache 2.0.
Contribuer
CONTRIBUTING.md — et lire d'abord la section « Ce qui ne se
négocie pas ».
Vulnérabilité : SECURITY.md, advisory privée, jamais d'issue
publique.
Available Tools
6 toolskb_governanceA
Retourne les règles de gouvernance d'une base (GOVERNANCE.md) et son schéma de frontmatter (schema.yaml) s'il existe. À lire avant de soumettre une proposition via kb_propose, et indispensable au rôle gestionnaire. Bases disponibles : aucune.
| Name | Required | Description | Default |
|---|---|---|---|
| base | Yes | Nom de la base (champ `name` du manifeste). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the disclosure burden. It names the two returned artifacts, notes the conditional existence of schema.yaml, and states that no bases are currently available. It does not cover errors or output formatting, but for a simple retrieval tool the behavioral information is sufficient.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences with the core return behavior front-loaded. The final sentence about available bases is short but potentially relevant. Minor awkwardness, but no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple: one required parameter and no output schema. The description covers what is returned, when to use it, and current availability. Missing explicit error or response-shape details, but these are not critical for a one-parameter retrieval tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents the single 'base' parameter at 100% coverage, including that it is the manifest `name` field. The description adds no additional parameter-level detail, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb ('Retourne') and a specific resource: governance rules from GOVERNANCE.md and the frontmatter schema from schema.yaml. It also distinguishes the tool from siblings by tying it to the governance/proposal workflow rather than generic reading.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: read before submitting via kb_propose and essential for the manager role. It does not name alternatives or exclusions, but the context is specific enough for an agent to decide when to call it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
kb_hub_rescanA
Relance la découverte des bases dans bases-dir : à appeler après avoir importé un bundle (git clone <url> bases/<nom>). PORTÉE MONO-INSTANCE : ce rescan n'affecte que la session qui l'appelle. Les autres sessions Claude connectées à ce hub continueront d'ignorer une base nouvellement importée jusqu'à leur propre rescan ou redémarrage.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the key behavioral trait: the rescan only affects the calling session (mono-instance scope), which is non-obvious and crucial. However, it does not mention what happens to existing discovered bases, whether the operation is idempotent, or what the return value is. The most important nuance is covered, but some secondary behavioral details are missing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences plus a bolded scope note. The first sentence states the action and trigger, and the second adds the scope warning. There is no fluff, and the most important content (action + when) is front-loaded. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 0-parameter action with no output schema, the description is quite complete. It tells the agent exactly when to invoke it (after import) and discloses the critical mono-instance limitation. It omits minor details like behavior when there are no new imports or any return value, but for such a simple tool, the provided context is sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has 0 parameters, and the schema is empty. The description adds no parameter info because there is nothing to explain. According to the rubric, 0 params is baseline 4, and nothing is missing; the description correctly focuses on the action and scope rather than parameter details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Relance la découverte des bases dans bases-dir') and the specific trigger (after importing a bundle). It is unambiguous and distinct from siblings like kb_list, kb_search, and kb_read, which are query tools; this is a rescan operation. The verb and resource are precise.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to call this tool: 'à appeler après avoir importé un bundle' (to be called after importing a bundle), with a concrete git clone example. It also warns about the mono-instance scope, clarifying that other sessions won't see the new base unless they rescan or restart. This gives the agent a clear trigger and context, even without naming specific siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
kb_listB
Liste les bases de connaissance disponibles sur ce hub, avec leur objet, leur nombre de documents et le nombre de propositions en attente. Aucune base n'est actuellement enregistrée.
| Name | Required | Description | Default |
|---|---|---|---|
| include_pending_concerns | No | Ajoute, pour chaque base, la liste (id, type, concerns) des propositions en attente. Utile pour éviter de soumettre un doublon, et pour inventorier à moindre coût. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses what the tool returns but does not state that it is read-only, nor any limits, errors, or side effects. More critically, the sentence 'Aucune base n'est actuellement enregistrée' asserts a current state that is not a permanent behavioral trait and may become false, misleading the agent into expecting an empty list. This adds confusion rather than transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is brief and front-loaded with the core purpose. However, the second sentence is a dynamic state claim that is not a stable fact, adding noise and potentially misleading the agent. This detracts from conciseness because the information is not consistently true and distracts from the tool's function.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with one optional parameter and no output schema, the description explains the output fields sufficiently. The parameter is documented in the schema, so the agent can discover it. There is no mention of error handling, but for a read-only list operation, this is not critical. The description covers the essential outcome and structure adequately.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description coverage is 100% and includes a detailed description of the single parameter 'include_pending_concerns' explaining its purpose and utility. The tool description adds no parameter information, but the baseline of 3 applies because the schema already covers semantics effectively.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists knowledge bases on the hub, specifying the returned fields (object, document count, pending proposals). This distinguishes it from siblings like kb_search (search) and kb_read (read a specific base). The core purpose is unambiguous, though the second sentence introduces confusion about current data state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this is for getting an overview of all bases, but it does not explicitly mention when to use it versus alternatives like kb_search or kb_propose. There are no exclusions or alternative routing, leaving the agent to infer usage from the tool name and sibling context. This is implied usage, not explicit guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
kb_proposeA
Dépose une proposition d'ajout ou de correction dans une base. La proposition n'est PAS intégrée automatiquement : elle est déposée dans proposals/pending/ et attend la revue du gestionnaire, qui l'intègre ou la rejette selon les règles de la base (kb_governance). Limitation v0 : la résolution (intégration ou motif de rejet) n'est pas consultable via MCP — elle l'est par accès git direct au dépôt. kb_list avec include_pending_concerns permet de vérifier avant soumission qu'une proposition proche n'est pas déjà en attente. Aucune base n'est actuellement enregistrée.
| Name | Required | Description | Default |
|---|---|---|---|
| base | Yes | Nom de la base (champ `name` du manifeste). | |
| type | Yes | observation : fait constaté, sans présumer d'un document existant. correction : contredit un contenu actuel. addition : complète un sujet déjà couvert. question : lacune identifiée, sans réponse fournie. | |
| content | Yes | L'affirmation elle-même, en markdown. 16 Ko maximum. | |
| sources | Yes | D'où vient l'affirmation : URL, référence d'incident, constat terrain… Une entrée par ligne, sans retour à la ligne. | |
| concerns | Yes | Sujet concerné, en une ligne. Sans retour à la ligne. | |
| confidence | Yes | ||
| submitted_by | Yes | Identité déclarée du contributeur — non authentifiée. Convention recommandée : `human:<id>`, `<agent>/<version>` ou `process:<id>`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It clearly discloses that proposals are not auto-integrated, are stored in proposals/pending/, and require manager review. It also discloses a v0 limitation: resolution is not consultable via MCP and requires direct git access, plus the current absence of registered bases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the primary action and then adds only high-value workflow constraints. Every sentence contributes something actionable: no auto-integration, review dependency, MCP resolution limitation, pre-check alternative, and current unusability. No filler is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a proposal-submission tool with no annotations and no output schema, the description covers the lifecycle, limitations, and pre-check workflow thoroughly. The main gap is that it does not describe what response or confirmation the agent should expect after submission beyond the pending-file location. Still, the context provided is substantial enough for safe invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is already high at 86%, so the schema carries most of the parameter meaning. The description adds context about the base lifecycle and the pending state, but does not substantially enrich individual parameter semantics beyond the schema. This matches the baseline expected when structured parameter documentation is strong.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: "Dépose une proposition d'ajout ou de correction dans une base." It immediately distinguishes this from the sibling read/list/search tools by stating the proposal is not integrated automatically and is queued for review. The workflow context makes the tool's submission role unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete pre-submission guidance: use kb_list with include_pending_concerns to check for existing pending proposals. It also warns that "Aucune base n'est actuellement enregistrée," which effectively tells the agent the tool is not currently usable. It does not exhaustively state when alternatives should replace this tool, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
kb_readA
Lit un document du corpus d'une base : document complet, ou une seule section si section est fourni. Au-delà d'un certain volume, un document lu sans section retourne sa table des headings plutôt que son contenu — rappelez alors kb_read avec la section voulue, ou force: true pour tout obtenir. Bases disponibles : aucune.
| Name | Required | Description | Default |
|---|---|---|---|
| base | Yes | Nom de la base (champ `name` du manifeste). | |
| path | Yes | Chemin du document, relatif au corpus, séparateur `/`. | |
| force | No | Retourne le document entier même s'il est volumineux, au lieu de sa table des headings. | |
| section | No | Titre du heading à extraire. La correspondance ignore la casse et le formatage markdown inline. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral disclosure burden. It usefully exposes the non-obvious behavior that large documents return a headings table unless force is used, and it explains the retry path. It does not detail the response format or possible errors, but covers the most important behavioral quirk.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short, purposeful sentences. The main use case is front-loaded, followed by the volume caveat and the current environment note. There is no redundant or filler wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and no annotations, the description provides enough to invoke the tool correctly: full-document vs section behavior, the large-document headings fallback, force override, and the fact that no bases are currently available. It is slightly limited by not describing response structure or error cases, but those are not essential for basic usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so parameter semantics are already fully documented in the schema. The description mostly re-contextualizes the behavior of section and force rather than adding new parameter-level meaning, matching the baseline for high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Lit un document du corpus d'une base' and immediately explains both main modes: full document or a single section. This clearly distinguishes kb_read from sibling tools like kb_list and kb_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete usage guidance: for large documents without a section, a headings table is returned, and the agent should retry with the desired section or use force: true. It does not explicitly compare kb_read with sibling alternatives, but the intended context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
kb_searchA
Recherche plein texte dans le corpus d'une base. Retourne les chemins, titres et extraits pertinents — jamais les documents entiers. Utilisez ensuite kb_read pour lire un document ou une section. Aucune base n'est actuellement enregistrée.
| Name | Required | Description | Default |
|---|---|---|---|
| base | Yes | Nom de la base (champ `name` du manifeste). | |
| mode | No | keyword : ET strict sur les termes, repli automatique en OU si aucun document ne les contient tous. regex : dialecte ripgrep (syntaxe Rust regex). | keyword |
| query | Yes | Termes recherchés. En mode keyword, les termes sont séparés par des espaces et combinés en ET. | |
| max_results | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of behavioral disclosure. It explains that the tool is a read-oriented search, explicitly states it never returns full documents, and names the follow-up tool. The 'Aucune base' note adds important environmental context. It does not discuss failure modes or limits, but these are partially covered by schema constraints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences deliver purpose, return behavior, follow-up guidance, and a status caveat without redundant filler. The most actionable information is front-loaded, and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter search tool with no output schema and no annotations, the description provides enough context: what is searched, what is returned, what is not returned, and which sibling to use next. It could name kb_list as a way to discover registered bases, but the explicit 'no base registered' warning compensates by setting expectations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 75%, and the schema already documents base, query, and mode in detail. The description adds no additional parameter-level meaning beyond stating that the search targets a corpus, so it stays at baseline. The max_results parameter lacks a description, but its semantics are inferable from its name and constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Recherche plein texte dans le corpus d'une base') and defines the return payload: paths, titles, and relevant excerpts, never full documents. It also distinguishes itself from kb_read by explicitly routing full-document reads to that sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: use kb_search to find relevant excerpts, then use kb_read to read a document or section. It also provides an important current-state caveat ('Aucune base n'est actuellement enregistrée') so the agent knows the search may have nothing to operate on. It does not enumerate when not to use the tool, but the guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
6 tool updates
v0.1.0- First observed
kb_governance - First observed
kb_hub_rescan - First observed
kb_list - First observed
kb_propose - First observed
kb_read - First observed
kb_search
TDQS
Each tool targets a distinct hub operation: listing bases, searching a corpus, reading documents, retrieving governance rules, submitting proposals, and rescaming the hub. There is no meaningful overlap between the six tools.
All tools share the kb_ prefix and use snake_case, and five of six follow a clear verb-first pattern. kb_governance is the only noun-style name, but it still fits the overall naming scheme without causing confusion.
Six tools is a well-scoped size for a knowledge-base hub: discovery, reading, searching, governance, contribution, and maintenance each have a dedicated tool. No tool feels redundant or unnecessary.
The core workflows are covered: exploring bases, reading documents, checking governance rules, and submitting proposals are all supported. The main gap is that proposal resolution is not visible through the MCP tools, and base creation happens outside the hub via git, but these are documented limitations rather than fatal omissions.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Persistent, governed institutional memory for Claude Code — specs, decisions, learnings.
Cross-agent artifact workspace with provenance across Claude Code, Codex, Cursor, LangGraph.
Share one project context across ChatGPT, Claude, Telegram and any MCP client.
Shared, versioned context that humans and AI agents can publish, review, annotate, and continue.
Related MCP Servers
- AlicenseAqualityAmaintenanceProvides agent coordination for Claude Code through a shared blackboard, decision tracking with rationale, and local semantic search over git-trackable JSONL files. It enables users to assemble tailored context packages and manage a lightweight knowledge graph for complex development tasks.153767MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to read and write a local-first knowledge base of plain markdown files in git, with governance gates for safe, hash-anchored edits.1Apache 2.0
- AlicenseNot gradedqualityBmaintenanceConnects claude.ai to a private GitHub repo of markdown files as a personal second brain, providing guarded read and write tools for knowledge management.20MIT
- AlicenseNot gradedqualityCmaintenanceCross-project memory for Claude Code, enabling local semantic recall and secure, git-versioned markdown storage of reusable knowledge across repositories.MIT
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/Movida/okf-hub'
If you have feedback or need assistance with the MCP directory API, please join our Discord server