Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Fenced Obsidian Sync

БесплатноНе проверен

A deny-by-default MCP server for Obsidian vaults where operators declare exact capabilities (list, read, create, etc.) scoped by path globs; everything not perm

GitHubEmbed

Описание

A deny-by-default MCP server for Obsidian vaults where operators declare exact capabilities (list, read, create, etc.) scoped by path globs; everything not permitted is impossible by construction as disallowed tools are never registered.

README

A deny-by-default, finely fenced MCP server over an Obsidian vault. The operator declares exactly which capabilities (list, read, create, …) an agent gets, each scoped by path globs — and everything else is impossible by construction, not merely guarded.

Other Obsidian MCP servers hand an agent broad read/write/search/delete. Here the fence is the product: you can run it so an agent may only create notes under Inbox/, or only see note titles, or touch nothing at all — and prove the rest is impossible because the tools are never registered.

Full design brief: docs/SPEC.md. The "Core principles (security invariants)" there are requirements, and each is backed by a test.

Install

pip install -e ".[http,dev]"     # http extra for remote serving; dev for tests

Requires Python ≥ 3.10.

Run

fenced-obsidian-sync-mcp --config examples/create-only.yaml
# or
python -m fenced_obsidian_sync_mcp --config examples/create-only.yaml

By default this speaks stdio (for a local MCP client). Set transport.type: http for remote serving (see below).

The three canonical postures

Each is a complete, runnable config (full files in examples/).

1. Deny-all — a dark vault

The server runs but exposes no tools at all.

mode: local
vault: /path/to/your/vault
capabilities: {}

2. Create-only — file, never read

The agent can drop new notes into Inbox/ and do nothing else. No read/list/update/delete tool is registered. Collisions never overwrite.

mode: local
vault: /path/to/your/vault
collision: suffix          # fail | suffix
capabilities:
  create:
    enabled: true
    allow: ["Inbox/**"]

3. Titles-only — see names, not bodies

The agent learns which notes exist (to suggest links) but no registered tool can open their contents. read and read_metadata are absent.

mode: local
vault: /path/to/your/vault
capabilities:
  list:
    enabled: true
    allow: ["**/*.md"]
    deny:  ["Private/**", "Journal/**"]

Capabilities

Every capability is off by default and independently path-scoped. Enabling one registers exactly one tool; disabling it means the tool is absent from the MCP tool list.

Capability Tool Exposes Opens file contents?
list list_notes enumerate paths / filenames no — readdir only
read_metadata read_metadata frontmatter, tags, stat frontmatter only
read read_note full note contents yes
search search_notes content search (implies read) yes
create create_note new files only, never overwrite no
update update_note modify / append existing files n/a
delete delete_note remove files n/a
move move_note rename / relocate, never overwrite n/a

search implies read: enabling search without read is a config error, because returning snippets while read is off would be a content oracle.

Glob semantics

