Skip to main content
Glama
sipho102
by sipho102

brain-mcp

Автор иконки: wenmeiZhou на iStock.

MCP-сервер, который предоставляет markdown-хранилище второго мозга, организованное по методу PARA (совместимое с Obsidian), в виде набора инструментов для чтения и одного ограниченного инструмента для записи (capture, который только создаёт новые заметки в 00-inbox/). Работает как Docker-контейнер, используется через streamable-HTTP клиентами Claude Code, opencode и другими MCP-клиентами.

Полная спецификация поведения: см. brain-mcp-spec.md в этом репозитории (или там, где вы его храните), если вам нужно «почему» за тем или иным проектным решением.

Примечания о парсере CONVENTIONS.md

brain_structure() читает перечисления type/status/domain напрямую из вашего файла 90-meta/CONVENTIONS.md, а не захардкоживает их (см. _extract_enum_values в src/brain_mcp/vault.py). Он был проверен на реальном файле хранилища: в этом файле три перечисления указаны как жирные встроенные метки под одним заголовком ## Enums (**type:** \note`, `project`, ...), а не каждое в отдельном подзаголовке, поэтому _extract_enum_values сначала пробует такую форму (ограничиваясь абзацем самой метки, чтобы не захватывать посторонние слова в кавычках-бэктиках в тексте ниже — например, «domain— основная ось запросов...»), а затем переходит к эвристике на основе заголовков для хранилищ, где перечисления описаны иначе. Если вы позже измените структуру раздела Enums вCONVENTIONS.md`, перепроверьте этот парсер — сервер громко падает при запуске, а не переходит к плохим значениям по умолчанию, если не может разобрать непустой список значений для всех трёх полей.

Формат uid: хранилище, на котором это проверялось, в настоящее время содержит противоречие в собственном CONVENTIONS.md — пример во frontmatter показывает UUIDv4, в тексте двумя строками ниже сказано, что реальный формат — YYYYMMDD-HHmm (+ буква при коллизиях в одну минуту), а реальные заметки на диске используют три разные схемы (UUIDv4 в одной заметке во входящих, 00000000-000N-заглушки в мета-документах, последовательные счётчики YYYYMMDD-000N в файлах _index.md). capture() генерирует UUIDv4 — это то, что просила исходная спецификация, соответствует текущему коду и сохраняет осмысленность поиска по короткому префиксу в read_note (≥8 символов), чего не было бы с низкоэнтропийным датированным id, где всё за один день имеет общий префикс. Если в вашем собственном CONVENTIONS.md описан другой формат uid, это стоит согласовать на стороне хранилища — сервер это автоматически не делает.

Related MCP server: Obsidian MCP Server

Требования

  • Структура PARA и схема frontmatter хранилища, как описано в собственном 90-meta/CONVENTIONS.md хранилища.

  • Docker (или Docker Compose) на Unraid-машине, или Python 3.12 + uv локально для разработки.

  • ripgrep в PATH (встроен в образ контейнера; установите отдельно для локальной разработки).

Конфигурация

Вся конфигурация через переменные окружения — ничего о конкретном хранилище (путь, имя, токен) не захардкожено, поэтому один и тот же образ обслуживает любое количество соседних хранилищ как отдельные контейнеры.

Переменная

Обязательная

По умолчанию

Значение

BRAIN_ROOT

да

Абсолютный путь к корню хранилища в контейнере

BRAIN_NAME

да

Имя экземпляра, например personal или family

BRAIN_TOKEN

да

Bearer-токен, обязательный для каждого MCP-запроса

PORT

нет

3100

Порт прослушивания

BIND_ADDRESS

нет

0.0.0.0

Адрес прослушивания

LOG_LEVEL

нет

INFO

DEBUG/INFO/WARNING/ERROR/CRITICAL

Скопируйте .env.example в .env и заполните BRAIN_NAME, BRAIN_VAULT_PATH (путь на хосте к вашему хранилищу) и BRAIN_TOKEN (случайный секрет — openssl rand -hex 32 подойдёт) перед запуском Compose.

Локальная разработка

uv sync --dev          # or: python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
uv run pytest          # or: .venv/bin/python -m pytest

Тесты полностью выполняются на синтетическом фикстурном хранилище, созданном в tests/conftest.py — никогда на реальных данных.

Чтобы запустить сервер локально на реальном (или тестовом) каталоге хранилища:

export BRAIN_ROOT=/path/to/vault
export BRAIN_NAME=personal
export BRAIN_TOKEN=dev-token
uv run brain-mcp

Запуск на Unraid

