NoteHarbor MCP
NoteHarbor MCP — TypeScript
Obsidian MarkdownをMCPツールとして接続し、PostgreSQL/pgvector検索で拡張するTypeScriptの例です。
NoteHarborはMCPインターフェースとベクターストレージを分離します。クライアントはMCPツールを呼び出し、サービスがドメインモデルとRepositoryを通じてストレージを使用します。
アーキテクチャ
MCP Client
│
▼
MCP Tools
(upsert_vector / search_vectors)
│
▼
Vector Service
(src/application/vectorService.ts)
│
▼
VectorRepository port
(src/domain/knowledge.ts)
│
├── 현재 실행 어댑터: in-memory Map 목업
│
└── 운영 전환 지점: PostgreSQL + pgvector
(src/infrastructure/postgres/)ノートは次の順序で検索データになります。
Obsidian Markdown
→ note chunk
→ externally generated embedding
→ note_chunks.embedding (pgvector)
→ cosine similarity search
→ MCP responseRelated MCP server: second-brain-mcp
実際のベクトル化フロー
upsert_vectorは、すでに作成したembeddingを保存するツールです。Markdownがチャンクとベクトルに変わる過程はindex_noteで確認できます。
Markdown text
→ splitMarkdownIntoChunks()
→ EmbeddingProvider.embed(chunk)
→ normalized number[]
→ NoteChunk
→ VectorService.indexChunk()
→ VectorRepository.save()主要なコードは次のファイルに分かれています。
chunker.ts: Markdownを段落単位で分割し、最大長を適用
embeddingProvider.ts: APIキーなしで動作する決定的なデモEmbeddingプロバイダー
indexingPipeline.ts: チャンク生成・Embedding・保存を接続
knowledge.ts:
EmbeddingProviderとVectorRepositoryのポートindex.ts:
index_note、upsert_vector、search_vectorsMCPツールを登録
デモプロバイダーはフローを確認するための決定的な実装です。意味ベースの検索品質を提供するモデルではなく、実際のサービスでは同じEmbeddingProviderポートに外部またはローカルモデルを接続します。
量子化はEmbedding生成後に適用します。
float embedding [-1, 1]
→ clamp
→ int8 = round(value / (1 / 127))
→ 저장: values + scale + zeroPoint
→ 복원: (int8 - zeroPoint) * scaleサンプルは対称型スカラーINT8量子化を使用します。
値の範囲:
[-1, 1]量子化範囲:
[-127, 127]scale:1 / 127zeroPoint:0元のEmbeddingとともに
embedding_int8、embedding_scale、embedding_zero_pointを保存するようにスキーマを定義現在の参照検索は復元可能なfloatベクターを使用し、量子化ANNインデックスは実際のアダプター選択時に追加
実装はquantizer.tsとindexingPipeline.tsにあります。index_note応答にもEmbedding次元と量子化ビット数が含まれます。
なぜこのように構成したのか
NoteHarborはObsidian Markdownを検索可能な知識単位に変換し、その機能をMCPツールとして提供する例です。
単純な文字列検索だけでは、表現が異なる関連内容を見つけるのは困難です。そこでノートを小さなチャンクに分割し、各チャンクをEmbeddingに変換して意味が近い内容を検索できるようにします。
量子化はこのEmbeddingをより小さな表現で保持するための選択です。
メモリとストレージ容量を削減
ベクター転送量を削減
大規模ナレッジベースでキャッシュとバッチ処理に有利
代わりに元のfloatより精度が低くなる可能性がある
そこで、各構成要素の役割を次のように分けました。
Embedding: テキストの意味を数値ベクターで表現
Quantization: ベクターの精度を下げて保存コストを削減
Vector search: 近いベクターを見つけて関連チャンクを返す
MCP: この機能をLLMクライアントが呼び出せるツールとして公開
このプロジェクトでINT8を選択した理由は、量子化の原理と保存形式をコードで説明しやすいからです。実際のサービスでは、検索品質・メモリ削減・レイテンシーを測定した後、float32・float16・INT8・binaryのいずれかを選択する必要があります。
現在の実装はフローを確認するためのモックアップです。意味ベースの検索品質や量子化パフォーマンスを保証するものではなく、実際の運用ではEmbeddingプロバイダーとpgvectorアダプターを接続する必要があります。
ベクターDB設計
ベクター保存単位はNoteChunkです。
フィールド | 意味 |
| 元のパスとチャンク順序で作成した識別子 |
| Obsidian Markdownの元のパス |
| ドキュメント内のチャンク順序 |
| 検索結果として返すテキスト |
| 外部Embeddingモデルが生成したベクター |
| タグ・ステータス・元の属性などの拡張情報 |
実行可能なSQL設計の例はsrc/infrastructure/postgres/schema.sqlにあります。基本的な例は1,536次元のEmbeddingとコサイン距離用のHNSWインデックスを使用し、実際のEmbeddingモデルの次元に合わせて調整します。
検索はPostgreSQLで次の形式に変換されます。
SELECT id, source_path, chunk_index, content, metadata,
1 - (embedding <=> $1::vector) AS score
FROM note_chunks
ORDER BY embedding <=> $1::vector
LIMIT $2;CRUDとORMスタイルの境界
ベクターストレージは検索専用ではなく、NoteChunkのライフサイクルを管理するRepositoryです。
Create/Upsert:
upsert_vector、index_note→VectorService.indexChunk()Read:
get_chunk、list_chunksUpdate:
update_chunk→ 既存のチャンクを読み取り、変更フィールドと量子化表現を一緒に更新Delete:
delete_chunkSearch:
search_vectors、search_knowledge
現在の実行アダプターはMapです。運用環境ではRepository内部の実装をDrizzle ORMとpgに置き換えます。
db.insert(noteChunks).values(row).onConflictDoUpdate(...)
db.select().from(noteChunks).where(eq(noteChunks.id, id)).limit(1)
db.update(noteChunks).set(values).where(eq(noteChunks.id, id))
db.delete(noteChunks).where(eq(noteChunks.id, id))MCPツールはSQLを直接実行せず、MCP → VectorService → VectorRepository → Drizzle/pgvectorの順序でCRUDと検索を渡します。
含まれるサンプル
Obsidian Markdownの一覧・読み取り・検索
index_note、search_knowledge、upsert_vector、search_vectorsMCPツールMCP → Service → Repository → pgvector階層Drizzle ORMベースの
note_chunksスキーママッピングPostgreSQL/pgvectorスキーマと検索SQL
Notion同期境界
Smithery開発サーバーとDocker実行例
現在のデフォルト実行は、個人データと外部資格情報を含まないメモリモックアップです。PostgreSQL接続では、src/infrastructure/postgres/postgresVectorRepository.tsのMap実装をDrizzle/pgベースのアダプターに置き換えます。READMEとスキーマは、その移行ポイントを公開するためのサンプルです。
Python/GraphQLバージョンはnoteharbor-pythonで確認できます。
開始
npm install
npm run devDocker:
docker build -f Dockerfile.typescript -t noteharbor-mcp-ts .
docker run --rm -p 8081:8081 noteharbor-mcp-tsなぜPostgreSQL + pgvectorなのか
NoteHarborの検索対象はベクターだけのデータではありません。元のパス、チャンク順序、タグ、状態、同期情報などのリレーショナルメタデータを一緒に扱う必要があります。
そこで、このサンプルでは別のベクターDBを追加するのではなく、PostgreSQLに次のものをまとめて配置します。
content: 検索結果として表示する原文の断片metadata: タグ・状態・元の情報embedding: コサイン検索用のfloatベクターembedding_int8: 保存・転送コストを削減するための量子化表現
pgvectorを選択した具体的な理由は次のとおりです。
データ結合: ベクター類似度と
source_path、タグ、状態条件を1つのSQLで組み合わせられる一貫性: 原文メタデータと検索インデックスを同じトランザクション境界で管理できる
運用の単純さ: アプリケーションがPostgreSQLと別のベクターDBをそれぞれ運用する必要がない
検索機能: コサイン距離(
<=>)とHNSWインデックスをPostgreSQL拡張として使用できる拡張パス: 初期は単一ストレージで開始し、規模が大きくなったときに検索専用アダプターを分離できる
検索規模が大きくなると、専用のベクターDBがより適している場合があります。ここでは、元のテキスト、メタデータ、ベクター検索を1つのアプリケーション境界で扱うフローを示すことに意味があります。
検索はどのように動作するか
検索は元の文字列を直接比較するのではなく、質問とノートチャンクを同じEmbedding空間に置き、距離を比較します。
사용자 질문
→ query embedding 생성
→ INT8 양자화 후 복원
→ PostgreSQL/pgvector cosine distance 검색
→ 가까운 NoteChunk 반환
→ sourcePath·content·metadata와 함께 MCP 응답実行可能なサンプルはsearch_knowledge MCPツールです。
index_noteがMarkdownをチャンクに分割し、各チャンクのEmbeddingを保存します。ユーザーが自然言語
queryを送信します。同じ
EmbeddingProviderでクエリEmbeddingを生成します。クエリを保存ベクターと同じ方法で量子化・復元します。
VectorRepository.search()がコサイン類似度基準で近いチャンクをソートします。検索結果には元のパス、チャンク内容、メタデータ、スコアが含まれます。
search_vectorsはすでに作成されたEmbeddingを直接受け取る低レベルツールで、search_knowledgeは自然言語の質問から検索結果までを接続するアプリケーションレベルのツールです。
現在のモックRepositoryはメモリMapでコサイン類似度を計算します。PostgreSQLアダプターに切り替えると、同じポートの背後でpgvectorの<=>演算とLIMIT検索を使用します。
追加技術と投入理由
技術 | 投入理由 |
Node.js ESM | TypeScript MCPサンプルを現在のNodeランタイム方式で単純に実行するため |
MCP SDK |
|
Zod | MCP入力値と設定値をランタイムで検証するため |
Drizzle ORM | PostgreSQLアダプターを接続するときに型安全なスキーマ・クエリ境界を提供するため |
pg | 実際のPostgreSQL接続アダプターに切り替えるときに使用するドライバー |
Smithery CLI | MCPサーバーを開発・検証する実行パスを提供するため |
Docker | ローカルとデプロイ環境のNode/MCP実行条件を固定するため |
chokidar・fast-glob | Markdown vaultの変更検知とファイル探索を担当するため |
gray-matter・marked | Markdown frontmatterと本文を知識チャンクとして扱うため |
dotenv | ローカル環境設定をコードと分離するため |
すべての依存関係がベクター検索の核心ではありません。一部はObsidian・Notion連携のための補助技術であり、検索パスの中心はMCP SDK → Vector Service → Repository → pgvectorです。
技術を選択した理由
技術 | 選択理由 |
Obsidian Markdown | 元のファイルがプレーンテキストファイルであるため、所有権と可搬性が高く、特定のSaaSに知識の元を依存させないため選択 |
MCP | LLMクライアントごとに別の連携コードを作成せず、同じ知識ツールを標準インターフェースとして公開するため選択 |
TypeScript | MCP SDKとの接続が自然で、ツールの入力・出力境界を型で管理するため選択 |
PostgreSQL | ドキュメントメタデータ・状態・検索結果を1つのストレージで一貫して管理し、運用移行パスを確保するため選択 |
pgvector | 別のベクターDBを追加せず、PostgreSQL内で元のメタデータとベクター検索を一緒に扱うため選択 |
Notion adapter | Notionを元のストレージとして使うのではなく、必要な場合に知識の断片を外部ワークスペースに同期する境界を示すため選択 |
Docker | ローカル環境とデプロイ環境でPostgreSQL・MCP実行条件を一定にするため選択 |
核心はツールを多く追加することではありません。元のファイルはMarkdownで保存し、検索用の派生データはPostgreSQL/pgvectorに置き、LLMにはMCPで必要な機能だけを提供することです。
したがって、このプロジェクトはObsidian・Notion・PostgreSQLをすべて元のストレージとして使用するシステムではありません。
Obsidian Markdown: 元の知識
PostgreSQL/pgvector: 検索用の派生インデックス
Notion: オプションの外部同期先
MCP: LLMアクセス境界
設計ポイント
元のMarkdownの保存
MCPツールとサービスレイヤーの分離
NoteChunkドメインモデルとVectorRepositoryポートPostgreSQL/pgvectorに置き換え可能なストレージ境界
実際の個人vaultと資格情報を除外
このプロジェクトはMCPと知識検索構造を確認するための公開例です。
ライセンス
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 semantic search capability over Obsidian vaults and exposes recent notes as resources to Claude through the MCP protocol.9
- AlicenseNot gradedqualityCmaintenanceTurns an Obsidian vault into semantic memory for coding agents, providing read-only semantic search and a human-approved write workflow via MCP.5MIT
- AlicenseNot gradedqualityAmaintenanceConnects AI assistants to an Obsidian vault as a semantic knowledge graph, enabling graph navigation, semantic search, and content operations through MCP.12456MIT
- AlicenseNot gradedqualityCmaintenanceExposes an Obsidian notes vault as MCP services, enabling AI assistants to search, read, create, update, and delete notes and folders.241MIT
Related MCP Connectors
Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.
Token-efficient MCP memory for Markdown vaults. Tiered search, GraphRAG, AI memories.
Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.
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-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server