Globs use wcmatch with GLOBSTAR, evaluated against vault-relative POSIX paths:

  • ** spans directories (**/*.md matches at any depth); * matches within a single segment.
  • Case-sensitive.
  • Dotfiles are not matched unless a pattern names the leading dot, so .obsidian/ stays out of **/*.md.
  • deny always beats allow on every capability.

Modes

  • mode: local — point vault at a directory you already keep current (Syncthing, iCloud, git, or nothing). No sync subprocess, no obsidian-headless dependency. Works anywhere, including a phone via Termux.
  • mode: syncvault is your remote Obsidian Sync vault name and vault_dir is the local directory the official obsidian-headless client (ob sync --continuous) mirrors into. The server supervises that process.

The fence is identical in both modes; only how the directory stays current differs.

⚠️ Sync-mode write warning: in sync mode, update/delete/move propagate to every device on your Obsidian Sync. Create-only is the conflict-free default; enable writes deliberately.

Transports

  • stdio (default) — for a local MCP client.
  • HTTP (transport.type: http) — streamable-http behind a bearer token (required) and TLS. Terminate TLS in-process (transport.tls.certfile / keyfile) or at a reverse proxy such as Caddy. Full OAuth is a future extension; bearer + TLS is the supported remote posture today.
transport:
  type: http
  host: 0.0.0.0
  port: 8080
  auth: { bearer_token: "a-long-random-secret" }
  tls:  { certfile: /etc/ssl/certs/server.crt, keyfile: /etc/ssl/private/server.key }

Audit log

Optional structured JSONL of every allowed and denied call (capability, path, decision, and — for denials — an internal reason never shown to the client):

audit:
  enabled: true
  path: /var/log/fenced-obsidian-sync-mcp/audit.jsonl   # omit -> stderr

Deploy with Docker (mode: sync)

The repo ships a Dockerfile, docker-compose.yml, and Makefile for running mode: sync behind a reverse proxy (e.g. the central Caddy on a Hetzner box). The image bundles both the Python server and the official obsidian-headless (ob) client; TLS is terminated at the proxy, so the container speaks plain HTTP on 0.0.0.0:4012 and the bearer token comes from $FOSM_BEARER_TOKEN.

# 1. one-time obsidian-headless auth (persists in named volumes)
make ob-login                      # interactive: email, password, MFA
make ob-setup VAULT="My Vault"     # links the remote vault into /vault

# 2. config + secret
cp examples/config.docker-sync.yaml config.yaml   # edit vault name + globs
cp .env.example .env && echo "FOSM_BEARER_TOKEN=$(openssl rand -hex 32)" > .env

# 3. run
make deploy                        # docker compose up -d --build

bearer_token_env: FOSM_BEARER_TOKEN in the config sources the token from the container environment, keeping the secret out of the config file and git. Point your reverse proxy at 172.18.0.1:4012 (the Docker bridge gateway) and, because MCP streamable-http uses SSE, disable proxy buffering — in Caddy: reverse_proxy 172.18.0.1:4012 { flush_interval -1 }.

Security invariants

These are guaranteed and tested (tests/):

  1. Deny by default — a disabled capability's tool is not registered.
  2. Capabilities are independent — knowing a note exists (list) is separate from its metadata (read_metadata) is separate from its body (read).
  3. Path confinement.., absolute paths, escaping symlinks, and percent-/double-encoded separators are all rejected.
  4. No silent overwritecreate uses O_EXCL; collisions fail or suffix.
  5. Glob-scoped, deny-winsdeny always beats allow.
  6. No existence oracle — denied paths return a uniform not permitted.
  7. Auditable — optional structured log; a small, readable codebase.

Development

pip install -e ".[http,dev]"
pytest        # full invariant + acceptance suite
ruff check .

License

MIT

from github.com/mmsge/fenced-obsidian-sync-mcp

Установить Fenced Obsidian Sync в Claude Desktop, Claude Code, Cursor

Рекомендуется · одна команда, все IDE
unyly install fenced-obsidian-sync-mcp

Ставит в Claude Desktop, Claude Code, Cursor и VS Code — сам разбирается с npx, uvx и сборкой из исходников.

Впервые? Поставь CLI: curl -fsSL https://unyly.org/install | sh

Или настроить вручную

Выполни в терминале:

claude mcp add fenced-obsidian-sync-mcp -- uvx --from git+https://github.com/mmsge/fenced-obsidian-sync-mcp fenced-obsidian-sync-mcp

FAQ

Fenced Obsidian Sync MCP бесплатный?

Да, Fenced Obsidian Sync MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Fenced Obsidian Sync?

Нет, Fenced Obsidian Sync работает без API-ключей и переменных окружения.

Fenced Obsidian Sync — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Fenced Obsidian Sync в Claude Desktop, Claude Code или Cursor?

Открой Fenced Obsidian Sync на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Fenced Obsidian Sync with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development