NoteHarbor MCP
NoteHarbor MCP — TypeScript
Ejemplo en TypeScript que conecta Obsidian Markdown con herramientas MCP y lo extiende con búsqueda PostgreSQL/pgvector.
NoteHarbor separa la interfaz MCP del almacén vectorial. El cliente invoca las herramientas MCP y el servicio utiliza el modelo de dominio y el repositorio para acceder al almacén.
Arquitectura
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/)Las notas se convierten en datos de búsqueda en el siguiente orden.
Obsidian Markdown
→ note chunk
→ externally generated embedding
→ note_chunks.embedding (pgvector)
→ cosine similarity search
→ MCP responseRelated MCP server: second-brain-mcp
Flujo real de vectorización
upsert_vector es la herramienta que guarda un embedding ya creado. El proceso de transformar Markdown en chunks y vectores se puede ver en index_note.
Markdown text
→ splitMarkdownIntoChunks()
→ EmbeddingProvider.embed(chunk)
→ normalized number[]
→ NoteChunk
→ VectorService.indexChunk()
→ VectorRepository.save()El código principal está dividido en los siguientes archivos.
chunker.ts: divide el Markdown por párrafos y aplica la longitud máxima
embeddingProvider.ts: proveedor de embedding determinista que funciona sin clave de API
indexingPipeline.ts: conecta la generación de chunks, embeddings y el guardado
knowledge.ts: puertos
EmbeddingProvideryVectorRepositoryindex.ts: registro de las herramientas MCP
index_note,upsert_vector,search_vectors
El proveedor de demostración es una implementación determinista para verificar el flujo. No ofrece calidad de búsqueda semántica; en un servicio real se conecta un modelo externo o local al mismo puerto EmbeddingProvider.
La cuantización se aplica después de generar el embedding.
float embedding [-1, 1]
→ clamp
→ int8 = round(value / (1 / 127))
→ 저장: values + scale + zeroPoint
→ 복원: (int8 - zeroPoint) * scaleLa muestra utiliza cuantización escalar simétrica INT8.
Valores:
[-1, 1]Rango de cuantización:
[-127, 127]scale:1 / 127zeroPoint:0El esquema guarda
embedding_int8,embedding_scale,embedding_zero_pointjunto con el embedding originalLa búsqueda de referencia actual usa el vector float restaurado; el índice ANN cuantizado se añade al elegir el adaptador real
La implementación está en quantizer.ts y indexingPipeline.ts. La respuesta de index_note también incluye la dimensión del embedding y el número de bits de cuantización.
Por qué está estructurado así
NoteHarbor es un ejemplo que convierte Obsidian Markdown en unidades de conocimiento buscables y expone esa funcionalidad como herramientas MCP.
Con la búsqueda de cadenas simple es difícil encontrar contenido relacionado expresado de otra forma. Por eso las notas se dividen en chunks pequeños y cada chunk se transforma en un embedding para poder buscar por cercanía semántica.
La cuantización sirve para guardar ese embedding en una representación más compacta.
Reduce el uso de memoria y almacenamiento
Reduce el volumen de transferencia de vectores
Favorece la caché y el procesamiento por lotes en bases de conocimiento grandes
A cambio, la precisión puede ser ligeramente menor que con float original
Por eso el rol de cada componente es el siguiente.
Embedding: representa el significado del texto como un vector numérico
Quantization: reduce la precisión del vector para disminuir el costo de almacenamiento
Vector search: encuentra los chunks cercanos comparando vectores
MCP: expone esta funcionalidad como una herramienta que los clientes LLM pueden invocar
En este proyecto se eligió INT8 porque es fácil de explicar el principio de cuantización y la implementación de demostración. En un servicio real se debe medir calidad de búsqueda, ahorro de memoria, latencia y elegir entre float32, float16, INT8 o binary.
La implementación actual es un simulacro para verificar el flujo. No garantiza calidad de búsqueda semántica ni rendimiento de cuantización; en producción se debe conectar un proveedor de embeddings real y un adaptador pgvector.
Diseño de la base de datos vectorial
La unidad de almacenamiento vectorial es NoteChunk.
Campo | Significado |
| Identificador formado por la ruta original y el número de chunk |
| Ruta original del Markdown de Obsidian |
| Número de chunk dentro del documento |
| Texto que se devuelve como resultado de búsqueda |
| Vector generado por el modelo de embeddings |
| Extensión con etiquetas, estado, atributos del origen |
El ejemplo de SQL ejecutable está en src/infrastructure/postgres/schema.sql. El ejemplo básico usa un embedding de 1536 dimensiones y un índice HNSW para distancia coseno; se ajusta según la dimensión del modelo real.
La búsqueda se transforma en la siguiente forma en 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;Límite entre CRUD y estilo ORM
El almacén vectorial no es solo para búsqueda; es un repositorio que gestiona el ciclo de vida completo de NoteChunk.
Create/Upsert:
upsert_vector,index_note→VectorService.indexChunk()Read:
get_chunk,list_chunksUpdate:
update_chunk→ lee el chunk existente y actualiza el campo modificado y la representación cuantizadaDelete:
delete_chunkSearch:
search_vectors,search_knowledge
El adaptador de ejecución actual es un Map en memoria. En un entorno de producción se reemplaza la implementación interna del repositorio por Drizzle ORM y 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))Las herramientas MCP no ejecutan SQL directamente; delegan en MCP → VectorService → VectorRepository → Drizzle/pgvector para las operaciones CRUD y búsqueda.
Ejemplos incluidos
Listado, lectura y búsqueda de Markdown de Obsidian
Herramientas MCP
index_note,search_knowledge,upsert_vector,search_vectorsCapas
MCP → Service → Repository → pgvectorEsquema
note_chunksbasado en Drizzle ORMEsquema PostgreSQL/pgvector y SQL de búsqueda
Límite de sincronización con Notion
Servidor de desarrollo Smithery y ejemplo de ejecución con Docker
La ejecución básica actual es un simulacro en memoria que no incluye datos personales ni credenciales externas. En la conexión PostgreSQL, la implementación Map de src/infrastructure/postgres/postgresVectorRepository.ts se reemplaza por un adaptador basado en Drizzle/pg. El README y el esquema son una muestra pública del punto de transición.
La versión Python/GraphQL está disponible en noteharbor-python.
Comenzar
npm install
npm run devDocker:
docker build -f Dockerfile.typescript -t noteharbor-mcp-ts .
docker run --rm -p 8081:8081 noteharbor-mcp-tsPor qué PostgreSQL + pgvector
El objetivo de búsqueda de NoteHarbor no son solo datos vectoriales. También hay que gestionar metadatos relacionales como la ruta original, el número de chunk, las etiquetas, el estado y la información de sincronización.
Por eso, en lugar de añadir una base de datos vectorial separada, este ejemplo mantiene todo junto en PostgreSQL.
content: fragmento de texto original que se muestra como resultado de búsquedametadata: etiquetas, estado e información del origenembedding: vector float para búsqueda por cosenoembedding_int8: representación cuantizada para reducir costo de almacenamiento y transferencia
Las razones concretas para elegir pgvector son las siguientes.
Combinación de datos: se puede combinar similitud vectorial con
source_path, etiquetas y condiciones de estado en una sola SQLConsistencia: los metadatos del texto original y el índice de búsqueda se gestionan dentro del mismo límite de transacción
Simplicidad operativa: la aplicación no necesita operar PostgreSQL y una base vectorial separada por separado
Funcionalidad de búsqueda: se puede usar distancia coseno (
<=>) e índice HNSW como extensión de PostgreSQLCamino de escalado: se comienza con un solo almacén y, cuando crece la escala, se puede separar un adaptador exclusivo de búsqueda
Cuando la escala de búsqueda crece, una base vectorial dedicada puede ser más adecuada. Aquí el valor está en mostrar el flujo que maneja texto original, metadatos y búsqueda vectorial dentro de un mismo límite de aplicación.
Cómo funciona la búsqueda
La búsqueda no compara directamente las cadenas del texto original; coloca la pregunta y los chunks de las notas en el mismo espacio de embeddings y compara distancias.
사용자 질문
→ query embedding 생성
→ INT8 양자화 후 복원
→ PostgreSQL/pgvector cosine distance 검색
→ 가까운 NoteChunk 반환
→ sourcePath·content·metadata와 함께 MCP 응답La muestra ejecutable es la herramienta MCP search_knowledge.
index_notedivide el Markdown en chunks y guarda el embedding de cada chunk.El usuario envía una
queryen lenguaje natural.Se genera el embedding de la consulta con el mismo
EmbeddingProvider.La consulta se cuantiza y restaura de la misma forma que los vectores guardados.
VectorRepository.search()ordena los chunks cercanos según similitud coseno.El resultado incluye la ruta original, el contenido del chunk, los metadatos y la puntuación.
search_vectors es una herramienta de bajo nivel que recibe directamente un embedding ya creado; search_knowledge es una herramienta de nivel de aplicación que conecta desde la pregunta en lenguaje natural hasta el resultado de búsqueda.
El repositorio simulado actual calcula la similitud coseno en un Map en memoria. Al migrar al adaptador PostgreSQL, se usará la operación <=> de pgvector y la búsqueda con LIMIT detrás del mismo puerto.
Tecnologías adicionales y motivo de su uso
Tecnología | Motivo de su uso |
Node.js ESM | Ejecutar el ejemplo TypeScript MCP de forma sencilla con el runtime Node actual |
MCP SDK | Registrar las herramientas |
Zod | Validar en runtime las entradas MCP y los valores de configuración |
Drizzle ORM | Proporcionar un límite de esquema y consultas con seguridad de tipos al conectar el adaptador PostgreSQL |
pg | Driver que se usará al migrar al adaptador de conexión PostgreSQL real |
Smithery CLI | Proporcionar una ruta de ejecución para desarrollar y verificar el servidor MCP |
Docker | Fijar las condiciones de ejecución de Node/MCP en entornos locales y de despliegue |
chokidar·fast-glob | Detección de cambios en el vault de Markdown y exploración de archivos |
gray-matter·marked | Tratar el frontmatter y el cuerpo del Markdown como chunks de conocimiento |
dotenv | Separar la configuración local del entorno del código |
No todas las dependencias son el núcleo de la búsqueda vectorial. Algunas son tecnologías auxiliares para la integración con Obsidian y Notion; el centro de la ruta de búsqueda es MCP SDK → Vector Service → Repository → pgvector.
Razones para elegir cada tecnología
Tecnología | Razón de la elección |
Obsidian Markdown | El original es un archivo de texto plano, por lo que la propiedad y la portabilidad son altas; se evita depender de un SaaS concreto para el conocimiento original |
MCP | No crear código de integración separado para cada cliente LLM; exponer la misma herramienta de conocimiento con una interfaz estándar |
TypeScript | La conexión con el MCP SDK es natural y los límites de entrada y salida de las herramientas se gestionan con tipos |
PostgreSQL | Gestionar metadatos de documentos, estado y resultados de búsqueda de forma coherente en un solo almacén y asegurar una ruta de migración a producción |
pgvector | Sin añadir una base vectorial separada, manejar metadatos del texto original y búsqueda vectorial juntos dentro de PostgreSQL |
Adaptador Notion | Más que usar Notion como almacén original, mostrar el límite para sincronizar fragmentos de conocimiento con un workspace externo cuando sea necesario |
Docker | Mantener uniformes las condiciones de ejecución de PostgreSQL y MCP entre el entorno local y el de despliegue |
El núcleo no es añadir muchas herramientas. Preservar el original como Markdown, poner los datos derivados de búsqueda en PostgreSQL/pgvector y ofrecer al LLM solo las funciones necesarias a través de MCP.
Por lo tanto, este proyecto no es un sistema que use Obsidian, Notion y PostgreSQL todos como fuentes originales.
Obsidian Markdown: conocimiento original
PostgreSQL/pgvector: índice derivado para búsqueda
Notion: destino opcional de sincronización externa
MCP: límite de acceso del LLM
Puntos de diseño
Preservación del Markdown original
Separación entre herramientas MCP y capa de servicios
Modelo de dominio
NoteChunky puertoVectorRepositoryLímite de almacenamiento reemplazable por PostgreSQL/pgvector
Exclusión del vault personal real y las credenciales
Este proyecto es un ejemplo público para verificar la estructura de MCP y la búsqueda de conocimiento.
Licencia
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