Skip to main content

obsidian-mcp

CI

An MCP (Model Context Protocol) server for Obsidian vaults. Connects Claude (or any MCP client) directly to your vault — read, write, search, navigate links, and manage notes, canvases, and kanban boards.

Why obsidian-mcp?

The official Obsidian MCP plugin requires the Obsidian desktop app to be running and only works on the same machine. obsidian-mcp is a standalone server — no Obsidian app needed.

The intended setup is to host obsidian-mcp on a server or NAS where your vault is continuously synced (via Syncthing, git, rclone, or Obsidian Sync). Claude then connects to that server over the network, so:

  • Always up to date — the server sees every change your Obsidian app writes, immediately
  • Access from anywhere — connect from Claude Desktop, Claude Code, or any MCP client on any machine, without the vault being present locally
  • Multiple clients — several Claude sessions can read the vault simultaneously; writes are serialized with per-file locking
  • No app dependency — the server runs headless and starts automatically (systemd, Docker, etc.)
[Obsidian app]  ──sync──►  [vault on server]  ◄──MCP──  [Claude on any machine]
  (phone/laptop)              (NAS / VPS)                  (Claude Desktop / Code)

Features

  • Read & Search — read notes, search full-text (exact/regex/fuzzy, optionally combined with a frontmatter filter or scoped to filenames), render embedded transclusions, inspect note outlines, list every file in the vault regardless of type
  • Duplicate prevention — find_similar_notes_tool ranks notes by TF-IDF similarity so a new note doesn't duplicate an existing one under different wording
  • Schema linting — lint_schema_tool validates frontmatter against the enums declared in your own _AI_INSTRUCTIONS.md, plus an optional cron-friendly health-check script
  • Write — create/overwrite notes (with automatic frontmatter preservation, dry-run previews, and unified diffs), patch sections or anchor-less body text, append content, update frontmatter (single or batch), manage tags, move notes with automatic wikilink rewriting
  • Folders — list (optionally recursive with a full tree dump), create, delete, rename folders; renaming rewrites path-based wikilinks vault-wide
  • Query & Graph — backlinks, broken links, orphan detection, BFS link graph, vault stats, task collection across vault
  • Dataview-like queries — filter notes by tags, status, frontmatter fields (exact match or $ne/$in/$nin/$exists operators), or inline fields (key:: value)
  • Audit log — every write-tool call is recorded ({timestamp, tool, path, summary}); get_audit_log_tool queries it (pass path= for one note's history)
  • Periodic Notes — read/preview daily, weekly, monthly, quarterly, yearly journal notes from templates
  • Canvas (opt-in via ENABLE_CANVAS) — read, create, and patch Obsidian Canvas (.canvas) files
  • Excalidraw (opt-in via ENABLE_EXCALIDRAW) — read, create, and patch Obsidian Excalidraw (*.excalidraw.md) drawings
  • Kanban (opt-in via ENABLE_KANBAN) — read, create, and manipulate Obsidian Kanban boards (columns and cards)
  • Bases (opt-in via ENABLE_BASES) — read, create, and patch Obsidian Bases (.base) files — YAML-defined table/cards/list views over existing frontmatter properties
  • Attachments — list, read (text or base64), and add binary files
  • Two auth variants — a static API key (Claude Code, Desktop, curl) and, optionally, GitHub OAuth (claude.ai Web/Mobile Custom Connector) — usable independently or at the same time
  • Multi-vault (opt-in via VAULTS_CONFIG) — serve several fully isolated vaults from one deployment, each identity (API key or GitHub login) mapped to only the vault(s) it may access
  • Templates — render Obsidian templates with built-in ({{date}}, {{title}}, …) and custom variables
  • MCP Resources — expose vault notes, stats, and tags as MCP resources for direct context injection
  • MCP Prompts — weekly_review, daily_note starting points for common workflows

Installation

Via uvx (no clone needed):

VAULT_PATH=/your/vault uvx obsidian-remote-mcp

Via Docker (no Python needed):

docker compose up -d   # see docker-compose.yml

From source:

git clone https://github.com/ykoellmann/obsidian-mcp.git
cd obsidian-mcp
uv sync
uv run obsidian-remote-mcp

Configuration

Copy .env.example to .env and set your vault path:

VAULT_PATH=/path/to/your/obsidian/vault
# Optional:
# READ_ONLY=true            # safe default for network Compose deployments
# READ_PATHS=Notes/,Inbox/  # restrict all reads to specific rooted scopes
# WRITE_PATHS=Notes/,Inbox/ # restrict writes to specific folders
# DENY_READ_PATHS=.obsidian/,.trash/ # security boundary for all reads
# DENY_WRITE_PATHS=.obsidian/,.trash/,_AI_INSTRUCTIONS.md
# ALLOW_PERMANENT_DELETE=false
# REQUIRE_WRITE_PRECONDITIONS=true # require read revision before full overwrite
# INDEX_RECONCILE_INTERVAL=900     # full Markdown hash sweep every 15 minutes
# TRANSPORT=stdio           # stdio (default), http (recommended for network use), or sse (legacy)

Slash-suffixed policy entries such as Notes/ cover that directory and its descendants. An entry without a trailing slash grants or denies only the exact path. For compatibility, native configuration still permits unrestricted writes when both READ_ONLY=false and WRITE_PATHS is empty; choose that combination explicitly, not as a network default. Use a case-sensitive filesystem for authoritative path scopes.

Docker upgrade note: this Compose configuration now defaults READ_ONLY=true, while a native Config invocation retains its historical false default. Existing Docker deployments that intentionally write must explicitly set READ_ONLY=false; pair it with a narrow WRITE_PATHS value. For a nested scope such as deep/nested/, create deep/ beforehand. MCP may create the configured nested/ scope and descendants, but never ancestors above the configured write boundary.

READ_PATHS is an optional allowlist using the same rooted exact/recursive syntax. When set, direct reads, listings, search, index construction, and resources are limited to those scopes; DENY_READ_PATHS still takes precedence. Ancestor directories may be traversed only to reach an allowed scope and do not expose sibling content.

EXCLUDE_PATHS uses those same rooted exact/recursive matching rules, but is only a discovery filter—not an access-control boundary. For example, private/ hides that root directory and its descendants, while it does not hide Projects/private/.

Revision-aware note mutation tools must read the target to determine existence, preserve frontmatter, calculate diffs, or derive an incremental edit. They therefore reject paths covered by DENY_READ_PATHS even if WRITE_PATHS also contains the path. Avoid overlapping those scopes for note workflows. The storage policy can still support intentionally write-only capabilities that do not inspect existing content, but write_note_tool is not one of them.

The best-effort JSONL audit log is application state, not vault content. It defaults beneath LOCK_PATH for native runs and to /data/audit.jsonl in Docker. AUDIT_LOG_PATH must remain outside VAULT_PATH; the final log file is opened without following symlinks.

New files and directories use the normal 0666/0777 creation modes filtered by the MCP process umask. Atomic overwrites preserve the existing file's permission bits. In a shared sync deployment, run the MCP and sync daemon with compatible UID/GID and umask settings so both can continue reading and updating new notes; the home-server profile exposes these as PUID and PGID.

Direct note reads return an opaque sha256:... revision. Pass it as expected_revision when replacing or appending to an existing note so an edit landed by Obsidian Sync during the client's think time is reported as a conflict instead of silently overwritten. Network Compose configurations enable strict full-overwrite preconditions by default. Incremental patch/tag/frontmatter tools always protect the exact version they read internally. This is optimistic concurrency, not exactly-once execution: after a lost append response, re-read and verify the result before retrying without the old revision.

Watcher events are debounced, and the index additionally hashes readable, indexable Markdown every 15 minutes by default to repair missed events. PDFs, images, other attachments, excluded paths, and Excalidraw files are not hashed. See the design note for the scope, measured cost, health fields, and remaining final-rename race.

Full list of variables — including API_KEY, PUBLIC_BASE_URL, and the OAUTH_GITHUB_* variables for the optional second auth variant — is documented with inline comments in .env.example; see Remote Setup for the two auth variants in detail.

Optional plugin-format tools (Canvas / Excalidraw / Kanban / Bases)

# ENABLE_CANVAS=true      # .canvas file tools
# ENABLE_EXCALIDRAW=true  # *.excalidraw.md file tools
# ENABLE_KANBAN=true      # Kanban board tools
# ENABLE_BASES=true       # .base file tools (Obsidian core plugin, 1.9.0+)

# High-impact mutations are absent from the MCP tool list unless enabled.
# ENABLE_MOVE=true             # move_note_tool
# ENABLE_FOLDER_RENAME=true    # rename_folder_tool
# ENABLE_BULK_REPLACE=true     # find_replace_in_vault_tool
# ENABLE_DELETE=true           # delete_tool, restore_tool and list_trash_tool

Each defaults to false. A disabled group's tools aren't just refused at call time — they're never registered, so they don't appear in the tool list at all.

The high-impact mutation groups are similarly opt-in: set ENABLE_MOVE, ENABLE_FOLDER_RENAME, ENABLE_BULK_REPLACE, or ENABLE_DELETE to register the corresponding tools. Their underlying Python functions remain available for local/unit-test use and future transactional implementations.

Usage with Claude Code

Add to your MCP config (e.g. ~/.claude/mcp.json):

{
  "mcpServers": {
    "obsidian": {
      "command": "uv",
      "args": ["--directory", "/path/to/obsidian-mcp", "run", "obsidian-remote-mcp"],
      "env": {
        "VAULT_PATH": "/path/to/your/obsidian/vault"
      }
    }
  }
}

Usage with Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "obsidian": {
      "command": "uv",
      "args": ["--directory", "/path/to/obsidian-mcp", "run", "obsidian-remote-mcp"],
      "env": {
        "VAULT_PATH": "/path/to/your/obsidian/vault"
      }
    }
  }
}

