{"id":"3fd35111-6626-489e-b4d5-75b4a1160183","slug":"mcp-notes","kind":"mcp","name":"mcp-notes","summary":"MCP server for personal knowledge management — markdown notes, semantic search, wiki links, knowledge graph","owner":"michaelkrauty","repoUrl":"https://github.com/michaelkrauty/mcp-notes","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-01-07T05:41:41.000Z","addedAt":"2026-10-21T04:11:54.746Z","logoUrl":"https://avatars.githubusercontent.com/u/4009419?u=36818535769a9df6310fa8b8719a078837d2b95d&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["memory-knowledge","search","files-documents"],"tags":["claude","knowledge-management","markdown","python","semantic-search"],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-27T01:17:31.040Z","sample":false,"url":"https://conduits.dev/tools/mcp-notes","language":"Python","transports":["stdio"],"install":{"pypi":"mcp-notes"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# mcp-notes\n\nMCP server for personal knowledge management with semantic search, git versioning, and knowledge graph capabilities.\n\nSupports stateless MCP `2026-07-28` requests and legacy MCP clients from the same stdio server through the official Python SDK v2.\n\n## Prerequisites\n\n- **Python 3.12+**\n- **Linux or macOS** (uses POSIX file locking via vector-core; not compatible with Windows)\n- [Qdrant](https://qdrant.tech/) vector database (default: `localhost:6333`)\n- An OpenAI-compatible embedding API (e.g., llama.cpp, Ollama, or any `/v1/embeddings` endpoint; default: `localhost:8080`)\n- **git** (must be on PATH for versioning features)\n\n## Installation\n\nRequires [vector-core](https://github.com/michaelkrauty/vector-core).\n\n```bash\npip install git+https://github.com/michaelkrauty/vector-core.git@v1.8.1\npip install git+https://github.com/michaelkrauty/mcp-notes.git\n```\n\nOr clone both repos and install locally:\n\n```bash\ngit clone https://github.com/michaelkrauty/vector-core.git\ngit clone https://github.com/michaelkrauty/mcp-notes.git\npip install -e vector-core/\npip install -e mcp-notes/\n```\n\n## Quick Start\n\n```bash\n# Register with Claude Code:\nclaude mcp add notes -- mcp-notes\n\n# Or add to your MCP client config (e.g., claude_desktop_config.json):\n# {\n#   \"mcpServers\": {\n#     \"notes\": {\n#       \"command\": \"mcp-notes\",\n#       \"env\": {\n#         \"VECTOR_QDRANT_URL\": \"http://localhost:6333\",\n#         \"VECTOR_EMBEDDING_URL\": \"http://localhost:8080\",\n#         \"VECTOR_EMBEDDING_MODEL\": \"your-model-name\"\n#       }\n#     }\n#   }\n# }\n```\n\n## Features\n\n- **Note Management**: CRUD operations on markdown notes with YAML frontmatter\n- **Semantic Search**: Hybrid dense + sparse vector search via Qdrant\n- **Git Versioning**: Automatic commits on changes, full history with `--follow`\n- **Wiki Linking**: `[[uuid]]` syntax for inter-note references with backlink tracking\n- **Tags & Categories**: Flexible organization with tag management tools\n- **Glossary**: Shared term definitions with aliases and domains\n- **Fact Graph**: Subject-predicate-object triples with source tracking\n\n## Tools (38 total)\n\n### Notes (4)\n| Tool | Description |\n|------|-------------|\n| `create_note` | Create note with auto-generated UUID |\n| `read_note` | Read note by UUID |\n| `update_note` | Update title, content, tags, or category |\n| `delete_note` | Delete note (keeps git history) |\n\n### Search (3)\n| Tool | Description |\n|------|-------------|\n| `search_notes` | Hybrid semantic + keyword search with filters |\n| `list_notes` | List notes with tag/category filters |\n| `find_similar_notes` | Find semantically similar notes |\n\n### Versioning (2)\n| Tool | Description |\n|------|-------------|\n| `get_note_history` | Git commit history for a note |\n| `restore_note_version` | Restore note to previous commit |\n\n### Links (1)\n| Tool | Description |\n|------|-------------|\n| `get_note_links` | Outgoing, incoming (backlinks), and broken links |\n\n### Tags (3)\n| Tool | Description |\n|------|-------------|\n| `list_tags` | All tags with note counts |\n| `rename_tag` | Rename tag across all notes |\n| `merge_tags` | Merge multiple tags into one |\n\n### Categories (2)\n| Tool | Description |\n|------|-------------|\n| `list_categories` | Category hierarchy with counts |\n| `move_category` | Move/rename a category |\n\n### Glossary (6)\n| Tool | Description |\n|------|-------------|\n| `add_glossary_entry` | Add term with expansion, definition, domain |\n| `lookup_term` | Exact lookup by term or alias |\n| `search_glossary` | Semantic glossary search |\n| `list_glossary` | List entries with optional domain filter |\n| `update_glossary_entry` | Modify entry metadata |\n| `delete_glossary_entry` | Delete entry |\n\n### Facts (11)\n| Tool | Description |\n|------|-------------|\n| `add_fact` | Add SPO triple with source tracking |\n| `add_facts_batch` | Batch import facts |\n| `update_fact` | Update fact metadata |\n| `delete_fact` | Delete fact and sources |\n| `query_facts` | Query by subject/predicate/object |\n| `get_entity` | All facts involving an entity |\n| `list_facts` | List fact summaries |\n| `search_facts` | Semantic fact search |\n| `index_facts` | Index facts for search |\n| `find_connections` | BFS graph traversal between entities |\n| `get_neighbors` | Immediate entity connections |\n\n### Integrity (4)\n| Tool | Description |\n|------|-------------|\n| `get_facts_with_stale_sources` | Facts with deleted/modified sources |\n| `get_source_statistics` | Source integrity stats |\n| `check_fact_integrity` | Check specific fact's sources |\n| `revalidate_fact_sources` | Reset sources after verification |\n\n### Health (2)\n| Tool | Description |\n|------|-------------|\n| `reindex_notes` | Force full reindex |\n| `check_note_health` | Validate note structure, find errors |\n\n## Data Model\n\n### Note\n```yaml\n---\nid: {uuid}\ntitle: Note Title\ncreated: 2024-01-01T00:00:00Z\nmodified: 2024-01-05T12:00:00Z\ntags: [tag1, tag2]\nlinks: [linked-uuid]\n---\nMarkdown content with [[uuid]] links.\n```\n\n### Fact (SPO Triple)\n```\nsubject: \"Ada Lovelace\" (type: person)\npredicate: \"works_at\"\nobject: \"Babbage Labs\" (type: organization)\ncontext: \"as lead engineer\"\nconfidence: 1.0\nvalid_from/to: date range\nsources: [{type: note, id: uuid, location: \"paragraph 3\"}]\n```\n\n## Storage\n\n| Data | Location |\n|------|----------|\n| Notes | `{NOTES_DIR}/notes/` (default `~/notes/notes/`) |\n| UUID index | `{NOTES_DIR}/.index/` |\n| Vectors | Qdrant collection `notes_{hash}` |\n| Git repo | `{NOTES_DIR}/.git/` |\n| Facts & glossary | `~/.local/share/vector-core/` (configurable via `VECTOR_SHARED_DATA_DIR`) |\n\n`NOTES_DIR` (default `~/notes`) is the base directory. Actual note files live in the `notes/` subdirectory within it. The base directory also contains `.index/`, `.git/`, and `.locks/`.\n\nNotes stored as `{slug}-{uuid}.md` organized by category subdirectories.\n\n## Configuration\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `NOTES_DIR` | `~/notes` | Notes storage directory |\n| `NOTES_GIT_ENABLED` | `true` | Enable git versioning |\n| `NOTES_GIT_USER_NAME` | `Notes MCP` | Git commit author |\n| `NOTES_GIT_USER_EMAIL` | `notes@localhost` | Git commit email |\n| `NOTES_AUTO_INDEX` | `true` | Auto-index on startup |\n| `NOTES_COLLECTION_PREFIX` | `notes` | Qdrant collection prefix |\n\nPlus inherited vector-core settings (`VECTOR_QDRANT_URL`, `VECTOR_EMBEDDING_URL`, etc.).\n\n### Changing embedding models\n\nUpdate the vector-core embedding configuration and restart the client. The first search or write automatically builds a compatible physical collection, including notes, chunks, glossary entries, facts, and other retained content in a shared collection. This also works with `NOTES_AUTO_INDEX=false`. There is no separate destructive reindex step.\n\nModel, resolved dimension, deployment namespace, and input formatting are part of the embedding identity. Change the deployment namespace whenever an unchanged model alias points to different weights. Reads and writes use a fixed physical generation; an older client that has been superseded must restart before further operations. Stop legacy server versions before changing configuration because those versions do not participate in migration locking.\n\nThe original collection is retained. Failed builds remain inactive, and retrying creates a fresh candidate. New records preserve complete embedding input. Retained inputs larger than the configured model capacity use independently searchable fragments rather than truncation or averaged vectors. Legacy records require sufficient retained text or readable original source; missing source and historically truncated payloads can prevent complete reconstruction and must be surfaced. When local source changes are detected, complete note/chunk groups are refreshed without changing unrelated record types. Their vocabulary contribution is reconciled by the next normal full indexing pass. Missing files or unavailable source directories never imply deletion during migration: complete retained groups survive, while legacy metadata-only summaries without a reconstructable body fail explicitly.\n\nNote-level semantic search ranks complete passage matches and returns distinct notes. Similar-note lookup compares all indexed source passages and uses the best passage-pair score, excluding the source note before retrieval. The short note summary is auxiliary; it does not limit body coverage. Chunk text retains exact body spans, including oversized paragraphs and header-only sections, and highlights use full retained searchable text. Limits include repeated metadata and model role formatting. Metadata that cannot fit as repeated context produces an explicit error rather than being silently shortened.\n\nExplicit fact and glossary searches return distinct entities. Default note/chunk and mixed all-types searches return distinct original source records, grouping their fragments while preserving markerless legacy matches. Winning fact and glossary fragments use lineage-validated canonical display fields and keep highlights from the matching snippet. Similar-note queries use bounded concurrency without limiting source coverage; a failed batch is canceled and joined before the error propagates.\n\nFor exact tokenizer-based input limits, install the optional extra with `uv sync --extra tokenizer` or `pip install 'mcp-notes[tokenizer]'`, then configure vector-core's tokenizer and token limit. Without that extra, vector-core uses its conservative fallback limit. Query and document formatting is handled by the embedding client; callers should provide ordinary, unprefixed text.\n\n## Search Query Syntax\n\n```\n# Filter by tag\ntag:project-x\n\n# Exclude a tag\n-tag:archived\n\n# Filter by category (exact match)\ncategory:work/projects\n\n# Date filters\nafter:2024-01-01\nbefore:2024-06-30\n\n# Title search\ntitle:meeting notes\n\n# Combined\nproject tag:active category:work after:2024-01-01\n```\n\n## MCP Resources\n\nStatic data endpoints:\n- `notes://index` - Full note index\n- `notes://tags` - All tags with counts\n- `notes://categories` - Category hierarchy\n- `notes://recent` - Last 20 modified notes\n- `notes://orphans` - Notes with no backlinks\n- `notes://broken-links` - Broken reference summary\n- `notes://parse-errors` - Notes that failed to parse\n\n## Dependencies\n\nRequires vector-core components:\n- EmbeddingClient, GlobalVocabulary (search)\n- QdrantStorage (storage)\n- GlossaryStore, FactStore (knowledge graph)\n\nExternal libraries:\n- GitPython (versioning)\n"}