Obsidian MCP
Reads and edits notes, folders and tags in local Obsidian vaults you name at startup
Read, search and edit notes, headings, tags and frontmatter in an Obsidian vault
By Casey Hand (individual) TypeScript Local · stdio ProductivityKnowledge and memory
70 popularity score ★ 702 ↓ 7.7k/wk
Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.
It needs OBSIDIAN_API_KEY. Replace each <NAME> with your value.
claude mcp add obsidian -e OBSIDIAN_API_KEY=<OBSIDIAN_API_KEY> -- npx -y obsidian-mcp-server{
"mcpServers": {
"obsidian": {
"command": "npx",
"args": [
"-y",
"obsidian-mcp-server"
],
"env": {
"OBSIDIAN_API_KEY": "<OBSIDIAN_API_KEY>"
}
}
}
}{
"mcpServers": {
"obsidian": {
"command": "npx",
"args": [
"-y",
"obsidian-mcp-server"
],
"env": {
"OBSIDIAN_API_KEY": "<OBSIDIAN_API_KEY>"
}
}
}
}{
"servers": {
"obsidian": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"obsidian-mcp-server"
],
"env": {
"OBSIDIAN_API_KEY": "<OBSIDIAN_API_KEY>"
}
}
}
}[mcp_servers.obsidian]
command = "npx"
args = ["-y", "obsidian-mcp-server"]
[mcp_servers.obsidian.env]
OBSIDIAN_API_KEY = "<OBSIDIAN_API_KEY>"gemini mcp add --scope user -e OBSIDIAN_API_KEY=<OBSIDIAN_API_KEY> obsidian npx -- -y obsidian-mcp-serverOpens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.
It needs OBSIDIAN_API_KEY. Replace each <NAME> with your value.
claude mcp add obsidian -e OBSIDIAN_API_KEY=<OBSIDIAN_API_KEY> -- docker run -i --rm -e MCP_TRANSPORT_TYPE=stdio -e OBSIDIAN_API_KEY -e OBSIDIAN_BASE_URL=http://host.docker.internal:27123 ghcr.io/cyanheads/obsidian-mcp-server:latest{
"mcpServers": {
"obsidian": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"MCP_TRANSPORT_TYPE=stdio",
"-e",
"OBSIDIAN_API_KEY",
"-e",
"OBSIDIAN_BASE_URL=http://host.docker.internal:27123",
"ghcr.io/cyanheads/obsidian-mcp-server:latest"
],
"env": {
"OBSIDIAN_API_KEY": "<OBSIDIAN_API_KEY>"
}
}
}
}{
"mcpServers": {
"obsidian": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"MCP_TRANSPORT_TYPE=stdio",
"-e",
"OBSIDIAN_API_KEY",
"-e",
"OBSIDIAN_BASE_URL=http://host.docker.internal:27123",
"ghcr.io/cyanheads/obsidian-mcp-server:latest"
],
"env": {
"OBSIDIAN_API_KEY": "<OBSIDIAN_API_KEY>"
}
}
}
}{
"servers": {
"obsidian": {
"type": "stdio",
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"MCP_TRANSPORT_TYPE=stdio",
"-e",
"OBSIDIAN_API_KEY",
"-e",
"OBSIDIAN_BASE_URL=http://host.docker.internal:27123",
"ghcr.io/cyanheads/obsidian-mcp-server:latest"
],
"env": {
"OBSIDIAN_API_KEY": "<OBSIDIAN_API_KEY>"
}
}
}
}[mcp_servers.obsidian]
command = "docker"
args = ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "-e", "OBSIDIAN_API_KEY", "-e", "OBSIDIAN_BASE_URL=http://host.docker.internal:27123", "ghcr.io/cyanheads/obsidian-mcp-server:latest"]
[mcp_servers.obsidian.env]
OBSIDIAN_API_KEY = "<OBSIDIAN_API_KEY>"gemini mcp add --scope user -e OBSIDIAN_API_KEY=<OBSIDIAN_API_KEY> obsidian docker -- run -i --rm -e MCP_TRANSPORT_TYPE=stdio -e OBSIDIAN_API_KEY -e OBSIDIAN_BASE_URL=http://host.docker.internal:27123 ghcr.io/cyanheads/obsidian-mcp-server:latestOBSIDIAN_API_KEY secret |
Required: API key from the Local REST API plugin settings. |
|---|---|
OBSIDIAN_BASE_URL |
Optional: Plugin address; use https://127.0.0.1:27124 for the HTTPS port or host.docker.internal from Docker. |
OBSIDIAN_VERIFY_SSL |
Optional: Check the plugin's TLS certificate; off because the plugin's certificate is self-signed. |
OBSIDIAN_READ_ONLY |
Optional: true turns off every write tool and the command tools. |
OBSIDIAN_ENABLE_COMMANDS |
Optional: true enables the two command-palette tools. |
OBSIDIAN_DELETE_ELICITATION |
Optional: true asks the user to confirm each delete; needs a client that supports elicitation. |
OBSIDIAN_OMNISEARCH_URL |
Optional: Omnisearch server address; taken from the base URL host on port 51361 when unset. |
OBSIDIAN_REQUEST_TIMEOUT_MS |
Optional: Per-request timeout in milliseconds. |
| Set together: path policy | |
OBSIDIAN_READ_PATHS |
Optional: Comma-separated vault folders the tools may read; unset means the whole vault. |
OBSIDIAN_WRITE_PATHS |
Optional: Comma-separated vault folders the tools may write; unset means the read scope or the whole vault. |
OBSIDIAN_DENY_PATHS |
Optional: Comma-separated paths kept from reads and writes alike, overriding both allowlists. |
In a container, a setting goes in with -e NAME=value after docker run.
obsidian-mcp-server talks to a running Obsidian vault through the community Local REST API plugin. The server never opens vault files on disk. Each read and write goes as an HTTP call to the plugin inside the Obsidian app, so Obsidian has to stay open while you use this.
On the read side you get a note whole, as a structured record, as a map of its headings, or one section at a time. Folder and tag listings come with filters. Search takes plain text or a JSONLogic query over path, content, frontmatter and tags, and a ranked omnisearch mode shows up when the Omnisearch plugin answers at startup. Edits can be aimed at a single heading, block reference or frontmatter field instead of the whole file. There are also tools for regex replacements, frontmatter keys, tags and deletes. Every write reports the note's size before and after the change, which makes an accidental clobber easy to spot. Three resources sit next to the tools: a note by path, the full tag list, and the plugin's status.
Of the 14 tools, 12 are active by default. The two command-palette tools stay off until OBSIDIAN_ENABLE_COMMANDS is true. With OBSIDIAN_READ_ONLY set, the seven write tools and the command pair drop out and five remain. One of those five is obsidian_open_in_ui, because the code registers it with the read tools (src/index.ts and tools/definitions/index.ts). Folder allowlists and a deny list narrow what the tools can reach. The config code lowercases each entry and refuses to start when one is an absolute path, contains '..' or names the vault root (src/config/server-config.ts). Transport is stdio by default, with a local Streamable HTTP mode as the other choice.
| Runtime | Node.js 24+ |
|---|---|
| Runs on | macOS, Windows, Linux |
| Also |
|
Copy the API key from Settings, Community Plugins, Local REST API in Obsidian and set it as OBSIDIAN_API_KEY. The default address http://127.0.0.1:27123 needs the plugin's 'Non-encrypted (HTTP) Server' switched on. Otherwise set OBSIDIAN_BASE_URL to https://127.0.0.1:27124. From Docker, point OBSIDIAN_BASE_URL at http://host.docker.internal:27123. Periodic-note targets on plugin v5.0.2 and later need the periodic-notes API extension. The omnisearch mode needs the Omnisearch plugin's HTTP server.
Works only while Obsidian is open with the plugin reachable; calls fail with obsidian_unreachable otherwise. There is no backlinks tool (a JSONLogic regex search stands in). obsidian_list_notes stops at 1,000 entries and goes 2 levels deep by default (up to 20); obsidian_list_tags returns 200 tags by default, up to 10000; omnisearch results are capped at 50 by the plugin. Omnisearch is probed once at startup, so the server must restart to pick it up. On plugin v4.x, heading writes to notes with CRLF line endings land mid-line; plugin v6.0 breaks two table-row write forms. Deletes have no undo beyond Obsidian's trash.
Suits someone who keeps notes in Obsidian on their own machine and wants an assistant to make targeted edits (one heading, one frontmatter key, a tag) rather than rewrite whole files, and who is willing to install the Local REST API plugin. The read and write allowlists, the deny list and the read-only switch make it workable for letting an assistant into part of a vault while keeping a private folder out. It is a community project, not from Obsidian. It is not a fit for a vault on a machine where Obsidian is not running, such as a server or a synced folder read without the app.
5 only read, 6 change things, 3 can delete or overwrite.
obsidian_get_noteobsidian_list_notesobsidian_list_tagsobsidian_search_notesobsidian_write_note deletesobsidian_append_to_note changesobsidian_patch_note changesobsidian_replace_in_note changesobsidian_manage_frontmatter changesobsidian_manage_tags changesobsidian_delete_note deletesobsidian_open_in_ui changesobsidian_list_commandsobsidian_execute_command deletesobsidian://vault/{+path}obsidian://tagsobsidian://status