Docker

# 1. Copy and edit the environment variables
cp .env.example .env

# 2. Set HOST_VAULT_PATH and API_KEY in .env, then:
docker compose up -d

The docker-compose.yml pulls the pre-built image from GHCR — no cloning or building required. To build locally instead, swap image: for build: . in the compose file.

GitHub OAuth state is stored under /data/fastmcp by default, inside the Compose mcp-data volume, so logins survive container restarts.

The image has a built-in HEALTHCHECK against GET /health (unauthenticated, with no vault content or filesystem paths). It reports index readiness plus the last reconciliation time, duration, and error, and is visible in docker ps/docker compose ps. Only meaningful for TRANSPORT=http/sse; a no-op for stdio.

Hardened home-server Compose profile

For a home server where Cloudflare Tunnel is the only network entry point, use docker-compose.home-server.yml. It builds the MCP image from the checked-out source, bind-mounts the complete vault read-only, overlays only the two configured AI memory/output directories read-write, sets matching WRITE_PATHS, runs as the configured non-root UID/GID, and publishes no host port. The MCP service is only on an internal network; cloudflared has that network plus a separate normal egress network so it can reach Cloudflare without making MCP externally reachable.

Create the nested writable directories before starting it, set HOST_VAULT_PATH, AI_MEMORY_PATH, AI_OUTPUT_PATH, PUID, PGID, MCP_DATA_PATH, API_KEY, CLOUDFLARE_TUNNEL_TOKEN, and a digest-pinned CLOUDFLARED_IMAGE (for example, cloudflare/cloudflared@sha256:<digest>) in .env. Create the data directory and make it owned by PUID:PGID; it stores /data/locks and application state. Cloudflare Access Managed OAuth authenticates the edge, but it does not inject this application's bearer API key. Clients must still send API_KEY to the origin; trusted-proxy header injection is a future phase, not part of this profile. Then run:

