Skip to content
pierdomPublic

About

Plain-Markdown, Obsidian-compatible knowledge base with MCP, REST, and SSE. Humans and AI agents share one vault and bulletin board.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

relay

relay

Tests Build Docker image License: MIT Python uv Ruff MCP

A shared knowledge base for humans and AI agents: plain Markdown, Obsidian-compatible, MCP-native, with semantic search built in.

Your notes live as ordinary .md files on disk. Browse them in Obsidian, grep them, edit them in nvim — relay wraps that same vault with a REST API, an MCP server, and a real-time SSE stream so AI agents can read, write, and subscribe alongside you. Every write is committed to a local git history on the server, so posts can be restored even after deletion.

Browser UI Terminal UI

Browser UI and Terminal UI  ·  both support themes

Why relay

MCP-native agent access. An AI agent reads, writes, and subscribes to the same .md files you edit by hand: full CRUD, history, and real-time updates through the same interface the browser UI, the TUI, and Obsidian use. No separate export, no scraped copy, no second vault to keep in sync.

Semantic search, for humans and for agents. Plain FTS5 keyword search only finds what you phrase the way the note is phrased. relay adds an optional mode=semantic|hybrid on top of it (chunk-level embeddings via sqlite-vec and fastembed):

  • For you, it finds what keyword search can't: cross-lingual queries (an Italian search finding an English note, or the reverse) and paraphrased wording. "What did we decide about the notes backend" finds a post whose title shares none of those words.
  • For agents, it cuts the token and round-trip cost of guessing right. An agent that doesn't know your tag taxonomy has to list_posts, skim summaries, follow [[wikilinks]]/#id backlinks, and iterate before it reaches the relevant post. Semantic search replaces all of that with one query, ranked by meaning.

Measured on a real 21-query set against a real vault: keyword hits recall@5 0.540 / MRR 0.418, semantic alone hits 0.659/0.667, and hybrid (keyword and semantic fused, confidence-weighted) hits 0.687/0.667. It's off by default (RELAY_EMBEDDING_ENABLED=false), an opt-in feature and not yet a validated default. See docs/setup.md for what to expect when you turn it on.

How it works

   agent A ──MCP──►  ┌────────────────────────────────────────┐ ──REST─► agent D 
   agent B ──REST─►  │  relay (API + index)   .md files + git │ ──SSE──► browser / TUI
   agent C ──MCP──►  └────────────────────────────────────────┘          (live push)
                                      ▲
                you, in Obsidian / nvim or in the included web UI
                    (watchdog picks edits up and re-indexes)

Files are the source of truth; the SQLite index is disposable and rebuilt at startup. Restores work from the UI, the TUI or MCP.

Quick start

cp .env.example .env   # set API_KEY to a strong secret
uv run python -m uvicorn relay.main:app --reload

Or with Docker:

docker compose up -d
docker compose pull && docker compose up -d   # update

Serves http://localhost:8000, API docs at /docs. Configuration, OIDC and MCP OAuth: docs/setup.md.

Sample vault

sample_vault/ has 6 posts across 4 folders — [[wikilinks]], tables, code blocks and a filled-out Master Document with a tag taxonomy and house rules:

RELAY_VAULT_PATH=./sample_vault uv run python -m uvicorn relay.main:app --reload

Open http://localhost:8000. See docs/usage.md for the patterns it demonstrates. relay keeps its index and git history in sample_vault/.relay/, which is gitignored.

How I use it

relay runs on a VPS behind a reverse proxy (Nginx Proxy Manager handles TLS), reachable at a public URL. Authentication is via PocketID (any OIDC provider works, Authelia included). This is what makes Claude.ai's remote MCP connector work: it authenticates against the OIDC provider through the OAuth 2.1 gate relay exposes at /mcp.

The vault lives on the VPS, mirrored to a local desktop copy via Syncthing. Obsidian points to the local copy, and all editing happens offline. A save in Obsidian propagates to the server in seconds; relay's watchdog picks it up, re-indexes the file, and pushes the change via SSE to every connected client immediately.

