Skip to main content
Glama

kb-mcp-server

CI Python 3.12+

A local-first MCP (Model Context Protocol) server exposing a searchable knowledge base of notes, backed by SQLite + FTS5. No external API keys required.

Status: under construction — this README grows as the project does. See ARCHITECTURE.md for design decisions and CHANGELOG.md for what's landed so far.

Prerequisites

  • uv (manages the Python interpreter and dependencies — you do not need Python 3.12 pre-installed, uv will fetch it)

Related MCP server: Obsidian MCP Server

Setup

cd project-1-mcp-server
uv sync --dev

This creates a .venv/ and installs both runtime and dev dependencies, pinned via uv.lock.

Running checks locally

uv run ruff check .        # lint
uv run ruff format --check .  # format check
uv run mypy                # type check (strict)
uv run pytest -v           # tests

Running the server

Over stdio (the transport Claude Desktop/Code use):

uv run kb-mcp-server

By default it stores notes in ./data/kb.sqlite3 (override with KB_DB_PATH). It speaks newline-delimited JSON-RPC on stdin/stdout — it's not meant to be run interactively in a terminal. To poke at it directly, use the MCP Inspector:

npx @modelcontextprotocol/inspector uv run kb-mcp-server

Over Streamable HTTP (for remote clients — requires a bearer token):

KB_TRANSPORT=http KB_AUTH_TOKEN=$(openssl rand -hex 32) uv run kb-mcp-server
# defaults to http://127.0.0.1:8000/mcp; override with KB_HTTP_HOST/KB_HTTP_PORT

Unauthenticated requests to /mcp or /metrics get 401. /health (no auth required — for load balancer/k8s liveness probes) checks real database connectivity, not just that the process is up:

curl http://127.0.0.1:8000/health
curl -H "Authorization: Bearer $KB_AUTH_TOKEN" http://127.0.0.1:8000/metrics

/metrics is exposed in Prometheus text exposition format (request counts by method/path/status, process uptime).

Currently implemented tools: create_note, get_note, update_note, delete_note, search_notes.

Currently implemented resources: notes://recent{?limit} (recently updated notes), notes://{note_id} (a single note).

Currently implemented prompts: summarize_note, draft_reply.

Running with Docker

The image always runs the HTTP transport (stdio doesn't make sense for a detached container — there's no host process piping its stdin/stdout).

cp .env.example .env
# edit .env: set KB_AUTH_TOKEN=$(openssl rand -hex 32)
docker compose up --build

docker compose auto-loads .env from the same directory — the exact file uv run also reads locally, so there's one place to set the token either way. Notes persist in a named volume (kb-data) across container restarts. Without KB_AUTH_TOKEN set, docker compose up refuses to start at all (fails at config-interpolation time, before Docker is even invoked) rather than launching something unauthenticated.

To run the container directly, without compose:

docker build -t kb-mcp-server .
docker run -d -p 8000:8000 -e KB_AUTH_TOKEN=$(openssl rand -hex 32) \
  -v kb-data:/app/data --name kb-mcp-server kb-mcp-server

The image runs as a non-root user (uid 1000), ships a HEALTHCHECK hitting /health, and forwards SIGTERM correctly on docker stop/docker compose down (exec-form CMD, so the app is PID 1, not a shell wrapping it).

Registering with an MCP host

Claude Code

claude mcp add kb-notes -s user -- uv run --directory /absolute/path/to/project-1-mcp-server kb-mcp-server

--directory matters: Claude Code spawns the command without first cd-ing into the project, so uv run kb-mcp-server alone (relying on an implicit cwd) would fail to find pyproject.toml. -s user registers it for every project (a personal notes tool isn't tied to any one codebase) — use -s local (the default) to scope it to just the directory you're in, or -s project to check a shared .mcp.json into a repo for teammates.

Verify with claude mcp get kb-notes — it actually spawns the server and completes the MCP handshake, so ✔ Connected means it really works, not just that the config was written. Then, in a new Claude Code session (MCP servers load at session start, not hot-reloaded into a running one), ask it to create and search a note.

Claude Desktop

Add an entry to claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "kb-notes": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/project-1-mcp-server",
        "run",
        "kb-mcp-server"
      ]
    }
  }
}

