NoteHarbor MCP
NoteHarbor MCP
Пример на Python для получения заметок Obsidian через MCP и GraphQL, расширяемый с помощью PostgreSQL/pgvector. Личные vault, реальные документы и API-ключи не включены.
Исходный материал NoteHarbor — это Markdown-файлы. Для поиска создаются только необходимые данные, а исходники сохраняются как есть.
Критерии этого проекта
Local first: исходные Markdown остаются локально, а внешние сервисы — лишь подключаемые опции.
Source preserving: результаты поиска, эмбеддингов и синхронизации не заменяют исходники.
Privacy by boundary: реальные vault, личные записи и API-ключи находятся за пределами публичного проекта.
Model neutral: генератор эмбеддингов и Vector DB не привязываются к конкретному поставщику.
Small and replaceable: адаптеры и сервисный слой остаются небольшими и заменяемыми.
Related MCP server: Notes RAG MCP Server
Три публичных примера
MCP: инструменты
upsert_vector,search_vectorsGraphQL: мутация
indexChunk, запросvectorSearchPostgreSQL/pgvector: модели SQLAlchemy, порт Repository, среда разработки Docker
Это пример для изучения структуры, а не рабочий сервис. Базовый Repository работает в памяти; также приведены точки перехода на PostgreSQL/pgvector и примеры SQL.
Быстрый старт
uv syncЗапуск примера MCP:
uv run noteharborЗапуск PostgreSQL через Docker
docker compose up -d postgresФайл docker-compose.yml определяет образ pgvector/pgvector и PostgreSQL для разработки Python MCP.
# PostgreSQL만
docker compose up -d postgres
# Python MCP까지
docker compose up --build python-mcpPOSTGRES_URL — это место для настройки подключения к реальной БД. Сейчас запуск по умолчанию выполняется на моке.
Пример GraphQL
Схема GraphQL находится в noteharbor/api/graphql_schema.py. Результат get_schema() можно подключить к внешнему ASGI-серверу.
Пример операции:
mutation {
indexChunk(
sourcePath: "sample.md"
content: "Obsidian knowledge"
embedding: [1.0, 0.0]
)
}
query {
vectorSearch(embedding: [0.9, 0.1], limit: 5) {
sourcePath
content
score
}
}Границы CRUD и ORM-стиля
Repository отвечает не только за поиск, но и за весь жизненный цикл NoteChunk — от создания до удаления.
Create/Upsert: MCP
upsert_vector, GraphQLindexChunk→VectorService.index_chunk()Read: MCP
get_chunk·list_chunks, GraphQLnoteChunk·noteChunksUpdate: MCP·GraphQL
updateChunk→ после чтения существующей записи обновляются только изменённые поляDelete: MCP·GraphQL
deleteChunkSearch: MCP
search_vectors, GraphQLvectorSearch
Текущий адаптер — это in-memory мок для проверки работы. Реальное хранение размещается за границей SQLAlchemy ORM. В реальном адаптере PostgreSQL MockPostgresVectorRepository заменяется на сеансовые операции следующего вида.
Код реального ORM-потока можно посмотреть в noteharbor/infrastructure/postgres/sqlalchemy_repository.py. Этот адаптер реализует тот же порт VectorRepository, используя Session.get, select, update, delete. Запуск по умолчанию по-прежнему моковый, поэтому пример можно читать и тестировать без подключения к PostgreSQL.
session.get(NoteChunkModel, chunk_id)
session.scalars(select(NoteChunkModel).limit(limit)).all()
session.execute(update(NoteChunkModel).where(NoteChunkModel.id == chunk_id).values(...))
session.execute(delete(NoteChunkModel).where(NoteChunkModel.id == chunk_id))API не работает с SQL напрямую, а передаёт CRUD и поиск по цепочке MCP/GraphQL → VectorService → VectorRepository → SQLAlchemy/pgvector.
Назначение
Этот репозиторий — образец Python-архитектуры, в которой один исходный Markdown-документ запрашивается через один и тот же сервис векторного поиска как через MCP, так и через GraphQL.
Вместо того чтобы заранее выбирать конкретного поставщика эмбеддингов или векторную БД, фокус сделан на явных точках замены.
MCP / GraphQL API
→ VectorService
→ VectorRepository port
→ 현재: in-memory MockPostgresVectorRepository
→ 전환: PostgreSQL + pgvectorОтветственность за векторизацию и поиск
Текущий Python-пример не создаёт эмбеддинги напрямую. Мутация indexChunk и инструмент upsert_vector принимают и сохраняют эмбеддинги list[float], созданные извне.
Причины выноса генерации эмбеддингов:
чтобы не привязывать модель эмбеддингов к одной из: OpenAI, Voyage или локальная модель
чтобы исключить API-ключи и личные данные из публичного примера
чтобы разделить ответственность API-слоя и хранилища поиска
чтобы в реальном сервисе конвейер чанкинга и генерации эмбеддингов можно было заменить отдельным worker'ом
Поиск выполняется в следующем порядке:
사용자 query embedding
→ GraphQL vectorSearch 또는 MCP search_vectors
→ VectorService.search()
→ Repository.search()
→ cosine similarity 계산
→ score가 높은 NoteChunk 반환Сейчас MockPostgresVectorRepository в repository.py воспроизводит этот поток в памяти. В реальном адаптере PostgreSQL косинусное расстояние вычисляется через embedding <=> :query_embedding, а 1 - distance возвращается как score.
Почему PostgreSQL + pgvector
NoteChunk — это не только значение с вектором, но и запись, содержащая исходный путь, порядковый номер чанка, текст и метаданные. Сочетание PostgreSQL и pgvector позволяет обрабатывать реляционные условия и поиск по векторной схожести в одном хранилище и в границах SQL.
PostgreSQL: метаданные исходников, состояние, информация о синхронизации и управление транзакциями
pgvector: колонка
vector, косинусное расстояние (<=>), индекс HNSWDocker: фиксирует условия запуска pgvector в среде разработки
SQLAlchemy Repository: точка замены хранилища
При росте масштаба поиска может оказаться более подходящей специализированная векторная БД. Здесь показан поток, в котором информация о документах и векторный поиск обрабатываются в одном хранилище.
Область квантования
В текущий Python-репозиторий реализация квантования не включена. Входные эмбеддинги принимаются как есть — значениями float — и используются для поиска; это выбор, сделанный, чтобы в первую очередь показать модель-нейтральную границу Repository.
Если квантование добавляется, предусматривается отдельный порт EmbeddingQuantizer, а этапы float32 → INT8/float16 → сохранение/восстановление размещаются между indexing worker'ом и адаптером Repository. Поскольку способ квантования следует выбирать после измерения качества поиска, памяти и задержки, этот пример не утверждает, что оно уже реализовано.
Связь двух примеров NoteHarbor
noteharbor-mcp: инструменты TypeScript MCP и поток эмбеддингов и INT8-квантования
noteharbor-python: Python MCP·GraphQL API и граница VectorService/Repository
Оба репозитория — это примеры одной и той же идеи на разных языках и через разные способы API; они не содержат реальных личных vault или рабочих данных.
Дополнительные технологии и причины их использования
Технология | Причина использования |
uv | для быстрого воспроизведения Python-зависимостей, виртуального окружения и lock-файла и использования того же пути установки в Docker |
FastMCP | для краткой и ясной демонстрации связи Python-функций с инструментами MCP |
Pydantic | для валидации входных моделей и настроек на границе API |
SQLAlchemy | чтобы Repository не был привязан к конкретному способу выполнения SQL и имел границу адаптера PostgreSQL |
psycopg | для обеспечения подключения к PostgreSQL из Python |
pgvector Python package | для представления типа vector PostgreSQL в моделях SQLAlchemy |
Strawberry GraphQL | для создания примера, в котором один и тот же VectorService доступен через GraphQL Query/Mutation |
Docker Compose | для совместного воспроизведения среды разработки PostgreSQL с включённым pgvector и Python MCP |
Каждая технология выбрана, чтобы описать разделение ролей API, сервиса, хранилища и среды разработки.
Структура проекта
.
├── noteharbor/
│ ├── mcp_server.py
│ ├── api/graphql_schema.py
│ ├── application/vector_service.py
│ ├── domain/
│ └── infrastructure/
│ ├── notion/mock_adapter.py
│ └── postgres/
│ ├── models.py
│ ├── repository.py
│ └── sqlalchemy_repository.py
├── tests/test_vector_repository.py
├── Dockerfile
├── docker-compose.yml
└── pyproject.tomlЛицензия
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides tools for ingesting documents into a local vector database and retrieving relevant information via semantic search, enabling retrieval-augmented generation for MCP clients.6
- FlicenseNot gradedqualityBmaintenanceEnables semantic search over personal markdown notes by indexing them into a vector database and exposing search, reindex, and status tools via MCP.
- AlicenseNot gradedqualityBmaintenanceIndexes local Markdown/text files into a SQLite database with vector embeddings and provides MCP tools for semantic search without cloud dependencies.GPL 3.0
- AlicenseNot gradedqualityAmaintenanceProvides MCP tools for semantic search over personal knowledge sources using pluggable embeddings and local vector indexing.1MIT
Related MCP Connectors
Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.
Hosted MCP memory: save sessions/decisions once, search from Claude, Cursor, ChatGPT. EU-hosted FTS.
Token-efficient MCP memory for Markdown vaults. Tiered search, GraphRAG, AI memories.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/kris-atelier/noteharbor-python'
If you have feedback or need assistance with the MCP directory API, please join our Discord server