npm.io
1.3.4 • Published 12h ago

@the-40-thieves/obsidian-tc-shared

Licence
AGPL-3.0-only
Version
1.3.4
Deps
1
Size
119 kB
Vulns
0
Weekly
0

obsidian-tc

Obsidian Turbocharged — governed, agent-ready vault access over MCP.

License: AGPL v3 Status: Shipped v1.3.4

npm install -g obsidian-tc      # Node >= 24 or Bun >= 1.1

Also ships as a Docker image (ghcr.io/the-40-thieves/obsidian-tc), a one-click .mcpb bundle, and standalone binaries.

Why this exists

An AI agent with raw filesystem access to your Obsidian vault can do real damage: overwrite years of notes, delete the wrong folder, read the journal you never meant to expose, or quietly leak plugin API keys sitting in .obsidian/. Most Obsidian MCP servers hand an agent that access with little more than an API key between it and everything you have written.

obsidian-tc gives agents governed access instead. Every tool call — no exceptions — runs through one dispatch pipeline: auth → scopes → folder ACL → read-only kill switch → idempotency → throttle → human-in-the-loop confirmation → handler → response governor → audit log. You decide which folders an agent can read, write, or delete (per vault, per caller); destructive operations fail closed until a human approves them; and every invocation is audited.

New here? Start with the 5-minute quickstart or the threat model and design rationale.

The interface: 3 tools, ~105 governed capabilities

By default the server advertises just three meta-tools instead of a wall of ~105:

  • find_capability — BM25 search over the caller-visible capability catalog ("how do I move a note?")
  • describe_capability — one capability's schema, required scopes, and safety hints
  • call_capability — invoke the named capability; the call routes through the same auth/scope/ACL/HITL/idempotency/throttle pipeline as a direct call, and the target's own schema validates the arguments

This keeps agent context lean while the full surface — 105 tools across 28 domains — stays reachable, and every tool remains directly callable by name. toolFacade.mode selects the shape: triad (default), domain (~a dozen domain meta-tools like notes, search, vault), or flat (the full advertised surface, the pre-facade behavior). The facade is boundary-only: no gate is ever bypassed, whichever mode you pick.

What it is

obsidian-tc is a comprehensive Model Context Protocol (MCP) server for Obsidian, designed for both humans and autonomous agents. Multi-vault native. Pluggable embeddings. Works with local Ollama or cloud models.

Three pillars:

  1. Broad. 105 tools covering the meaningful Obsidian operations, including native Bases (.base) support with a real expression-DSL evaluator — the broadest open-source Obsidian MCP surface we know of (surveyed 2026-07).
  2. Governed by default. JWT auth (HS256 or asymmetric RS256/ES256/EdDSA via a local JWKS with kid rotation), folder ACLs (per vault), read-only kill switch, human-in-the-loop elicit on destructive operations, compare-and-swap on writes, idempotency keys, bulk throttling.
  3. Observable from day one. OpenTelemetry traces, Prometheus metrics, structured CloudEvents emission on every tool call — all opt-in export streams that fail soft.

