Skip to main content
Glama
lcalmejane

Kimono MCP Server

by lcalmejane

Kimono MCP Server

Standalone MCP server for an AI-KIDO knowledge base, usable by tatami-core, VS Code, Claude Code and other MCP clients. Commands, agents/personas, skills, workflows, concepts, techniques, use cases and hard points are discovered from AIKIDO_ROOT, not a static catalogue.

The standard AI-KIDO base is protected. A separate, explicitly writable project/fork can be edited and synchronized with its own Git remote.

Short usage guides / Guides pratiques

Related MCP server: andish-mcp

MCP capabilities

Tool

Operations

aikido

list, search, read, activate, execute, refresh

aikido_embed

Generate a local text embedding with usage=query (default) or document; returns the numeric vector and model metadata without changing ROOT/indexes

aikido_root

status, init: initialize the configured ROOT from the official or another Git repository

aikido_search

Literal/regex/semantic/vector search; pre-limit scope/path/type filters, source ranges, bounded excerpts, deduplicated headers and JSON byte budget

aikido_index

update, rebuild, compact, stats; non-blocking status for mode=semantic; otherwise mode: literal (default) or semantic

aikido_git

Scoped, structured Git operations on the configured project

aikido_file

Read-only JSON metadata, outline, read (lines/section/full); writable-project write/delete retain exact previous-content guards