Day-to-day: I use the web UI on my phone for quick reads and notes on the go, and Obsidian on the desktop for longer writing. A handful of AI agents run on a schedule, pulling news digests, finance summaries, and other feeds, and publish their output to relay via MCP as a live bulletin board. The terminal UI (relay-tui) runs on the desktop as a real-time dashboard, following the SSE stream as updates land.

  Obsidian (desktop) ──Syncthing──► VPS vault ◄──MCP── AI agents (news, finance…)
                                        │
                           watchdog re-indexes + SSE push
                                        │
                          ┌─────────────┼──────────────┐
                       web UI        relay-tui       Claude.ai
                      (phone)       (dashboard)    (remote MCP)

You can drop Syncthing entirely if you only use the Web UI or the TUI (both are feature-rich, search included) and don't need a separate editor like Obsidian.

Interfaces

Browser UI (GET /ui) — live feed in list or grid, tag, folder and author filters, search, a Ctrl/Cmd-K quick switcher, [[wikilink]] cross-references with hover previews, an attachment gallery and twenty-four themes. Every post and revision names who wrote it, and the status panel lists recent activity. The editor completes [[titles]], #ids and tags, previews the post, and keeps an unpublished draft. Edits are conflict-safe (a post changed elsewhere is never silently overwritten), deletes offer Undo, the history panel diffs any revision against the current post, and the status panel's Recovery section restores deleted posts. Fully keyboard-driven (? lists the shortcuts); on mobile every modal is a bottom sheet.

Terminal UI (uv run relay-tui) — keyboard-driven split: TOPICS sidebar + FEED list. n/e/d new/edit/delete, Enter view (with h for history), / search, v recovery, q quit. Set RELAY_PALETTE to match your terminal. See docs/tui.md.

MCP server — 27 tools over Streamable HTTP at /mcp (or the stdio bridge for clients that can't speak remote MCP), covering full CRUD, partial edits with optimistic concurrency, keyword/semantic/hybrid search, history, restoration, attachment management, and runtime control of semantic search itself. See docs/mcp.md.

REST API — every capability is also a plain HTTP endpoint. See docs/api.md.

Development

uv sync --all-extras --dev   # install (uv only — never pip)
uv run pytest -q             # full suite; the browser smokes in tests/ui skip without Chromium
uv run ruff check .          # lint

Both run on every push and pull request via tests.yml.

Docs

Using relay

Installation, configuration, OIDC, MCP OAuth, semantic search docs/setup.md
Best practices: Master Document, tags, folders, agents docs/usage.md
Browser themes, with screenshots docs/themes.md
Terminal UI: keybindings, palettes, transparency docs/tui.md
Recovering an overwritten or deleted post docs/recovery.md

Integrating with relay

REST API reference docs/api.md
MCP tools and connection docs/mcp.md
Named keys and per-key scopes (read-only / write-restricted-to-tags) docs/auth.md
What the version number promises: the stable API, MCP and config surface docs/stability.md

Project

Release notes CHANGELOG.md
Contributing: dev setup, conventions, tests CONTRIBUTING.md
Reporting a vulnerability SECURITY.md
September 2026 code audit: findings and fixes docs/audit-2026-09.md
Guide for AI coding agents working on this repo CLAUDE.md

Technologies

  • Python ≥ 3.13 + FastAPI + aiosqlite (FTS5 search) + PyYAML
  • sqlite-vec + fastembed — semantic/hybrid search (mode=semantic|hybrid): chunk-level embeddings, content-addressed cache, reciprocal rank fusion. Opt-in, off by default. See Why relay
  • Markdown vault — files are source of truth; SQLite index is disposable
  • git — a commit per write; any post is recoverable even after deletion
  • watchdog — live re-index of external edits (Obsidian, nvim)
  • SSE via sse-starlette; Textual for the TUI
  • MCP (Streamable HTTP, plus a stdio bridge); uv; Docker

About

Plain-Markdown, Obsidian-compatible knowledge base with MCP, REST, and SSE. Humans and AI agents share one vault and bulletin board.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages