Obsidian-MCP-Server
About
Seamlessly integrate Claude AI into your Obsidian vault! This guide provides a straightforward setup for the Model Context Protocol (MCP) server on Windows 11, empowering Claude to directly assist your brainstorming, notetaking, and knowledge management within Obsidian.
Details
- License
- MIT
Explore
- Read your vault’s content for summarization and analysis.
- Create and modify notes based on AI prompts.
- Search your vault for relevant information.
- Secure access via Obsidian’s Local REST API plugin.
- Works with Claude Desktop on Windows 11.
Setting up with Highlight
This MCP is not yet compatible with Highlight’s one-click setup. However, you can still use it with Highlight by following these steps:
- Download and install Highlight from highlightai.com/download
- Navigate to the plugins tab and select "Add Custom Plugin"
-
Configure the plugin with the settings below
Plugin Name
Obsidian-MCP-ServerCommand (node, npx, python, etc.)Please refer to the README for specific instructions on how to obtain API keys or other required environment variables.
- Enable "Start Automatically" if you want the plugin to start when Highlight launches
From the repository
Before you start, ensure you have the following:
Obsidian Installed: An active Obsidian vault you wish to integrate with AI.
Node.js (Version 20 or higher): The MCP server runs on Node.js.
Check your version: Open PowerShell and run: node -v
If you don't have Node.js or it's an older version, download and install the latest LTS (Long Term Support) version from nodejs.org.
Claude Desktop: The AI application you'll be connecting.
---
Follow these instructions carefully to get your Obsidian MCP server integrated with Claude Desktop.
In this phase, you'll configure Claude Desktop to automatically launch and manage the Obsidian MCP server whenever Claude Desktop starts.
1. Close Claude Desktop Completely: Ensure the application is fully closed, not just minimized to the system tray. Use Task Manager (Ctrl+Shift+Esc) if necessary, find "Claude" in the "Apps" or "Background processes" section, right-click, and select "End task."
2. Locate Claude Desktop's Configuration File:
Open File Explorer.
In the address bar, type: %APPDATA%\Claude\ and press Enter.
You should find a file named claude_desktop_config.json directly in this folder. If it doesn't exist, create a new plain text file with this exact name.
3. Edit the Configuration File:
Open claude_desktop_config.json with a plain text editor (e.g., Notepad, VS Code, Notepad++).
Important: If you have an existing configuration (e.g., for a Blender MCP server), you'll add the Obsidian entry alongside it, separated by a comma.
Add or modify the mcpServers section to include your Obsidian MCP server configuration:
{
"mcpServers": {
"obsidian": { // You can name this anything, "obsidian" is descriptive.
"command": "npx",
"args": ["-y", "obsidian-mcp", "YOUR_OBSIDIAN_VAULT_PATH_HERE"],
"env": {
"OBSIDIAN_API_KEY": "YOUR_ACTUAL_OBSIDIAN_API_KEY_HERE"
}
}
// If you have other servers (like Blender), they would be listed here,
// separated by a comma from the "obsidian" entry, like this:
// "anotherServerName": { ... },
// "obsidian": { ... }
}
}
Key points for the configuration above:
Replace YOUR_OBSIDIAN_VAULT_PATH_HERE with the exact, full, absolute path to your Obsidian vault folder on your system.
Example for Windows: "C:/Users/YourUser/Documents/MyVault" (using forward slashes, generally recommended in JSON)
Alternatively (Windows): "C:\\Users\\YourUser\\Documents\\MyVault" (using double backslashes)
Replace YOUR_ACTUAL_OBSIDIAN_API_KEY_HERE with the exact API key you copied from Phase 1, step 9. This is a long string of characters.
Save the claude_desktop_config.json file.
4. Validate JSON Syntax:
Copy the entire content of your modified claude_desktop_config.json file.
Go to an online JSON validator like jsonlint.com.
Paste your JSON into the validator and click "Validate JSON." It must say "Valid JSON." If it shows any errors (e.g., "Missing comma," "Bad string"), fix them precisely in your claude_desktop_config.json file and save again.
5. Restart Claude Desktop: Launch Claude Desktop. Allow a minute or two for it to fully load and attempt to start the MCP server.
Once Claude Desktop starts, it should now be able to communicate with your Obsidian vault! Look for indications within Claude Desktop's UI that it recognizes the Obsidian server.
---
obsidian_get_note
Read a note from the vault — by path, the active file, or a periodic note. Choose a `format` projection: raw body, full object, structural document map, or a single section.
obsidian_list_notes
List notes and subdirectories at a vault path. Defaults to the vault root when `path` is omitted. Tune recursion with `depth`, or filter the walk with `extension` / `nameRegex`. Capped at 1000 entries per call — when reached, walking stops and `excluded` is set; narrow `path` or tighten filters to surface the rest.
obsidian_list_tags
List every tag found across the vault, with usage counts. Includes hierarchical parents — `work/tasks` contributes to both `work` and `work/tasks`. Filter to a subset with the optional `nameRegex`. To find notes by tag, use `obsidian_search_notes` in jsonlogic mode (e.g. `{"in": ["work", {"var": "tags"}]}`).
obsidian_open_in_ui
Open a file in the Obsidian app UI. By default fails when the path does not exist; the `failIfMissing` flag controls the open-or-create behavior. Opening an existing file needs read access; opening a missing one creates it, so that case needs write access to the path.
obsidian_search_notes
Search the vault by text substring or JSONLogic predicate. Pick the mode that matches the query shape. Results paginate via opaque cursors: omit `cursor` for the first page, then pass `nextCursor` from the prior response. Text-mode hits additionally clip per file at `maxMatchesPerHit`.
obsidian_write_note
Create or overwrite a note. With `section`, replaces just that heading/block/frontmatter section in place — use `obsidian_get_note` with `format: "document-map"` to discover available targets. A nested heading may be named either by its full `Parent::Child` path or by a bare leaf name that matches exactly one heading; a leaf shared by several headings is rejected with `ambiguous_section`. Whole-file writes fail with `file_exists` against an existing note unless `overwrite: true` — for in-place edits, prefer `obsidian_patch_note` (sections), `obsidian_append_to_note` (append), or `obsidian_replace_in_note` (find-and-replace). For heading sections, `content` is the new body; the heading line is preserved automatically.
obsidian_append_to_note
Append content to a note. **Without `section`: appends to the end of the file, or creates the file if it does not exist (your content becomes the full file).** With `section`: appends to the end of that heading/block/frontmatter — use `obsidian_get_note` with `format: "document-map"` to discover available targets. A nested heading may be named either by its full `Parent::Child` path or by a bare leaf name that matches exactly one heading; a leaf shared by several headings is rejected with `ambiguous_section`. For block-reference targets, content is concatenated adjacent to the block line without inserting a separator — include a leading newline in `content` if you want one. Set `createTargetIfMissing` to bring the target section into existence rather than failing when it does not exist.
obsidian_patch_note
Edit a heading, block reference, or frontmatter field in place — append to, prepend to, or replace the target's body. Use `obsidian_get_note` with `format: "document-map"` to discover available targets first. A nested heading may be named either by its full `Parent::Child` path or by a bare leaf name that matches exactly one heading; a leaf shared by several headings is rejected with `ambiguous_section`.
obsidian_replace_in_note
Search and replace inside a single note, literally or by regex. Replacements run in array order, each over the previous one's output. Use for edits that don't fit `obsidian_patch_note`'s structural targets — e.g., body-wide find-and-replace.
obsidian_manage_frontmatter
Get, set, or delete a single frontmatter key on a note, atomically. `set` requires a JSON-typed `value` (string, number, boolean, array, or object).
obsidian_manage_tags
Add, remove, or list a note's tags. Defaults to the frontmatter `tags:` array — set `location` to `inline` or `both` to mutate the note body. `add` ensures the tag is present in the requested location(s); `remove` strips it; `both` reconciles across both representations. Inline `#tag` occurrences inside fenced code blocks are intentionally left alone, and inline-location additions append the new tag at end-of-file. `list` ignores the input `tags` array.
obsidian_delete_note
Permanently delete a note from the vault. Confirms with the user before deleting when the client supports interactive confirmation. Recovery requires the local trash in Obsidian — there is no API-level undo.
- obsidian_get_note: Read a note from the vault — by path, the active file, or a periodic note. Choose a format projection: raw body, full object, structural document map, or a single section.
- obsidian_list_notes: List notes and subdirectories at a vault path. Defaults to the vault root when path is omitted. Tune recursion with depth, or filter the walk with extension / nameRegex. Capped at 1000 entries per call — when reached, walking stops and excluded is set; narrow path or tighten filters to surface the rest.
- obsidian_list_tags: List every tag found across the vault, with usage counts. Includes hierarchical parents — work/tasks contributes to both work and work/tasks. Filter to a subset with the optional nameRegex. To find notes by tag, use obsidian_search_notes in jsonlogic mode (e.g. {"in": ["work", {"var": "tags"}]}).
- obsidian_open_in_ui: Open a file in the Obsidian app UI. By default fails when the path does not exist; the failIfMissing flag controls the open-or-create behavior. Opening an existing file needs read access; opening a missing one creates it, so that case needs write access to the path.
- obsidian_search_notes: Search the vault by text substring or JSONLogic predicate. Pick the mode that matches the query shape. Results paginate via opaque cursors: omit cursor for the first page, then pass nextCursor from the prior response. Text-mode hits additionally clip per file at maxMatchesPerHit.
- obsidian_write_note: Create or overwrite a note. With section, replaces just that heading/block/frontmatter section in place — use obsidian_get_note with format: "document-map" to discover available targets. A nested heading may be named either by its full Parent::Child path or by a bare leaf name that matches exactly one heading; a leaf shared by several headings is rejected with ambiguous_section. Whole-file writes fail with file_exists against an existing note unless overwrite: true — for in-place edits, prefer obsidian_patch_note (sections), obsidian_append_to_note (append), or obsidian_replace_in_note (find-and-replace). For heading sections, content is the new body; the heading line is preserved automatically.
- obsidian_append_to_note: Append content to a note. Without section: appends to the end of the file, or creates the file if it does not exist (your content becomes the full file). With section: appends to the end of that heading/block/frontmatter — use obsidian_get_note with format: "document-map" to discover available targets. A nested heading may be named either by its full Parent::Child path or by a bare leaf name that matches exactly one heading; a leaf shared by several headings is rejected with ambiguous_section. For block-reference targets, content is concatenated adjacent to the block line without inserting a separator — include a leading newline in content if you want one. Set createTargetIfMissing to bring the target section into existence rather than failing when it does not exist.
- obsidian_patch_note: Edit a heading, block reference, or frontmatter field in place — append to, prepend to, or replace the target's body. Use obsidian_get_note with format: "document-map" to discover available targets first. A nested heading may be named either by its full Parent::Child path or by a bare leaf name that matches exactly one heading; a leaf shared by several headings is rejected with ambiguous_section.
- obsidian_replace_in_note: Search and replace inside a single note, literally or by regex. Replacements run in array order, each over the previous one's output. Use for edits that don't fit obsidian_patch_note's structural targets — e.g., body-wide find-and-replace.
- obsidian_manage_frontmatter: Get, set, or delete a single frontmatter key on a note, atomically. set requires a JSON-typed value (string, number, boolean, array, or object).
- obsidian_manage_tags: Add, remove, or list a note's tags. Defaults to the frontmatter tags: array — set location to inline or both to mutate the note body. add ensures the tag is present in the requested location(s); remove strips it; both reconciles across both representations. Inline #tag occurrences inside fenced code blocks are intentionally left alone, and inline-location additions append the new tag at end-of-file. list ignores the input tags array.
- obsidian_delete_note: Permanently delete a note from the vault. Confirms with the user before deleting when the client supports interactive confirmation. Recovery requires the local trash in Obsidian — there is no API-level undo.
Claude Desktop / Cursor
Paste into your MCP client config file to install this server.
{
"mcpServers": {
"obsidian-mcp-server": {
"obsidian": {
"command": "npx",
"args": [
"-y",
"obsidian-mcp",
"YOUR_OBSIDIAN_VAULT_PATH_HERE"
],
"env": {
"OBSIDIAN_API_KEY": "YOUR_ACTUAL_OBSIDIAN_API_KEY_HERE"
}
}
}
}
}
McpServers
{
"obsidian": {
"command": "npx",
"args": [
"-y",
"obsidian-mcp",
"YOUR_OBSIDIAN_VAULT_PATH_HERE"
],
"env": {
"OBSIDIAN_API_KEY": "YOUR_ACTUAL_OBSIDIAN_API_KEY_HERE"
}
}
}
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.



