Skip to main content
Glama

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つ

  1. MCP: upsert_vector, search_vectors ツール

  2. GraphQL: indexChunk Mutation, vectorSearch Query

  3. PostgreSQL/pgvector: SQLAlchemyモデル、Repositoryポート、Docker開発環境

運用サービスではなく、構造を確認するための例です。デフォルトのRepositoryはメモリ上で動作し、PostgreSQL/pgvectorへ移す箇所とSQL例をあわせて提供します。

クイックスタート

uv sync

MCPサンプルを実行:

uv run noteharbor

DockerでPostgreSQLを起動する

docker compose up -d postgres

docker-compose.ymlpgvector/pgvector イメージとPython MCP用の開発用PostgreSQLを定義します。

# PostgreSQL만
docker compose up -d postgres

# Python MCP까지
docker compose up --build python-mcp

POSTGRES_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、GraphQL indexChunkVectorService.index_chunk()

  • Read: MCP get_chunklist_chunks、GraphQL noteChunknoteChunks

  • Update: MCP・GraphQL updateChunk → 既存レコードを読み取ったうえで、変更フィールドのみ反映

  • Delete: MCP・GraphQL deleteChunk

  • Search: MCP search_vectors、GraphQL vectorSearch

現在のアダプターは動作確認用のインメモリモックです。実際の保存方法はSQLAlchemy ORM境界の背後に置きます。実際のPostgreSQLアダプターでは、次のようなセッション操作で MockPostgresVectorRepository を置き換えます。

実際のORMフローをコードで確認したい場合は、noteharbor/infrastructure/postgres/sqlalchemy_repository.py を参照してください。このアダプターは同じ VectorRepository ポートを実装しながら、Session.getselectupdatedelete を使用します。デフォルト実行は依然としてモックなので、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.pyMockPostgresVectorRepository は、このフローをメモリ上で再現します。実際の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

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides tools for ingesting documents into a local vector database and retrieving relevant information via semantic search, enabling retrieval-augmented generation for MCP clients.
    6
  • A
    license
    Not graded
    quality
    B
    maintenance
    Indexes local Markdown/text files into a SQLite database with vector embeddings and provides MCP tools for semantic search without cloud dependencies.
    GPL 3.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides MCP tools for semantic search over personal knowledge sources using pluggable embeddings and local vector indexing.
    1
    MIT

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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