Skip to main content
Glama
agent-notes

agent-notes

by pitolabs

πŸ‘‹ Welcome to agent-notes

Give your AI agent a folder of Markdown notes as its knowledge base β€” an Obsidian vault, or one folder of it. The agent lists, reads and searches the notes by keyword and by meaning ("what did we already check when the internet kept dropping?" finds the network note even if it never says "internet"), and writes notes back without clobbering an edit that arrived from your phone in the meantime.

Use it as an MCP server for any client (Claude Code, Cursor, OpenCode, your own agent), as Mastra tools in your process, or as a plain TypeScript SDK.

✨ What you get

  • πŸ—’οΈ Four tools: list_notes, read_note, search_notes, write_note (left out with --read-only).

  • πŸ”Ž Hybrid search in a single libSQL file: FTS5 keywords (accents folded) + chunk vectors, fused by reciprocal rank, filtered by folder or tag; plain word search over the files when no index is configured.

  • πŸ›‘οΈ Writes that never overwrite someone else's edit: changing a note needs the sha from read_note; if the file changed since (Obsidian Sync, LiveSync, Syncthing, a git pull), the write is refused and the agent reads again.

  • πŸ”„ An index that follows the folder by itself: a sweep by sha every 10 minutes and after each write β€” new or changed notes are re-indexed, deleted ones dropped, unchanged ones skipped.

  • 🏷️ Obsidian-aware: YAML frontmatter title, tags, aliases, modified; hidden files and symlinks never read; paths outside the folder refused.

  • πŸ”Œ Pick your embedder: Amazon Bedrock, OpenRouter, or any OpenAI-compatible /embeddings (OpenAI, Ollama, LM Studio, vLLM).

  • 🌐 stdio or HTTP: agent-notes mcp --http serves Streamable HTTP with an optional Bearer token and a /health endpoint; a Dockerfile runs it as a container.

Related MCP server: mor

πŸͺΆ Light, cheap, yours

  • πŸͺΆ Lightweight: five runtime dependencies (@libsql/client, @modelcontextprotocol/sdk, @pitolabs/agent-docs, yaml, zod); no model to download, no vector database to run. The index is one SQLite file; the image fits in a 256 MB container.

  • πŸ’Έ Low cost: one embedding pass per changed note; a search is one keyword query and one query embedding.

  • πŸ” Yours: the notes stay in your folder, the source of truth. Only note text goes to the embeddings provider you choose (a local Ollama keeps it on your machine); errors and logs never carry it. Delete the database file and the index rebuilds itself from the folder.

πŸš€ Quick start

As an MCP server, for any client (here Claude Code; the guide has Cursor, OpenCode and Docker):

claude mcp add notes -e EMBEDDINGS_PROVIDER=openai-compatible -e EMBEDDINGS_BASE_URL=http://localhost:11434/v1 \
  -e EMBEDDINGS_MODEL=bge-m3 -- npx -y @pitolabs/agent-notes mcp --dir ~/notes --db file:$HOME/.cache/agent-notes/notes.db

As Mastra tools, in your process:

bun add @pitolabs/agent-notes      # or: npm install @pitolabs/agent-notes
import { Agent } from "@mastra/core/agent";
import { createEmbedder, embeddingsConfig, NotesFolder, notesTools, openAgentNotes } from "@pitolabs/agent-notes/mastra";

const folder = await NotesFolder.open({ dir: "/srv/notes/company" }, "[clerk]");
const cfg = embeddingsConfig(process.env); // EMBEDDINGS_PROVIDER, EMBEDDINGS_*, OPENROUTER_API_KEY
if ("off" in cfg) throw new Error(cfg.off);
const embedder = createEmbedder(cfg);
const opened = await openAgentNotes({ url: "file:./notes-clerk.db", folder, embedder, log: "[clerk]" });
if ("off" in opened) throw new Error(opened.off);
opened.indexer.start(); // sweeps the folder now and every 10 min

export const clerk = new Agent({
	id: "clerk",
	name: "Clerk",
	model: "openai/gpt-4o-mini",
	instructions: "You answer from the company's notes. Read a note before you state a fact from it.",
	tools: notesTools({ folder, ...opened, embedder, kbName: "da empresa" }),
});

kbName is the base's name in the tool descriptions. What the host still decides β€” which folder, which model, whether the agent may write (readOnly) β€” is in the guide.

πŸ“š Learn more

πŸ“– Guide

MCP clients, HTTP and Docker, Mastra, the SDK; one folder per agent

πŸ”Ž Reference

CLI flags, environment, /health, the tools' inputs and outputs, the sweep, what is stored

πŸ—ΊοΈ Design notes

Why a sweep and not events, why not QMD as an SDK, why one index per folder

πŸ§‘β€πŸ’» Contributing

Hooks, formatting, tests, the privacy scan

🧭 When to use something else

  • Basic Memory: a complete MCP server with a knowledge graph over Markdown (Python, AGPL).

  • foam-notes-mcp: a TypeScript MCP server with a wikilink graph and local embeddings.

  • QMD: a local search engine for Markdown with a reranker; read-only.

This package is for one folder per agent, writes that never overwrite edits made elsewhere, and the choice between in process, MCP over stdio, or a container.

🌍 Languages

Tool descriptions and messages are in Brazilian Portuguese in this release (the model reads them and answers in that language). An English set is on the list.

πŸ’› Made by Pito Labs

Extracted from the agents we run for our own businesses, whose knowledge lives in an Obsidian vault. MIT licensed β€” use it, fork it, tell us what you built.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI assistants to search, read, create, update, and remove personal markdown notes stored locally, providing persistent memory across sessions.
    18 npm
    2
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to list, search, read, and append to Markdown notes through MCP tool calls, making it easy to interact with a second brain folder.
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to interact with a local folder of Markdown notes, supporting listing, reading, searching, creating, and appending to notes with strict security boundaries.
    5
    MIT