Documents also appear as resources (aikido://<encoded-relative-path>) and prompts (aikido.<kind>.<encoded-relative-path>), with completions.

activate and its execute alias return instructions/context for the connected assistant. They do not claim an LLM workflow has run. The client executes those instructions with its own tools/approvals, including Kimono's file/Git tools when enabled. Kimono has no embedded LLM or unrestricted shell.

The initial Kimono scaffold lacked Git/file actions and indexed search; these are now separate MCP tools.

Requirements

  • Node.js 24+, Git, and fgr on PATH for native execution.

  • Rust/Cargo to install the published fast-grep crate.

  • Or Docker Engine with Compose v2: the Linux arm64/x64 image contains Node.js, Rust, Cargo, Git, OpenSSH, fgr, kimono-semantic, ONNX Runtime and the multilingual embedding model.

cargo install fast-grep --version 0.5.0 --locked
npm ci
npm run build

The crate is named fast-grep; its binary is fgr, not fgrep.

Initialize or select a ROOT

Select an existing AI-KIDO checkout, or explicitly install one:

# Standard base:
node dist/cli.js init --root /absolute/path/to/aikido --ref main
# Separate project/fork:
node dist/cli.js init --root /absolute/path/to/project \
  --repository https://github.com/your-org/your-aikido.git --ref main
# Serve an existing ROOT:
node dist/cli.js serve --root /absolute/path/to/project

The default source is https://github.com/lcalmejane/aikido.git. --repository overrides AIKIDO_REPOSITORY; --ref overrides AIKIDO_REF. HTTPS, SSH and absolute local repository paths are accepted.

Installation retains full history, uses argument arrays (no shell interpolation), validates prompts/index.md or index.md, and places the clone at its target only after success. Absent/empty targets are accepted; non-empty targets are never overwritten.

The server can also start with an absent/empty configured ROOT. Invoke:

{"operation":"init","repository":"https://github.com/your-org/your-aikido.git","ref":"main"}

on aikido_root to initialize that ROOT only, never an arbitrary path provided by the client. Discovery requires initialization first. MCP initialization needs a writable disk mount, but does not unlock subsequent writes to the standard base.

Literal/regex searches use fast-grep 0.5.0, installed from crates.io. The default remains literal, so existing clients do not change behavior.

At startup, Kimono builds/updates the index for the actual ROOT. Before every search it rescans the catalogue and incrementally updates the index, covering added/changed/deleted files, including external edits. MCP Git/file operations also update it.

Only discovered text documents enter a private search mirror. Symlinks, dependency/build/cache directories, .env*, nested .gitignore exclusions and files over 2 MiB are excluded. prompts/spec/ (or spec/ when ROOT is the prompts directory) requires AIKIDO_INCLUDE_SPEC=true. Excluded files never enter the fgr index.

The persistent cache lives outside AIKIDO_ROOT. This allows indexing a read-only standard base without changing it. Treat the cache as sensitive: it contains document copies. An image cannot ship a prebuilt index for a ROOT chosen later.

Updates/searches are serialized in-process. Use one server process per ROOT/cache; independent processes need distinct cache directories.

# Maintain the index without starting MCP:
AIKIDO_ROOT=/absolute/path/to/aikido node dist/cli.js index

Use aikido_search (or aikido with operation: "search") with:

{"mode":"semantic","query":"Comment proteger les identifiants secrets ?","limit":5}

For a raw embedding, call aikido_embed:

{"text":"Comment proteger les identifiants secrets ?","usage":"query"}

For model introspection without text or inference, call the same tool:

{"operation":"info"}

This returns the active local model, not a hard-coded catalogue: engine, version, model (the identifier to reuse as embeddingModel), name, dimensions, normalized, maxTokens, pooling, queryPrefix, documentPrefix, and sha256 for each of model.onnx, tokenizer.json and model.json, plus a compatibility disclaimer. The helper opens the model to validate it, but computes no embedding, reads no ROOT document and updates no index. Retain this response alongside stored vectors to identify and reproduce the exact files/preprocessing later; retain the model files or their pinned download sources too (hashes do not provide a download service). Only the currently configured model is served; this is not a multi-model registry or automatic historical-model installer. A missing/incompatible model produces an explicit error. Existing calls without operation still embed text.

The response contains engine, version, model, usage, dimensions, normalized, maxTokens, and vector (384 finite numbers with the bundled model). query uses E5's query prefix; document uses its passage prefix. Compare vectors generated by the same model and preprocessing settings. This tool works even before ROOT initialization and does not read knowledge documents or update either index. Its private temporary request file is removed after execution. Input must be non-blank and at most 32,768 UTF-8 bytes. The model tokenizer truncates to its token cap (512 for the bundled model); this operation returns one vector, not automatic chunking of a long document. Missing/incompatible models return an explicit MCP error.

Search using an existing vector

Pass the vector and exact model returned by aikido_embed to aikido_search as vector and embeddingModel, respectively:

// embedding = parsed result of aikido_embed({ text: "...", usage: "query" })
const argumentsForSearch = {
  mode: "semantic",
  vector: embedding.vector,
  embeddingModel: embedding.model,
  limit: 5
};

Supply exactly one of query or vector. Vector input requires explicit mode: "semantic" and embeddingModel; kind and limit work as for text search. The aikido tool also accepts these fields with operation: "search". The index synchronizes before vector searches too; Kimono does not re-embed the supplied query vector, but still embeds new/changed knowledge passages. The response has the same passage/score shape as text semantic search.

Model compatibility disclaimer: dimensions alone are not enough. Kimono rejects model identifiers differing from its active model, wrong dimensions, non-finite float32 values and zero vectors. The caller remains responsible for truthfully identifying vector provenance and using the same weights, tokenizer, pooling, normalization and prefix conventions. Labeling an incompatible vector with the expected model identifier does not make it compatible and cannot be detected reliably. Normally embed search questions with usage: "query". A document vector can also retrieve similar passages, but a single truncated document vector is not equivalent to the knowledge base's chunk embeddings. Model changes require regenerating client-held vectors.

embsearch-core 0.3.4 generates real embeddings with ONNX Runtime 1.31.0 and multilingual-e5-small int8 (384 dimensions, normalized mean pooling, E5 query/passage prefixes). French questions can retrieve English passages and vice versa. Documents and queries stay local: no external inference API. The image downloads the pinned public model/tokenizer (~135 MB combined) and runtime at build time, verifying SHA-256. Runtime inference works offline.

Results contain engine, version, model, chunks, embedded, count, and results with document metadata, path, line, excerpt, score (cosine similarity, higher is better, not a probability). Filtering by kind happens before the result limit. There is no relevance threshold: unrelated queries can still produce nearest neighbors. Results are chunks, so a document can appear more than once.

The semantic index initializes lazily, refreshes against the current catalogue before every MCP search/full-index call, and only re-embeds changed chunks. Targeted aikido_index update calls refresh only their explicit paths (see below). The persistent vector store lives alongside the literal index outside ROOT. The same exclusions apply, including private specs. Chunking bounds passages to 500 Unicode characters with starting line numbers. It is not a reranker or an LLM answer generator. The current flat cosine index targets knowledge bases, not large document warehouses; each request accepts at most 64 MiB of discovered text. Requests load the model locally and verify its fingerprint; initial indexing takes longer than cached searches. Reserve at least 1 GiB of container memory initially and measure on your corpus; this is not a hard memory bound. Semantic subprocesses time out explicitly after ten minutes. For a sizeable base, pre-index using the CLI before exposing the server, or configure a sufficiently long MCP client request timeout for the first indexing call. The index is lazy to avoid blocking server startup.

Measured on the standard AI-KIDO Git base in the local Linux arm64 Docker environment: 322 documents / 4,378 chunks, initial indexing ~6 min 12 s, then a cached semantic query ~1.74 s, with zero chunks re-embedded. These are observations, not performance guarantees; CPU/corpus size matters.

Maintain it with aikido_index:

{"operation":"rebuild","mode":"semantic"}

update, compact and stats also synchronize first (and can initialize an absent index). CLI equivalent:

AIKIDO_ROOT=/absolute/path/to/aikido node dist/cli.js index --mode semantic

For native semantic execution, build the locked helper and supply a compatible ONNX model directory and runtime:

ORT_SKIP_DOWNLOAD=1 cargo build --release --locked --manifest-path semantic/Cargo.toml
export KIMONO_SEMANTIC_BIN="$PWD/semantic/target/release/kimono-semantic"
export KIMONO_MODEL_DIR=/absolute/path/to/model
export ORT_DYLIB_PATH=/absolute/path/to/libonnxruntime.so

The model directory must contain model.onnx, tokenizer.json, and a model.json specification matching its dimensions, pooling and input names (input_ids, attention_mask, token_type_ids). Missing or incompatible models/runtimes return MCP errors, never a lexical or fake-vector fallback. Use Docker for the bundled, verified combination.

Versions are pinned for reproducibility in versions.json and Cargo.lock. ort 2.0.0-rc.10 is constrained by embsearch-core; it loads the newer runtime's backward-compatible C API, tested with real inference. Run node scripts/check-search-versions.mjs to compare the pins with the latest stable crates/runtime and model revision; the weekly GitHub workflow fails visibly when an update is available. Upgrades require new checksums/lockfile and passing the real semantic tests, not silent untested downloads at startup. Third-party provenance is in THIRD_PARTY_NOTICES.md.

Integration with per-workspace instance managers

Kimono remains one ROOT per process. A manager such as Tatami can run one instance per (user, project) workspace, using the same immutable image. Mount only that workspace, provide its own persistent cache and HTTP bearer token, and keep HTTP ports private to the backplane. Do not mount the entire workspace parent into each instance or expose a client-controlled ROOT. If every container sees /knowledge, use separate cache volumes: the cache key is based on the visible ROOT path, not the container identity. Set the container UID/GID and writable cache permissions to match the workspace; the default image user is UID 1000. Git credentials and authorization remain the manager's responsibility; never share a user's token across unrelated instances.

HTTP probes:

Endpoint

Authentication

Meaning

GET /healthz

None

Process liveness only; unchanged minimal response.

GET /readyz

Instance bearer token

200 if ROOT was initialized, still has a readable entry point and the instance is not draining; otherwise 503. Semantic indexing is not required.

GET /statusz

Instance bearer token

200 with ready, stopping, ROOT availability and semantic state, including failure details. Does not start indexing/inference.

Keep readiness distinct from liveness: an empty ROOT awaiting aikido_root init is alive but not ready. Readiness checks filesystem availability, not Git remote connectivity or a complete rescan of every document. Status/error details must remain behind instance authorization, not exposed as public diagnostics.

Poll semantic progress through MCP, including while an indexing call is pending:

{"operation":"status","mode":"semantic"}

on aikido_index. Unlike stats, status does not update or initialize an index and bypasses the tool queue so it remains responsive. Another HTTP MCP session may poll the same instance. Semantic state is unknown, running, ready or error, with operation/timestamps, last chunks/model and progress: {completed, total} when available. Progress counts changed chunks embedded, not elapsed time or a percentage of all scanning/model loading/ saving work. ready means the last index operation succeeded, not proof that no external files changed since. Subsequent searches always synchronize as before. State is in memory and returns to unknown on restart even if vectors persist; the next search/update validates and reuses the persistent store. Failures are explicit in both the original tool result and status.

On SIGTERM/SIGINT, the running server rejects new tool work, reports not ready, drains accepted calls, then closes MCP sessions and the HTTP listener. After 30 seconds, remaining managed subprocesses are killed, HTTP connections are forced closed and shutdown is reported as failed (non-zero CLI exit). Compose uses init: true and a 40-second stop grace period; an external manager must allow more than 30 seconds too. Do not start a second process on the same cache during draining. Index generations are published before their previous generation is removed, allowing a later instance to reuse the last published store after interrupted indexing.

This adds the server-side integration contract only: container provisioning, workspace membership checks, public-client credentials, idle eviction and quotas are not implemented by Kimono.

Targeted synchronization (v0.3.0)

{"operation":"update","mode":"all","paths":["prompts/concepts","src/changed.ts","src/deleted.ts"]}

Call aikido_index with paths as one ROOT-relative string or a list (1–256). Files and directory subtrees are accepted, including missing paths: previously indexed files under missing targets are deleted. Prefixes match directory boundaries, not similarly named neighbors. Overlapping paths are deduplicated. Absolute paths, traversal, backslashes, empty lists and paths on other operations fail explicitly. Gitignored/private/excluded paths and symlinks never expose source content.

mode is literal (default), semantic, or all. Each engine reports its own changes: {added:[], modified:[], deleted:[]} ROOT-relative paths under indexes.literal / indexes.semantic; single-engine legacy metadata remains available at the top level. A cold targeted cache stays partial: unrelated source bodies are not read, indexed or embedded to build a baseline. Semantic model changes require a full update before targeted reuse. Reports are relative to each engine's last successful synchronization, not Git status; all is sequential, not an atomic cross-engine transaction (failures remain explicit).

Search still refreshes the whole current catalogue automatically, so changes outside the targeted scope become searchable on the next search. Omitting paths keeps full synchronization; rebuild, compact, stats remain full-corpus. Both read-only and writable clients may update caches outside ROOT.

CLI: kimono index --root ./project --mode all --paths '["src/file.ts","prompts/concepts"]'.

MCP clients

Stdio is the default transport. Example VS Code configuration:

{
  "servers": {
    "kimono": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/kimono-mcp-server/dist/index.js"],
      "env": { "AIKIDO_ROOT": "/absolute/path/to/aikido" }
    }
  }
}