Restart Claude Desktop for it to pick up the change, then look for the tools under the 🔌 (plug/MCP) icon in a chat.

Available Tools

5 tools
create_noteC

Create a new note with a title and body, and return the saved note.

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyYes
titleYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
bodyYes
titleYes
created_atYes
updated_atYes

TDQS

C2.8/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 behavioral burden, and it mostly doesn't. It discloses only that the saved note is returned; nothing about auth/permissions, failure modes, or that this is a persistent mutation. That's thin for a write tool with zero annotation coverage.

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?

A single front-loaded sentence with no padding. The clause about returning the saved note is slightly redundant given an output schema exists, but overall it is tight and well-ordered.

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 (2 required string params) and an output schema covers the return value, so the bar is low. Still, for a mutation with no annotations and no parameter documentation, the description leaves behavioral essentials (permissions, error behavior, whether the note persists) unaddressed.

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 should compensate, but it only echoes the parameter names (title, body) without adding meaning. Length limits, constraints, and any format expectations remain unstated in prose even though the schema encodes min/max lengths.

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 (Create) and resource (note) plus the required inputs and that the result is returned. The action is unambiguously distinct from get_note/update_note/delete_note, though the description never names or contrasts those siblings.

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

Usage Guidelines2/5

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

No when-to-use guidance and no exclusions. With update_note as a sibling, the agent gets no explicit signal that this tool is for brand-new notes rather than modifying existing ones; usage is only inferable from the name and verb.

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

delete_noteC

Delete a note by its id.

ParametersJSON Schema
NameRequiredDescriptionDefault
note_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes

TDQS

C2.9/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 behavioral burden. For a destructive operation it says nothing about irreversibility, whether the deletion is soft or hard, permission requirements, or error behavior for a nonexistent id.

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?

A single front-loaded sentence with no wasted words. Terseness here is efficiency rather than padding, though the brevity borders on under-specification for a destructive tool.

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?

An output schema exists, so return values need not be explained. However, for a one-parameter destructive tool with zero annotations and zero schema description coverage, the description is missing the irreversibility and permission context an agent needs to invoke it safely.

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?

Only one parameter, and schema description coverage is 0%, so the schema gives no format or source hints for note_id. The description adds that the id identifies the note to delete, but no format, origin, or example, so it only marginally compensates for the coverage gap.

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 ('Delete') and resource ('a note') with the keying parameter identified. It doesn't explicitly distinguish itself from siblings like update_note or get_note, but the destructive verb makes the distinction inferable.

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

Usage Guidelines2/5

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

No when-to-use guidance, no prerequisites, no exclusions. There is no warning that this is a permanent removal versus a soft delete, and no mention of what the caller needs to have done beforehand (e.g. obtaining the note_id).

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

get_noteB

Retrieve a single note by its id.

ParametersJSON Schema
NameRequiredDescriptionDefault
note_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
bodyYes
titleYes
created_atYes
updated_atYes

TDQS

B3.2/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 full behavioral burden, and it discloses almost nothing beyond the implied read nature of 'Retrieve'. It does not state permission requirements, behavior on a missing/invalid id, or whether deleted notes are visible.

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?

A single tight sentence with the resource and lookup key front-loaded and no filler. It is efficient, though terse enough that it forgoes useful context.

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?

An output schema exists, so return values need not be described, and one identifier parameter is a simple contract. Still, with zero annotations and no schema parameter description, the definition omits error/not-found behavior and authorization context that an agent would want before calling.

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 schema does not explain note_id; the description partially compensates by identifying it as the note's id. It adds no format, type, or sourcing detail (e.g., where the id comes from), leaving the parameter only half-documented.

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 states a specific verb ('Retrieve') and resource ('a single note') plus the lookup key ('by its id'), so an agent can distinguish it from list/search-style siblings. It stops short of explicitly contrasting itself with search_notes, which would be the natural source of confusion.

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?