docker compose -f docker-compose.home-server.yml up -d

Folder/note trash and restore are intentionally unavailable in this nested-bind profile: moving from a writable overlay into the read-only parent vault's .trash would cross mounts. Keep ENABLE_DELETE=false (hard-coded here) and do not enable folder restore in this topology.

The static Compose checks are covered by the test suite. A real deployment test (Docker mount precedence, host UID/GID permissions, and the Cloudflare Tunnel route) remains environment-specific and must be run on the target server before relying on it. To update Cloudflared, choose a reviewed release, resolve its immutable RepoDigest, update CLOUDFLARED_IMAGE, then recreate the sidecar; rebuild the MCP service after source changes with docker compose -f docker-compose.home-server.yml build --pull.

Health-Check Cron (Frontmatter Schema)

Separate from the /health liveness check above: scripts/health_check.py runs lint_schema_tool's logic directly (no MCP client needed) and, only if it finds notes whose frontmatter violates the enums declared in your _AI_INSTRUCTIONS.md, drops a report note into your vault's inbox folder. Silent when the vault is clean — no note, no noise.

# One-off / manual run:
VAULT_PATH=/path/to/vault HEALTH_CHECK_INBOX=00-Inbox python scripts/health_check.py

To run it weekly via cron against the running container:

# crontab -e (on the Docker host)
0 6 * * 1 docker exec obsidian-mcp-obsidian-mcp-1 \
  env VAULT_PATH=/vault READ_ONLY=false WRITE_PATHS=00-Inbox/ \
  HEALTH_CHECK_INBOX=00-Inbox python scripts/health_check.py

