Query Markup Documents - On-device hybrid search for markdown files with BM25, vector search, and LLM reranking
Kybase is installed from its publisher's own source and answers where it runs, so this marketplace is not in the path of a single call. There is no address here to send one to, and a panel that pretended otherwise would be showing you an answer we made up. Install it and call it from your own client — the Installation tab has the entry for each one.
What it does
Self-hosted Markdown memory for AI agents: notes you can read and edit, with hybrid search.
Quickstart
# 1 — add it to Claude Code
claude mcp add --scope user kybase-mcp '--' npx -y kybase-mcp
# 2 — ask your agent for something these tools do
# list_notes, get_note, create_note and 15 more
Kybase costs nothing on mcprush: there is no plan to choose here, no cap to set and nothing mcprush can bill you for.
Where are you running it?
Every route below installs the same thing and ends at the same approval screen. This one runs on your machine: your client starts Kybase as a process under your own user, with your files and your network, so the tool surface below is what it can do to your computer rather than to a server somewhere else. Its scan result is on the Security tab — read the surface before you approve it.
This is a public server: you run it yourself and this marketplace is not in the path. You need Node.js — the current LTS (24) is the safe choice; npx comes with it. Claude Code registers it in one command; --scope user makes it available in every project. The '--' is in quotes so that PowerShell passes it on.
claude mcp add --scope user kybase-mcp '--' npx -y kybase-mcpReconnect, or start a new session, and the tools appear in the model’s tool list.
Nothing is required, but it can take KYBASE_DATA_DIR (Where the embedded database and instance secret live. Defaults to ~/.kybase), EMBEDDING_PROVIDER (Embedding provider for semantic search), OLLAMA_URL (Ollama endpoint for local embeddings. Without any provider, full-text search still works), OLLAMA_MODEL (Ollama embedding model), GOOGLE_API_KEY (Google API key, when EMBEDDING_PROVIDER=google. Sends note text to Google), OPENAI_API_KEY (OpenAI API key, when EMBEDDING_PROVIDER=openai. Sends note text to OpenAI), DATABASE_URL (Use an existing Kybase Postgres instead of the embedded one (migrations are left to the app)) if you want to set them.
One config entry your client uses to start the process locally. A local server runs with your file system and your network, which is why it is priced without metering.
18 tools, with what each one reads, writes and reaches shown before you agree — the same list on every route above. Read the tool surface.
Tool surface
What the model actually sees. Descriptions are diffed on every release — see version history.
List notes newest first, filtered by folder, tag or date. This is the tool for "what is new" and "what changed lately": search_notes ranks by relevance and never by recency. created_* is when a note was made, updated_* when its own text last changed — a rename elsewhere rewriting a [[link]]…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| folder_id | yes | — | |
| folder_path | string | no | Same filter by path (e.g. "Projects/Kybase") instead of UUID — that folder itself, not its subfolders |
| tag | string | no | Filter by tag |
| created_after | string | no | ISO timestamp — only notes created at or after this |
| created_before | string | no | ISO timestamp — only notes created at or before this |
| updated_after | string | no | ISO timestamp — only notes whose own content actually changed at or after this |
| updated_before | string | no | ISO timestamp — only notes whose own content actually changed at or before this |
| sort | string | no | Which date drives the ordering |
| limit | integer | no | Maximum notes to return per page. Applies in trashed mode too |
| offset | integer | no | Skip this many notes — pass back next_offset from the previous page |
| trashed | boolean | no | List soft-deleted notes instead of live ones |
Read one note, by id or title. - Long notes come back windowed — … chars by default: check content_truncated and pass next_offset back as offset for the rest. A windowed reply carries headings — the H1–H3 outline with character offsets — so name one in section to get that heading and…
No parameter schema on file.
Create a new note. Embedding is generated automatically in the background. The server instructions' wikilink and tag rules apply: search_notes for the topic first and link the related notes it finds, and call list_tags before coining a new tag.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| title | string | yes | Unique across live notes, case-insensitively; a clash is refused rather than merged. This is the string other notes link to as [[Title]] |
| content | string | no | Markdown body. Empty by default, so a note can be created first and filled with append_to_note |
| folder_id | yes | — | |
| folder_path | string | no | Folder path (e.g. "Projects/Kybase") as alternative to folder_id |
| tags | array | no | Tags for the new note: lowercase, kebab-case, in the language already in use. Call list_tags first and reuse an existing tag where one fits |
Update note fields. Re-embeds if title or content changed. Updates wikilinks if title changed. The server instructions' wikilink and tag rules apply when substantially rewriting — in particular, call list_tags before coining a new tag. Pass expected_updated_at (the updated_at you read) to be…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | yes | — | |
| title | string | no | New title. Renaming rewrites every [[link]] pointing here in other notes |
| content | string | no | Replaces the whole body. To add to a note use append_to_note, to change part of one use replace_in_note — both leave the rest untouched |
| folder_id | yes | — | |
| tags | array | no | Replaces the entire tag list — anything left out is removed. To add one tag, send the existing tags plus the new one |
| expected_updated_at | string | no | ISO updated_at from when you read the note; refuses the write if it changed since |
Add text to a note without resending the rest — prefer it over update_note for journals, logs and running lists. A blank line separates your text from what was there. The note is locked for the read-modify-write, so two sessions appending at the same moment keep both additions instead of the later…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | yes | — | |
| title | string | no | Alternative to id; resolved like get_note |
| content | string | yes | Text to add. Trailing whitespace is trimmed and a blank line is inserted before it, so the addition never runs into the preceding paragraph |
| section | string | no | Target this section (heading text or slug) instead of the whole note. Valid values come from a search hit's section, get_note's headings, or a heading line in the note's own text — the slug form i |
| at | string | no | Where the text lands. Defaults to section_end when section is given, else note_end. note_end: the very end. note_start: above the first heading nested under the opening one — NOT offset 0, except on a |
Replace exact text in a note without resending the rest. Either find/replace or old_string/new_string — the same pair, either spelling. For several replacements pass edits rather than the singular fields (one lock and one re-embed for the batch, not one per call); the two forms cannot be…
No parameter schema on file.
Soft-delete a note by id — it disappears from list_notes/search/get_note/the graph, but is recoverable with restore_note for … days before being purged for good. Use list_notes with trashed:true to see what's currently in the trash.
No parameter schema on file.
Undo delete_note: brings a soft-deleted note back. Errors if the note isn't in the trash (never deleted, already restored, or purged past the retention window), or if a live note has since taken the same title (rename one of them first, then retry).
No parameter schema on file.
No parameter schema on file.
No parameter schema on file.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| limit | integer | no | Max tags to return, most-used first |
List folders with the full path already resolved — no need to walk parent_id yourself. Pass a folder's own id as parent_id to create_folder/update_folder to nest under it. Sorted by path, so a page is a contiguous slice of the tree read top to bottom; the reply is `{folders, has_more,…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| limit | integer | no | Folders per page |
| offset | integer | no | Skip this many folders — pass back next_offset from the previous page |
Create a new folder. Optionally nested under a parent.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| name | string | yes | Folder name. Unique among its siblings — the same name under a different parent is fine |
| parent_id | yes | — |
Rename a folder and/or move it under a different parent (set parent_id to null for top level). Provide at least one of name/parent_id. The response includes the resolved path so a rename or move can be confirmed without a follow-up list_folders call.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | yes | — | |
| name | string | no | New name. Must stay unique among this folder's siblings |
| parent_id | yes | — |
Delete a folder and its full subtree of child folders (cascade). Every note inside — including notes in nested subfolders — is soft-deleted into the trash along with it (see delete_note), recoverable via restore_note within the retention window. To preserve organization instead, move…
No parameter schema on file.
Notes that link to this one via [[Title]] wikilinks, by id or title. Each comes back as id/title/folder_path plus a snippet around the link; include_content:true returns their full text instead, which is expensive when many notes link here — prefer get_note on the ids you actually want. offset and…
No parameter schema on file.
What is around ONE note in the [[wikilink]] graph, out to depth hops: a flat list of titles, no node indices to decode and no whole-vault payload. For the shape of that neighbourhood — which of them link to each other — use get_graph with root_title instead. Traversal is undirected: a note…
No parameter schema on file.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| folder_id | yes | — | |
| root_title | string | no | Keep only nodes within depth wikilink-hops of this note — resolved like get_note: exact, then unique prefix, then unique substring, case-insensitive |
| depth | integer | no | Hop count for root_title; ignored without it |
| include_semantic | boolean | no | Include semantic_edges at all |
| min_score | number | no | Cosine floor for semantic_edges — lower to see more (noisier) edges |
| unresolved_only | boolean | no | If true, return only { unresolved_links } without nodes and edges (fast check for broken links) |
| max_nodes | integer | no | Ceiling on nodes returned, most recently edited first. The reply says truncated: true when it applies — scope with folder_id or root_title instead of raising this |
- Every tool, no call limit
- No card, and mcprush charges nothing for it
- Source published under AGPL-3.0
- Runs on your machine — nothing of it reaches our gateway
- Nothing to cap, because mcprush bills nothing
What counts against your monthly calls
| Tool | Unit | Calls used | Out of the allowance |
|---|
Nothing here is billable: mcprush charges nothing to install Kybase or to call it, at any volume.
Two independent axes, because powerful and malicious are different questions. The grade is threat only. The capability level is blast radius, and it is never a penalty on the grade — it is priced as one subtract-only term in the score, where you can see it.
| Term | Level | What it prices | Points |
|---|---|---|---|
| capability-exposure | moderate | capability blast radius (moderate) — client exposure if the model is manipulated | −3 |
| verification-discount | repo | publisher verification (public source) — no provenance, but the source is public and inspectable | −1 |
| coverage-honesty | source | inspection depth (source) — how much of the target the scan could see | −0 |
What the scan could actually read
A grade is only as meaningful as its coverage, so the scanner publishes its own depth before it publishes its result.
Tools were statically extracted from the published source (18 recovered), not enumerated from a running server. Tool-poisoning, Unicode-smuggling, capability and toxic-flow analysis ran on this inferred surface, but a mis-parsed registration could be missed or mis-attributed, so tool-derived findings are capped below “confirmed”. To grade the real runtime surface, scan the running server: --command "npx -y <package>".
Capability — what it could do if the model were manipulated
Tags derived from each tool’s schema and the implementation, not from what the tool calls itself. moderate is the level these add up to.
| Tool | Capability tags | Why the tag was assigned |
|---|---|---|
| list_notes | no tags | |
| get_note | no tags | |
| create_note | state-write | state-write: handler runs a DELETE statement at dist/cli.js:1629, handler runs a INSERT statement at dist/cli.js:1631, handler runs a UPDATE statement at dist/cli.js:1637 |
| update_note | state-write | state-write: handler runs a UPDATE statement at dist/cli.js:1754, handler runs a DELETE statement at dist/cli.js:1629, handler runs a INSERT statement at dist/cli.js:1631 |
| append_to_note | state-write | state-write: handler runs a UPDATE statement at dist/cli.js:1927, handler runs a DELETE statement at dist/cli.js:1629, handler runs a INSERT statement at dist/cli.js:1631 |
| replace_in_note | state-write | state-write: handler runs a UPDATE statement at dist/cli.js:2035, handler runs a DELETE statement at dist/cli.js:1629, handler runs a INSERT statement at dist/cli.js:1631 |
| delete_note | no tags | |
| restore_note | no tags | |
| search_notes | external-sink | external-sink: handler sends an HTTP POST (fetch(${cfg.url}/rerank) at dist/cli.js:2903 |
| indexing_status | no tags | |
| list_tags | no tags | |
| list_folders | no tags | |
| create_folder | no tags | |
| update_folder | state-write | state-write: handler runs a UPDATE statement at dist/cli.js:3695 |
| delete_folder | state-write | state-write: handler runs a DELETE statement at dist/cli.js:3713 |
| get_backlinks | no tags | |
| get_neighbors | no tags | |
| get_graph | no tags |
Toxic-flow graph
The lethal trifecta, checked as a graph rather than as a checklist: untrusted input, a sensitive source and an external sink have to meet before there is a path worth worrying about.
The public result for this release does not print the flow graph, so there is nothing to show here. That is not the same as "no paths were found": what the scan did read is above, under coverage.
Supply chain and provenance
This is the first scan of this surface here, so there is nothing yet to compare it against.
Every result on this tab comes from one deterministic pass over the published package — offline, rule by rule, and auditable line by line above. Same methodology version, same bytes, same score.
Release history
Always latest — the install command names no version, so it installs the newest release when it runs; the current release on file is 0.2.2. Pin a release below and the command asks for exactly that one.
No release note was published with this version.
- The version this listing was on when mcprush began following its releases. The registry was not asked when it shipped, so this row carries no date.
One review per account, from a signed-in account that does not publish this listing. Nothing else is asked — you can say what you think before you install it. Publishers can reply once per review, and a review can be edited or deleted by whoever wrote it.
Any signed-in account that does not publish Kybase can review it, once — before installing it or after. A review from an account that has installed it is marked as one.
Nobody has reviewed this listing. The rating on the card is the mean of the reviews written here and nothing else, so there is no rating until somebody writes the first — which takes a signed-in account that does not publish it, and nothing else.