NoteHarbor MCP
NoteHarbor MCP
Ein Python-Beispiel zum Abfragen von Obsidian-Notizen über MCP und GraphQL und zur Erweiterung mit PostgreSQL/pgvector. Es enthält keine persönlichen Vaults, echten Dokumente oder API-Schlüssel.
Die Originale von NoteHarbor sind Markdown-Dateien. Es werden nur die für die Suche benötigten Daten separat erstellt, die Originale bleiben unverändert erhalten.
Kriterien dieses Projekts
Local first: Die ursprünglichen Markdown-Dateien bleiben lokal, externe Dienste sind optionale Verbindungsmöglichkeiten.
Source preserving: Suchergebnisse, Embeddings und Synchronisierungsergebnisse ersetzen nicht die Originale.
Privacy by boundary: Echte Vaults, persönliche Aufzeichnungen und API-Schlüssel bleiben außerhalb des öffentlichen Projekts.
Model neutral: Der Embedding-Generator und die Vektor-DB sind nicht an einen bestimmten Anbieter gebunden.
Small and replaceable: Adapter und Service-Schichten bleiben klein.
Related MCP server: Notes RAG MCP Server
Drei öffentliche Beispiele
MCP: Werkzeuge
upsert_vector,search_vectorsGraphQL: Mutation
indexChunk, QueryvectorSearchPostgreSQL/pgvector: SQLAlchemy-Modelle, Repository-Port, Docker-Entwicklungsumgebung
Es handelt sich nicht um einen Produktionsdienst, sondern um ein Beispiel zur Veranschaulichung der Struktur. Das Standard-Repository arbeitet im Speicher; die Stelle für den Wechsel zu PostgreSQL/pgvector sowie SQL-Beispiele werden mitgeliefert.
Schnellstart
uv syncMCP-Beispiel ausführen:
uv run noteharborPostgreSQL mit Docker starten
docker compose up -d postgresDie docker-compose.yml definiert das pgvector/pgvector-Image und eine PostgreSQL-Entwicklungsdatenbank für Python MCP.
# PostgreSQL만
docker compose up -d postgres
# Python MCP까지
docker compose up --build python-mcpPOSTGRES_URL ist der Platzhalter für die Konfiguration, wenn eine echte DB-Verbindung hergestellt wird. Die aktuelle Standardausführung ist ein Mock.
GraphQL-Beispiel
Das GraphQL-Schema befindet sich in noteharbor/api/graphql_schema.py. Das Ergebnis von get_schema() kann in einen externen ASGI-Server eingebunden werden.
Beispieloperation:
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- und ORM-Stil-Grenzen
Das Repository ist nicht nur für die Suche zuständig, sondern für den gesamten Lebenszyklus von NoteChunk, von der Erstellung bis zur Löschung.
Create/Upsert: MCP
upsert_vector, GraphQLindexChunk→VectorService.index_chunk()Read: MCP
get_chunk·list_chunks, GraphQLnoteChunk·noteChunksUpdate: MCP·GraphQL
updateChunk→ liest den vorhandenen Datensatz und übernimmt nur die geänderten FelderDelete: MCP·GraphQL
deleteChunkSearch: MCP
search_vectors, GraphQLvectorSearch
Der aktuelle Adapter ist ein In-Memory-Mock zur Funktionsprüfung. Die tatsächliche Speicherung erfolgt hinter der SQLAlchemy-ORM-Grenze. Im echten PostgreSQL-Adapter wird MockPostgresVectorRepository durch die folgenden Session-Operationen ersetzt.
Wenn Sie den tatsächlichen ORM-Ablauf im Code sehen möchten, schauen Sie in noteharbor/infrastructure/postgres/sqlalchemy_repository.py. Dieser Adapter implementiert denselben VectorRepository-Port und verwendet Session.get, select, update, delete. Die Standardausführung ist weiterhin ein Mock, sodass Sie das Beispiel ohne PostgreSQL-Verbindung lesen und testen können.
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))Die API behandelt SQL nicht direkt, sondern übergibt CRUD und Suche in der Reihenfolge MCP/GraphQL → VectorService → VectorRepository → SQLAlchemy/pgvector.
Zweck
Dieses Repository ist ein Python-Architekturbeispiel, das eine einzelne Markdown-Quelle sowohl über MCP als auch über GraphQL mit demselben Vektorsuchdienst abfragt.
Der Fokus liegt darauf, austauschbare Punkte klar zu definieren, anstatt einen bestimmten Embedding-Anbieter oder eine bestimmte Vektor-DB festzulegen.
MCP / GraphQL API
→ VectorService
→ VectorRepository port
→ 현재: in-memory MockPostgresVectorRepository
→ 전환: PostgreSQL + pgvectorVerantwortung für Vektorisierung und Suche
Das aktuelle Python-Beispiel erzeugt keine Embeddings selbst. Die Mutation indexChunk und das Werkzeug upsert_vector empfangen extern erzeugte list[float]-Embeddings und speichern sie.
Die Gründe für die Trennung der Embedding-Erstellung sind folgende:
Um das Embedding-Modell nicht auf OpenAI, Voyage oder ein lokales Modell festzulegen
Um API-Schlüssel und persönliche Daten aus dem öffentlichen Beispiel auszuschließen
Um die Verantwortung der API-Schicht und des Suchspeichers zu trennen
Um im echten Dienst die Chunking- und Embedding-Batch-Pipeline durch einen separaten Worker zu ersetzen
Die Suche erfolgt in folgender Reihenfolge:
사용자 query embedding
→ GraphQL vectorSearch 또는 MCP search_vectors
→ VectorService.search()
→ Repository.search()
→ cosine similarity 계산
→ score가 높은 NoteChunk 반환Der MockPostgresVectorRepository in repository.py reproduziert diesen Ablauf im Speicher. Im echten PostgreSQL-Adapter wird die Kosinus-Distanz mit embedding <=> :query_embedding berechnet und 1 - distance als Score zurückgegeben.
Warum PostgreSQL + pgvector?
NoteChunk ist nicht nur ein Wert mit Vektoren, sondern enthält auch den Quellpfad, die Chunk-Reihenfolge, den Text und Metadaten. Mit PostgreSQL und pgvector lassen sich relationale Bedingungen und Vektorähnlichkeitssuche in einem Speicher und innerhalb einer SQL-Grenze behandeln.
PostgreSQL: Verwaltung von Originalmetadaten, Status, Synchronisierungsinformationen und Transaktionen
pgvector:
vector-Spalte, Kosinus-Distanz (<=>), HNSW-IndexDocker: Festlegung der pgvector-Ausführungsbedingungen in der Entwicklungsumgebung
SQLAlchemy-Repository: Austauschpunkt für den Speicher
Wenn der Suchumfang wächst, kann eine dedizierte Vektor-DB besser geeignet sein. Hier wird der Ablauf gezeigt, bei dem Dokumentinformationen und Vektorsuche in einem Speicher behandelt werden.
Quantisierungsumfang
Im aktuellen Python-Repo ist keine Quantisierungsimplementierung enthalten. Die Eingabe-Embeddings werden als Float-Werte direkt für die Suche verwendet; dies ist eine bewusste Entscheidung, um zuerst die modellneutrale Repository-Grenze zu zeigen.
Falls Quantisierung hinzugefügt wird, sollte ein separater EmbeddingQuantizer-Port eingerichtet und die Schritte float32 → INT8/float16 → Speichern/Wiederherstellen zwischen dem Indexierungs-Worker und dem Repository-Adapter platziert werden. Da die Quantisierungsmethode erst nach Messung von Suchqualität, Speicher und Latenz entschieden werden sollte, wird in diesem Beispiel nicht behauptet, dass sie implementiert ist.
Beziehung zwischen den beiden NoteHarbor-Beispielen
noteharbor-mcp: TypeScript-MCP-Werkzeuge und Ablauf für Embedding und INT8-Quantisierung
noteharbor-python: Python-MCP- und GraphQL-API sowie VectorService/Repository-Grenze
Beide Repos sind Beispiele, die dieselbe Idee in verschiedenen Sprachen und API-Ansätzen umsetzen; sie enthalten keine echten persönlichen Vaults oder Betriebsdaten.
Zusätzliche Technologien und Gründe für ihren Einsatz
Technologie | Grund für den Einsatz |
uv | Schnelle Reproduktion von Python-Abhängigkeiten, virtuellen Umgebungen und Lock-Dateien; gleicher Installationspfad auch in Docker |
FastMCP | Kurze und klare Verbindung zwischen Python-Funktionen und MCP-Werkzeugen |
Pydantic | Validierung von Eingabemodellen und Konfiguration an der API-Grenze |
SQLAlchemy | Grenze für den PostgreSQL-Adapter, damit das Repository nicht an eine bestimmte SQL-Ausführungsweise gebunden ist |
psycopg | Zuständig für die PostgreSQL-Verbindung in Python |
pgvector Python package | Darstellung des PostgreSQL-Vektor-Typs in SQLAlchemy-Modellen |
Strawberry GraphQL | Beispiel, um denselben VectorService als GraphQL-Query/Mutation bereitzustellen |
Docker Compose | Gemeinsame Reproduktion der Entwicklungsumgebung mit pgvector-aktiviertem PostgreSQL und Python MCP |
Jede Technologie wurde ausgewählt, um die Rollen von API, Service, Speicher und Entwicklungsumgebung klar zu trennen.
Projektstruktur
.
├── 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.tomlLizenz
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