Swap the container name for whatever docker compose ps shows, and set both HEALTH_CHECK_INBOX and WRITE_PATHS to your vault's actual inbox folder (default Inbox). The command must have write access because it creates a report when violations are found. With the home-server profile, choose an inbox inside one of its writable nested mounts (for example AI-Output/).

Run obsidian-mcp on a server and connect to it remotely. Network transports (sse/streamable-http) need at least one of the two auth variants below — API key and GitHub OAuth are independent and can be used at the same time: keep the API key for Claude Code/Desktop/curl while adding OAuth only for claude.ai, or use either one alone.

Security: Always put a TLS-terminating reverse proxy (e.g. Caddy) in front when exposing to the internet — required for GitHub OAuth callbacks in particular, since GitHub rejects plain http:// callback URLs except on localhost. API_KEY/OAuth are not needed for stdio transport (local use only).

Option A: API key (Claude Code, Claude Desktop, curl, mcp-remote)

1. Generate an API key:

openssl rand -hex 32

2. Configure the server (docker-compose.yml or .env):

VAULT_PATH=/data/vault
TRANSPORT=http
API_KEY=your-generated-key

(sse also works here, but see the note under Option B — http is the more robust choice and works identically for this bearer-key setup.)

3. Start:

docker compose up -d   # or: uv run obsidian-remote-mcp

4. Connect from your MCP client (anywhere on the network):

{
  "mcpServers": {
    "obsidian": {
      "type": "http",
      "url": "https://your-server/mcp",
      "headers": {
        "Authorization": "Bearer your-generated-key"
      }
    }
  }
}

Option B: GitHub OAuth (claude.ai Web/Mobile Custom Connector)

claude.ai's "Custom Connector" UI only has fields for OAuth (Authorization URL, Token URL, Client ID/Secret) — no field for a bearer token or custom header. obsidian-mcp handles the whole OAuth protocol for you (discovery endpoints, PKCE, token exchange); you only ever hand claude.ai your server's URL.

