Skip to main content
Glama
gronare

notes-vault-mcp

by gronare

notes-vault-mcp

An MCP server for a vault of markdown notes — the kind Obsidian keeps: a folder of .md files with YAML frontmatter. The vault lives either in a local directory or in an S3 bucket (MinIO included), and the server gives an agent a cheap, indexed way to read and write it.

The point is that an agent should be able to answer "what do we already know about this?" in one call, and should be told when the vault has drifted away from the code. So the server does more than read and write files:

  • A local SQLite index. Every tool call refreshes it, fetching only the notes whose version changed. Search never downloads the vault.

  • Full-text search with BM25 ranking, folder weights, recency decay and a status factor, so the living system note outranks a two-year-old archived plan on the same words.

  • A schema. The frontmatter contract lives in the vault as .vault/schema.yml: which folders exist and what each is for, which fields are required, which statuses and kinds are legal, which folders must link an area. Writes are validated against it and refused when they do not hold.

  • A lifecycle. close archives a finished note and stamps its status; log_append writes one dated line per repo per session; lint reports every kind of drift it can see.

  • Session hooks for Claude Code: session-start hands the agent the system notes for the repo it is about to touch — plus the commits made since each note was last updated — and stop refuses to end a session that left commits unlogged or notes stale.

Swedish or English notes both work: the index folds diacritics, and the schema carries a synonym list so bokning finds booking.

Install

As a Claude Code plugin

claude plugin marketplace add https://github.com/gronare/claude-plugins
claude plugin install vault@gronare

The plugin asks for the vault settings and passes them as CLAUDE_PLUGIN_OPTION_* environment variables, which this server reads as if they were the bare names.

As an MCP server, straight from PyPI

claude mcp add vault -s user \
  -e VAULT_PATH=$HOME/vault \
  -- uvx notes-vault-mcp

Or against S3 / MinIO:

claude mcp add vault -s user \
  -e S3_ENDPOINT=https://minio.example.com \
  -e S3_ACCESS_KEY=... \
  -e S3_SECRET_KEY=... \
  -e S3_BUCKET=vault \
  -- uvx notes-vault-mcp

As a container

claude mcp add vault -s user -- \
  docker run --rm -i \
  -e S3_ENDPOINT -e S3_ACCESS_KEY -e S3_SECRET_KEY -e S3_BUCKET \
  ghcr.io/gronare/notes-vault-mcp:latest

Related MCP server: obsidian-mcp

Configuration

Every variable is also read from CLAUDE_PLUGIN_OPTION_<NAME>, which is how the Claude Code plugin passes its user config. The bare name wins when both are set.

Variable

Required

Meaning

VAULT_PATH

for a local vault

Directory holding the vault. Selects the local backend.

S3_ENDPOINT

for an S3 vault

Endpoint URL, e.g. https://minio.example.com.

S3_ACCESS_KEY

for an S3 vault

Access key.

S3_SECRET_KEY

for an S3 vault

Secret key.

S3_BUCKET

for an S3 vault

Bucket holding the vault.

S3_PREFIX

no

Key prefix inside the bucket.

S3_REGION

no

Region, default us-east-1.

VAULT_CACHE_DIR

no

Where the index lives, default ~/.cache/notes-vault-mcp.

VAULT_SCHEMA

no

Local path to a schema file, overriding the one in the vault.

VAULT_TOKEN

for --auth bearer

Static bearer token for the LAN mode of --transport http.

VAULT_STOP_HOOK

no

off disables the stop hook.

Set VAULT_PATH or the four S3_* variables. With neither, the server exits with one line saying so.

First run

uvx notes-vault-mcp init

init writes into the vault, and refuses to overwrite anything without --force:

  • .vault/schema.yml — the frontmatter contract, copied from the built-in default so you can edit it.

  • Areas.base, Open tasks.base, Resources.base, Backlog.base, Log.base — Obsidian Bases views over the same structure.

It then prints a CLAUDE.md snippet to stdout: the workflow rules an agent needs on its side of the conversation.

The schema

.vault/schema.yml is deep-merged over the built-in default, so it only needs to carry what differs. The default lays out five folders:

Folder

Kind

Weight

Role

Areas/

system

3.0

One living note per system. Current state only. The hubs of the graph.

Resources/

reference

2.0

Traps, how-tos and decisions with their reasons.

Projects/

task

1.0

Open work spanning sessions. Closed with close.

Log/

log

1.0

Append-only log per repo, one note per repo.

Archive/

archive

0.3

History. Searched only on request.

and the contract for a note:

