Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": true
}

Tools

Functions exposed to the LLM to take actions

NameDescription
list_notesA

List notes, sorted by recency (newest first). Optional filters: folder_id, tag, created_after/created_before, updated_after/updated_before, limit (max 200). created_after answers "what is new" — a note's creation date never changes after it is made. updated_after answers "what changed since I was last here" — it moves only when this note's own title/content/folder/tags were actually edited, NOT when renaming some other note rewrote a [[link]] to it in passing (that still touches updated_at, returned separately, but not this filter/sort). They are NOT interchangeable: a note edited today but created months ago matches updated_after, not created_after. sort picks which of the two dates drives the ordering (default "updated"). Each note carries content_length (characters in the full note) so you can tell a long note from a short one before spending a get_note call on it. Pass trashed:true to see soft-deleted notes instead (recoverable with restore_note until they age out of the trash) — other filters are ignored in that mode.

get_noteA

Get full note content by id or title. Title matching is case-insensitive and forgiving: an exact match wins, otherwise it falls back to prefix then substring, so a unique partial title resolves. An ambiguous title returns the candidate list (id + title) to retry with. Large notes are windowed: content is capped at 20000 chars by default (see limit/offset) — check content_truncated and content_total_length in the response, and pass next_offset back as offset to fetch the rest. Every response carries headings — the H1–H3 outline with character offsets, so a truncated note still shows what is in the part you did not get. Jump there with that offset, or name it in section to get that heading and its body alone — with section, headings narrows to that section's own subheadings too (offsets re-based to the section's own start, matching offset/limit's meaning in that mode), not the whole note's. Pass resolve_links: true to also resolve [[wikilinks]] inside it one level deep — use when you need a note's linked context without extra round-trips. Each linked note comes back as id/title/folder_path only by default; pass include_content:true for the full text of each (expensive if the note links to many others), capped at 4000 chars — call get_note on a specific id for its full text. updated_at moves on any stored change, including another note's rename rewriting a [[link]] to this one — pass it back as expected_updated_at on a write. content_updated_at only moves when THIS note's own title/content/folder/tags were actually edited — that's the one that answers "did anyone really touch this". Unresolved links (targets not found) are listed separately.

create_noteA

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.

update_noteA

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 refused instead of overwriting a change made in between.

append_to_noteA

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. Re-embeds in the background like any content change.

replace_in_noteA

Replace exact text in a note without resending the rest. Refuses unless find occurs exactly expected_count times (default 1) — protects against a loose find rewriting more than intended. Accepts either find/replace or old_string/new_string (same pair, either naming works).

For several replacements in one note, pass edits (array of {find/old_string, replace/new_string, expected_count}) instead of the singular fields — one row lock and one re-embed for the whole batch instead of one per call. Edits apply in order, and each one's find is matched against the note as already changed by the edits before it, not the original content — an earlier edit can create the text a later one needs, or remove the text a later one expects to find; sequence them accordingly. If any step's count does not match, the whole batch is refused and the note is left completely untouched — the error names which edit index failed and how many times its find text actually occurred. Do not combine edits with the singular find/replace/old_string/new_string/expected_count fields — use one form or the other.

delete_noteA

Soft-delete a note by id — it disappears from list_notes/search/get_note/the graph, but is recoverable with restore_note for 30 days before being purged for good. Use list_notes with trashed:true to see what's currently in the trash.

restore_noteA

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).

search_notesA

Search notes. type: "text" (fast), "semantic" (meaning-based), "hybrid" (best, uses RRF). Hybrid is the right default; prefer type=text for exact identifiers, code fragments, or quoted phrases, where FTS beats meaning-matching. Returns short excerpts, not full notes — call get_note on the top 1-2 hits to read them. A query is required, because this ranks text against text: to list or filter notes by folder, tag or recency with no keywords, use list_notes instead. has_more says whether hits exist past the page you got, so a short result is never mistaken for a small vault; read the next page with the next_offset it comes with. It is deliberately a flag and not a total — the only number available here is a capped candidate pool, and for meaning-based matching "how many match" has no answer at all.

A hit in a long note may carry excerpt_offset — where that excerpt sits in the text. Pass it to get_note as offset with a small limit to read around the answer in one call. That is how you read a book or a log: prose with no markdown headings has no outline and no section, so the position is the only way in short of paging from the top.

Read the SECTION, not the note. When a hit carries section, that is the markdown heading its excerpt came from — pass that exact string to get_note's section and you get that part alone (measured on a real 13000-character note: 681 characters). When a hit has no section and its content_length is large, get_note with a small limit still returns the note's FULL headings outline for about a kilobyte — choose a heading from it, then re-read with section. Two small calls beat one 13-60 KB one; pull a whole note only when you genuinely need the whole note. Each hit carries relevance (0..1, how close to the best hit in THIS response) and matched_by (which arms found it). Both describe the response, not the world: relevance orders hits, it does not judge them, and there is deliberately no confidence score. Judge a hit by reading its excerpt.