For Claude Code or another stdio client, use the same executable, arguments and environment in that client's MCP configuration. Diagnostic output goes to stderr, preserving the MCP stdout stream.

Docker Compose

cp .env.example .env
# Set AIKIDO_HOST_PARENT and AIKIDO_DIR.
# Set MCP_AUTH_TOKEN to a long random secret.
docker compose up --build -d

The image installs fast-grep using cargo install fast-grep --version 0.5.0 --locked and retains Rust/Cargo at runtime. It runs as UID 1000 (node). Host directories must be readable by that UID and writable for installation/project editing.

Defaults expect ./data/aikido. The knowledge mount is read-only by default; a named kimono-cache volume stores the index. Only 127.0.0.1 is published. HTTP MCP requests need Authorization: Bearer <MCP_AUTH_TOKEN>. /healthz is unauthenticated and reveals no knowledge data.

# Explicit installation using AIKIDO_REPOSITORY and AIKIDO_REF from .env:
docker compose --profile install run --build --rm install-aikido
docker compose up --build -d kimono-mcp-server

The server never performs an implicit Git fetch/pull at startup. For remote/public use, terminate TLS and enforce an authenticated, authorized reverse proxy; do not expose HTTP directly to the Internet.

Writable projects

For a separate trusted project/fork, set both:

AIKIDO_WRITABLE=true
AIKIDO_VOLUME_MODE=rw

This does not unlock the official base: the origin and its effective fetch/push URLs are checked before mutations. Adding or pushing/fetching an official remote is rejected. Use separate Kimono instances for the standard base and a writable project.

Supported structured Git operations:

status log diff show blame ls-files reflog remote
add restore rm commit fetch pull push switch checkout branch tag
merge rebase rebase-abort rebase-continue cherry-pick revert reset
stash stash-pop remote-add

Examples for aikido_git:

{"operation":"add","paths":["prompts/gen/concepts/architecture.md"]}
{"operation":"commit","message":"docs: update project architecture"}
{"operation":"push","remote":"origin","ref":"main","confirm":true}

As intentionally agreed, this is a structured Git API, not an unrestricted Git/shell runner. Branch/tag operations create refs; reset is mixed and pull is fast-forward only. Force-push/hard-reset, custom aliases and arbitrary Git flags/configuration are not exposed. push/reset need confirm=true only after explicit client/user approval. Relevant hooks, fsmonitor, external diff and textconv are disabled.

Configure Git identity and credentials on the runner, not in tool arguments or source files. Native Git supports GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL. With Compose, pass these explicitly through a local service override or mount an appropriate scoped Git config. For SSH, explicitly provide a scoped key/known_hosts or an agent socket; credentials are not bundled in the image.