frontmatter:
  required: [title, date, updated, tags, status]
  optional: [kind, area, summary, path, superseded_by]
  area_required_in: [Projects, Resources, Log]
  status_values: [draft, active, complete, superseded]
  kind_values: [system, task, trap, howto, decision, reference, log]

path is what ties a note to code: a comma-separated list of directories (~ is kept as written and also indexed expanded). That is what context and the session hook match against.

The repo log is one note per repo, and both its filename and its line format are schema settings:

log:
  folder: Log
  file_format: "{repo}-log.md"
  entry_format: "- [{date}] {line} | commits: {commits} | {area}"

file_format takes a single {repo} placeholder, and the default suffix is what keeps the log clear of the hub note: with Areas/myapp.md and Log/myapp.md both in the vault, Obsidian cannot resolve [[myapp]]. Every place that builds the log path reads this setting — log_append, the log tail in context, the stop hook's unlogged-commit check, changelog and lint — so changing it moves all of them at once. Rename the existing files to match when you change it.

Also configurable: the tag vocabulary and whether it is enforced, the synonym groups search expands, stale_after_days, and the search weights.

Tools

Every call refreshes the index first, throttled to at most once every 20 seconds.

Tool

Cost

What it does

search

cheap

Full-text over the index. Title, summary, tags and body, with synonyms, prefixes, quoted phrases and folded diacritics. A bare commit sha finds the notes that mention it. Hides archive and superseded notes and says how many.

context

cheap

The session-start call: the system notes covering a path, the open tasks, a triage list of open notes older than stale_after_days with the three ways to settle each, the backlog, the reference notes and the tail of the repo log, in one answer.

list_files

cheap

Paths only.

read_file

moderate

One note, prefixed with etag: <version>. A superseded note carries a warning callout.

obsidian_access

write

--auth forwarded only. Mints the personal token Obsidian's Remotely Save plugin uses over WebDAV and shows it once; a new token revokes the previous one.

lint

moderate

Reads every note and reports drift.

init

write

Sets a vault up: writes .vault/schema.yml and the Obsidian Bases views into the root and keeps what exists; force overwrites. The plugin's /vault:init calls it.

write_file

write

Validates against the schema and refuses the write if it does not hold. Stamps updated, fills date. Pass expected_etag to make the write conditional. Files that are not notes (.vault/schema.yml, .base views) are stored verbatim.

append_file

write

Appends and bumps updated. Creates the note when missing.

set_status

write

Changes a note's status without rewriting it: backlog with a priority parks it, active picks it up again.

close

write

Sets status complete (or superseded, with superseded_by, when merged_into is given) and moves the note into the archive.

log_append

write

One dated line in the repo log, with the commits it produced. Creates the log when missing.

move_file

write

Moves or renames.

delete_file

write

Deletes for good. Prefer close.

search filters: folder, status, tag, kind, area, path_prefix, since, include_archive, include_superseded, limit.

What lint reports

broken_frontmatter, missing_required (per field), missing_area, unknown_tags (only when the vocabulary is strict), unresolved_links, orphans (no inbound wikilink; log and archive ignored), stale_active, archive_status_mismatch, duplicate_stems, superseded_target_missing. With --park-stale the open task notes untouched for longer than stale_after_days are set to backlog (priority low, source veckolint <date>) before the report and listed under parked, so active always means touched within the window; reviving one is set_status(path, "active").

uvx notes-vault-mcp lint
uvx notes-vault-mcp lint --write "Log/lint-$(date +%F).md"
uvx notes-vault-mcp lint --write Log/lint.md --park-stale

Hooks

Two Claude Code hooks, both reading the hook JSON on stdin and both exiting 0 whatever happens.

session-start prints the context bundle for the working directory, then — for each system note it returned — the commits touching that note's path since the note was last updated. That is the answer to "is this note still true?" before the agent believes it.

stop blocks the end of a session that left work unrecorded: commits from the last 24 hours whose sha does not appear in the repo log, and open task notes older than the schema's stale_after_days that the session read or wrote (found through the vault tool calls in the session transcript). It returns {"decision": "block", "reason": ...}, or nothing at all when the vault is up to date. Stale notes the session did not touch are the next session's business: context lists them under triage with the three ways to settle each (close, a dated line, or park in the backlog), not at every stop. Set VAULT_STOP_HOOK=off to silence the hook.

{
  "hooks": {
    "SessionStart": [
      { "hooks": [{ "type": "command", "command": "uvx notes-vault-mcp hook session-start" }] }
    ],
    "Stop": [
      { "hooks": [{ "type": "command", "command": "uvx notes-vault-mcp hook stop" }] }
    ]
  }
}