This is candidate retrieval, not a factual answer, and the search does NOT decide for you whether the vault knows something. Semantic search returns the nearest passages it has; by default nothing is filtered out for being too dissimilar, so an EMPTY result means the index returned nothing at all — and a NON-empty one is not evidence that what you asked about is in there. (An owner may configure a minimum similarity; threshold in the response says whether one is in force, and is null when none is.)

So a hit found ONLY by the semantic arm (matched_by is semantic_score alone) says the passage is ABOUT something similar — never that it confirms what you asked. The two are routinely different: a query about a technology a vault has never used still returns its nearest neighbours with nothing about that technology in them. When a hit is semantic-only and its excerpt does not actually contain what you asked about, the honest reading is "no confirmation found" — say that, or open the note to check. Do not report it as evidence the thing exists. The excerpt is the evidence; the score never is.

text_tier, coverage and exact are observed facts about the text match, shipped when they say something you would not assume. A tier of "or"/"substring" means the strict query found nothing and a looser pass filled in — recall, not confirmation. coverage measures LEXICAL overlap: the share of your query's significant words that occur in the hit, weighted by how rare each is here. A low or zero value does NOT mean irrelevant — a paraphrase or a cross-language match legitimately shares no words with the question, and that is what the semantic arm is for. Read it as "how much of what you typed is literally in there", nothing more. exact: true is the one thing FTS cannot express, and it means exactly this and nothing more: the query occurs as a contiguous, case-insensitive substring of that note (wildcards escaped — A_B does not match AxB). It is set only for a whitespace-free query that still splits into several words — a filename, an identifier, a code symbol, the case where the tokenizer takes one name apart and cannot put it back. Never for a phrase or a question: a note QUOTING your question is not a note answering it. Such hits take the top half of the relevance scale, ranked among themselves by their own text score. Neither tier nor coverage is comparable across different queries, only within one response. Filters: folder_id (or folder_path, the same folder written as a path — no need to look the UUID up first), tag, created_after/before (when a note was made), updated_after/before (when its own content/title/folder/tags last actually changed — a rename elsewhere rewriting a [[link]] to this note does not count) — these are NOT interchangeable. Dates filter, they do not rank: a note edited an hour ago and one untouched for months compete on relevance alone, and nothing here prefers the fresher one. So for "what is the LATEST state of X" this is the wrong first call — list_notes already sorts by recency, newest first, and takes updated_after. Search finds a topic; list_notes finds what changed. A question about the current state of something usually needs both. Every semantic/hybrid response includes threshold/best_score/pending_embeddings so you can tell "nothing was found" from "a configured filter removed it" from "embeddings not generated yet", even when results came back non-empty. Freshness: a hit carrying index_pending:true has an excerpt built from a PREVIOUS version of that note — the note row itself always holds the current text, only its search vectors lag. Call get_note on it (with section, if one is reported) and quote that, not the excerpt, before telling the user what the note says. Response-level pending_embeddings counts how many notes are in that state vault-wide, and stale_generation_chunks counts vectors left over from a previous embedding model, which are excluded from semantic results until reindexed — a non-zero value there explains a thin semantic arm rather than an empty vault. question_echo:true means the note LISTS your question without answering it (an FAQ or agenda of questions); treat it as a pointer to the topic, never as the answer. When reranked:true, prefer type="text" for a term you already know is written in your notes verbatim — an identifier, a filename, a code symbol, a product name. Reranking judges a passage by meaning, and a model that has never seen your vault can rank a passage that reads as more on-topic above the note that literally contains your term — a hit carrying most of your query's words can end up below one carrying far fewer. Only exact:true hits are protected from this. So hybrid remains the right default when you do not know the wording, and text is the better tool when you do — check coverage on a hybrid response to see whether the top hit actually contains what you typed. When the response carries reranked:true, a cross-encoder chose this order instead of rank fusion, and each hit's rerank_score is its best passage's score. That score is a model's opinion about ONE passage of the note, ordering this response only — it is not a confidence value, not comparable between queries, and not evidence the note answers you. reranked:false alongside it means the reranker was asked and did not answer, so you are reading the ordinary fused order. Read the text either way. That model is by far the slowest part of a search, and reranking is off unless an owner turned it on — it is optional and unproven, not an upgrade you are missing. Where it is on, pass rerank:false whenever you want an answer rather than a better ORDER: checking whether a term appears at all, or finding the note holding a value whose shape you already know. Pass explain:true to also see each hit's raw text_score/semantic_score/rrf_score and created_at — only useful for debugging the ranking itself, omitted by default to keep responses short.

indexing_statusA

