Team Vault MCP
by kremdigital
README.md
# Team Vault MCP
[MCP](https://modelcontextprotocol.io)-сервер, который отдаёт REST API Team Vault
как набор инструментов для ИИ-агентов. Позволяет другим агентам **читать и
править заметки вальта программно**, без Obsidian — поверх того же серверного
API, что использует плагин.
Транспорт — **stdio** (агент запускает процесс и общается по JSON-RPC).
Аутентификация — заголовок `X-API-Key`.
## Конфигурация (env)
| Переменная | Обяз. | Описание |
| ----------------------- | ----- | ---------------------------------------------------------------------- |
| `TEAM_VAULT_URL` | да | URL сервера, напр. `https://teamvault.artillect.pro` |
| `TEAM_VAULT_API_KEY` | да | API-ключ Team Vault (веб-UI → API-ключи) |
| `TEAM_VAULT_PROJECT_ID` | нет | проект по умолчанию для инструментов без `projectId` |
| `TEAM_VAULT_READ_ONLY` | нет | `1`/`true` — отключить запись (`write_note`/`move_note`/`delete_note`) |
## Инструменты
| Инструмент | Режим | Что делает |
| -------------------- | ------ | ------------------------------------------------ |
| `whoami` | чтение | владелец API-ключа |
| `list_projects` | чтение | доступные проекты (id, slug, name) |
| `list_notes` | чтение | пути файлов проекта (`prefix` — фильтр по папке) |
| `read_note` | чтение | содержимое текстовой заметки по пути |
| `list_note_versions` | чтение | история версий файла |
| `write_note` | запись | создать/перезаписать заметку по пути |
| `move_note` | запись | переместить/переименовать |
| `delete_note` | запись | мягко удалить (tombstone, восстановимо) |
Инструменты **путь-ориентированы**: агент оперирует путями (`персонажи/кузьма-минин.md`),
а MCP сам резолвит путь ↔ fileId. Путь можно написать в любом виде, который
сервер сводит к одному: `./a.md`, `dir\a.md`, `dir//a.md`, `x/../dir/a.md` — это
те же `a.md` и `dir/a.md`. В `read_only`-режиме инструменты записи не
регистрируются вовсе.
## Надёжность: таймауты, повторы и `Idempotency-Key`
У каждого вызова инструмента один бюджет времени — **45 с на все его запросы
вместе** (резолв пути и запись). Это меньше 60-секундного таймаута запроса в
MCP SDK: вызов заканчивается раньше, чем хост от него откажется. Если хост всё
же отменил вызов (`notifications/cancelled`), текущий запрос обрывается и
повторов больше нет. Таймаут одной попытки — 20 с, но не больше остатка
бюджета; новая попытка не начинается, если от бюджета осталось меньше 2 с.
Повторяются только сбои без ответа: сетевая ошибка, таймаут, `429`, `502`,
`503`, `504` — до 3 попыток с паузами 1 и 3 с (плюс до 0,25 с случайно), с
учётом `Retry-After` сервера (не больше 10 с). `409 idempotency_key_in_use`
(предыдущая попытка ещё выполняется) повторяется до конца бюджета. Остальные
ответы (`400`, `401`, `403`, `404`, `409 path_exists`, `422`, `500`) не
повторяются.
Каждая запись (`write_note`, `move_note`, `delete_note`) отправляет заголовок
`Idempotency-Key` — один UUID на вызов, одинаковый во всех попытках. Сервер
применяет запись один раз, а повтор получает исходный ответ с заголовком
`Idempotent-Replayed: true`. `422 idempotency_key_mismatch` означает ошибку
клиента и не повторяется.
Новый вызов инструмента — новый ключ. Если запись упала без определённого
ответа (сеть, таймаут, `5xx`, ключ всё ещё занят), текст ошибки заканчивается
подсказкой «The change may or may not have been applied…»: перед новым вызовом
агенту стоит проверить состояние через `read_note` или `list_notes`.
Повторы записи безопасны только с сервером Team Vault с поддержкой
`Idempotency-Key` (ревизия `79fb5d9` и новее, на проде с 2026-10-05). Старый сервер заголовок молча
игнорирует, и повтор после таймаута может применить запись второй раз
или откатить правку коллеги. Поэтому сначала обновляйте сервер, потом MCP.
## Сборка и запуск
```bash
pnpm install
pnpm build # tsup → dist/index.js (один бандл)
TEAM_VAULT_URL=… TEAM_VAULT_API_KEY=… node dist/index.js
```
Гейты: `pnpm typecheck && pnpm format:check && pnpm build && pnpm test`.
## Тесты
```bash
pnpm test # vitest run (однократно); pnpm test:watch — в режиме наблюдения
```
Тесты не ходят в сеть: глобальный `fetch` в каждом тесте подменён заглушкой
(`tests/setup.ts`), а тест, которому нужен HTTP, ставит свой мок с ответами
сервера (`tests/helpers/fetch.ts`). Клиент перехватывает ошибку заглушки и
превращает её в обычную `TeamVaultError`, поэтому заглушка ещё и запоминает
каждый вызов: тест, который забыл мок, падает после выполнения, даже если сам
ждал ошибку.
- `tests/client.test.ts` — REST-клиент: заголовок `X-API-Key`, резолв пути
через `GET /files?path=…` (включая `200` с пустым списком), `404`,
`409 path_exists`, `5xx`, сетевые ошибки (одна попытка).
- `tests/client-retry.test.ts` — повторы и бюджет времени на поддельных
таймерах: ключ `Idempotency-Key` одинаков во всех попытках и разный у разных
вызовов, что повторяется и что нет (`422` — нет), паузы и `Retry-After`,
ответ-повтор как успех, таймаут попытки по остатку бюджета, отмена.
- `tests/server.test.ts` — инструменты через настоящий MCP-клиент поверх
in-memory транспорта: версия в `initialize`, режим только для чтения,
`write_note` (создание и обновление), чтение, перемещение, удаление; путь в
другом написании (`./a.md`, `dir\a.md`); общий бюджет резолва и записи,
отмена вызова хостом, подсказка «may or may not have been applied».
- `tests/paths.test.ts` — написание пути, под которым его хранит сервер
(`storedPathOf`).
- `tests/config.test.ts` — разбор переменных окружения.
- `tests/entry.test.ts` — точка входа `src/index.ts` как дочерний процесс по stdio
(`initialize` + `tools/list`, выход с кодом 1 без обязательных переменных).
- `tests/network-guard.test.ts` — заглушка `fetch`: юнит-проверки и дочерний
прогон vitest на `tests/fixtures/*.fixture.ts` (основной прогон эти файлы
не собирает).
## Подключение в Claude Code / MCP-клиенте
```json
{
"mcpServers": {
"team-vault": {
"command": "node",
"args": ["/абсолютный/путь/TeamVaultMCP/dist/index.js"],
"env": {
"TEAM_VAULT_URL": "https://teamvault.artillect.pro",
"TEAM_VAULT_API_KEY": "osync_…",
"TEAM_VAULT_PROJECT_ID": "cmq…"
}
}
}
}
```
## Лицензия
MIT · krem.digital
TDQS
A3.7/5.0
Scored across 8 tools
Disambiguation5/5
Each tool has a distinct purpose: note CRUD, versioning, project listing, user info, and file moves. No two tools overlap in function.
Naming Consistency4/5
Most tools follow a consistent 'verb_note' pattern (delete_note, list_notes, move_note etc.), with the exception of 'whoami', which deviates slightly but is a common convention.
Tool Count5/5
Eight tools is well-scoped for a note management system, covering creation, reading, deletion, listing, moving, versioning, project enumeration, and user info.
Completeness4/5
CRUD and versioning are covered, but there is no explicit restore for soft-deleted notes or support for binary file operations, which are noted as server-side recoverable or external respectively.
Maintenance
ActivityMaintained
ResponsivenessNo issues