Dynamic per-instance Git profile

For a platform-managed instance, set KIMONO_GIT_PROFILE_FILE to an absolute path outside ROOT, pointing to a private JSON file (0600 or 0400, <=64 KiB). The runner must be able to read it. This is server configuration, never an MCP tool argument; all clients of the instance share this Git identity.

SSH profile schema (placeholders, not working credentials):

{
  "transport": "ssh",
  "host": "github.com",
  "username": "git",
  "secret": "<unencrypted private SSH key with JSON-escaped newlines>",
  "knownHosts": "github.com ssh-ed25519 <verified-server-public-key>",
  "authorName": "Project contributor",
  "authorEmail": "contributor@example.org"
}

For HTTPS, use "transport": "https", the Git account username and access token as secret; omit knownHosts. The schema matches the core fields of Tatami Git connections. Tatami must authorize the selected connection, retrieve/decrypt its secret (including resolving a managed SSH key), and provision this file itself; Kimono does not connect to Tatami's account database.

The profile is reread for Git commands, including CLI/MCP installation, fetch/pull/push and local commits. Rotate it by atomically replacing the file inside a mounted secret directory; do not rely on replacing the source of a single-file bind mount (it may retain the old inode). Commands already running keep their credential snapshot; subsequent commands use the replacement. No restart or secrets in MCP messages are necessary.

Managed mode enforces the exact host/transport, standard ports (SSH 22 / HTTPS 443) and matching SSH username, including effective remote URLs after Git rewrites and push URLs. Local-path remotes and cross-host/transport redirects are not supported with a profile; use a separate instance/configuration. HTTPS uses a temporary askpass helper with credential helpers disabled and redirects disabled. SSH uses the selected key only, no agent, strict known_hosts verification and no user SSH config. Verified non-hashed host-key lines for the exact host are required; Kimono never trusts ssh-keyscan output automatically. Passphrase-protected keys are unsupported in managed mode. Author/committer identity is supplied per process, not written to .git/config.

Temporary key/helper files are owner-only and removed after the command. Use a private tmpfs /tmp for managed containers to avoid persisting leftovers after an abrupt kill. Never expose the profile directory to repository code, commit it, include it in a Docker build context or mount it into another user's instance. Git subprocesses necessarily receive the credentials needed for their transport; this remains a trusted-runner feature, not a repository sandbox. Managed Git failures are intentionally generic to avoid echoing credentials; HTTPS tokens are redacted from captured process output. Profile load failures fail closed, without falling back to ambient credentials.