Semantic-index progress: total/indexed/pending notes, complete=true when pending=0. Pending notes are still found by text search; notes with previous embeddings remain in semantic search with their last vector, while notes never embedded are excluded from semantic/hybrid until processed (automatic, background). Stuck pending count while nothing is being edited = check Ollama/server logs. Also names the active embedding model and says whether any automatic semantic cutoff is in force. By default there is none: semantic_profile reads "none" and semantic_min_similarity is null, meaning semantic search returns its nearest matches and refuses nothing on its own. Automatic abstention is deliberately not part of the default retrieval contract — a shipped per-model cutoff was measured and withdrawn, because it cost real answers (cross-language matches share no words, so nothing else finds them) without reliably stopping confident near-misses. An owner who has measured their own corpus can set one; then semantic_profile reads "configured" and the number is theirs. Raw cosines are NOT comparable between models: a number that means a good match on one means noise on another, which is why the model is named here rather than left to be inferred from the score.

list_tagsA

List tags in use with the number of notes carrying each, most-used first, capped at limit (default 40). Call this before tagging a note and reuse an existing tag when one fits, rather than coining a near-duplicate (a translation, transliteration, or plural of an existing tag) — the vault has no tag synonyms, so near-duplicates fragment the same concept into separate tags. The default cuts off the one-off tail: a tag used once is not one worth reusing, so it is not shown unless you raise limit.

list_foldersA

List all folders (flat array) 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.

create_folderB

Create a new folder. Optionally nested under a parent.

update_folderA

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.

delete_folderA

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 notes/subfolders out first.

get_backlinksA

Get notes that link to the given note via [[Title]] wikilinks. By default returns id/title/folder_path plus a short snippet around the link occurrence, not full content — pass include_content:true for the full text of each (expensive if many notes link here; prefer the default and call get_note on specific ids instead). Paginated like get_note. Takes id or title, like get_note — title resolves the same forgiving way (exact, then prefix, then substring).

get_neighborsA

What is around ONE note in the [[wikilink]] graph, out to depth hops. Answers "what is this connected to" with a flat list of titles — no node indices to decode, no whole-vault payload. For the shape of that neighbourhood — which notes link to each other, not just which are near — use get_graph with root_title and depth instead; it scopes the same way and keeps the edges.

Traversal is undirected: a note linking HERE is a neighbour just as much as one linked FROM here, because "what is this connected to" means both. links_out and links_in describe the direct relation to the note you asked about, and are sent only when true — so a depth-2 row carries neither. That is not a missing value: "which way does the arrow point" has no answer two hops away. Each note appears once, at the shortest depth that reaches it, and depth: 1 means directly linked.

These are LINKS people wrote, not similarity — a note about the same subject that nobody linked is not here. get_graph's semantic_edges cover that, and search covers finding it at all. An empty result means nothing links to or from this note, which is a fact about the writing, not about the topic.

get_graphA

Get the knowledge graph: note nodes, directed edges from [[wikilinks]], and undirected semantic_edges (embedding cosine similarity) between related notes that may lack explicit links. Nodes are {id, t} (t = title); edges and semantic_edges reference nodes by their position in the nodes array (not id) — ["edges"][0] = [2, 5] means nodes[2] links to nodes[5], and a semantic_edges triple's third number is the cosine score. unresolved_links lists [[wikilink]] targets in this scope that match no note title — dangling links, not edges (no node index, since there is no node to point at); rename the target or fix the link text to resolve one. Unfiltered, this returns the ENTIRE vault in one response — fine for small vaults, but it will stop fitting in context as the vault grows. Scope it with folder_id (a subtree) or root_title+depth (the neighborhood around one note) when you only need part of the graph. Node titles in the result are valid [[wikilink]] targets — but only within whatever scope you asked for.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A4.1/5.0

Scored across 18 tools

Disambiguation4/5

Most tools are clearly distinct (get_note vs list_notes vs search_notes; create/update/delete/restore_note; folder operations). The only mild overlap is get_neighbors vs get_graph, but their descriptions explicitly differentiate scope and output shape, so an agent can choose correctly.

Naming Consistency5/5

All tools follow a consistent verb_noun pattern: get_note, list_notes, create_note, update_note, delete_note, restore_note, search_notes, list_folders, create_folder, update_folder, delete_folder, get_graph, get_backlinks, get_neighbors, append_to_note, replace_in_note, indexing_status, list_tags. No mixed conventions or vague verbs.

Tool Count4/5

18 tools is on the higher end but appropriate for a knowledge-management server covering notes, folders, search, graph, and indexing. Each tool earns its place; the count is justified by the domain breadth.

Completeness5/5

The surface covers the full note lifecycle (create, read, update, append, replace, delete, restore), folder management, search (text/semantic/hybrid), graph traversal, backlinks, tags, and indexing status. No obvious dead ends: every write has a corresponding read, and soft-delete has restore.

Maintenance

ActivityActive
ResponsivenessNo issues