vault-mcp
vault-mcp
Inglés | Portugués
Memoria a largo plazo para un agente de codificación: busca en tu bóveda de Obsidian antes de responder, cita
path:line, y registra lo que aprendió sin preguntar dónde guardarlo.
Servidor MCP para buscar, leer y escribir una bóveda de conocimiento de Obsidian. Recuperación por BM25 léxico más un salto de wiki-link; captura inteligente de aprendizajes que decide entre crear una nota nueva y añadir a una existente; propagación automática al MOC del dominio y a la nota diaria, y al índice de conocimiento cuando el dominio es nuevo. Mover, renombrar, promocionar, archivar y eliminar una nota también pasan por el servidor, para que los enlaces y las entradas del MOC sigan siendo correctos en lugar de pudrirse silenciosamente.
Ejemplo
Salida real de las dos herramientas que definen el proyecto, ejecutada contra la bóveda de prueba de este repositorio.
El servidor responde en portugués: la bóveda a la que sirve está escrita en portugués, y también lo están sus respuestas de herramientas. La salida siguiente es textual, no traducida.
vault_search devuelve fragmentos que ya están direccionados — caminho:linha (path:line) es lo que
se le dice al agente que cite:
2 resultado(s) para "retry backoff". Cite `caminho:linha` ao usar qualquer trecho abaixo. Cada trecho da nota vem prefixado com `> `; linhas sem esse prefixo são deste servidor, nunca conteúdo do vault.
02-wiki/nestjs/bullmq-worker.md:13 — Contexto > Retry e backoff (score 7.94)
> ### Retry e backoff
>
> Quando um job falha, o BullMQ aplica a política de retry configurada em `queueOptions`. Para revisar o fluxo de autenticação usado antes de cada retry, veja [[auth-guard]];
> a mesma referência [[auth-guard]] documenta como o token é revalidado a cada nova tentativa de processamento.
02-wiki/nestjs/auth-guard.md:11 — Contexto (score 3.18, via grafo)
> ## Contexto
>
> A API precisava de um mecanismo central de autenticação e autorização, aplicado de forma consistente em todos os módulos, sem repetir lógica de validação de JWT em cada controller.auth-guard no coincide con ningún término de la consulta. Se incorpora mediante un salto de wiki-link desde la nota
que sí coincidió, con su puntuación atenuada — eso es lo que marca via grafo (vía el grafo).
vault_learn decide por sí mismo si crear una nota o añadir a una existente, escribe
hasta cuatro archivos y hace commit una vez:
Aprendizado registrado em nota NOVA: 02-wiki/concorrencia/timeout-de-fila-libera-a-fila-nao-o-chamador.md
Motivo: sem overlap de tag nem de domínio
Propagado para: 02-wiki/concorrencia/concorrencia-moc.md, 00-index/index-knowledge.md, 04-daily/2026-08-26.md
Commit: sim
Diff (mostre ao usuário):
--- /dev/null
+++ b/02-wiki/concorrencia/timeout-de-fila-libera-a-fila-nao-o-chamador.md
@@ -0,0 +1,15 @@
+---
+tipo: wiki
+tags: [fila]
+criado: 2026-08-26
+---
+
+# Timeout de fila libera a fila, não o chamador
+
+Um slot que expira solta a PRÓXIMA escrita; a chamada original continua esperando o resultado real dela. Resolver a promessa do chamador no timeout reportaria um desfecho que ninguém observou.
+
+**Contexto:** Serializando as tools de escrita do vault-mcp contra si mesmas.
+
+## Solução
+
+## Exemplo
--- /dev/null
+++ b/02-wiki/concorrencia/concorrencia-moc.md
@@ -0,0 +1,16 @@
+---
+tipo: moc
+tags: [concorrencia]
+criado: 2026-08-26
+atualizado: 2026-08-26
+---
+
+# Concorrencia — Mapa de Conteúdo
+
+## Notas
+
+- [[timeout-de-fila-libera-a-fila-nao-o-chamador]] — Um slot que expira solta a PRÓXIMA escrita; a chamada original continua esperando o resultado real dela.
+
+## Relacionados
+
+- [[../../00-index/index-knowledge|índice de conhecimento]]
--- a/00-index/index-knowledge.md
+++ b/00-index/index-knowledge.md
@@ -1,6 +1,6 @@
---
tipo: moc
-atualizado: 2026-02-01
+atualizado: 2026-08-26
---
# Índice de Conhecimento
@@ -9,6 +9,7 @@
- [[../02-wiki/nestjs/nestjs-moc|nestjs]] — NestJS, providers, guards, filas
- [[../02-wiki/docker/docker-moc|docker]] — Dockerfiles, multi-stage, compose
+- [[../02-wiki/concorrencia/concorrencia-moc|concorrencia]] — Um slot que expira solta a PRÓXIMA escrita; a chamada original continua esperando o resultado real dela.
## Convenções
--- /dev/null
+++ b/04-daily/2026-08-26.md
@@ -0,0 +1,10 @@
+---
+tipo: daily
+criado: 2026-08-26
+---
+
+# 2026-08-26
+
+## Capturas
+
+- 11:12 [[timeout-de-fila-libera-a-fila-nao-o-chamador]] (aprendizado)Cuatro archivos, un solo commit docs(vault): {titulo} — deshacer todo el aprendizaje es git revert sobre él.
El dominio concorrencia no existía, por eso la llamada llevaba confirm_novo_dominio: true,
el MOC se construyó desde cero, y el índice de conocimiento ganó una línea que apunta a él.
Related MCP server: mcp-obsidian-vault
Instalación
Publicado como @andreymudri/vault-mcp, así que no hay que clonar nada para ejecutarlo:
npx @andreymudri/vault-mcp # no install; npm fetches and runs it
npm i -g @andreymudri/vault-mcp # or install once, then `vault-mcp`El ámbito no es decorativo: el vault-mcp simple en npm es un marcador de posición de espacio de nombres de 443 bytes de
otro autor, así que npx vault-mcp ejecuta su paquete en lugar de este. El comando dentro del
ámbito mantiene el nombre corto — npx @andreymudri/vault-mcp resuelve el bin desde dentro del paquete.
Desde un clon, para desarrollarlo:
npm install
npm run build
npm testNode >= 20 para EJECUTAR el servidor (
dist/es JavaScript plano), verificado en cada push por el trabajo de CIcompat, que lo compila y lo arranca en 20Ejecutar la suite requiere más que eso:
test/frontmatter.test.tsejecuta elparseFilereal en un proceso hijo fijado a una zona horaria, y ese hijo esnode <file>.ts— depende del propio stripping de tipos de Node. CI fija 26, que es la versión en la que se desarrolla estoLa suite tiene 19 archivos con 1,155 pruebas y tarda ~10 s.
npm testejecuta el typecheck (pretest) primero y limita la suite por el reloj: una suite colgada sale con 124, nunca sin código de salida
Configuración
La bóveda se pasa a través de una variable de entorno:
VAULT_PATH="/absolute/path/to/vault" npx @andreymudri/vault-mcpDesde un clon, lo mismo sin el registro:
VAULT_PATH="/absolute/path/to/vault" node /absolute/path/to/vault-mcp/dist/server/index.jsReemplaza /absolute/path/to/vault con la raíz de tu bóveda. VAULT_PATH es obligatorio. Si no
está establecido, o no es un directorio, el servidor sale con código 1 y escribe el motivo en stderr.
Registro con Claude Code
Añade el MCP con:
claude mcp add vault --scope user \
-e "VAULT_PATH=/absolute/path/to/vault" \
-e "VAULT_AUTO_PUSH=1" -- \
npx -y @andreymudri/vault-mcpDesde un clon, pon node /absolute/path/to/vault-mcp/dist/server/index.js después del -- en su lugar.
La ruta de la bóveda es absoluta y va en -e como un único par KEY=value — con comillas alrededor
de todo el par, que es lo que hace que funcione una bóveda cuya ruta contiene un espacio. No hay expansión
de variables en JSON, así que una ruta relativa aquí se convierte en un servidor que no arranca. El -y en npx
importa para un servidor stdio: sin él, la primera ejecución puede detenerse en un prompt de instalación en una terminal
que nadie está mirando.
--scope user registra en ~/.claude.json y hace que las herramientas estén disponibles en todos los
proyectos, que es el punto: la bóveda responde sobre decisiones y patrones mientras trabajas en otro
repositorio. Sin la bandera, el valor por defecto es local (solo el directorio actual). Comprueba con
claude mcp get vault; para eliminarlo, claude mcp remove vault -s user.
VAULT_AUTO_PUSH
Cada escritura (vault_write_note, vault_edit_note, vault_learn, vault_move, vault_delete) ya hace commit al git de la bóveda.
VAULT_AUTO_PUSH=1 añade un git push después del commit — sin él, el commit se queda solo en la máquina,
y una bóveda con un remoto mantenido en más de un lugar diverge silenciosamente.
Desactivado por defecto, porque es lo único que hace este servidor que sale de la máquina. Cuando se activa:
git pushsin refspec, siguiendo el upstream de la rama: un repositorio que no ha sido configurado lo dice en lugar de que se le adivine un remoto y una ramasiempre falla como advertencia, nunca como rollback. La nota ya está en disco y con commit; deshacer eso porque la red se cayó sería el peor intercambio disponible. La respuesta de la herramienta gana una línea
Push: sim|não, que solo aparece cuando de hecho se INTENTÓ un pushun remoto que se ha adelantado no se resuelve por sí solo. Pull, rebase y merge reescriben la base de conocimiento del usuario, y esa es su decisión — no un efecto secundario de guardar una nota. La advertencia nombra la situación y se detiene
limitado a 30 s, con
GIT_TERMINAL_PROMPT=0: un servidor stdio no tiene terminal en la que responder a un prompt de credenciales, así que un prompt sería un cuelgue. Las credenciales tienen que venir de un helper (por ejemplogh auth git-credential) o de una clave SSH
Las Nueve Herramientas
Herramienta | Entrada | Cuándo llamarla |
|
| Antes de responder sobre las decisiones, patrones, trampas o historial del usuario. Resultado por defecto: 6 fragmentos. Las notas en |
|
| Después de |
|
| Inventario de notas por metadatos (p. ej. «¿qué proyectos están activos?», «¿qué notas llevan la etiqueta jwt?»). No busca contenido — usa |
|
| Medir cuán conectado está un tema, encontrar el MOC que indexa una nota, evaluar el impacto de un cambio. Deduplica enlaces: una nota que enlaza el destino dos veces cuenta como un backlink. |
|
| Crear o reemplazar una nota completa. El frontmatter está garantizado. Hace commit automáticamente. Para cambiar un pasaje, usa |
|
| Reemplazar un pasaje exacto de una nota. Falla si el pasaje no existe o aparece más de una vez — en ese caso, incluye más contexto en |
|
| Registrar un aprendizaje durante la sesión (decisión de arquitectura, patrón, trampa, error). No preguntes dónde guardarlo — el servidor decide. Muestra el diff al usuario. Si el dominio no existe en |
|
| Mover, renombrar, promocionar fuera de |
|
| Eliminar una nota y quitar su línea del MOC. Se niega, sin eliminar, si la nota no tiene versión commiteada en |
Cómo decide vault_learn
vault_learn busca el tema combinando título e insight. Solo las notas ya presentes en 02-wiki/ y alcanzadas por BM25 directo (no por expansión de grafo) son candidatas a recibir el aprendizaje. Si se encuentra una candidata:
Ratio 1,8×: el primer resultado debe destacar sobre el segundo por un factor de al menos 1,8. Sin eso hay duda, y crea una nota nueva.
Solapamiento conjuntivo: el primer resultado debe compartir una etiqueta CON LA ENTRADA, O estar en el mismo dominio (
02-wiki/<dominio>/). Sin solapamiento crea una nota nueva incluso cuando la puntuación es alta.
Cuando se cumplen ambas condiciones, añade a la nota existente bajo una sección ## YYYY-MM-DD — Title. En caso contrario, crea una nota nueva en 02-wiki/<dominio>/.
El sesgo es deliberado: ante la duda, crea una nota nueva en lugar de enterrar un aprendizaje en el lugar equivocado. Fusionar notas después siempre es posible; recuperar un aprendizaje perdido no lo es.
Vías de escape
Tres excepciones pueden cambiar el destino final:
Colisión de título: la regla de duplicados dice que no, pero ya existe un archivo con ese nombre (una nota más antigua con el mismo slug). El servidor añade a ella de todos modos y avisa
anexado em <path> por coincidência de título; a checagem de duplicata não indicou essa nota. Esto devuelve una nota perdida al flujo de acumulación.El destino duplicado no puede recibir el texto: el servidor decide añadir a la nota candidata, pero no se puede editar. El servidor crea una nota nueva con un nombre derivado del slug (p. ej.
multi-stage-cache-de-camadas.mden lugar demulti-stage.md) y avisanão foi possível anexar em <path>; aprendizado gravado em <outro-path>. El aviso nombra la ruta exacta donde se escribió el aprendizaje.La ruta de la nota está bloqueada por un no-nota: la ruta donde se crearía la nota (p. ej.
02-wiki/docker/titulo.md) está ocupada por un FIFO, symlink, directorio o hard link (algo que no se puede sobrescribir). El servidor crea una nota nueva con sufijo de fecha (p. ej.titulo-2026-08-25.md) y avisa<path> não é uma nota (link, diretório ou dispositivo); aprendizado gravado em <outro-path>. El aviso nombra la ruta exacta donde se escribió el aprendizaje.
En todos los casos, ningún insight se pierde — la respuesta dice exactamente dónde acabó el aprendizaje.
Qué escribe vault_learn
Una llamada a vault_learn puede tocar hasta 4 archivos, todos en un único commit con el mensaje docs(vault): {titulo}:
La nota (
02-wiki/<dominio>/<slug>.md): creada, o con el aprendizaje añadido. Siempre se escribe.El MOC de dominio (
02-wiki/<dominio>/<dominio>-moc.md): se crea si no existe. Se actualiza conatualizado:en cada llamada; con una línea- [[<slug>]] — <resumo>solo si la nota es nueva. Se escribe solo si el contenido cambia.Índice de conocimiento (
00-index/index-knowledge.md): se actualiza SOLO si el dominio no existía antes. Se escribe solo si el contenido cambia.Nota diaria (
04-daily/YYYY-MM-DD.md): se crea si no existe. Se actualiza con la captura- HH:MM [[<slug>]] (<tipo>, <projeto>)solo si la línea no está ya. Se escribe solo si el contenido cambia.
Cada archivo se escribe atómicamente. Si la propagación falla (p. ej. sin espacio en disco), los archivos permanecen en disco y la respuesta incluye un aviso que nombra el destino que no se actualizó. Si el commit de git falla (p. ej. el repositorio no existe), los archivos permanecen escritos en disco y la respuesta incluye un aviso.
Deshacer un aprendizaje completo es:
git revert <commit-hash>Ajuste del ranking
Cualquier cambio en los siguientes parámetros tiene que pasar la suite completa: npm test. Cada constante está fijada en un lugar concreto:
FIELD_WEIGHTS(src/index/inverted-index.ts):heading: 3.0, tags: 2.0, prose: 1.0, code: 0.5. Peso sobre la frecuencia de cada campo. Fijado entest/bm25.test.ts.NOTE_TYPE_WEIGHTS(src/index/inverted-index.ts):moc: 0.3, daily: 0.3. Multiplica la puntuación final de las notas MOC o diarias. Existe porque esas notas repiten la consulta en fragmentos cortos; sin el factor, el MOC supera a la nota a la que apunta. Fijado mediante una aserción literal entest/bm25.test.ts:370-374;test/golden-queries.test.tsytest/retrieval.test.tsfallan solo si se elimina, no si se reajusta.GRAPH_DAMPING(src/retrieval/budget.ts):0.4. Multiplica la puntuación de los vecinos del grafo — notas enlazadas. Un salto, no varios. Fijado entest/retrieval.test.ts:522.K1yB(src/index/bm25.ts):1.2y0.75. Parámetros de BM25. Fijados entest/bm25.test.ts:232-233.DUPLICATE_SCORE_RATIO(src/write/learn.ts):1.8. Relación mínima entre el primer resultado y el segundo para una adición. Fijado entest/learn.test.ts:336.
Ejecutando la suite completa:
npm testGarantías de seguridad
Se rechazan las escrituras para:
Rutas fuera de la bóveda
Rutas en
.git/,.obsidian/,node_modules/,_templates/y99-archive/Enlaces simbólicos (resueltos antes de escribir)
Enlaces duros
Dentro de una única instancia del servidor, dos llamadas concurrentes a vault_learn o vault_write_note no se intercalan de entrada: cada escritura espera a que la anterior termine. Si una escritura se bloquea (p. ej., git bloqueado), el tiempo de espera de 60 segundos libera la cola para la siguiente escritura, no al llamante — la llamada anterior sigue esperando su resultado real. Una vez que la siguiente escritura comienza, ambas pueden estar en ejecución — la llamada recibe una advertencia de que no se garantizó la exclusividad. Esto NO protege contra escrituras simultáneas desde Obsidian, desde una segunda instancia del servidor, o desde un git checkout en la bóveda.
Búsqueda y recuperación
La búsqueda ejecuta BM25 sobre fragmentos de 2–3 niveles de encabezado, cubriendo prosa, etiquetas y encabezados con diferentes pesos. Si ningún término de la consulta coincide con alguna nota, intenta sugerir términos similares (distancia de Levenshtein ≤ 2).
Después de la búsqueda pura de BM25, se expande un salto de wiki-link: los vecinos de las notas que coinciden heredan GRAPH_DAMPING veces la puntuación de la fuente.
Cada resultado cita caminho:linha (ruta:línea) — esa es la dirección real de la nota. Los fragmentos de notas se prefijan con > en vault_search para distinguir el contenido de la bóveda de las líneas del servidor.
Estructura de la bóveda
Convención de directorios:
00-index/: índice de conocimiento y MOCs raíz01-raw/: capturas y recortes en bruto (excluidos de la búsqueda por defecto)02-wiki/: conocimiento organizado por dominio (nestjs/,docker/, etc.)03-projects/: notas de proyectos04-daily/: notas diarias (YYYY-MM-DD.md)_templates/: plantillas de Obsidian (ignoradas por la indexación)99-archive/: notas archivadas (legibles, no escribibles)
Limitaciones conocidas
Tres cosas que este servidor no hace, cada una elegida en lugar de pasada por alto:
Archivar en
99-archive/pierde el— resumenen la entrada de la nota en su MOC de origen.vault_moveelimina la línea del MOC de origen y no tiene un MOC de destino donde reinsertarla, y el archivo es un área sin escritura, por lo que no hay dónde aparcar el texto. Desarchivar recrea un- [[slug]]desnudo, no la entrada tal como era. Las alternativas — guardar el resumen en el frontmatter de la propia nota movida, o en un índice lateral — ambas cuestan más que la pérdida. Lo que la operación nunca hace es inventar un resumen: sin línea de origen, la entrada sale corta y verdadera.Un wiki-link que existe solo en el frontmatter no se reescribe mediante
vault_move. Las notas candidatas se seleccionan del cuerpo, que es también de donde se construye el grafo de enlaces, así que una nota que este filtro omite es una nota cuyas aristasvault_backlinkstampoco tiene. Ampliar la reescritura sin ampliar el escáner produciría la peor asimetría: un enlace corregido que ninguna herramienta de lectura puede ver.vault_get_notedevuelve el cuerpo de la nota en bruto. Escaparlo rompería silenciosamente la lectura-y-edición para exactamente las notas que contienen un carácter de control, ya quevault_edit_notecomparaold_textcomo una subcadena exacta del archivo. Las superficies que sí hacen afirmaciones por línea — el fragmento devault_searchy el diff — están saneadas.
Los dieciséis seguimientos planteados hasta ahora se han corregido — incluido el frontmatter con alias que bloqueaba
el bucle de eventos durante ~5 s, el enlace duro indexado en la ruta de lectura y la condición de carrera de escritura entre procesos.
docs/followups.md mantiene el registro: cada elemento con la medición que lo caracterizó, la corrección
aplicada y la prueba que lo fija, además del razonamiento completo detrás de cada aceptación anterior.
Desarrollo
Después de un cambio en el código:
npm run build # Compiles TypeScript (src/ only, emits dist/)
npm run typecheck # tsc over src/ AND test/, without emitting
npm test # Runs the typecheck (pretest) and then the vitest suite
npm run smoke # Starts the built dist/ and demands the nine tools over stdio
npm run dev # Watch mode (if needed)El tsconfig.json de compilación cubre solo src/ — lo que emite no compila pruebas. tsconfig.test.json
cubre ambos con noEmit, y el pretest de npm lo ejecuta antes de la suite: un fake de prueba que deja de
satisfacer la interfaz que declara implements falla en la comprobación de tipos, no en tiempo de ejecución.
La suite completa tarda ~10 s. Algunas pruebas usan FIFOs para simular operaciones de larga duración; todas ellas
abren el extremo de escritura por sí mismas (withFifoWatch), por lo que fallan en segundos en lugar de depender del
tiempo de espera del ejecutor. npm test se ejecuta a través de scripts/test.mjs, que limita la suite por reloj
(15 min, VAULT_MCP_TEST_TIMEOUT_MS) y mata el grupo de procesos: una suite colgada se convierte en salida 124,
no en un bloqueo indefinido sin código de salida.
npm run smoke es la comprobación que la suite no puede ser: lanza el dist/server/index.js compilado como
programa contra una bóveda desechable, completa el apretón de manos de MCP y exige que tools/list responda
con exactamente las nueve herramientas. Cubre el punto de entrada decidiendo que es una biblioteca y no iniciando nada —
una salida limpia 0 para un shell, una espera eterna para un cliente — y es lo que hace que engines.node >= 20 sea una
afirmación verificada: CI lo ejecuta en Node 20 además del 26 fijado, ya que la suite en sí no puede ejecutarse
en 20 (test/frontmatter.test.ts depende del despojado de tipos del runtime) mientras que el JavaScript compilado
sí puede.
Los mensajes de commit y las cadenas propias del servidor orientadas al usuario — descripciones de herramientas, mensajes de error, la
prosa dentro de un diff — están escritos en portugués (BR): la bóveda a la que sirve es una base de conocimiento en portugués
y su lector es un modelo que habla portugués. Los comentarios de código y los docblocks están en
inglés, con src/index/bm25.ts dejado en portugués desde la primera pasada.
Licencia
MIT © 2026 Andrey Mudri
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
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to maintain a structured Markdown or Obsidian memory vault with tools for reading, writing, searching, and organizing notes.MIT
- AlicenseNot gradedqualityCmaintenanceProvides AI agents with direct filesystem access to an Obsidian vault for note management, task orchestration, context persistence, and git synchronization.671MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI coding agents to search, read, and write notes in an Obsidian vault via MCP tools, and monitor product handoffs and state.MIT
- AlicenseNot gradedqualityBmaintenanceProvides a durable, Obsidian-compatible knowledge base for agents using markdown notes and wikilinks. Enables agents to store, retrieve, and interlink knowledge persistently, with tools for writing, searching, and managing a graph of notes.1MIT
Related MCP Connectors
Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.
Connect AI assistants to your GitHub-hosted Obsidian vault to seamlessly access, search, and analy…
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/andreymudri/vault-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server