cp .env.example .env   # fill in BRAIN_NAME, BRAIN_VAULT_PATH, BRAIN_TOKEN
docker compose up -d --build   # or: docker compose pull && docker compose up -d
curl http://<unraid-host>:3100/health

--build собирает из этого репозитория; pull вместо этого загружает тот же образ, предварительно собранный из GHCR (см. «Установка как приложение Unraid» ниже) — оба варианта дают локальный тег ghcr.io/sipho102/brain-mcp:latest.

Файл compose монтирует BRAIN_VAULT_PATH в режиме только для чтения и поверх него монтирует только 00-inbox/ в режиме чтения-записи:

volumes:
  - ${BRAIN_VAULT_PATH}:/vault:ro
  - ${BRAIN_VAULT_PATH}/00-inbox:/vault/00-inbox:rw

Это намеренно и критически важно — даже ошибка в пути записи не может затронуть ничего за пределами входящих, независимо от того, что думает код Python. Не упрощайте это до единого монтирования чтения-записи.

Установка как приложение Unraid вместо этого

Если вы предпочитаете управлять этим через вкладку Docker в Unraid, как любым другим приложением — форма вместо редактирования .env, кнопки Start/Stop/Update после — для этого есть шаблон в unraid/brain-mcp.xml. .github/workflows/publish.yml собирает образ этого репозитория и публикует его в GHCR (ghcr.io/sipho102/brain-mcp:latest) при каждом push в main, и шаблон тянет его напрямую — без клонирования или сборки на Unraid-машине вообще.

Сделайте шаблон доступным для Unraid:

  • Рекомендуется — на вкладке Docker нажмите Add Container и вставьте URL сырого шаблона этого репозитория прямо в поле шаблона: https://raw.githubusercontent.com/sipho102/brain-mcp/main/unraid/brain-mcp.xml Так ничего не записывается в локальную папку шаблонов Unraid, поэтому не остаётся лишнего файла, который мог бы конфликтовать позже — см. предупреждение ниже об альтернативном методе.

  • Или скопируйте его в локальную папку шаблонов Unraid через SSH:

    curl -o /boot/config/plugins/dockerMan/templates-user/brain-mcp.xml \
      https://raw.githubusercontent.com/sipho102/brain-mcp/main/unraid/brain-mcp.xml

    Затем он появится в Docker → Add Container → выпадающем списке шаблонов — но см. примечание сразу после Add Container об удалении этого файла после создания контейнера.

В любом случае вы получите форму для пути к хранилищу, пути к входящим (должен быть <путь к хранилищу>/00-inbox — шаблон не может вывести его за вас), имени экземпляра и bearer-токена; всё остальное предзаполнено разумными значениями по умолчанию в «расширенном виде».

Если вы использовали метод локального копирования выше, удалите этот файл-затравку после добавления контейнера:

rm /boot/config/plugins/dockerMan/templates-user/brain-mcp.xml

Когда вы нажимаете Apply в Add Container, Unraid сохраняет второй файл с вашими реальными значениями — my-brain-mcp.xml, рядом с пустым, который вы скачали — и оба объявляют одно и то же имя контейнера. С двумя шаблонами, претендующими на это имя, Update может в итоге пересоздать контейнер из пустого оригинала вместо вашего сохранённого, стирая BRAIN_NAME/BRAIN_TOKEN/пути и оставляя его неработоспособным. Как только my-brain-mcp.xml существует (проверьте ls /boot/config/plugins/dockerMan/templates-user/), файл-затравка выполнил свою задачу и больше не нужен — удалите его, чтобы не было двусмысленности. После этого нажатие Update потянет самое свежее из ghcr.io/sipho102/brain-mcp:latest, используя вашу сохранённую конфигурацию, как и ожидается.

Обслуживание второго хранилища

Один контейнер обслуживает одно хранилище — намеренно нет списка мульти-хранилищных сервисов в docker-compose.yml, и нет мульти-хранилищной формы в шаблоне Unraid. На пути приложения Unraid это просто означает повторное Add Container из того же шаблона с другим именем/путями/токеном/портом. На пути Compose скопируйте этот каталог развёртывания (или просто docker-compose.yml + .env) в другое место, заполните в копии .env другие BRAIN_NAME, BRAIN_VAULT_PATH, BRAIN_TOKEN и PORT, и запустите docker compose up -d --build оттуда. Тот же образ (brain-mcp:latest), независимые контейнеры.

Пользователь контейнера / права доступа

Контейнер работает от непривилегированного пользователя, UID:GID 99:100 по умолчанию (Unraid nobody:users) — переопределите при сборке через BRAIN_UID/BRAIN_GID в .env, если вашему ресурсу нужны другие права владельца. Этот пользователь должен иметь доступ на запись к 00-inbox/ на хостовом ресурсе.