Other commands

notes-vault-mcp serve --transport stdio          # the default
notes-vault-mcp sync --rebuild                   # drop the index and read every note again
notes-vault-mcp search "bokning" --limit 5       # the same ranking, from a shell
notes-vault-mcp changelog myapp 2026-08 --repo-path ~/projects/myapp
notes-vault-mcp changelog myapp 2026-08 --repo-path ~/projects/myapp --write
notes-vault-mcp changelog --all                  # this month (and last month during its first week)

changelog prints the log lines, the git commits grouped by day, and the repo's notes dated inside the period. With --write it keeps that as a period page, Log/<repo>-<period>.md, between the markers <!-- changelog:generated --> and <!-- /changelog:generated -->; prose above the markers (a summary written by an agent at month end) is left alone, and the page's status follows the calendar. --all does it for every repo the session-start hook has seen on this machine, and the stop hook runs that once a day, so the pages stay current without a cron.

Backlog

notes-vault-mcp backlog --area myapp --priority high

A backlog item is a task note with status: backlog, an area, a one-line summary, an optional priority (urgent, high, medium, low) and an optional source (who said it and when, or a sha). backlog_add files one from a conversation the moment something is deferred; backlog lists them by priority then age, filtered by area or family; context shows the ones relevant to the current repo apart from the open tasks. Picking an item up is setting its status to active; finishing it is close. Lint leaves backlog notes alone however old they get, and flags a complete note that was never closed. init writes Backlog.base next to the other Obsidian bases.

HTTP transport

VAULT_TOKEN=$(openssl rand -hex 32) notes-vault-mcp serve --transport http --host 0.0.0.0 --port 8765

Streamable HTTP on /mcp, with four ways to authenticate: --auth bearer (the default), --auth oidc, --auth builtin and --auth forwarded.

bearer is the LAN mode. Every request must carry Authorization: Bearer $VAULT_TOKEN; anything else gets 401 before it reaches the server. VAULT_TOKEN is mandatory in this mode — the command refuses to start without it. It is a single token with full access, and claude.ai cannot use it.

oidc and builtin speak OAuth, which is what a Claude connector needs. See Remote: claude.ai, Claude Desktop and mobile.

forwarded is for a server that sits behind a proxy which already did the OAuth: it trusts a signed identity header and serves one vault per subject. See Behind a proxy: one vault per person.

Remote: claude.ai, Claude Desktop and mobile

Run the server over HTTPS with --auth builtin or --auth oidc and claude.ai can add it as a custom connector. Connect it once on the web and the same connector appears in Claude Desktop and in the mobile app.

One server instance serves one vault.

Prerequisites

  • A vault: an S3-compatible bucket with a key scoped to it, or a folder on the host.

  • Docker, or uv on the host.

  • A domain pointing at the machine, with TLS in front of the server. The examples under deploy/ put Caddy there, which fetches the certificate itself.

  • For --auth oidc: an OpenID Connect provider you already run.

The two modes

--auth builtin

--auth oidc

Who logs in

one owner, against a password this server holds

anyone the provider admits

Client registration

dynamic, nothing to configure in claude.ai

dynamic when the provider supports it, otherwise a client id and secret pasted into claude.ai

Read-only clients

two checkboxes on the login page

group membership

State on disk

auth.sqlite under VAULT_AUTH_DIR

none

Environment

Variable

Mode

Meaning

VAULT_PUBLIC_URL

oidc, builtin

Required. The https address clients reach, path included when the server is not at the root. No default: the server refuses to start without it, and refuses anything that is not https:// (or http://localhost for a local trial).

VAULT_AUTH_DIR

builtin

Where auth.sqlite lives — the owner's password hash, the registered clients, the hashed tokens. Default ~/.cache/notes-vault-mcp/auth.

VAULT_OIDC_ISSUER

oidc

Required. The provider's issuer URL.

VAULT_OIDC_AUDIENCE

oidc

The client id the provider puts in aud. Checked when set, ignored when empty.

VAULT_OIDC_READ_GROUP

oidc

Group granting vault:read. Default vault.

VAULT_OIDC_WRITE_GROUP

oidc

Group granting vault:read and vault:write. Default vault-writers.

VAULT_OIDC_SCOPES

oidc

Scopes the resource metadata advertises, so the client asks the provider for scopes it knows. Default openid profile email groups. When the access token carries no groups, the server asks the provider's userinfo endpoint.

VAULT_TOKEN

bearer

The static token.

VAULT_CACHE_DIR

all

Where the index lives. Default ~/.cache/notes-vault-mcp.

S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY

all

The vault, unless VAULT_PATH names a local folder.

