NoteHarbor MCP
NoteHarbor MCP
ObsidianノートをMCPとGraphQLで検索し、PostgreSQL/pgvectorで拡張するPythonの例です。個人の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
公開サンプル3つ
MCP:
upsert_vector,search_vectorsツールGraphQL:
indexChunkMutation,vectorSearchQueryPostgreSQL/pgvector: SQLAlchemyモデル、Repositoryポート、Docker開発環境
運用サービスではなく、構造を確認するための例です。デフォルトのRepositoryはメモリ上で動作し、PostgreSQL/pgvectorへ移す箇所とSQL例をあわせて提供します。
クイックスタート
uv syncMCPサンプルを実行:
uv run noteharborDockerでPostgreSQLを起動する
docker compose up -d postgresdocker-compose.yml は pgvector/pgvector イメージとPython MCP用の開発用PostgreSQLを定義します。
# PostgreSQL만
docker compose up -d postgres
# Python MCP까지
docker compose up --build python-mcpPOSTGRES_URL は実際のDB接続を設定するときに使う設定場所です。現在のデフォルト実行はモックです。
GraphQLサンプル
GraphQLスキーマは noteharbor/api/graphql_schema.py にあります。外部ASGIサーバーに get_schema() の結果をマウントできます。
処理例:
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
現在のアダプターは動作確認用のインメモリモックです。実際の保存方法は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を直接扱わず、MCP/GraphQL → VectorService → VectorRepository → SQLAlchemy/pgvector の順でCRUDと検索を引き渡します。
目的
このリポジトリは、1つのMarkdown原本をMCPとGraphQLの両方から、同じベクトル検索サービスで参照するPythonアーキテクチャのサンプルです。
特定のembeddingベンダーやベクトルDBを決めるよりも、置き換えられる箇所を明確にする点を重視しています。
MCP / GraphQL API
→ VectorService
→ VectorRepository port
→ 현재: in-memory MockPostgresVectorRepository
→ 전환: PostgreSQL + pgvectorベクトル化と検索の責任
現在のPythonサンプルは、embeddingを直接生成しません。indexChunk mutation と index で、外部から生成された list[float] embedding を受け取って保存します。
embedding生成を分離した理由は次のとおりです。
embeddingモデルをOpenAI・Voyage・ローカルモデルのうち1つに固定しないため
APIキーと個人データを公開サンプルから除外するため
API層と検索ストレージの責任を分離するため
実サービスでは、chunking・embeddingのバッチパイプラインを別のワーカーに置き換えるため
検索は次の順序です。
사용자 query embedding
→ GraphQL vectorSearch 또는 MCP search_vectors
→ VectorService.search()
→ Repository.search()
→ cosine similarity 계산
→ score가 높은 NoteChunk 반환現在の repository.py の MockPostgresVectorRepository は、このフローをメモリ上で再現します。実際のPostgreSQLアダプターでは、embedding <=> :query_embedding でコサイン距離を計算し、1 - distance をスコアとして返します。
なぜPostgreSQL + pgvectorなのか
NoteChunkはベクトルだけを持つ値ではなく、元のパス・チャンク番号・本文・メタデータも一緒に持ちます。PostgreSQLとpgvectorを組み合わせることで、関係条件とベクトル類似度検索を1つのストレージとSQL境界内で扱えます。
PostgreSQL: 原文メタデータ、状態、同期情報、トランザクション管理
pgvector:
vectorカラム、コサイン距離(<=>)、HNSWインデックスDocker: 開発環境でpgvectorの実行条件を固定
SQLAlchemy Repository: ストレージの置き換え箇所
検索規模が大きくなると、専用ベクトルDBの方が適している場合があります。ここでは、ドキュメント情報とベクトル検索を1つのストレージで扱うフローを示します。
量子化の範囲
現在のPythonリポジトリには、量子化の実装を実装していません。入力embeddingはfloat値のまま保存・検索します。これはモデルに依存しないRepository境界を先に示すための選択です。
量子化を追加する場合には、EmbeddingQuantizer ポートを別途設けて、float32 → INT8/float16 → save & restore の段階を indexing worker と Repository adapter の間に配置します。量子化方法は検索品質・メモリ・遅延時間を測定してから決める必要があるため、このサンプルでは実装済みとは説明しません。
2つのNoteHarborサンプルの関係
noteharbor-mcp: TypeScript MCPツールとembedding・INT8量子化フロー
noteharbor-python: Python MCP・GraphQL APIとVectorService/Repository境界
2つのリポジトリは、同じ考えを異なる言語とAPI方法で表現した例であり、実際の個人vaultや本番データは含みません。
追加技術と採用理由
技術 | 採用理由 |
uv | Pythonの依存関係・仮想環境・lockファイルをすばやく再現し、Dockerでも同じ導入経路を利用するため |
FastMCP | Python関数とMCPツールの接続を短く明確に示すため |
Pydantic | API境界の入力モデルと設定を検証するため |
SQLAlchemy | Repositoryが特定のSQL実行方法に固定されないよう、PostgreSQL adapter境界を置くため |
psycopg | PythonからPostgreSQLへの接続を担当するため |
pgvector Python package | SQLAlchemyモデルでPostgreSQLの vector 型を表現するため |
Strawberry GraphQL | 同じVectorServiceをGraphQL Query/Mutationとして公開する例を示すため |
Docker Compose | pgvectorが有効化されたPostgreSQLと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