1. Create a GitHub OAuth App: GitHub → Settings → Developer settings → OAuth Apps → New OAuth App.

  • Homepage URL: your server's public URL (e.g. https://obsidian.example.com)
  • Authorization callback URL: the same URL + /auth/callback (e.g. https://obsidian.example.com/auth/callback)

Copy the generated Client ID and Client Secret.

2. Configure the server (docker-compose.yml or .env):

VAULT_PATH=/data/vault
TRANSPORT=http
PUBLIC_BASE_URL=https://obsidian.example.com   # must match the GitHub callback host
OAUTH_GITHUB_CLIENT_ID=your-client-id
OAUTH_GITHUB_CLIENT_SECRET=your-client-secret
OAUTH_GITHUB_ALLOWED_LOGINS=your-github-username # comma-separated; required, no "allow anyone" fallback

OAUTH_GITHUB_ALLOWED_LOGINS is enforced at login: only the listed GitHub accounts can authenticate, everyone else is rejected, even with a valid GitHub account.

Use TRANSPORT=http, not sse. sse caused OAuth authorization errors with claude.ai specifically (token issued fine server-side, but claude.ai never followed up with a request) — http fixed it.

3. Start:

docker compose up -d   # or: uv run obsidian-remote-mcp

4. Connect from claude.ai: Settings → Connectors → Add Custom Connector, and enter just the server URL (https://obsidian.example.com/mcp). claude.ai discovers everything else (/.well-known/oauth-authorization-server, PKCE, etc.) automatically and redirects you to GitHub to log in on first connect.

Persistence in Docker: OAuth client registrations and tokens are stored under FastMCP's own data directory, which is not inside the vault volume by default. Without a persistent mount there, every container restart logs claude.ai out and forces re-authentication. Set FASTMCP_HOME to a mounted path (see docker-compose.yml) to avoid that.

Keep the vault synced on the server with Syncthing, git+cron, rclone, or Obsidian Sync. The file watcher picks up normal changes, while periodic Markdown reconciliation repairs missed watcher events.

Multi-Vault Setup

By default obsidian-mcp serves one vault (VAULT_PATH). If you need several completely separate vaults from one deployment — e.g. a private vault and a work vault, each only reachable by its own identity — set VAULTS_CONFIG to the path of a JSON file instead. Vault path-policy settings (VAULT_PATH, READ_PATHS, WRITE_PATHS, DENY_READ_PATHS, DENY_WRITE_PATHS, and EXCLUDE_PATHS) and identity settings (API_KEY and OAUTH_GITHUB_ALLOWED_LOGINS) then come from that file. See vaults.json.example:

{
  "vaults": {
    "private": {"path": "/vaults/private", "exclude_paths": ["private/", ".obsidian/", ".trash/"]},
    "monari":  {"path": "/vaults/monari",  "write_paths": ["02-Areas/monari/"]}
  },
  "identities": [
    {"type": "api_key",      "value": "sk-...",              "vaults": ["private"]},
    {"type": "github_login", "value": "your-github-username", "vaults": ["private", "monari"], "default": "private"}
  ]
}

Each vault entry can set read_paths, write_paths, deny_read_paths, deny_write_paths, exclude_paths, and read_only independently. Path rules are rooted: a trailing slash includes descendants, while a rule without one matches only that exact path. exclude_paths controls discovery/indexing; the read/write/deny fields are the access-control boundary.

VAULT_PATH=              # unused — vaults.json defines paths instead
VAULTS_CONFIG=/data/vaults.json
TRANSPORT=http

Multi-vault mode requires an authenticated network transport (http, sse, or streamable-http). It cannot be used with stdio, because stdio has no authenticated request identity to map to a vault.

Each identities entry is either an API key (Authorization: Bearer <value>, same as Option A above) or a GitHub login (same allowlist mechanism as Option B — set OAUTH_GITHUB_CLIENT_ID/SECRET/PUBLIC_BASE_URL as usual, just skip OAUTH_GITHUB_ALLOWED_LOGINS since vaults.json replaces it). Both kinds can be mixed and used at the same time, exactly like today. Whichever identity a request authenticates as, every tool call is transparently scoped to that identity's vault(s) — there is no way to reach a vault an identity isn't listed for.

An identity with more than one entry in "vaults" can switch between them: every tool accepts an optional vault=<name> argument for that one call. If omitted, it uses the identity's configured "default"; an identity with several vaults and no default must pass vault= explicitly. list_vaults_tool() returns [{name, description, is_default}] for whichever identity is calling, so an MCP client can discover what it's allowed to pass — the built-in instructions tell Claude to call it first and pass vault= when the conversation clearly points at a non-default vault. There's no server-side memory of which vault was picked last; it's re-selected on every call, same as any other argument.

/attachments/* (the direct binary upload/download route) is fully multi-vault-aware: a plain Authorization: Bearer request resolves to that identity's default vault, or pass ?vault=<name> in the URL to pick a different one of its allowed vaults (same rule as the vault= tool argument). create_attachment_token_tool's short-lived scoped tokens (?exp=&sig=) work too, signed against the calling identity's own key and bound to a specific vault — but only for api_key identities, since a GitHub login has no static secret of its own to sign with; use a plain Authorization: Bearer request for those instead.

Known limitation: /health doesn't go through per-request auth/vault resolution — it always reports on the first vault listed in vaults.json, regardless of which identity would be calling. It exposes no vault content either way (just process liveness), so this doesn't leak anything.

Vault Conventions (Customization)

Create _AI_INSTRUCTIONS.md in your vault root to teach the AI how your specific vault is organized:

## Structure
- `Notes/` — evergreen notes and concepts
- `Projects/` — active and archived projects (tag: #project/active, #project/done)
- `Journal/` — daily notes (YYYY-MM-DD.md)

## Frontmatter Schema
- status: active | done | inbox
- tags: nested with / (e.g. #concept/programming)

## Conventions
- Link by stem only, never by full path
- Every note needs a created: date in frontmatter

In single-vault mode, the server loads this file at startup and sends it to the AI as system instructions. Without it, built-in generic Obsidian syntax guidance is used. Multi-vault servers always use the generic startup instructions because MCP server instructions are shared by every identity; use get_vault_conventions_tool(vault=...) to load the selected vault's conventions after authorization. The _AI_INSTRUCTIONS.md is the right place for everything vault-specific — folder layout, tag schema, naming conventions, and any workflow rules.

Tool Reference

Category Tools
Read list_notes, read_note (mode: full/outline/rendered), search_notes
Write write_note, patch_note, delete, restore, append_to_note, patch_frontmatter (one note or many), manage_tags, move_note, find_replace_in_vault
Folders list_folder, create_folder, rename_folder, list_trash* (folders are deleted/restored by delete/restore)
Query query_notes, get_backlinks, get_broken_links, get_orphans, get_link_graph, get_vault_stats, get_tasks, resolve_alias
Tags list_all_tags (mode: flat/tree; notes for one tag: query_notes(tags=[...]))
Periodic get_periodic_note
Canvas list_canvases, read_canvas, write_canvas, patch_canvas
Excalidraw list_excalidraw, read_excalidraw, write_excalidraw, patch_excalidraw
Kanban read_kanban, create_kanban_board, add_kanban_card, move_kanban_card, delete_kanban_card
Bases list_bases, read_base, write_base, patch_base
Attachments list_attachments, read_attachment, add_attachment
Templates list_templates, create_from_template

* Delete, restore, and trash-listing tools are registered only when ENABLE_DELETE=true.

Canvas, Excalidraw, Kanban, and Bases are each opt-in (see Optional plugin-format tools above) — their tools only appear once the matching ENABLE_* flag is set.

Full parameter documentation is embedded in the server and shown automatically to connected AI clients.

Architecture

src/obsidian_mcp/
├── config.py          # env-based config and read/write security boundaries
├── server.py          # FastMCP entry point, tool and resource registrations
├── domain/
│   ├── models.py      # Note dataclass (frontmatter, tags, wikilinks, tasks, …)
│   ├── parser.py      # Markdown parser (YAML frontmatter, wikilinks, block refs, …)
│   └── index.py       # VaultIndex — alias resolution, backlinks, tag tree, BFS
├── storage/
│   ├── filesystem.py  # VaultStorage authorization and atomic writes
│   ├── locking.py     # hashed locks outside the synced vault
│   └── watcher.py     # watchdog-based vault change detection (polling fallback)
└── tools/
    ├── read.py        # read_note, search_notes, render_note, get_note_outline
    ├── write.py       # write_note, patch_note, move_note, manage_tags, …
    ├── query.py       # graph tools, task aggregation, periodic notes, query_notes
    ├── folders.py     # folder management
    ├── canvas.py      # Obsidian Canvas (.canvas JSON) tools
    ├── excalidraw.py  # Obsidian Excalidraw (*.excalidraw.md) tools
    ├── kanban.py      # Obsidian Kanban plugin tools
    ├── bases.py       # Obsidian Bases (.base YAML) tools
    ├── attachments.py # binary and text attachment handling
    ├── templates.py   # template rendering with variable substitution
    └── prompts.py     # MCP Prompts (weekly_review, daily_note)

Development

uv run pytest -q       # complete automated suite
uv run ruff check src/ tests/ scripts/run_local_smoke_test.py scripts/smoke_test_mcp.py

Local HTTP functional smoke test

The automated suite exercises most behavior in process. This command also starts the installed server entry point and connects a real authenticated MCP client over HTTP:

uv run python scripts/run_local_smoke_test.py

The runner chooses a free localhost port, creates a disposable vault and API key, starts and health-checks the server, then invokes smoke_test_mcp.py. The client lists tools, creates and reads a uniquely named note, overwrites it, verifies the bytes on disk, and confirms that a write outside WRITE_PATHS is rejected. The runner always stops the server and removes successful test data; pass --keep to retain the disposable vault and server log for inspection.

Use smoke_test_mcp.py directly for an already-running local, containerized, or remote server. It reads the bearer token from OBSIDIAN_MCP_API_KEY (or prompts securely), so secrets do not need to appear in command history or process arguments. Its denied-write probe is opt-in via --denied-note PATH; only provide a path known to be outside that server's configured write scope.

License

MIT

Metadata

Release files for obsidian-remote-mcp 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for obsidian-remote-mcp 2.0.0
File Size Uploaded Provenance Actions
obsidian_remote_mcp-2.0.0.tar.gz 250.9 kB Without provenance Details for obsidian_remote_mcp-2.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for obsidian-remote-mcp 2.0.0
File Interpreter ABI Platform Actions
obsidian_remote_mcp-2.0.0-py3-none-any.whl Python 3 none any Details for obsidian_remote_mcp-2.0.0-py3-none-any.whl

Total release size: 361.1 kB

Release files / obsidian_remote_mcp-2.0.0.tar.gz

Download URL obsidian_remote_mcp-2.0.0.tar.gz
Size 250.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3398f84006cc8c1bec8e0591ae0e06e974b338f1e30da53c1a3a05a42e6d670a
BLAKE2b-256 checksum
How to use checksums
7d270b8418739c7c3b98197fcb75cafe3c2a43395125ca2ca883286369ff4591
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / obsidian_remote_mcp-2.0.0-py3-none-any.whl

Download URL obsidian_remote_mcp-2.0.0-py3-none-any.whl
Size 110.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5976a44c782fd122a954ce22758c25f90d7650e570a47b0b762d4fd5ca21bb24
BLAKE2b-256 checksum
How to use checksums
eba8e7b2bb24ea424b64c9f2309184bf86295d2793de8e5b85be9eadcbee6c70
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for obsidian-remote-mcp 2.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page