The MCP endpoint is VAULT_PUBLIC_URL + /mcp. That is the URL you paste into claude.ai.

Scopes

  • vault:readsearch, read_file, list_files, context, lint, backlog.

  • vault:writewrite_file, append_file, move_file, delete_file, close, log_append, backlog_add.

A write tool called with a read-only token fails with an error saying the token may only read the vault, rather than half-writing or silently doing nothing.

Built-in login, from zero

cd deploy/caddy-builtin
cp .env.example .env
$EDITOR .env
docker compose up -d
docker compose exec vault notes-vault-mcp owner set-password

Then, in claude.ai: Settings → Connectors → Add custom connector → the /mcp URL, e.g. https://vault.example.com/mcp. Nothing else is needed: the server registers the client itself. The browser lands on the server's login page, which asks for the owner password and shows two checkboxes, read and write. Clear write to hand out a read-only connector.

What has been connected, and how to disconnect it:

docker compose exec vault notes-vault-mcp tokens list
docker compose exec vault notes-vault-mcp tokens revoke <client_id>

The password hash and the tokens live in auth.sqlite in the vault-data volume. Back that volume up; losing it means every client has to connect again.

OIDC, from zero

cd deploy/caddy-oidc
cp .env.example .env
$EDITOR .env
docker compose up -d

The server is a resource server here: it validates the provider's access tokens and never sees a password. A user in the write group gets vault:read and vault:write, a user in the read group only vault:read, and anyone in neither is refused.

Add the connector in claude.ai the same way. With a provider that supports dynamic client registration you are done. With one that does not (Pocket ID, Authentik), register the client in the provider first and paste its client id and secret under the connector's Advanced settings; the redirect URI to allow in the provider is the one claude.ai shows in that dialog.

Pocket ID

claude.ai sends the MCP resource (the /mcp URL) as an OAuth resource parameter, and Pocket ID only accepts a resource it knows as an API. So:

  1. Settings → APIs → Add API: a name and the resource identifier, exactly VAULT_PUBLIC_URL + /mcp. Add two permissions: key vault:read and key vault:write, with the names your family will see on the consent screen.

  2. Settings → User Groups: create vault (read) and vault-writers (write) and put users in them.

  3. Settings → OIDC Clients → Add: name claude.ai, callback URL https://claude.ai/api/mcp/auth_callback, PKCE on, public client off, allowed user groups vault. Under API access, grant the API with both permissions (user-delegated). Copy the client id and secret.

  4. On the server: VAULT_OIDC_ISSUER is Pocket ID's base URL, VAULT_OIDC_AUDIENCE is the resource identifier from step 1 (Pocket ID puts it in aud), and VAULT_OIDC_SCOPES is openid profile email groups vault:read vault:write.

  5. In claude.ai, add the connector with the client id and secret under Advanced settings.

The user's groups decide what a token may do; the client's permissions only matter when the provider reports no groups at all, in the token or through userinfo.

Kubernetes

deploy/k8s/ holds plain manifests: a Deployment with a PVC mounted at /data, a Service, an Ingress and an example Secret.

cp deploy/k8s/secret.example.yaml secret.yaml
$EDITOR secret.yaml
$EDITOR deploy/k8s/ingress.yaml
kubectl apply -f secret.yaml -f deploy/k8s/deployment.yaml -f deploy/k8s/service.yaml -f deploy/k8s/ingress.yaml

The Deployment runs --auth builtin; for OIDC change the --auth argument and fill the VAULT_OIDC_* keys in the Secret. The readiness probe hits /.well-known/oauth-protected-resource/mcp, the one route that answers without a token in both modes; when VAULT_PUBLIC_URL carries a path, that path sits in the probe URL too. Set the owner password once the pod is up:

kubectl exec -it deploy/notes-vault-mcp -- notes-vault-mcp owner set-password

Fill in ingressClassName and point secretName at a TLS certificate — an existing secret, or one cert-manager issues.

Behind a proxy: one vault per person

--auth forwarded is for an organisation that already runs an OAuth authorization server in front of its MCP servers and forwards the caller's identity as a signed token in a header (the pattern Cloudflare Access uses with Cf-Access-Jwt-Assertion). The server verifies that token with the proxy's public key, takes the subject from it, and serves that subject's own vault: a prefix per person in one bucket (or a folder per person under VAULT_PATH), with its own index, its own .vault/schema.yml and a welcome note, all created on the first request. Nothing is provisioned by hand; granting access at the proxy is the whole onboarding.

notes-vault-mcp serve --transport http --host 0.0.0.0 --port 8765 --auth forwarded