Подключение клиента

Claude Code

claude mcp add --transport http --scope user brain \
  http://<unraid-host>:3100/mcp \
  --header "Authorization: Bearer <token>"

Затем /mcp в сессии должен показать все шесть инструментов.

Известная особенность: у Claude Code были повторяющиеся ошибки, когда заголовки, заданные через --header, не отправлялись при установлении сессии, что приводило к 401, хотя curl с тем же токеном работал. Если вы столкнулись с этим, запишите объект headers напрямую в JSON-конфиг (~/.claude/mcp_servers.json или соответствующий файл области):

{
  "mcpServers": {
    "brain": {
      "type": "http",
      "url": "http://<unraid-host>:3100/mcp",
      "headers": {
        "Authorization": "Bearer <token>"
      }
    }
  }
}

(type также принимает streamable-http как псевдоним для http в JSON-конфигах.)

opencode

opencode по умолчанию пытается выполнить OAuth-обнаружение на удалённых MCP-серверах и игнорирует статический bearer-токен, если вы явно не отключите это:

{
  "mcp": {
    "brain": {
      "type": "remote",
      "url": "http://<unraid-host>:3100/mcp",
      "oauth": false,
      "headers": {
        "Authorization": "Bearer <token>"
      }
    }
  }
}

Без oauth: false opencode попытается выполнить (и провалит) OAuth-рукопожатие вместо использования заголовка.

Клиенты без поля заголовка вообще

Некоторые интерфейсы MCP-клиентов принимают только имя, транспорт и URL — нет способа задать пользовательский заголовок Authorization. Для таких поместите токен в URL:

http://<unraid-host>:3100/mcp?token=<token>

Сервер сначала проверяет заголовок Authorization, а затем переходит к параметру запроса ?token=, так что это работает везде, где работает и конфигурация с заголовком выше. Стоит знать, прежде чем полагаться на это: токен в URL может оказаться в большем количестве мест, чем заголовок — в сохранённой конфигурации клиента, в истории браузера, если URL когда-либо открыт напрямую, в истории оболочки, если вы вставили его в терминал. Журналы доступа здесь не проблема (журнал доступа uvicorn выключен), но относитесь к самому URL как к носителю секрета, так же, как и к самому токену.

Инструменты

Шесть инструментов, намеренно небольших (схемы инструментов стоят контекста клиента):

  • brain_structure() — ориентация: папки PARA + счётчики, живые перечисления из CONVENTIONS.md, схема frontmatter, полный текст соглашений, количество заметок. Вызывайте это первым в сессии.

  • search_notes(query, domain, type, status, para, tag, limit) — полнотекстовый поиск (ripgrep) с фильтрацией по frontmatter. Возвращает метаданные + фрагмент ~200 символов, никогда полные тела.

  • read_note(identifier) — полная заметка по пути относительно хранилища, полному uid или однозначному префиксу uid (≥8 символов).

  • list_notes(para, domain, status, type, limit) — просмотр только метаданных, без поиска по содержимому.

  • get_backlinks(identifier) — заметки, ссылающиеся на эту, с контекстной строкой.

  • capture(title, body, domain, tags, source, links) — единственная запись: создаёт новую заметку в 00-inbox/. Никогда не перезаписывает, никогда не касается ничего за пределами входящих.

Что это намеренно не делает

Нет семантического поиска/эмбеддингов, нет доступа на запись за пределами 00-inbox/, нет зависимости от Obsidian Local REST API (читает файловую систему напрямую), нет получения документов paperless-ngx (возвращает ID документов из frontmatter, чтобы клиент мог связать их с отдельным MCP-сервером paperless), нет операций с git. См. brain-mcp-spec.md §2 для обоснования.

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

  • A
    license
    A
    quality
    A
    maintenance
    A generic Markdown vault MCP server with FTS5 full-text search, semantic vector search, frontmatter-aware indexing, incremental reindexing, and non-markdown attachment support that exposes search, read, write, and edit tools.
    38
    31
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Exposes an Obsidian notes vault as MCP services, enabling AI assistants to search, read, create, update, and delete notes and folders.
    24
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Exposes a personal markdown-based second brain (Obsidian-style) as an MCP server, enabling agents to search, read, and write notes with privacy controls.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server that turns a Markdown folder (e.g. Obsidian vault) into a second brain, capturing readings and ideas, connecting them as concepts, and resurfacing related notes on demand.
    235
    MIT

View all related MCP servers

Related MCP Connectors

  • Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.

  • Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.

  • Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

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/sipho102/brain-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server