Usage is only implied: 'by its id' signals this is for cases where the identifier is already known, contrasting implicitly with search_notes. There is no explicit statement of when to prefer this over search_notes or what happens if the id is unknown.

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

search_notesA

Full-text search over note titles and bodies, ranked by relevance. Supports FTS5 syntax: quote a phrase for an exact match, combine terms with AND/OR/NOT, or prefix-match with an asterisk (e.g. kaf*).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryYes
offsetNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
itemsYes
limitYes
totalYes
offsetYes

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 full burden, and it does disclose meaningful behavior: relevance-ranked results and supported FTS5 query semantics (phrase quoting, AND/OR/NOT, asterisk prefix matching) with a concrete example. It omits result ordering details beyond relevance and any pagination/limit behavior.

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-loaded with the core purpose before the syntax detail. Every clause adds value; no filler.

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?

An output schema exists, so return values need not be explained. For a read-only search tool with three parameters, the core query semantics are well covered; only limit/offset behavior is unaddressed, a minor gap.

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?

Schema description coverage is 0%, so the description must compensate. It richly documents the required query parameter's syntax, which is the critical semantic. The limit/offset parameters are left to the schema, but their names, defaults, and min/max bounds make them largely self-explanatory.

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 ('Full-text search over note titles and bodies') and specifies ranking behavior. It is immediately distinguishable from the CRUD siblings get_note/create_note/update_note/delete_note.

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?

No explicit when-to-use or when-not-to-use guidance and no sibling is named as an alternative. Usage is only implied by the verb 'search' versus the CRUD siblings.

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

update_noteC

Replace an existing note's title and body.

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyYes
titleYes
note_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
bodyYes
titleYes
created_atYes
updated_atYes

TDQS

C2.7/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 behavioral burden. 'Replace' usefully signals full overwrite semantics rather than a merge, but it says nothing about required permissions, what happens on a nonexistent note_id, whether changes are reversible, or any rate/size constraints beyond the schema.

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?

A single front-loaded sentence with no filler; every word earns its place. Brevity is appropriate for a simple three-parameter tool, though the terseness coincides with the informational gaps noted elsewhere.

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?

An output schema exists, so return values need not be described, but for a mutation tool with zero annotation coverage the description should say more about prerequisites and side effects. As written it is incomplete relative to the tool's write semantics.

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% and all three parameters are required with constraints (minLength/maxLength) that the description never mentions. The description names title and body, mapping to two params, but note_id is never referenced and no format or value guidance is given.

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 ('Replace') and resource ('note') plus the fields affected (title and body), so it is clearly distinguishable from get_note, create_note, delete_note, and search_notes. It stops short of explicitly naming how it differs from siblings or referencing them.

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

Usage Guidelines2/5

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

No when-to-use guidance, no mention of prerequisites such as the note existing, and no routing to alternatives like create_note or get_note. The agent must infer usage entirely from the verb.

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. 5 tool updatesv0.1.0
    • First observedcreate_note
    • First observeddelete_note
    • First observedget_note
    • First observedsearch_notes
    • First observedupdate_note

TDQS

A3.5/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct action on a single note resource: create, retrieve, update, delete, and search. There is no overlap or ambiguity; an agent can easily select the correct tool.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case: create_note, get_note, update_note, delete_note, search_notes. The convention is predictable and readable.

Tool Count5/5

With 5 tools, the set is well-scoped for a note management server. It covers essential operations without bloat, and each tool earns its place.

Completeness4/5

The server provides full CRUD plus full-text search, covering the core lifecycle. However, it lacks an explicit 'list all notes' operation, which could be a minor gap for some workflows.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    Enables indexing and retrieving notes with full-text search using SQLite, plus building knowledge graphs to find relationships between concepts. Supports natural language note management, tagging, and semantic connections.
    16
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to interact with Obsidian vaults for creating, reading, searching, and managing notes, daily notes, TODOs, session reports, and backlinks through both stdio and HTTP/SSE transports.
    10
    2,778
    4
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    A lightweight, intelligent note-organizing server that acts as an AI-powered personal memory vault for capturing, organizing, and retrieving insights using FastMCP and SQLite.
    8
    2
    -