The contract with the proxy: a request without a valid identity gets 403 with no WWW-Authenticate challenge (advertising an authorization server here would point clients past the proxy), the transport is stateless with plain JSON responses so a buffering proxy needs no Mcp-Session-Id, the Host header is not checked, and /up answers ok without a token for readiness probes. The OAuth metadata routes are not served in this mode; the proxy owns them.

Variable

Meaning

VAULT_PUBLIC_URL

Required. The address clients reach the server on; its hostname is the aud the token must carry, its path (if any) prefixes every route.

VAULT_IDENTITY_PUBLIC_KEY

Required. The proxy's PEM public key (RS256 or ES256), raw or base64 on one line.

VAULT_IDENTITY_ISSUER

Required. The iss in the proxy's tokens.

VAULT_IDENTITY_HEADER

The header carrying the token. Default X-Forwarded-Identity.

VAULT_IDENTITY_TYP

When set, the token's typ must match.

VAULT_IDENTITY_WRITE_CLAIMS

Entitlement names (in the token's entitlements list or scope) that grant vault:read and vault:write. Default vault:write.

VAULT_IDENTITY_READ_CLAIMS

Entitlement names that grant vault:read only. Default vault:read. A token with neither gets 403 insufficient_scope.

VAULT_SUBJECT_PREFIX

Where the vaults live under the bucket or folder: <prefix>/<sub>/. Default users.

VAULT_AUTH_DIR

Where personal.sqlite keeps the hashed personal tokens.

VAULT_CACHE_DIR

One SQLite index per subject lives here; give it a volume.

The token needs iss, aud, sub and exp; email and name are used when present. Subjects that are not plain identifiers are hashed before they name a folder.

Obsidian through the same server

Each vault is also served over WebDAV at VAULT_PUBLIC_URL/dav/, for Obsidian's Remotely Save plugin, which cannot do OAuth. The person asks Claude to run obsidian_access; the server mints a personal token, returns it once and stores only its hash. Remotely Save gets the /dav/ address, any username (the email is the convention) and that token as the password. Running obsidian_access again rotates the token. The proxy must pass /dav/* straight through, with the client's Authorization header and the WebDAV verbs and headers (PROPFIND, MKCOL, MOVE, COPY, Depth, Destination, Overwrite) intact. The welcome note written on the first request carries these instructions for the person.

Development

uv sync
uv run pytest
uv run ruff check .

The test suite runs against a fixture vault under tests/fixtures/vault/ and a moto-mocked S3 bucket. It never touches a real bucket.

License

MIT. See LICENSE.

Available Tools

11 tools
append_fileA

WRITE — appends to a note and bumps updated. Creates the note when it is missing.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
contentYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description carries the full burden. It discloses that appending occurs, `updated` is bumped, and the note is created if missing, which is useful behavioral context. However, it does not mention permissions, failure modes, or idempotency, leaving some gaps for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no fluff. Each sentence carries meaningful information, and the 'WRITE' category and 'appends' action are front-loaded for quick scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter append operation with an output schema, this description covers the core behavior and the key edge case (create-if-missing). It does not discuss path formats or error handling, but those are minor for this tool. The 'bumps updated' detail adds useful context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, so the description must compensate. It implies 'content' is the data to append and 'path' identifies the note, but it does not explicitly map either parameter. Since both names are self-explanatory, this is adequate but not thorough.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('appends') and resource ('a note'), and clarifies it also creates the note when missing. However, it does not explicitly distinguish itself from the sibling 'write_file' though the word 'appends' implies the difference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies usage for appending to a note and notes the create-when-missing behavior, but does not explicitly state when to choose it over alternatives like write_file. No clear when/when-not guidance is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

closeA

WRITE — finishes a note: sets status complete (or superseded with superseded_by when merged_into is given) and moves it into the archive. Run it in the same pass as the last commit of the work; a note left open is what makes the vault drift.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
statusNo
merged_intoNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden. It discloses the mutation (WRITE), the exact status transitions, the archive move, the superseded_by behavior when merged_into is provided, and a consequence of not calling it. This goes well beyond the raw schema, though it stops short of describing error cases or permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences with no filler. The WRITE marker and core verb are front-loaded, followed immediately by the specific behavioral effects and a motivating warning. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is self-sufficient for a 3-parameter tool with an output schema: it explains what the tool does, when to run it, what the status/merged_into parameters mean, and why the operation matters. It does not mention explicit prerequisites or failure cases, but none are critical for invoking this close operation correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains the merged_into and status interplay, but it does not explicitly document the path parameter or enumerate valid status values beyond complete and superseded. The parameter names are helpful, but the description only partially substitutes for missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('finishes'), a specific resource ('a note'), and the precise outcomes: setting status to complete or superseded and moving the note into the archive. It clearly distinguishes this lifecycle-closing operation from sibling file tools like write_file, move_file, and delete_file.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear timing guidance: run it in the same pass as the last commit of the work, and explains why leaving a note open causes vault drift. It does not explicitly name alternatives or say when not to use it, but the context is strong enough for an agent to recognize this as the completion step for a note.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

contextA

CHEAP — the session-start call. Returns the system notes covering the code at path, the open tasks for it, the reference notes and the tail of the repo log, in one answer. Use it before searching blind.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNo
repoNo
limitNo
queryNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must carry the burden of behavioral disclosure. It reveals that the tool is cheap in cost, and that it aggregates multiple context sources into one answer, which are useful behavioral hints. However, it does not explicitly state that this is a read-only operation, nor does it mention any rate limits, side effects, or failure behavior, leaving a gap in transparency for an agent assessing risk.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: it opens with a cost flag ('CHEAP'), states what the tool does in one sentence, and closes with a usage directive. Every clause earns its place, and no redundant phrasing exists. It is front-loaded with the most relevant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having an output schema, the input side is underdescribed: four parameters at 0% schema coverage, and the description only really explains `path` and vaguely implies `repo`. The tool's purpose and workflow are clear, but an agent would be left guessing about `limit`, `query`, and behaviors when parameters are omitted. For a call that is meant to be the session-start, this level of completeness is insufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate and explain parameters. It only clarifies `path` ('the code at `path`') and indirectly touches on `repo` via the 'repo log.' The `limit` and `query` parameters receive no explanation at all, so an agent cannot confidently infer their meaning or usage from the description. This is a significant inadequacy.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Returns') and a clear resource: system notes for the code at `path`, open tasks, reference notes, and the tail of the repo log, delivered in one answer. It also frames itself as the session-start call, which distinguishes it from siblings like search and read_file. This is a focused, unambiguous purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Use it before searching blind,' giving a clear directive on when to call this tool (at session start, before exploration/search). It does not spell out when not to use it or mention alternative tools by name, but the placement and 'session-start' framing strongly imply the intended workflow. Sibling tools like search are addressed contextually.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_fileA