Beyond Tools, the server exposes your vault as MCP Resources (resources/list + resources/read over obsidian-tc://<vault>/<path> URIs, read-scope and folder-ACL enforced) and a set of built-in Prompts (prompts/list + prompts/get).

Status

Shipped — v1.3.4 (2026-07-03). Published to npm as provenance-signed packages, with a container image at ghcr.io/the-40-thieves/obsidian-tc:1.3.4. The surface is 105 tools across 28 domains, presented by default via the triad facade described above. v1.3.x adds (see the CHANGELOG): per-vault ACLs with the root ACL as inherited default, mandatory symlink-canonical ACL enforcement, a notes-metadata table + trigram FTS5 search substrate with index-on-write coverage across every note mutation (disk-scan fallback when FTS is unavailable), vec0 KNN vault pushdown, an Obsidian Bases expression-DSL subset evaluator with realigned view keys, compute-abuse budgets (regex worker timeout, JSONLogic op budget), a periodic cache-maintenance sweep, single-serialization dispatch, server_health index/notes_ready/fts_enabled reporting and config-key parity, a companion API-version floor with a bundle shape self-check, asymmetric JWT via a local JWKS, the sleep-time consolidation scheduler, and the AGPL-3.0 relicense.

Milestone Scope Status
M0 Walking skeleton: dispatch pipeline, folder ACL, HITL elicit, migrations Merged
M1 Core vault access — 30 tools (CRUD, frontmatter, tags, links) Merged
M2 Search + embeddings — 6 tools + retrieval substrate Merged
M3 Structured formats — 23 tools (Bases, Canvas, Periodic, Attachments, Bookmarks, Workspaces) Merged
M4 Plugin bridges + companion plugin — 20 tools across 9 domains Merged
M5 Memory + capture substrate — 15 tools (capture queue, memory entities + [[link]] graph, workspace sessions + JSONL traces, plur read proxy) Merged
M6 Bulk + admin + URI — 7 tools Merged
M7 Harden + ship: OpenTelemetry tracing, Prometheus /metrics, CloudEvents spool, rate limiter, 8-triple native prebuilds, release workflow Shipped (v1.0.2)

This repository is public under The-40-Thieves, licensed AGPL-3.0-only.

Architecture

Polyglot monorepo:

Package Language Purpose
packages/server TypeScript (Bun) MCP protocol layer, auth, routing, tool implementations, plugin bridges
packages/plugin TypeScript Companion Obsidian plugin extending Local REST API
packages/shared TypeScript Shared Zod schemas and types
packages/native Rust (via napi-rs) Optional acceleration with a numerically-identical pure-JS fallback — see below

Where the native module actually matters: the main native win is cosine similarity on the brute-force vector path (used when the bundled sqlite-vec extension can't load). The native tokenizer + BM25 scorer power the fallback lexical ranker (the exhaustive disk scan used for sub-trigram queries or when the FTS index is missing/unhealthy) and the find_capability catalog search — the primary lexical ranking for search_text is SQLite FTS5's own bm25() over the trigram notes_fts index. Everything works without a prebuild; the native module makes some cold paths faster.

obsidian-tc is the converged memory engine: vault read/write, search, and control, plus folded-in retrieval intelligence (GraphRAG graph-walk via vault_graph_search, hybrid BM25 + vector search with RRF fusion, rerank via the inference gateway, and a knowledge_challenge decision red-team). Ambient consolidation (weekly synthesis + decision audit) runs on the sleep-time plane when the inference gateway is configured; the GraphRAG ship-gate eval (recall@10 vs baseline) still requires an out-of-band run against a live embedding backend — machinery present and scheduled, headline retrieval numbers pending (THE-296). This supersedes the earlier "access MCP, retrieval out of scope" framing (the 2026-06-25 single-converged-product decision; see ARCHITECTURE.md). The reserved "V2 ML sidecar" (and the native kmeansAssign / actrDecayScore hooks) was removed; the typed-atom MemIR substrate is a downstream engine-build phase, not this v1.x line.

Quick start

Full walkthrough (Claude Desktop / Claude Code wiring, first queries, a governed write): docs/QUICKSTART.md.

Install, then point obsidian-tc at a JSON config — a vault id and path is the minimum (every other field has a default):

npm install -g obsidian-tc

obsidian-tc runs on Node (>= 24) or Bun (>= 1.1)npm / npx installs run under Node (which uses better-sqlite3, falling back to the built-in node:sqlite); under Bun it uses bun:sqlite. The runtime is auto-detected, so the same install works either way.

The fastest start is zero-config: point it at a vault folder and it boots a single vault named main with sensible defaults.

obsidian-tc /path/to/your/vault

For multi-vault, auth, ACLs, or custom embeddings, pass a config file instead:

obsidian-tc.config.json:

{
  "vaults": [{ "id": "main", "path": "/path/to/your/vault" }]
}
obsidian-tc ./obsidian-tc.config.json
# or set the path in the environment:
OBSIDIAN_TC_CONFIG=./obsidian-tc.config.json obsidian-tc

# inspect the effective config (secrets redacted), or print the version:
obsidian-tc config show ./obsidian-tc.config.json
obsidian-tc version

# install the companion Obsidian plugin into your vault (then enable it in Obsidian):
obsidian-tc plugin install --vault /path/to/your/vault
Runs locally by default

No cloud account or API key is required. With the defaults, everything runs on your machine: embeddings via a local Ollama model (nomic-embed-text, 768-dim), vector search via the bundled sqlite-vec (with a pure-JS cosine fallback), and a per-vault SQLite cache. Pull the model once, then start:

ollama pull nomic-embed-text       # the default embeddings model
obsidian-tc /path/to/your/vault    # boots local-only, no config file

The optional inference gateway (OBSIDIAN_TC_GATEWAY_URL) powers rerank and the knowledge_challenge red-team; leave it unset and those degrade gracefully while everything else keeps working. Cloud embedding providers (OpenAI, Voyage, Cohere) are opt-in via a config file.

Install in Cursor / VS Code

One-click install (launches via npx; after installing, set the config path to your own obsidian-tc JSON config):

Add to Cursor Install in VS Code

Or add it by hand. The server object is the same; only the wrapper key differs — Cursor (~/.cursor/mcp.json) uses mcpServers, VS Code (.vscode/mcp.json) uses servers:

{
  "mcpServers": {
    "obsidian-tc": {
      "command": "npx",
      "args": ["-y", "obsidian-tc"],
      "env": { "OBSIDIAN_TC_CONFIG": "/ABSOLUTE/PATH/TO/obsidian-tc.config.json" }
    }
  }
}

OBSIDIAN_TC_CONFIG is the absolute path to your obsidian-tc JSON config (vaults, ACL, transports); it may also be passed as the first CLI argument. A prebuilt MCPB bundle (bun run bundledist/obsidian-tc.mcpb) is also available for one-click install in Claude Desktop and other MCPB hosts.

How it compares

Most Obsidian MCP servers are thin access wrappers over the Local REST API. obsidian-tc is a server-grade product: a centralized dispatch pipeline (auth -> scopes -> folder ACL -> read-only -> idempotency -> throttle -> HITL -> handler -> response governor -> audit), a hybrid retrieval substrate, and observability. A rough comparison of the open-source servers (tool counts and features as of 2026-07 — these projects move; check their repos):

Tools Search Auth / ACL / HITL Observability
obsidian-tc ~105 (3-tool facade) FTS5 BM25 + vector + RRF + graph JWT (HS256/JWKS) + per-vault folder ACL + HITL elicit OTel + Prometheus + CloudEvents
cyanheads/obsidian-mcp-server ~14 text / regex JWT/OAuth + folder-scoped paths + read-only mode + HITL; MCP 2025-11-25 pagination console logs
MarkusPfundstein/mcp-obsidian ~13 text + JsonLogic / DQL Local REST API key console logs
StevenStavrakis/obsidian-mcp ~11 text path validation, no auth layer console logs

Where obsidian-tc goes further: multi-vault in one process with per-vault ACLs, hybrid lexical + vector + graph retrieval, compare-and-swap and idempotency on writes, a per-invocation audit trail, and production observability. Where the community servers win: footprint and simplicity — see the next section.

When NOT to use obsidian-tc

Honest guidance — obsidian-tc is deliberately a heavier product:

  • You want the smallest possible footprint. A single trusted human driving a chat client over one vault is well served by the simpler community servers above; the governance pipeline here mostly pays off with autonomous or multi-agent access.
  • You only need read access. A read-only wrapper (or cyanheads' read-only mode) is less machinery for a similar safety outcome.
  • You want everything inside Obsidian. obsidian-tc is a standalone server, not an Obsidian plugin — the optional companion plugin only bridges plugin-specific features. If you never leave the app, community plugins may be all you need.
  • You don't need MCP at all. Obsidian URI or the Local REST API plugin can cover simple scripting directly.

Migrating the other way — replacing an existing Obsidian MCP setup with obsidian-tc — is covered in docs/CUTOVER.md.

Docs

Trademark

obsidian-tc is an independent, community-built open-source project. It is not affiliated with, endorsed by, or sponsored by Obsidian or its maker, Dynalist Inc. "Obsidian" is a trademark of Dynalist Inc.; it is used here only nominatively — to describe the application this MCP server interoperates with — including within the package, image, and plugin names (obsidian-tc), which denote compatibility, not origin or endorsement. For the official app, visit obsidian.md.

License

GNU Affero General Public License v3.0 (AGPL-3.0-only). See LICENSE. A commercial-exception license may also be available for use that cannot meet the AGPL's network-copyleft terms — open a discussion to enquire. Contributions are accepted under the Developer Certificate of Origin; see CONTRIBUTING.md for how to sign off your commits.

Contributing

See CONTRIBUTING.md. All contributors agree to the Code of Conduct.

For security issues, see SECURITY.md.