Skip to main content
Glama

NoteHarbor MCP

一个 Python 示例,用于通过 MCP 和 GraphQL 查询 Obsidian 笔记,并使用 PostgreSQL/pgvector 进行扩展。不包含个人 vault、真实文档和 API 密钥。

NoteHarbor 的原始形态是 Markdown 文件。仅为搜索所需的数据单独创建内容,原始文件则原样保留。

本项目的准则

  • 本地优先(Local first):原始 Markdown 保留在本地,外部服务仅作为可连接的选项。

  • 保留源文件(Source preserving):搜索、嵌入、同步的结果不会取代原始内容。

  • 边界隐私(Privacy by boundary):实际 vault、个人记录和 API 密钥均保留在公开项目之外。

  • 模型中立(Model neutral):不将 embedding 生成器和 Vector DB 绑定到特定厂商。

  • 小而可替换(Small and replaceable):保持适配器和服务层足够小。

Related MCP server: Notes RAG MCP Server

三个公开示例

  1. MCPupsert_vectorsearch_vectors 工具

  2. GraphQLindexChunk 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.yml 定义了 pgvector/pgvector 镜像和用于 Python MCP 的开发用 PostgreSQL。

# PostgreSQL만
docker compose up -d postgres

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

POSTGRES_URL 是接入真实数据库连接时使用的配置占位。当前默认执行为 mock。

GraphQL 示例

GraphQL schema 位于 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、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。默认执行为基于 mock,因此无需连接 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 和检索。

目的

本仓库是一个 Python 架构示例,展示同一个 Markdown 源文件如何通过 MCP 和 GraphQL 两侧由同一个向量检索服务进行查询。

与其预先固定某个特定 embedding 厂商或某个特定向量数据库,更注重于明确标注出可替换的切入点。

MCP / GraphQL API
  → VectorService
  → VectorRepository port
  → 현재: in-memory MockPostgresVectorRepository
  → 전환: PostgreSQL + pgvector

向量化与检索的职责

当前 Python 示例不会直接生成 embedding。由 indexChunk mutation 和 upsert_vector 工具接收外部生成的 list[float] embedding 保存。

将 embedding 生成分开的原因如下:

  • 为了不将 embedding 模型固定为 OpenAI、Voyage 或本地模型之一

  • 为了排除 API 密钥和个人数据不进入公开示例

  • 为了分离 API 层与检索存储的职责

  • 为了在实际服务中把 chunking·embedding 批处理流水线替换为独立 worker

检索按以下顺序进行:

사용자 query embedding
  → GraphQL vectorSearch 또는 MCP search_vectors
  → VectorService.search()
  → Repository.search()
  → cosine similarity 계산
  → score가 높은 NoteChunk 반환

目前 repository.py 中的 MockPostgresVectorRepository 在内存中再现此流程。真实 PostgreSQL 适配器使用 embedding <=> :query_embedding 计算余弦距离,并以 1 - distance 作为 score 返回。

为什么选择 PostgreSQL + pgvector

NoteChunk 不只是包含向量的值,还同时具有原始路径、chunk 序号、正文和元数据。将 PostgreSQL 与 pgvector 结合,可以在同一个存储库与 SQL 边界内处理关系型条件和向量相似度检索。

  • PostgreSQL:原始元数据、状态、同步信息和事务管理

  • pgvector:vector 列、余弦距离(<=>)、HNSW 索引

  • Docker:在开发环境中固定 pgvector 的运行条件

  • SQLAlchemy Repository:替换存储的切入点

检索规模扩大时,专用向量数据库可能更合适。这里展示的是在同一个存储中处理文档信息与向量检索的流程。

量化的范围

当前的 Python 仓库中尚未加入量化实现。输入 embedding 以 float 值原样接收并检索,这是为了优先展示模型中性的 Repository 边界。

如需加入量化,会单独设置 EmbeddingQuantizer 端口,并由 float32 → INT8/float16 → 存储与恢复 放置于 indexing worker 与 Repository adapter 之间。由于量化方式必须在搜索质量、内存和延迟时间测量后再确定,因此本示例并不夸张地声称已经实现。

两个 NoteHarbor 示例的关系

  • noteharbor-mcp :TypeScript MCP 工具和 embedding、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

用于在 Python 中处理 PostgreSQL 连接

pgvector Python package

用于以 SQLAlchemy 模型表示 PostgreSQL 的 vector 类型

Strawberry GraphQL

提供将同一个 VectorService 暴露为 GraphQL Query/Mutation 的示例

**postgreSQL **

用于复现已启用 pgvector 的 PostgreSQL 与 Python 开发环境

每种技术都按 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