WRITE — deletes a note for good. Prefer close, which keeps it.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Since no annotations are provided, the description carries the responsibility for disclosing destructive behavior. It does this well with 'deletes ... for good' and the 'WRITE' signal, which strongly communicates irreversibility. It could additionally mention what happens for missing paths or directories, but the core behavioral risk is transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short, purposeful clauses: the destructive action is front-loaded, and the preferred alternative is stated immediately after. There is zero redundant wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter delete tool with an output schema, the description covers the essential context: what action is performed, that it is irreversible, and which sibling tool should be preferred. The only notable gap is `path` semantics, but the overall context is sufficient for safe usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description needed to compensate, but it gives no details about the `path` parameter—no format, scope, or examples. It only indirectly suggests that `path` identifies the note to delete. The schema merely labels it 'Path', so an agent is left to infer the parameter's expected value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('deletes') and resource ('a note') and sharply distinguishes the tool from the sibling `close` by noting that `close` keeps the note. An agent can immediately understand this is a permanent delete operation, not a soft close.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Prefer `close`, which keeps it,' giving direct routing guidance toward the non-destructive alternative. It clearly implies that `delete_file` should only be used when permanent removal is intended.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lintA

MODERATE — reads every note to report drift: broken frontmatter, missing required fields, missing area, unresolved wikilinks, orphans, stale open tasks, archived notes still marked active, duplicate stems and superseded targets that do not exist.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does well: 'reads every note' explicitly signals a read-only, potentially expensive operation, and the enumerated drift categories disclose what the tool inspects. It does not mention output shape or failure behavior, but the presence of an output schema covers that area.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the core behavior ('reads every note to report drift') before listing checks. The list is long but each item earns its place by clarifying the tool's scope. It is compact and scannable, though slightly dense as a run-on.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter analysis tool with an output schema, the description covers what the tool operates on and what issues it detects. It lacks an explicit statement of expected cost or side effects, but 'MODERATE' plus 'reads every note' gives a reasonable completeness level for invocation decisions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes no parameters, so there is no semantic burden on the description. The schema is fully covered by virtue of having no properties, and the description adds contextual meaning about what data is scanned rather than needing to explain input formats.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb-resource pair: 'reads every note to report drift' and enumerates the exact categories of drift it detects (broken frontmatter, missing fields, unresolved wikilinks, etc.). This clearly distinguishes it from siblings like search or read_file, which retrieve content rather than perform whole-corpus analysis.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool—when you need a whole-note health check—but it does not explicitly state when to prefer it over alternatives or when not to use it. With siblings like search and read_file, an explicit routing note would strengthen the guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_filesA