Example local Compose override (adapt owner/permissions to the instance UID):

services:
  kimono-mcp-server:
    environment:
      KIMONO_GIT_PROFILE_FILE: /run/kimono-git/profile.json
    volumes:
      - /secure/project-git:/run/kimono-git:ro
    tmpfs:
      - /tmp:mode=1777
  install-aikido:
    environment:
      KIMONO_GIT_PROFILE_FILE: /run/kimono-git/profile.json
    volumes:
      - /secure/project-git:/run/kimono-git:ro
    tmpfs:
      - /tmp:mode=1777

Without KIMONO_GIT_PROFILE_FILE, the existing runner environment/SSH-agent behavior is unchanged. Managed credentials never bypass official-origin write protection, AIKIDO_WRITABLE, writable-mount requirements or push approval.

Writable mode is for trusted repositories and authorized clients: Git configuration/filters and remote servers can execute code. This API is not a sandbox. HTTP tokens authorize the whole configured instance, including enabled writes. Git history/diff tools expose repository contents independently of the search index exclusions; those exclusions are not Git access controls.

Validation and publication

npm run typecheck
npm test
npm run build
# Equivalent real Git/fgr tests without local Rust:
docker build --target test -t kimono-mcp-test .
docker run --rm kimono-mcp-test

CI builds the Docker test stage and runs type checking, all tests (including real ONNX inference) and the TypeScript build. Native npm test skips semantic tests unless KIMONO_MODEL_DIR is set; Docker/CI always sets it. Rust unit tests run while building the helper. The container publication workflow publishes GHCR images for v* tags to ghcr.io/lcalmejane/kimono-mcp-server.

Source repository: lcalmejane/kimono-mcp-server (currently private).

License

MIT. See LICENSE. Third-party dependencies retain their own licenses.

Configuration

Variable

Default

Description

AIKIDO_ROOT

required

Existing AI-KIDO root or absent/empty initialization target.

AIKIDO_REPOSITORY

official Git URL

Default source for CLI/MCP/Compose installation.

AIKIDO_REF

main

Branch/tag for explicit installation.

AIKIDO_WRITABLE

false

Opt-in project mutations; cannot unlock the official base.

AIKIDO_INCLUDE_SPEC

false

Explicitly expose private personal specs in discovery/indexing.

KIMONO_GIT_PROFILE_FILE

unset

Private server-managed SSH/HTTPS profile outside ROOT; reread for Git commands, supports rotation without restart.

KIMONO_CACHE_DIR

~/.cache/kimono

Cache parent outside ROOT; contains sensitive document copies.

FGR_BIN

fgr

Path to the fast-grep executable.

KIMONO_SEMANTIC_BIN

kimono-semantic

Local embsearch-core helper executable.

KIMONO_MODEL_DIR

/opt/kimono/model in Docker

Local ONNX model, tokenizer and spec; required for semantic mode.

ORT_DYLIB_PATH

/opt/kimono/onnxruntime/lib/libonnxruntime.so in Docker

Dynamic ONNX Runtime library; use the native library extension outside Linux.

MCP_TRANSPORT

stdio

stdio or authenticated Streamable http.

MCP_HOST

127.0.0.1

HTTP address; Compose uses 0.0.0.0 inside the container.

MCP_PORT

3000

HTTP port, 1-65535.

MCP_AUTH_TOKEN

required for HTTP

Bearer token protecting the complete MCP instance.

AIKIDO_HOST_PARENT

./data

Compose host parent directory.

AIKIDO_DIR

aikido

Checkout directory relative to the host parent.

AIKIDO_VOLUME_MODE

ro

Compose mount mode; rw for editing/MCP initialization.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables interaction with a local knowledge repository via MCP, providing tools for capturing, indexing, and searching Markdown notes with Git version control and optional semantic search.
    0
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables MCP-compatible clients to search and query a team knowledge graph, retrieve document context, upload files for indexing, explore entities and connections, and monitor workspace usage and server health.
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables to build and query a knowledge base with retrieval-augmented generation, supporting document ingestion, hybrid search, and live data integration from external APIs via MCP tools.
    2
    -