CHEAP — paths only, no metadata and no bodies. search answers context questions better.

ParametersJSON Schema
NameRequiredDescriptionDefault
prefixNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral disclosure burden. It clearly states the tool is 'CHEAP', returns paths only, and excludes metadata and bodies—key behavioral traits for an agent deciding whether to call it. It doesn't mention recursion, directory inclusion, or error cases, but for a simple list operation the most relevant behaviors are covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise—one short sentence plus a comparison—yet packs in the cost profile, output scope, and routing guidance. It is front-loaded with 'CHEAP' and every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity—one optional parameter and an existing output schema—the description covers most essential context: cost, return type, and when to prefer an alternative. It does not explain the prefix parameter, but that gap is already captured under parameter semantics. Overall, an agent can select and use this tool correctly with the provided information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description does not mention the `prefix` parameter at all, failing to compensate for the missing schema documentation. The parameter name and default are somewhat self-explanatory, but the description adds zero meaning beyond them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description makes the tool's purpose reasonably clear: it returns paths only, implying it lists files. It also distinguishes itself from `search` by noting that `search` answers context questions better, providing sibling differentiation. However, it relies on the tool name 'list_files' for the verb and never explicitly states 'lists file paths' in the description itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly names `search` as a better alternative for context questions, which implies this tool should be used when cheap path enumeration is needed. This gives clear comparative guidance, but it could be more explicit about specific scenarios (e.g., 'use when you only need file paths').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

log_appendA

WRITE — appends one dated line to the repo log, with the commits it produced. Run once at the end of a session per repo. Creates the log note when it is missing.

ParametersJSON Schema
NameRequiredDescriptionDefault
areaNo
lineYes
repoYes
commitsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral disclosure burden. It clearly marks the call as a WRITE, states that it appends rather than overwrites, and documents the create-if-missing side effect. It stops short of auth/error behavior, but the core side effects are transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences front-load the core action and then add cadence plus the create-if-missing behavior. There is no filler, repetition, or unnecessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the action, target, usage timing, and an important side effect, which is most of what an agent needs for this simple write tool. The presence of an output schema reduces the need to document return values; the main gap is the undocumented optional area parameter.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must add meaning. It maps repo, line, and commits to real semantics, but the optional area parameter is never mentioned, and format details for dates or commit identifiers are absent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('appends') and a precise resource ('the repo log'), and clarifies scope: 'one dated line ... with the commits it produced.' This clearly distinguishes it from append_file and other file-oriented siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit cadence guidance: 'Run once at the end of a session per repo.' It does not list alternatives or when-not-to-use conditions, but the session-end trigger is a clear usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_fileA

WRITE — moves or renames a note. Use close to archive finished work.

ParametersJSON Schema
NameRequiredDescriptionDefault
destYes
sourceYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. 'WRITE' and 'moves or renames' imply mutation, but the description does not explain what happens to the source, whether destinations can be overwritten, whether paths are relative or absolute, or what the outcome/response signals look like. For a mutating operation with zero annotation support, this is a meaningful gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no filler. The 'WRITE' prefix immediately signals operation type, the core action is front-loaded, and the sibling pointer to 'close' earns its place by preventing misuse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple with only two required string parameters and an output schema present, so a minimal description can be adequate. However, with no annotations and no parameter-level documentation, the description leaves important operational details like overwrite behavior and path resolution to inference. It is minimally viable rather than complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for the bare parameter names 'source' and 'dest.' It adds only that the operation moves or renames a 'note,' which weakly implies source is the original note and dest is the target path/name. It does not clarify expected path formats, whether 'dest' can be a new name only, or what happens if dest already exists.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action — 'moves or renames a note' — with a clear verb and resource. It also differentiates itself from the sibling tool 'close' by explicitly saying close is for archiving finished work, so an agent can distinguish them without extra context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It directly provides an alternative: 'Use `close` to archive finished work.' This gives a clear when-to-use-vs-alternative signal for the most likely confusion. It does not enumerate all sibling distinctions, but the core routing guidance is present and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_fileA

MODERATE — one round trip to storage. Returns the note with an etag: first line; pass that etag back to write_file to refuse a write over someone else's change. Search first.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it delivers meaningful behavioral disclosure: cost/latency ('MODERATE — one round trip to storage', where the dash explains the label), exact return shape (etag first line), and the critical optimistic-concurrency contract with write_file. It omits error behavior (missing file, permissions), but the decision-relevant traits for an agent are covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three terse sentences with zero filler; the etag hand-off, round-trip cost, and concurrency behavior are packed efficiently. The 'MODERATE' tier is self-explained by the following dash clause, and the key imperative 'Search first' is placed last rather than front-loaded — a minor structural flaw.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter tool with an output schema and no annotations, the description covers the essentials: purpose, return format, concurrency contract, and a workflow hint. Minor gaps — path format specifics and behavior on missing files — are acceptable at this simplicity level. The description is complete enough for an agent to call the tool correctly without opening the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, but it barely does. 'the note' and 'storage' loosely tie the `path` parameter to a note in storage, yet no format, resolution rules, or allowed values are given. The parameter's meaning is left almost entirely to inference from the tool name and parameter name.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Returns') with a concrete resource ('the note') and discloses the distinctive return format (`etag:` first line). The 'Search first' line hints at its place in the sibling workflow, giving partial differentiation. However, the primary read operation is stated indirectly, and it does not distinguish read_file from list_files or context, which could also return note data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Search first' is an explicit workflow directive — search should precede reading — which gives the agent real usage context. But there is no statement of when to prefer read_file over list_files or context, and no exclusions or conditions are given. Selection criteria are implied rather than stated, so guidance is thin but present.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

write_fileA

WRITE — validates the frontmatter against the vault schema and refuses the write if it does not hold. Stamps updated with today and fills date when missing. Pass expected_etag from read_file to make the write conditional.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
contentYes
expected_etagNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden. It discloses validation, refusal to write, automatic stamping of `updated` and `date`, and conditional writes via expected_etag. It does not mention overwrite semantics or failure details on ETag mismatch, but core behavior is transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise, high-information sentences. The main behavior and key conditional flow are front-loaded, and there is no filler or redundant restating of schema fields.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-parameter tool with an output schema and no annotations, the description covers the important conceptual pieces: validation, automatic mutation, and conditional writes. It could be more complete about overwriting behavior or what happens when the ETag does not match, but it is largely sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It usefully explains expected_etag's purpose and the frontmatter-validating nature of content, but path is left entirely to its name and no content structure details are given. This partial compensation earns a mid score.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies a write operation on a vault file, with specific behaviors: frontmatter validation, refusal on invalid schema, and automatic field stamping. This differentiates it from sibling tools like append_file, move_file, and delete_file.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context through 'Pass expected_etag from read_file to make the write conditional,' which also hints at sequencing with read_file. However, it does not explicitly contrast this tool with alternatives like append_file or state when not to use it.

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.

  1. 11 tool updatesv0.2.1
    • First observedappend_file
    • First observedclose
    • First observedcontext
    • First observeddelete_file
    • First observedlint
    • First observedlist_files
    • First observedlog_append
    • First observedmove_file
    • First observedread_file
    • First observedsearch
    • First observedwrite_file

TDQS

A3.9/5.0

Scored across 11 tools

Disambiguation5/5

Each tool owns a clearly distinct operation: search/list_files/context/lint cover different discovery and integrity concerns, while read_file/write_file/append_file/move_file/delete_file/close/log_append cover separate mutation or lifecycle actions. Even the pair write_file/append_file is well separated by full-file conditional write versus append-and-create behavior.

Naming Consistency3/5

Most file operations follow a clean verb_noun pattern (read_file, write_file, append_file, move_file, delete_file, list_files), but search, close, context, and lint are single words and log_append reverses the pattern. The naming is readable and grouped by function, but it is not consistently predictable across the whole surface.

Tool Count5/5

Eleven tools is well within the ideal scope for a notes vault server: discovery, read/write, move/delete, archive, session context, logging, and lint each have a dedicated tool. No tool feels redundant or like filler.

Completeness4/5

The surface covers the core lifecycle thoroughly: search/read/create/update/append/move/delete/archive, plus session context, logging, and lint. The main gap is the lack of an explicit restore/reopen operation for archived notes, though move_file combined with write_file can work around it.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables Claude Code read/write access to an Obsidian vault, including creating, editing, searching, and browsing notes.
    8
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables reading, writing, searching, and managing an Obsidian vault through Claude, operating directly on markdown files via Node.js fs without requiring the Obsidian app.
    5,145 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables Claude to search, read, write, and manage a local markdown vault through 8 tools, turning your notes into an AI-accessible knowledge base.
    3 npm
    AGPL 3.0